最近的 Exim 升级将其添加到默认acl_smtp_data
ACL 中:
.ifndef NO_CHECK_DATA_VERIFY_HEADER_SYNTAX
deny
!acl = acl_local_deny_exceptions
!verify = header_syntax
message = header syntax
log_message = header syntax ($acl_verify_message)
.endif
这会导致某些邮件被拒绝。例如,垃圾邮件中的以下标头:
2020-03-02 09:22:48 1j8hHk-0000gS-3Y H=(static-181-143-69-27.une.net.co) [181.143.69.27] F=<[email protected]> rejected after DATA: header syntax (unqualified address not permitted: failing address in "From:" header is: =?utf-8?B?IkRhbmlrYSIgPERhbmlrYUB1bmUubmV0LmNvPg==?=): unqualified address not permitted: failing address in "From:" header is: =?utf-8?B?IkRhbmlrYSIgPERhbmlrYUB1bmUubmV0LmNvPg==?=
解码有问题的标头,我们得到:
00000000 22 58 69 6d 65 6e 61 22 20 3c 58 69 6d 65 6e 61 |"Ximena" <Ximena|
00000010 40 76 69 6c 2e 63 6f 6d 2e 75 61 3e |@vil.com.ua>|
0000001c
对我来说,这看起来就像是一个非常好的标题值From
。
使用 是否会有拒绝合法邮件的风险verify = header_syntax
,或者像上面这样的标题是否无效并且可以安全地拒绝?
答案1
深入研究 RFC 2047:
5. Use of encoded-words in message headers
An 'encoded-word' may appear in a message header or body part header
according to the following rules:
[...]
(3) As a replacement for a 'word' entity within a 'phrase', for example,
one that precedes an address in a From, To, or Cc header. The ABNF
definition for 'phrase' from RFC 822 thus becomes:
phrase = 1*( encoded-word / word )
[...]
These are the ONLY locations where an 'encoded-word' may appear. In
particular:
+ An 'encoded-word' MUST NOT appear in any portion of an 'addr-spec'.
似乎encoded-word
可以用于标头中地址前面的文本,但不能用于地址本身。因此,使用 是安全的verify = header_syntax
,只要我们假设合法邮件不会包含违反 RFC 2047 的标头(将地址偷偷放入标头的编码部分)。
另一方面...RFC 6854? 这允许如下标头:
From: Automated System:;
公平地说,RFC 还说这种语法“仅适用于有限使用”(“仅适用于有限或独特的情况下”,例如实验、每RFC 2026)所以我不会为此失眠!
答案2
RFC2047 被误用
第 5 节允许以三种不同的方式使用编码词,但这并不符合其中任何一种。
一个编码单词最多可以涵盖一个“短语”或一个“原子”
"Ximena" <[email protected]>
"phrase" <[email protected]>
答案3
在 Exim4 中
2022-12-20 12:08:55 [20316] 1p7g6p-0005Hg-7L ***************** 正在运行 acl_custom_check_data ++++++++++++++
2022-12-20 12:08:55 [20316] 1p7g6p-0005Hg-7L H=(mx27.sXXXXXXXse.com) [XXX.XXX.XXX.XXX]:XI=[XXX.XXX.XXX.XXX]:25[电子邮件保护]数据后被拒绝:地址格式错误:[电子邮件保护]\n 不能跟随[电子邮件保护]:“收件人:”标头中的错误地址是:[电子邮件保护]<[电子邮件保护]>
该电子邮件是通过 Python 脚本发送的。Python 脚本将收件人标头设置为“[电子邮件保护]<[电子邮件保护]>”
我发现这种拒绝是由于在收件人标题开头有一个电子邮件地址字符串的问题。将 Python 脚本更改为使用“steve <[电子邮件保护]>“该电子邮件未被 Exim4 的标头验证拒绝。
根据上述 Sam Morris 提供的信息我将收件人标题“名称”前缀中的“@”符号解释为“编码”词,这就是该消息被 Exim4 拒绝的原因。
另一种可能性是 Python 脚本中用于将参数传递给 smtp api 的 json 对象在“名称”后有一个换行符:“[电子邮件保护]“在源代码中,该换行符被传递给 api,并在 smtp 消息头中编码,从而触发了 exim4 中的拒绝。
我希望这能帮助那些在 exim4 rejectionlog 中遇到同样拒绝错误的人。