Some of the e-mail passing through my server is forwarded to external accounts.
Unfortunately, my upstream SMTP-server is very picky about spam -- and rejects some of the legitimate messages as such. When this happens to the forwarded mail, I get the bounces (as the postmaster) -- not the originators.
I understand, that this is because sendmail queues the messages locally, disconnects from the relay, and only then proceeds to forward them further. If the further forwarding breaks for any reason -- such as because the next relay misidentifies the message as spam -- my sendmail is left to hold the pieces.
Can things be configured so that the forwarding begins immediately instead (as soon as the forwarding destination is determined)? The status -- success or failure -- can then be communicated directly to the previous relay still on the line...
If sendmail can not do it, can any other MTAs? Thanks!
No, it's not possible as it's not implemented with any wide spread SMTP software; you would have to program your own SMTP server that supports this kind of behavior, which would be out of scope on Serverfault. In this answer I explain, why all MTAs have implemented the SMTP protocol very similarly, using queue, and how that is the best way to accomplish all requirements of the protocol.
A mail transport agent MTA always either denies a message or accepts and queues it, based on its own settings. Then, it's relayed or delivered from the queue.
That's because
there can be both permanent and temporary errors. If the MTA can't connect the nexthop immediate, it'll try again later and bounces only if the delay reaches the limit set. Neither can it wait for another MTA to respond before closing the connection, as it may have other messages to deliver first.
there can be several recipients. While a client can simply list all recipients at once with
RCPT TO
commands, the message can be finally delivered to several other servers, of which some can be available now and some later. Furthermore, the MTA can't open all these connections at once during the initial connection and wait for their responses. There's no practical reason to have totally different workflow for messages with a single recipient.it should always be clear which MTA currently has the responsibility for delivering the message. (This has been explained by examples in MadHatter's answer.)
That's just how SMTP was designed. Rather than syntactical requirement for the connection commands this leads to very similar architectures; Sendmail, Postfix and even MS Exchange has separate components for sending and receiving mail.
The requirement still comes from the SMTP specification; RFC 5321 2.1 on SMTP model basic structure:
And a bit further:
I think Esa's answer is excellent, but I'm going to disagree with some of it. I think that what you want is possible, but it's a bad idea, and it won't help you. As he says, RFC5321 s2.1 notes that
In the case that server B receives a message from server A and delivers it on to server C, I don't see that this bars B from waiting to confirm receipt to A until it has had confirmation of receipt from C - which is what you're asking for. But the problem is that between two servers
250 OK
is atomic (either the receiver has accepted it, and so is responsible for delivery, or it hasn't, and so the sender remains responsible), while between three it isn't.Consider the case where client A is unintentionally disconnected after it has sent the mail but before it's had the
250 OK
, while B is delivering it on to C. C then confirms receipt from B with its250 OK
, so B knows that C has it. But A doesn't, so A must still be responsible, and must continue to redeliver to B. If there is some systematic communications issue between A and B (eg, one of those lovely firewalls that think it's their job to mess with the contents of SMTP conversations), this could result in a very large number of copies of the same message being delivered.Moreover, sendmail already does what you think it doesn't: in the event of failed delivery to C, it will try to pass the buck back to A. This generally only fails where A is malicious, and either lies in the envelope-From (to whom such notification should be made) or doesn't run a mail server at all. In such cases the mail must be delivered to B's postmaster, for B is responsible for delivery (having said
250 OK
to A, but not had it from C), cannot deliver to C (it's tried and got a 5xx permanent failure) and cannot hand back to A (because A has made this impossible) so has no-one else to give it to. Here's an example I got this morning:Note how the original email purports to come from an aol.com address. How, then, am I not trying to deliver the failure report back to them? Because they lied in their original SMTP transaction:
It's my fault that I haven't yet set up SPF for that particular domain of mine (
stphilipschurch.org.uk
), but since I haven't, nothing stops me from accepting that lie - and then I'm stuck with an undeliverable message which cannot be returned to sender, for the sender is malicious and uninterested (being connected via an ISP in Azerbaijan).tl; dr: sendmail already does what you're asking for, when it can. What you want to do won't help it when it can't, and will create problems. Don't do it.