通过我的服务器的一些电子邮件被转发到外部帐户。
不幸的是,我的上游 SMTP 服务器对垃圾邮件非常挑剔——并且拒绝一些合法的邮件。当转发的邮件发生这种情况时,我会收到退回邮件(作为邮件管理员)——而不是发件人。
我理解,这是因为 sendmail 在本地对消息进行排队,与中继断开连接,然后才继续进一步转发它们。如果进一步的转发由于任何原因而中断——例如因为下一个中继错误地将邮件识别为垃圾邮件——我的 sendmail 将保留这些碎片。
是否可以将事情配置为立即开始转发(一旦确定转发目的地)?然后可以将状态(成功或失败)直接传达给仍然在线的前一个继电器......
如果 sendmail 做不到,其他 MTA 可以吗?谢谢!
不,这是不可能的,因为它没有通过任何广泛传播的 SMTP 软件实现;您必须编写自己的支持这种行为的 SMTP 服务器,这超出了 Serverfault 的范围。在这个答案中,我解释了为什么所有 MTA 都非常相似地使用队列实现了 SMTP 协议,以及这是实现协议所有要求的最佳方式。
邮件传输代理MTA 始终根据自己的设置拒绝邮件或接受邮件并将其排队。然后,它从队列中中继或传递。
那是因为
可能存在永久性错误和临时错误。如果 MTA 不能立即连接下一跳,它会稍后再试,并且只有在延迟达到设置的限制时才会反弹。它也不能在关闭连接之前等待另一个 MTA 响应,因为它可能要先传递其他消息。
可以有多个收件人。虽然客户端可以简单地使用命令一次列出所有收件人
RCPT TO
,但消息最终可以传递到其他几个服务器,其中一些现在可用,一些稍后可用。此外,MTA 无法在初始连接期间立即打开所有这些连接并等待它们的响应。对于具有单个收件人的消息,没有任何实际理由具有完全不同的工作流程。应该始终清楚当前哪个 MTA 负责传递消息。(这已通过 MadHatter 回答中的示例进行了解释。)
这就是 SMTP 的设计方式。这导致了非常相似的架构,而不是连接命令的语法要求;Sendmail、Postfix甚至MS Exchange都有用于发送和接收邮件的独立组件。
该要求仍然来自 SMTP 规范;RFC 5321 2.1 关于 SMTP 模型的基本结构:
更进一步:
我认为 Esa 的回答非常好,但我不同意其中的一些。我认为你想要的是可能的,但这是一个坏主意,它不会帮助你。正如他所说,RFC5321 s2.1 指出
如果服务器 B 收到来自服务器 A 的消息并将其传递到服务器 C,我看不到这会阻止 B 等待确认收到 A,直到它收到来自 C 的确认 - 这就是你的要求。但问题是两台服务器之间
250 OK
是原子的(接收方已经接受了它,因此负责传递,或者它没有接受,因此发送方仍然负责),而在三台服务器之间则不是。考虑这样一种情况,客户端 A 在发送邮件之后但在它拥有 之前无意断开连接
250 OK
,而 B 正在将邮件传递给 C。C 然后用它的 确认来自 B 的接收250 OK
,因此 B 知道 C 拥有它。但是 A 没有,所以 A 必须仍然负责,并且必须继续重新交付给 B。如果 A 和 B 之间存在一些系统性的通信问题(例如,那些认为弄乱内容是他们的工作的可爱防火墙之一SMTP 会话),这可能会导致发送大量相同邮件的副本。此外,sendmail 已经做了你认为它没有做的事情:如果发送到 C 失败,它会尝试将责任转嫁给 A。这通常只会在 A 是恶意的情况下失败,或者位于信封-From (应向谁发出此类通知)或根本不运行邮件服务器。在这种情况下,邮件必须投递给 B 的邮递员,因为 B 负责投递(已经
250 OK
对 A 说过,但没有从 C 那里得到),不能投递给 C(尝试过,出现 5xx 永久故障)并且不能交还给 A(因为 A 让这成为不可能)所以没有其他人可以给它。这是我今天早上得到的一个例子:请注意原始电子邮件如何声称来自 aol.com 地址。那么,我如何不尝试将故障报告返回给他们呢?因为他们在原来的 SMTP 交易中撒了谎:
我还没有为我的那个特定域设置 SPF 是我的错
stphilipschurch.org.uk
(发件人,因为发件人是恶意且不感兴趣的(通过阿塞拜疆的 ISP 连接)。tl; 博士:sendmail 已经可以满足您的要求。当它做不到时,你想做的事情将无济于事,并且会产生问题。不要这样做。