Postfixにて、spam対策として strict_rfc821_envelopes = yes の設定と、 「出来の悪いメーラを拒否してしまう」という記述はよく見かけます。 が、実際に何が拒否されるのか考察する資料はほとんど見かけません。
$Keywords: Postfix strict_rfc821_envelopes reject dot-user, dot-domain, excess tokens in MAIL FROM, blank username, domain only $
$Id: postfix821.html,v 1.14 2015-11-05 12:58:18+09 kabe Exp $
メールのヘッダ(To:など)に関してはもっと制限がゆるいのですが、 ユーザの目には触れない SMTPの MAIL FROM (envelope from) と RCPT TO (envelope to) に関しては制限があります。
RCPT TO: <.user@domain.name>
| 頭に "." |
RCPT TO: <user.@domain.name>
| ユーザ名末尾が "." |
RCPT TO: <user..name@domain.name>
| "."が連続している |
RCPT To: Hogemoge Taro <taro@domain.name>
| ヘッダのTo:を丸ごとコピー。 sendmailは これでも動いてしまう |
RCPT TO: <hogemoge taro@domain.name>
| 空白をクオートしていない。 サーバによって解釈が異なるので危険 |
RCPT TO: <user@.domain.name>
| ドメイン頭に"." |
RCPT TO: <@domain.name>
| ユーザ名が空。 PostfixではMAILER-DAEMONに配送 |
MAIL FROM: <ぷぎゃww@domain.name>
| 8bit文字。UTF-8もダメ‡。
クオートしてもダメ。 |
MAIL FROM: <#@[]>
| qmail の doublebounce。
[] は空のIPアドレスのつもりらしい |
逆に、以下のようなものは変に見えても違反とは言えません。 実際に使ってメールサーバが想定通りに動作するか、は、また別の問題。
MAIL FROM: <"..do=co#!{mo :-):-)..."@domain.name> MAIL FROM: <"<paypal@ebay.com>"@domain.name>
| " でクオートすればほぼなんでもあり |
MAIL FROM: <`authenumerate`@domain.name> MAIL FROM: <%RNDCHAR16%@domain.name> MAIL FROM: <-#@domain.name>
| クオート無しで使える特殊記号もあり (空白は要クオート) |
MAIL FROM: <paypal!ebay@domain.name>
| UUCP経路指定。UUCPは絶滅危惧種なうえ、
解釈がシステムによって違う。† |
MAIL FROM: <@paypal.com,@ebay.com:trustme@domain.name>
| source route指定。今時のメールサーバはsource routeは無視するが、
人間をだます程度の用途はある。 |
† RFC 976, UUCP Mail Interchange Format Standard
‡ RFC 5336, SMTP Extension for Internationalized Email Addresses (UTF8SMTP
, Experimental) ではUTF-8も使えるが、広く知られているとは言いがたい。
現在では RFC2821 (Simple Mail Transfer Protocol, 2001) が最新で、 こちらのほうが文法が単純なので RFC2821を参照してみましょう。
Reverse-path = Path Forward-path = Path Path = "<" [ A-d-l ":" ] Mailbox ">" Mailbox = Local-part "@" Domain Local-part = Dot-string / Quoted-string Dot-string = Atom *("." Atom) Quoted-string = """ *qcontent """ Domain = (sub-domain 1*("." sub-domain)) / address-literal sub-domain = Let-dig [Ldh-str] Let-dig = ALPHA / DIGIT Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig address-literal = "[" IPv4-address-literal / IPv6-address-literal / General-address-literal "]" # これ以下の要素は RFC2822にて定義 atom = [CFWS] 1*atext [CFWS] atext = ALPHA / DIGIT / ; Any character except controls, "!" / "#" / ; SP, and specials. "$" / "%" / ; Used for atoms "&" / "'" / "*" / "+" / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}" / "~" qcontent = qtext / quoted-pair qtext = NO-WS-CTL / ; Non white space controls %d33 / ; The rest of the US-ASCII %d35-91 / ; characters not including "\" %d93-126 ; or the quote character quoted-pair = ("\" text) / obs-qp NO-WS-CTL = %d1-8 / ; US-ASCII control characters %d11 / ; that do not include the %d12 / ; carriage return, line feed, %d14-31 / ; and white space characters %d127 text = %d1-9 / ; Characters excluding CR and LF %d11 / %d12 / %d14-127 / obs-text
このうち、<a-d-l> は現在のTCPでのSMTPとDNS MXを使う配送では 使いませんので、無視してかまいません。単純に <mailbox> 以下だけを 考えれば良いでしょう。
address-literalを使うメールアドレス (root@[192.168.0.0]
)
は設定不良の際の一時回避用なので、考察から外します。
Local-part (ユーザ名部分)は文法上はコントロールコードも使えますが、 RFC2821 [Page 37] では解説部分にて「使ってはいけない」(MUST NOT)と されています。
ここから mailbox を正規表現に書き直すとこうなります。 余計分かりにくいですが、計算機に食わせるにはこの形式でないと。
local-part = dot-string | quoted-string dot-string = [A-Za-z0-9!#$%&'*+/=?^_`{|}~-]{1,}(\.[A-Za-z0-9!#$%&'*+-/=?^_`{|}~]{1,})* atom = [A-Za-z0-9!#$%&'*+/=?^_`{|}~-]{1,} domain = [A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)* quoted-string = "(([][ !"#$%&'()*+,./0-9:;<=>?@A-Z^_`a-z{|}~-])|(\\[][ !"#$%&'()*+,./0-9:;<=>?@A-Z\^_`a-z{|}~-]))*" mailbox = ^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-]{1,}(\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]{1,})*)|("(([][ !"#$%&'()*+,./0-9:;<=>?@A-Z^_`a-z{|}~-])|(\\[][ !"#$%&'()*+,./0-9:;<=>?@A-Z\^_`a-z{|}~-]))*"))@[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)*$
この記述で直接 egrep に食わせることが出来ますが、 シェルスクリプトに引数として埋め込むにはエスケープが大変なので、 いったん here-document でファイルに書いてからシェル変数に代入するか、 egrep -f regexpを書いたファイル とするのがよいでしょう。
.user@domain
とか user.@domain
はダメです。
"abc<def>(with space)@..."@domain.name
は
有効です。
ただ発信側のメールサーバでちゃんとクオートしてくれるかは 別の話。 とくに巨大プロバイダやケータイキャリアはインターネットとの接続部分に 独自開発のメールサーバを使うことが多く、往々にして 実装がおかしかったりします。 なおドコモのメールサーバがクオートを行うようになったのは 2005/06月から。 (他キャリアについては不明)
MAIL FROM:<>
だけ
例外扱いされています。
なお宛先 (RCPT TO)としては空アドレスは意味が無いので使えません。
spam対策と称して「空のenvelope-fromは受け取らない」という 対策をするサイトもあるようですが、 エラーメールが誰にも届かないという大事故につながります。 やめましょう。 受信拒否されたエラーメールは、どうしようもないので捨てられます。 メールが届いていない、という事実を把握できる人がいなくなります。
現実には空のenvelope-fromのspamは多くありません。 エラーメールに見えるので、受け取っても人間が読まないため。
さて実際に Postfix で strict_rfc821_envelopes = yes にすると どうなるかというと、
結論から言ってしまうとドコモのアドレスは受けられます。 ただ他のケータイキャリアのアドレスは受信不可になる、という報告も あるようです。
以下は Postfix 2.2.x の実装。
strict_rfc821_envelopes = | no | yes |
---|---|---|
MAIL FROM:user@domain.name | ○ | × |
MAIL FROM:<"comment 1" <abc@def>> | ○ | × |
MAIL FROM:<(comment 2) abc@def> | ○ | × |
MAIL FROM:<@domain.name> | ○ | × |
MAIL FROM:<user@domain1 user@domain2> | × | × |
MAIL FROM:<user@.domain.name> | × | × |
MAIL FROM:<8ビット文字@domain.name> | ○ | ○ |
MAIL FROM:<..user..@domain.name> | ○ | ○ |
RCPT TO: <-t@.domain.name> | × | × |
なお、拒否されるアドレスが入力されると、/var/log/maillog には 以下のようなメッセージが出力されます。
Illegal address syntax from unknown[58.61.138.35] in MAIL command: sz;o';[970689yuf@163.com
MAIL FROM:<..do.co.mo..user...@domain.name>
)
<文字化け@domain.name>
)
ただしどちらも RFC821的には禁止です。
MAIL FROM:user@domain.name
)
MAIL FROM:<"comment" <user@domain.name>>
@
(MAIL FROM:<@domain.name>
)
MAIL FROM:<user@domain1 user@domain2>
)
MAIL FROM:<user@...domain>
)
-
"頭が "-
" (RCPT TO: <-t@dom.ain>
)の
アドレスは、RFC的には問題ないですが、
外部コマンド起動時にオプションと誤解されるのを予防するため、
宛先としては Postfixでは bounce 扱いします。(rejectにはならない)
Apr 1 11:55:69 sha postfix/qmgr[65538]: E79E0E33D2: to=<-t@dom.ain>, relay=none, delay=0, status=bounced (invalid recipient syntax: "-t@dom.ain")
ケータイ宛などで扱いたいなら allow_min_user = yes
に設定。
ただし、利用者が.forward
や .procmailrc
を
自由に書換えられる環境では
大穴があく可能性があるので控えましょう。
ex. sendmail -t
は「電文中のTo,Cc,Bccに従って配送」なので、
メールサーバ内部の設定次第では第三者中継に使える、かも。
debug_peer_level を上げてコマンドを発行するとある程度判明しますが、
Postfixが RCPT TO:<@my.destination>
を受信すると、
内部的にはトークン解析器によって
""@my.destination
と、
ユーザ名部分がクオートされます。
空文字列は null address と解釈されるので、
empty_address_recipient (デフォルト MAILER-DAEMON) の設定にて、
内部ではさらに MAILER-DAEMON@my.destination
になります。
MAILER-DAEMON は通常 /etc/aliases にて rootやpostmasterに 振り替えられているので、エラーになりません。