<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Outbound shaping and IP warm-up: one slow destination must not stall the queue]]></title><description><![CDATA[<p dir="auto">Since 6.3.4 the delivery queue shapes what it sends. It pauses a destination that asked it to slow down, caps how many sessions it holds open to one destination and how many deliveries one tenant has in flight, and holds a new outbound address to a daily ceiling at each large provider. Everything in this topic is new in 6.3.4 except <code>MaxOutboundPerDestinationPerMinute</code>, a fixed per-destination rate that 6.3.3 already has. What to know first: of what this topic covers, two things change behaviour on upgrade without a switch. The back-off is <strong>on by default</strong>, and <strong>a deferral this server chose does not spend a message's retries</strong> until the message has been queued for longer than its retry schedule spans; only a failure at a remote does. The second covers every hold in this topic, and so changes an upgraded server that already sets <code>MaxOutboundPerDestinationPerMinute</code>. The connection ceilings, the tenant share and the warm-up do nothing until you set them.</p>
<h3><a class="anchor-offset" name="the-order-of-the-checks"></a>The order of the checks</h3>
<p dir="auto">For each batch of recipients on one target, the server judges in this order, before any connection is opened:</p>
<ol>
<li>The remote domain policy's <strong>largest message</strong>: <code>5.3.4</code>, permanent, measured on the queued message.</li>
<li>The destination's <strong>back-off window</strong>. Held until the window ends; then one delivery goes through as the probe, and any other arriving meanwhile waits a minute.</li>
<li>The policy's <strong>messages a minute</strong> (<code>max_messages_per_minute</code>).</li>
<li>The <strong>connection ceiling</strong>: the policy's <code>max_connections</code> where the policy sets one, otherwise the server-wide <code>MaxOutboundConnectionsPerDestination</code>.</li>
<li>The <strong>tenant share</strong>, <code>MaxOutboundConnectionsPerTenant</code>.</li>
<li>The server-wide <strong><code>MaxOutboundPerDestinationPerMinute</code></strong>.</li>
<li>DNS: the MX lookup (or the route's host) and MTA-STS; then the <strong>IP warm-up</strong>'s daily ceiling; then, where DANE applies, whether the MX set is DNSSEC-validated.</li>
<li><strong>Gateway encryption</strong>, for a domain whose policy encrypts. The copy is made here, so a batch that is only going to be deferred is never encrypted.</li>
<li>The connection attempts.</li>
</ol>
<p dir="auto">Every one of 2 to 6 is a deferral with <code>4.4.5</code> ("mail system congestion") and a sentence naming the rule. The <strong>target</strong> each check is keyed by is what the batch is delivered to: the recipient domain of an MX delivery, or the host of a route or a relay, or its address when the route names an IP literal, lower-cased.</p>
<h3><a class="anchor-offset" name="the-back-off-a-destination-said-slow-down"></a>The back-off: a destination said slow down</h3>
<p dir="auto">When a destination answers a delivery with a request to slow down, it gets a <strong>back-off window</strong>: nothing is sent to it until the window ends, one delivery then probes it, and the same answer doubles the window. Deliveries to every other destination are untouched.</p>
<p dir="auto"><strong>What is read as a signal.</strong></p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Reply</th>
<th>Read as</th>
</tr>
</thead>
<tbody>
<tr>
<td>Code <strong>421</strong>, unless an exclusion below applies</td>
<td>A signal, whatever the text, at the banner or anywhere after it</td>
</tr>
<tr>
<td>A 4xx whose enhanced status is <code>4.7.0</code>, <code>4.7.28</code>, <code>4.7.500</code>, <code>4.7.650</code>, <code>4.7.652</code> or <code>4.3.2</code></td>
<td>A signal</td>
</tr>
<tr>
<td>A 4xx whose text, lower-cased, contains one of the phrases below</td>
<td>A signal</td>
</tr>
</tbody>
</table>
<p dir="auto">The phrases: <code>rate limit</code>, <code>rate-limit</code>, <code>ratelimit</code>, <code>too many messages</code>, <code>too many connections</code>, <code>too much</code>, <code>unusual rate</code>, <code>unexpected volume</code>, <code>temporarily deferred</code>, <code>temporarily rate</code>, <code>throttl</code>, <code>try again later</code>, <code>server busy</code>, <code>back off</code>, <code>slow down</code>. They are English, and a remote that says the same in another language is read by its codes alone. The table is fixed and cannot be edited.</p>
<p dir="auto"><strong>What is deliberately not a signal</strong>, each of which wins over the text and over the 421 rule:</p>
<ul>
<li>any <strong>5xx</strong>: a refusal is not a request to wait;</li>
<li><strong><code>4.7.1</code></strong>, which greylisting and policy refusals answer, and any reply whose text says greylist or graylist;</li>
<li><strong><code>4.2.x</code></strong>: one mailbox, never the destination;</li>
<li><strong><code>4.5.3</code></strong>: too many recipients for one message;</li>
<li><strong><code>4.4.x</code></strong>: <code>421 4.4.2 timeout exceeded</code> is the remote's idle timeout on a slow DATA;</li>
<li>a connection that was <strong>refused or timed out</strong>, a <strong>DNS failure</strong>, and this server's <strong>own deferrals</strong>.</li>
</ul>
<p dir="auto"><strong>The window and the probe.</strong> The first slow-down reply opens a window of <code>OutboundBackoffMinutes</code>. While it is open a batch for that destination is held with <code>4.4.5</code>, and the application log says:</p>
<pre><code class="language-text">Delivery to &lt;target&gt; deferred: the destination asked this server to slow
down at &lt;time&gt; (&lt;reply&gt;); next attempt after &lt;time&gt;.
</code></pre>
<p dir="auto">When the window has passed, the first delivery goes through as the probe. If it is delivered, or fails with anything that is not a slow-down reply, the window is cleared. If it is answered with a slow-down reply, the window doubles, up to <code>OutboundBackoffMaxMinutes</code>. A probe nobody ended - a delivery thread that died with it - goes stale after fifteen minutes and the next delivery takes it over.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Setting</th>
<th>Default</th>
<th>Range</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>OutboundBackoffMinutes</code></td>
<td><code>2</code></td>
<td>0 to 10080</td>
<td>The first window. <code>0</code> turns the back-off off</td>
</tr>
<tr>
<td><code>OutboundBackoffMaxMinutes</code></td>
<td><code>60</code></td>
<td>1 to 10080</td>
<td>The ceiling a doubling window stops at</td>
</tr>
</tbody>
</table>
<p dir="auto">The two refuse to cross each other on every surface: to move both, move the ceiling first when raising and the base first when lowering.</p>
<p dir="auto"><strong>A relay is one destination.</strong> With <code>SMTPRelayer</code> set, or a route through a smart host, one slow-down reply from it holds every message that goes through it for the window.</p>
<p dir="auto"><strong>One miss, stated in the document.</strong> The delivery client keeps a recipient's first non-fatal reply, so a genuine 421 from a second MX host after a plain 4xx from the first is not seen for that recipient.</p>
<h3><a class="anchor-offset" name="connection-ceilings-and-the-tenant-share"></a>Connection ceilings and the tenant share</h3>
<p dir="auto">Both use the same counting semaphore, and it never blocks: a delivery thread that waited for a slot would be a thread not delivering anybody else's mail. Over the ceiling the batch is deferred one to five minutes.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Setting</th>
<th>Default</th>
<th>Range</th>
<th>What it bounds</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>MaxOutboundConnectionsPerDestination</code></td>
<td><code>0</code>, off</td>
<td>0 to 1000</td>
<td>Sessions open at once to one target that no remote domain policy sets <code>max_connections</code> for</td>
</tr>
<tr>
<td><code>MaxOutboundConnectionsPerTenant</code></td>
<td><code>0</code>, off</td>
<td>0 to 1000</td>
<td>Deliveries one tenant may have in flight at once</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>The per-domain ceilings</strong> are on the remote domain policy, whose TLS half is in <a href="/topic/28257">Requiring TLS</a>:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Policy field</th>
<th>0 means</th>
<th>Beyond it</th>
</tr>
</thead>
<tbody>
<tr>
<td>Largest message (KB)</td>
<td>no limit of ours</td>
<td>Not attempted: no connection is opened, and the message is bounced at once with <code>5.3.4</code>, naming the policy and both sizes</td>
</tr>
<tr>
<td>Simultaneous connections</td>
<td>unlimited</td>
<td>Deferred with <code>4.4.5</code> for one to five minutes. The count covers every domain the policy's pattern matches</td>
</tr>
<tr>
<td>Messages a minute</td>
<td>unlimited</td>
<td>Deferred with <code>4.4.5</code> for one to five minutes. Independent of <code>MaxOutboundPerDestinationPerMinute</code>; both apply</td>
</tr>
</tbody>
</table>
<p dir="auto">A policy's connection ceiling wins over the server-wide one wherever the policy sets it.</p>
<p dir="auto"><strong>Who a tenant is.</strong> The hosted domain of the envelope sender, with an alias domain resolved to its domain. A sender this server does not host - mail relayed for an IP range or a route, forwarded external mail, the null sender - is the one tenant <code>(external)</code>, so relayed mail cannot starve the hosted domains either.</p>
<p dir="auto"><strong>The tenant share is not a volume control.</strong> It is a share of connections, bounded by <code>MaxDeliveryThreads</code>: a share larger than the thread count is no share at all. <a href="/topic/28239">The per-account sending limits</a> are the volume control. This server's own delivery reports have the null sender, so they share <code>(external)</code> with relayed mail.</p>
<p dir="auto"><strong>Where the settings are.</strong> The four new settings are on the Control Panel's <strong>Delivery of e-mail</strong> page beside <code>MaxOutboundPerDestinationPerMinute</code> (Windows), on the Deck's Settings view, over COM as <code>Settings.OutboundBackoffMinutes</code>, <code>OutboundBackoffMaxMinutes</code>, <code>MaxOutboundConnectionsPerDestination</code> and <code>MaxOutboundConnectionsPerTenant</code> (Windows), and over REST on <code>/api/v1/settings</code> as <code>outbound_backoff_minutes</code>, <code>outbound_backoff_max_minutes</code>, <code>max_outbound_connections_per_destination</code> and <code>max_outbound_connections_per_tenant</code>. In <code>hm_settings</code> the two connection rows are named <code>MaxOutboundConnsPerDestination</code> and <code>MaxOutboundConnsPerTenant</code>, because the column holds thirty characters.</p>
<h3><a class="anchor-offset" name="a-deferral-this-server-chose-is-not-counted"></a>A deferral this server chose is not counted</h3>
<p dir="auto">When <strong>every</strong> non-fatal failure of a delivery pass was one of this server's own deferrals, the message's next try is set to the longest deferral of the pass with <strong>the tries counter untouched</strong>, and the log says so:</p>
<pre><code class="language-text">Delivery deferred by this server's own shaping, not by a remote server.
Scheduling it for later delivery in N minute(s); the attempt is not
counted against the retry limit.
</code></pre>
<p dir="auto">When any recipient of the pass failed at a remote, the counted path runs as it always has. Before this, with a small retry count, a message could be bounced having never been offered to anybody.</p>
<p dir="auto"><strong>The hold is bounded.</strong> A message queued for longer than the span its counted schedule would have allowed - (retries + 1) times the minutes between tries, from the time it was accepted - takes the counted path from then on, so that a destination that says "slow down" for ever still ends in a bounce:</p>
<pre><code class="language-text">Deferred by this server's own shaping, but it has been queued for N
minute(s), longer than the M minute(s) its retry schedule spans. This
deferral is counted, so that the message is not held for ever.
</code></pre>
<p dir="auto"><strong>A held pass is a first pass only once.</strong> DKIM and ARC signing, the mirror copy and a rule's policy notice happen once, however many passes a message is held through. Nor does a held pass forward, copy, reply or call a rule's script function again: those four actions run once per counted attempt.</p>
<h3><a class="anchor-offset" name="ip-warm-up"></a>IP warm-up</h3>
<p dir="auto"><em>Schema 6093.</em> A <strong>schedule</strong> holds one outbound address to a daily ceiling of recipients per provider, rising day by day along a fixed plan; the queue sends up to the ceiling and holds the rest, usually until the next UTC day. <strong>Nothing is held until an administrator makes a schedule.</strong></p>
<p dir="auto"><strong>A schedule is about one address, and the address has to be bound.</strong> It is the local address a delivery leaves from: a global rule's <em>bind to address</em> action when one applies, otherwise <code>SMTPDeliveryBindToIP</code> (<em>Bind outbound connections to IP</em>, <code>smtp_delivery_bind_to_ip</code>). A delivery that binds no address leaves from whatever the operating system chooses, and no schedule is consulted for it. So a schedule does nothing, even enabled, until the address is configured on the host and one of those binds it. The server can check the setting and nothing else: the listing says <code>in_bind_setting</code>, and the Deck warns when it is false.</p>
<p dir="auto"><strong>The provider is decided from the mail host, never from the recipient's domain.</strong> A company on Google Workspace is reached through Google's MX hosts, and it is Google that judges the address. The first host the batch will try decides.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Provider</th>
<th>Key</th>
<th>Mail host names</th>
</tr>
</thead>
<tbody>
<tr>
<td>Google</td>
<td><code>google</code></td>
<td><code>google.com</code>, <code>googlemail.com</code>, <code>aspmx.l.google.com</code></td>
</tr>
<tr>
<td>Microsoft</td>
<td><code>microsoft</code></td>
<td><code>outlook.com</code>, <code>hotmail.com</code>, <code>protection.outlook.com</code>, <code>olc.protection.outlook.com</code></td>
</tr>
<tr>
<td>Yahoo</td>
<td><code>yahoo</code></td>
<td><code>yahoodns.net</code>, <code>yahoo.com</code>, <code>aol.com</code></td>
</tr>
<tr>
<td>Apple</td>
<td><code>apple</code></td>
<td><code>icloud.com</code>, <code>apple.com</code></td>
</tr>
<tr>
<td>Proton</td>
<td><code>proton</code></td>
<td><code>protonmail.ch</code>, <code>proton.me</code></td>
</tr>
<tr>
<td>Every other provider</td>
<td><code>other</code></td>
<td>everything else, counted together at five times the named providers' ceiling</td>
</tr>
</tbody>
</table>
<p dir="auto">Mail relayed through a smart host that is not one of those names is <code>other</code>, whoever the smart host delivers it to.</p>
<p dir="auto"><strong>The plans</strong>, in recipients per named provider per day. After a plan's last day there is no ceiling, and the schedule holds and counts nothing.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Day of <code>standard</code></th>
<th>Ceiling</th>
<th><code>other</code></th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>50</td>
<td>250</td>
</tr>
<tr>
<td>2</td>
<td>100</td>
<td>500</td>
</tr>
<tr>
<td>3</td>
<td>200</td>
<td>1,000</td>
</tr>
<tr>
<td>4</td>
<td>500</td>
<td>2,500</td>
</tr>
<tr>
<td>5</td>
<td>1,000</td>
<td>5,000</td>
</tr>
<tr>
<td>6</td>
<td>2,000</td>
<td>10,000</td>
</tr>
<tr>
<td>7</td>
<td>5,000</td>
<td>25,000</td>
</tr>
<tr>
<td>8 to 10</td>
<td>10,000</td>
<td>50,000</td>
</tr>
<tr>
<td>11 to 14</td>
<td>20,000</td>
<td>100,000</td>
</tr>
<tr>
<td>15 to 21</td>
<td>50,000</td>
<td>250,000</td>
</tr>
<tr>
<td>22 to 30</td>
<td>100,000</td>
<td>500,000</td>
</tr>
</tbody>
</table>
<p dir="auto">The plans side by side:</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Plan</th>
<th>Length</th>
<th>Day 1</th>
<th>Last day</th>
<th>Rule</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>standard</code></td>
<td>30 days</td>
<td>50</td>
<td>100,000</td>
<td>the table above</td>
</tr>
<tr>
<td><code>gentle</code></td>
<td>60 days</td>
<td>25</td>
<td>50,000</td>
<td>half of each ceiling, twice the days</td>
</tr>
<tr>
<td><code>fast</code></td>
<td>15 days</td>
<td>100</td>
<td>200,000</td>
<td>twice each ceiling, half the days</td>
</tr>
</tbody>
</table>
<p dir="auto">Days are UTC days, whatever the server's time zone, and a start later than today is refused.</p>
<p dir="auto"><strong>Recipients, not messages.</strong> A message to forty people at Gmail is forty to Google. Before a delivery connects, its recipients reserve room out of the day's allowance; when the attempts are over, every recipient that was delivered is added to <code>sent</code> and the reservation is let go. A recipient that was not delivered is not counted. So a provider that refuses the warming address is offered as many recipients a day as the queue has; its slow-down replies are answered by the back-off. The counts are written to <code>hm_warmupcounts</code> at every change, so a restart resumes the day. Local delivery is not counted.</p>
<p dir="auto"><strong>The hold.</strong> Recipients that do not fit - the last of the batch, not chosen by any priority - are marked <code>4.4.5</code>. When the day's ceiling was reached, the next try is one to five minutes after the next midnight UTC:</p>
<pre><code class="language-text">SMTPDeliverer - Message 1234: 1 recipient(s) held by the IP warm-up of
192.0.2.10: day 1 of its standard schedule allows 50 recipient(s) a day at
Google, and today's have been sent. Next attempt after midnight UTC, in
723 minute(s); the attempt is not counted against the retry limit.
</code></pre>
<p dir="auto"><strong>How long a backlog is carried.</strong> With the default schedule - four retries, sixty minutes apart, a five-hour span - a recipient queued in the morning comes back on each of the next five UTC days and is returned if the fifth still has no room. Send no more from a warming address than the sum of those days' ceilings, or raise the retry count for the duration of the warm-up.</p>
<p dir="auto"><strong>Managing schedules.</strong> On the Control Deck's <strong>Delivery queue</strong> page, in the <strong>Warm-up</strong> box, or over REST. The desktop Control Panel has nothing for it, and there is no COM interface.</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Route</th>
<th>What it does</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>GET /api/v1/warmup</code></td>
<td>Today's UTC date and the schedules, each with its day, <code>in_bind_setting</code>, and per provider <code>sent</code>, <code>deferred</code> and <code>ceiling</code></td>
</tr>
<tr>
<td><code>POST /api/v1/warmup</code></td>
<td>Adds one: <code>address</code> (required), <code>plan</code> (<code>standard</code> by default), <code>started</code> (<code>YYYY-MM-DD</code>, today by default), <code>enabled</code></td>
</tr>
<tr>
<td><code>PUT /api/v1/warmup/{id}</code></td>
<td>Changes <code>plan</code>, <code>started</code> or <code>enabled</code>. The address cannot be changed</td>
</tr>
<tr>
<td><code>DELETE /api/v1/warmup/{id}</code></td>
<td>Removes a schedule and its counts</td>
</tr>
<tr>
<td><code>GET /api/v1/warmup/{id}/history</code></td>
<td>The counts, newest first, with the day and ceiling in force then</td>
</tr>
</tbody>
</table>
<p dir="auto">Reading takes <code>view_queue</code> and changing takes <code>manage_queue</code>; a credential confined to named domains is refused. A second schedule for one address is <code>409</code>. <strong>Back up settings</strong> carries the schedules but not the counts.</p>
<p dir="auto"><strong>When the database does not answer</strong>, the queue does not stop: schedules that cannot be read (<code>7210</code>) and a day's count that cannot be read or started (<code>7211</code>, <code>7212</code>) leave the delivery going as though the address had no schedule. A count that cannot be saved (<code>7213</code>) is kept in memory; if the service restarts first, the day can go past its ceiling by that much.</p>
<h3><a class="anchor-offset" name="where-to-see-it"></a>Where to see it</h3>
<ul>
<li><strong><code>GET /api/v1/queue/shaping</code></strong> (<code>view_queue</code>, server-wide): the open back-off windows - destination, since, until, the window's minutes, the reply and the host that gave it, how many deliveries it has held, whether a probe is out - and the connections open under each ceiling and each tenant.</li>
<li><strong><code>DELETE /api/v1/queue/shaping/{destination}</code></strong> (<code>manage_queue</code>) clears one window once you have fixed the cause: <code>200</code> with <code>{"cleared":true}</code>, <code>404</code> when no window is open for that name, and an event on the audit trail.</li>
<li><strong>The Deck's Delivery queue</strong> shows the same as <em>Slowed destinations</em>, with a <em>Resume</em> button, and the connection counts as they were when the page was drawn.</li>
<li><strong>The application log</strong> says, for each batch held, which rule held it and until when.</li>
</ul>
<p dir="auto"><strong>What is per process.</strong> The windows and the connection counts live in memory. A restart forgets every window, which costs at most one more slow-down reply per destination. Nothing is shared between the nodes of a <a href="/topic/28232">warm-standby pair</a>.</p>
<h3><a class="anchor-offset" name="what-it-does-not-do"></a>What it does not do</h3>
<ul>
<li><strong>The signal phrases, the providers and the plans are fixed.</strong> A sixth provider, or a plan of your own, is not possible.</li>
<li><strong>No per-tenant volume quota</strong> beyond the per-account one: this shares connections, not messages a day.</li>
<li><strong>No pool of addresses.</strong> A schedule is about one address, and mail that did not fit waits.</li>
<li><strong>No reputation feedback.</strong> The ceilings rise by the calendar, not by how the providers are answering.</li>
<li><strong>No delayed delivery report.</strong> A sender learns of a long hold only when it ends in a bounce.</li>
<li><strong>A deferral by a rate or a ceiling costs one delivery pass per message every one to five minutes</strong> for as long as the backlog lasts.</li>
<li><strong>The warm-up counts are not exported as metrics.</strong></li>
</ul>
<p dir="auto"><strong>Not proved by any test</strong>, according to <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/IpWarmup.md" rel="nofollow ugc">IpWarmup.md</a>: room held by deliveries in progress; a later host of the other address family skipped for being reached from another warming address; what a database failure does (<code>7210</code> to <code>7213</code>); the audit trail's entry; the configuration backup's round trip of the schedules; and an MX lookup's own host names reaching the classification, since every delivery in the fixture goes through a route.</p>
<h3><a class="anchor-offset" name="where-to-read-more"></a>Where to read more</h3>
<ul>
<li>Operator documents at the v6.3.4 tag: <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/OutboundShaping.md" rel="nofollow ugc">OutboundShaping.md</a>, <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/IpWarmup.md" rel="nofollow ugc">IpWarmup.md</a> and <a href="https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/RemoteDomains.md" rel="nofollow ugc">RemoteDomains.md</a>.</li>
<li>Wiki: <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Outbound-Shaping" rel="nofollow ugc">Outbound Shaping</a> and <a href="https://gitlab.com/hmailserver/hmailserver/-/wikis/Routes-and-Relays" rel="nofollow ugc">Routes and Relays</a>.</li>
<li>Public documentation: <a href="https://www.progressiverobot.com/hmailserver-documentation/#267-the-delivery-queue-and-the-retry-schedule" rel="nofollow ugc">26.7 The delivery queue and the retry schedule</a> and <a href="https://www.progressiverobot.com/hmailserver-documentation/#141-sending-through-a-smart-host" rel="nofollow ugc">14.1 Sending through a smart host</a>.</li>
<li>On this forum: <a href="/topic/28192">The Control Deck</a>, <a href="/topic/28193">Upgrading to 6.3.4</a>, <a href="/topic/28257">Requiring TLS</a> for the remote domain policy's TLS half, and <a href="/topic/28258">DKIM rotation, DMARC and TLS reports, complaints, bounces and the reputation watch</a> for bounces, complaints and block lists.</li>
</ul>
]]></description><link>https://www.hmailserver.co.uk/topic/28259/outbound-shaping-and-ip-warm-up-one-slow-destination-must-not-stall-the-queue</link><generator>RSS for Node</generator><lastBuildDate>Fri, 06 Nov 2026 09:05:50 GMT</lastBuildDate><atom:link href="https://www.hmailserver.co.uk/topic/28259.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 27 Sep 2026 19:41:13 GMT</pubDate><ttl>60</ttl></channel></rss>