No.1391 SAFE MODE 時のにメールを送信できない
Warning: Cannot modify header information - headers already sent by (output started at /home/users/1/moo.jp-rainbowcafe/web/openpne/webapp/lib/util/mail_send.php:60) in /home/users/1/moo.jp-rainbowcafe/web/openpne/webapp/lib/util/util.php on line 34
こんなエラーが出る→XAREAなどのレンサバでよくある
SAFE MODE 時はmail()関数の第5引数が指定できないのよ
config.phpの設定を
define('MAIL_SET_ENVFROM', false);
にすべし
参考↓
PHP の mail 関数でメールが送信できずに格闘した記録
今北産業
- メールの From ヘッダとは別にエンベロープ From というものが存在
- エンベロープ From が FQDN でないと受け付けない SMTP サーバが有る
- ドメイン無しで送らないように append_at_myorigin は切らない事
事の発端
Drupal による CMS サイト構築をしていたのだが,外部のメールアドレスにメールを送る事が出来ていないようだった.最初,Drupal のコードに原因が有るのではないかと思い,メールを送信して欲しい部分のソースコードを調べてみた.具体的に言えば, 新規ユーザ登録をした時にメールを送信する部分の処理が上手く行っていないようである. しかし,ソースコード自体には特に問題は見当たらなかった.
因みに,Drupal のメール処理は include/mail.inc の drupal_mail 関数と drupal_mail_send 関数,ユーザ登録でのメール処理は modules/user/user.module の _user_mail_notify 関数で行われていて,最終的な送信は drupal_mail_send 関数において mail 関数を利用して行われている.
空の from
メールの処理が上手く行かない時に最初に見るべくは,/var/log/maillog である.ここでメールのログを見ていると,
Sender address rejected: need fully-qualified address (in reply to RCPT TO comm
and)
とある.よく見ると,from=<root> となっている事から,正しくドメイン名が指定できていないらしい.サーバによっては,ドメイン名を持たない From を弾くようだ.しかし,差出人のメールアドレスは From ヘッダで正しく指定してあるはずなので,これではおかしいと思い,色々と調べる羽目になった.
PHP の mail 関数
次に疑うべくは PHP の mail 関数の挙動である.この関数が From ヘッダの付加を正しく行っていないのではないかと思ったのである.セーフモードが影響しているのかとも思ったが,そもそもセーフモードでは動作していない事が判明.$additional_parameters オプションで -fexample@example.com というオプションを sendmail (私の環境では Postfix へのシンボリックリンクとなっているようだ)に渡してやると動く.
エンベロープ From と From ヘッダ
その理由を探るためにより調べてみると,興味深い話を見付けた.今まで,From ヘッダ以外に宛先のメールアドレスを記述する所などないと思っていたが,実は From ヘッダは受取人がメールを処理するためのもので,Postfix 等の MTA がメールの配送の際に見るのは「エンベロープ From」と呼ばれる全く別のヘッダらしい.エンベロープ From は,その名の通り封筒の宛名のようなもので,封筒の中の手紙に書かれているとも言える From ヘッダとはそもそも階層が違う(はず).
メーリングリストではこの仕組みが利用されているそうだ.本当はメーリングリストのサーバから送られたメールも, From ヘッダを本来の差出人に設定しておけば,受信者は元々どの差出人からメールが送られたかが分かる.
mail 関数で From ヘッダを指定しても外部へ送信できなかったのは,このエンベロープ From が正しく設定されていなかった事が原因だった訳だ.sendmail -f でエンベロープ From が指定できたから,mail 関数でも -f オプションを渡せば送信できたのだ.
myorigin は大切に
mail コマンドもそうだが,PHP の mail 関数もエンベロープ From は実行したユーザの名前になるようだ.例えば,root が PHP で mail 関数を利用してメールを送信すると,
from=<root>
となる.ドメイン名はくっ付いてこない.これをどう解決すれば良いのか考えあぐねていたが,仮想ドメインの設定をした際に訳も分からず myorigin 辺りを弄った事を思い出した.そこで,/etc/postfix/main.cf を見ると,myorigin の記載は無く,
append_at_myorigin = Off
となっていた.これを
myorigin = $myhostname
として,append_at_myorigin の行を削除すると,Postfix が自動で root@$myhostname としてくれるので,PHP の mail 関数でメールを送信する事が出来た.(本当は $myhostname が DNS の MX で引けないドメインのために弾かれ,DNS の MX レコード登録の反映を待つのが面倒であったため,$mydomain と同じにしてある.)
参考 URL
PHP: mail – Manual
http://jp.php.net/function.mail
Manpage of SENDMAIL
http://www.linux.or.jp/JM/html/sendmail/man8/sendmail.8.html
電子メールの仕組みと迷惑メール対策の基礎知識
http://www.soi.wide.ad.jp/class/20050042/slides/05/index_30.html
問題点と対策 – よくきたWiki
http://wiki.poyo.jp/read/Writing/kiwameru_php_vol.2/01.mail/030.problem
Postfix の設定 – アドレス操作
http://www.postfix-jp.info/jhtml/rewrite.html