前置き
タイトルまんまですが、、、
PHPで通常のメール送信処理を書いたら少々こまったことになったので、その備忘です。
環境
Vagrant + Oracle Virtual Box → CentOS6
PHP5.6
ごめんなさい、マイナーバージョンは忘れました。。
まぁ、内容はそこに縛られるものではないのでご容赦ください・・・・(´・ω・`;)
メールを送信したよ
個人的に久しぶりのWeb系サービスの開発にて、あるあるのメール送信処理を書きました↓
class Mail
{
/**
* メール送信
*
* @access public
* @param string $to
* @param string $subject
* @param string $message
* @param string $from
* @param string $cc
* @return [type] [description]
*/
public function send($to, $subject, $message, $from = '', $cc = '')
{
$headers = [];
if (!empty($from)) {
$headers[] = "From: {$from}";
}
if (!empty($cc)) {
$headers[] = "Cc: {$cc}";
}
return mb_send_mail($to, $subject, $message, implode("\r\n", $headers));
}
}
こんな感じ(途中、PJ特有のコードがあったけどさすがに割愛)。
ちゃんとローカル~本番環境までメール送信されることも確認済み。
先にも書いた通り、結構久しぶりにメール送信処理なんて書いたので、なんだか懐かしさにほっこりしてみたり・・・・(=_=)
まぁ、メール送信処理なんてこんなもんだよねぇ・・・・(^。^)y-.。o○
大きな問題もなく本番テストへ・・・
と、インフラ担当からひとこと
Mr.インフラ(以下Mr)「メール確認しましたけど、このままだと迷惑メールになるよ?(■_■)」
ME「(; ゚Д゚)ファッ?! でもちゃんと届いてますよ?」
Mr「今はね。ソースみたけど、SPF対応してないっぽいんで、時間の問題だよ(■_■)」
ME「SPF・・・・?そんなライブラリありましたっけ・・・・?(´・ω・`)
ていうか、Mr.インフラはPHPみれるんでしたっけ?」
Mr「や、そっちのソースじゃなくて、メールの方ね(■_■)」
ME「・・・・ボク5さいだからよくわかんないや(´・ω・`)」
Mr「ちょっとぉ・・・・(■_■;)」
SPFってのがあるっぽいんですよ奥さん
・・・・ですって。
正直、ここ数年はアプリのAPI開発ばかりで、PHPとDB以外は特に意識してなかった、、、
それに加え、Web開発やってたときもインフラ関係はそれ専門にしてるチーム(ていうか部門)にお任せして自分はプログラムに専念できる状態だった(というか、そうでもしないと終わらないPJばかりだった)ので、自分は未だにインフラ設定がよく分かってないです。。
ええ、お金もらってる仕事である以上、全く持って言い訳ですよ・・・・(´・ω・`)
なんか迷惑メールとしてよくある**「なりすましメール」を抑制するために用意されたもの**っぽい・・・・?
で、ウチはどうなってたかというと
めーるのそーすみたらこーなってた↓
spf=neutral (google.com: ××.×××.××.×× is neither permitted nor denied by best guess record for domain of 【ウチのサーバー】)
これは、Gmailなら返信の横にあるメニューから「このメッセージのソースを表示」から確認できる、メールヘッダーに記載されてるです。
(その他メーラーでも確認できると思うんだけど、手元のThunderbirdだと表示されてなかったので正確なことは分からない。。)
Mr「正常だと**spf=pass
**、それ以外はだいたいダメね(■_■)」
ME「こんなの絶対おかしいよ(ノД ` )・゜・。」
てことで、やった対策
【1コ目】メールアドレスを許可してもらう
特にここまで説明してなかったけど、今回は所謂ひとつの受託開発案件で、メール送信元アドレスもそれ用のメアドを先方から用意してもらっていた。
・・・・んだけど、そもそも論でそのメアドが相手メールサーバで許可されていなかったらしい。。
なんか先方も(ちょうど同じ時期に自分が別のこと頼んでたから)うっかり忘れてたんだそうな。。
なので、Mr.インフラから先方へこちらのサーバIPを追加してもらえるよう依頼してた。
・・・・この辺は**「SPFレコード 追加」**とかでググって・・・・
説明してもらったんだけど、ボク5さいだからよくわかんないや(´・ω・`)
なお、対応したって聞いてからなかなか反映されてるように見えなくて、あまりに心配で質問したところ、
Mr「すぐには反映されないから2~3日は待ちなさい(■_■)」
と言われてたんで、やる人は2~3日は全裸待機でお願いします。
シルクハットとネクタイは忘れないでください(´・ω・`)
や、**「DNSまわりの設定」**と言われたら待つのは分かるんだけど、**所詮メール関係の設定でしょ?**と思ってすぐ終わるんじゃないかと思ってたのよ。。。
ちなみに、SPFが反映されてるかを確認するのには↓のサイトを使ったよ。
http://mxtoolbox.com/spf.aspx
このとき、アスメルが提供するチェックツールもやってみたけど、
こっちはあくまで**「アスメルが提供している、アスメル顧客のためのツール」**らしく、
設定されているSPFレコードに「include:1lejend.com」が含まれていません。
SPFレコードを編集して「include:1lejend.com」を加えてください。
と言われてFailになったので気をつけて(´・ω・`)
【2コ目】ソースで送信先を指定する
実をいうと、1コ目の対応後にたっぷり2週間ほど待ってた(というか忘れてた)んだけど、さらさら状況が変わらなかった。
それどころか、
先方「何回やってもezwebにメールが届かない・・・・なんかコッチの設定わるかった?(;´Д`)アセアセ」
といわれる始末。。
忘れてたとも言えなかったので
ME「あら不思議(´・ω・`)」
とテキトーに返してお茶を濁す有様ですよ。
とはいえ、さすがにちょっと考える。
携帯メール・・・・といえば迷惑フィルタか?「ezweb 迷惑メールフィルタ」でググる。
ヘッダFrom,エンベロープFrom(ReturnPath)の認証が不可のメールを拒否
書いてあるやんけ!(;´Д`)
てことでソース側も対応↓
class mail
{
/**
* メール送信
*
* @access public
* @param string $to
* @param string $subject
* @param string $message
* @param string $from
* @param string $cc
* @return [type] [description]
*/
public function send($to, $subject, $message, $from = '', $cc = '')
{
$headers = [];
$additional_parameters = "";
if (!empty($from)) {
$headers[] = "From: {$from}";
$additional_parameters = "-f {$from}"; // エンベロープ追加
}
if (!empty($cc)) {
$headers[] = "Cc: {$cc}";
}
return mb_send_mail($to, $subject, $message, implode("\r\n", $headers), $additional_parameters);
}
}
ローカルで確認したところ、
spf=softfail (google.com: domain of transitioning 【送信元メアド】 does not designate 【ウチのサーバーIP】 as permitted sender)
事態悪化
いやいや、ローカルだからはじかれて当たり前。むしろちゃんと「ダメ」と言われる子になった。
不良も卒業だね、母さんうれしいよ(ノД`)・゜・。
いや、自分、男だけどさ・・・・心境はまさにそれよ
これを本番環境へ反映し、テストでメールを送信してみると↓
spf=pass (google.com: domain of 【送信元メアド】 designates 【ウチのサーバーIP】 as permitted sender) smtp.mailfrom=【送信元メアド】
やったゼ
まぁ、対応したの本番リリースした後だったんだけどさ・・・・(´・ω・`)
対応できただけ良かった・・・・良かったよね?(´・ω・`)
まとめ
- Mr.インフラは良い人(最重要)
- プログラマーだからってインフラ毛嫌いしちゃダメ
- 万全の知識なんてない。経験したことがあっても油断するな
- SPFってのがあるんですってよ奥さん
余談
今回の一件でふと思い出したのが
「ヒマならPHPマニュアル読みな、色々書いてあるし面白いから」
という先輩の言葉。
その先輩はdateのマニュアルがお気に入りでございました・・・・。
仕様書がないPJばかり経験してたこともあり、有名FWだろうが既存ソースだろうが、PJに関係するソースは出来る限り読んで理解しようとするクセがついてると思ってたけど、それ以前に使ってるプログラム言語のマニュアルを熟読するって大事ですな。
そこを疎かにしてたかなぁと気づいたアラサーの春、
皆さんご健勝いただければ幸いでございます(`・ω・´)キリッ