Webアプリを作るにあたって、メールが送られない、と相談されることがたまにあります。
他にも、送信者認証(SPFやDMARCなど)が行われていない場合がある、といった質問もあります。
今更メールと思わないでくださいね。
インターネットにおけるメッセージのスタンダートはやはりメールなのです。
でも、メールは歴史的背景から多くの拡張が行われており、そこそこ複雑な仕組みになっています。
でもメールを使う事自体はそれほど難しくないため、メールの使い方は知っていても仕組みを知らないエンジニアは少なからずいます。
そこで今回は基本に立ち返り、メールというものがどういう仕組みで動いているのか、というところを紐解いていこうと思います。
基本を知れば、何かあったときも迷わず問題に対処できるようになります。エンジニアであればぜひご覧いただきたいです。
メール配送の全体像
送信者のメーラー(上の例だとOutlookやGmail)を使って、受信者(Outlook)にメールを送る例を、上の図を使って説明します。
メール配送の大まかな流れ
①送信者のメーラーから、メーラーに登録したSMTPサーバに対しメールを送ります。
②SMTPサーバは、受け取ったメールアドレス(To)を見ます。
自身のドメインAであれば、ユーザー(@より前で示されるもの)毎に用意されたメールボックスに蓄積します。これをローカル配送と呼びます(★ポイント1)。この時DNSは参照しません(★ポイント2)。
ユーザー毎に蓄積されたメールは、受信サーバー(POP3/IMAPサーバ)を経由して受信者のメーラーで受信します。
③上記②以外のメールについては、他のSMTPサーバー(ドメインX)にメールを転送します。
そのとき、DNSサーバーを参照して転送先のSMTPサーバーを特定したり、送信者認証を行うなどします。
このような流れです。
メールはバケツリレー方式
③で他のSMTPサーバーに転送された後はどうなるのか?
上の流れで説明したように、②または③が行われます。
自身のドメイン宛のメールであればローカル配送をしてメールの転送を止めますし、他ドメイン宛のメールであればさらに転送を行います。
このように、SMTPサーバー間を転送し続ける事で、最終的に相手に届く仕組みになっています。
メールを「バケツリレー」だと例える事があるのは、こういう理由なのです。
もっとも、これは過去(UUCPを使っていた時代)の話で、現在はDNSにより直接送信先を特定出来るようになりましたので、外部へのメール配送でバケツリレーを行っている事はほぼありません。
エラーメールは返送ではなく、新しいメールとして配送される
SMTPサーバーが何かしらの理由でメールを処理できなかった場合は、エラーメールを新たに作り、そのメールの送り主にエラーメールを送ります。
そもそも返送する、という仕組みが無いのです。
シンプルに、かつメール転送という方式で全部が完結する仕組みなのです。
ちなみにエラーメールの送信先は、通常は元メールのRetuen-Path ヘッダーにに記載されたメールアドレスです。
Retuen-Pathはメーラー、又は最初に受け付けたSMTPサーバーが付与します。
もしReturn-Pathがなければ Fromアドレスなどに送られます。
現実にはSMTPサーバーの実装により動きが異なりますので、参考程度に留めてください。
Webアプリがメーラーとなる場合
メールの基本形がわかったところで、続けてWebアプリがメール配信元となる例を作ってみました。
私どもの本業はWebシステム開発ですが、多くのWebアプリケーションエンジニアと接して分かったのは、意外とメール配送の事を分かっていない、という事です。
冒頭でも書きましたが、Webアプリを作るにあたって、メールが送られない、とエンジニアから相談されたり。
送信者認証(SPFやDMARCなど)が行われなかった、といった質問もあります。
そこで、上の相談や質問について説明していきたいと思います。
メールが送られないという問題
ここでは話を簡単にするために、WordPressを例に動きを説明します。
上の絵の左上にWordPressがあり、そこから②ドメインAのメールサーバー宛にメールを送ろうとした例です。
でもWordPressから見ると、メール送信処理は成功した、と見えています。
では、送ったメールはどこに行ったのでしょう?
ここで必要な前提知識は、「WordPressの標準では PHP の mail()関数が用いられる」という点です。
メーラーと違い、WordPressがいきなり外部SMTPサーバーに接続しに行っていない、という事です。
もちろんプラグインを入れる事でSMTPサーバーへ送信する事は出来ますが、ここではそういうプラグインは使っていない、という前提で話を進めます。
話を戻します。
PHPのmail()関数は sendmail の wrapper です。sendmail は MTAの実装の一部です。
つまり、WordPressはまずsendmailとやりとりを始めるという点です。
ローカル配送か外部SMTPサーバーへの転送か、いずれかが行われるわけです。
では、どちらの処理が動くのでしょう?
ポイントとなるのは、Webサーバー上にメールアカウントがあるかどうか。
もしメールアカウントがあれば、転送は行われません。
ローカル配送となり、Webサーバー上にメールデータが蓄積されます。
ウェブサーバー上にメールアカウントが登録されていたため、ローカル配送されていた
ということで早速サーバー管理画面を開いて確認したところ、案の定メールアカウントが設定されていました。
原因はこいつです。
このメールアカウントは誰も使っていないという事を確認しましたので、このメールアカウントを削除しました。
送信者認証(SPFやDMARCなど)が行われないという問題
当社とお取引のあるウェブサイト制作業者から、困ったので助けてほしいという連絡がありました。
何かというと、WordPressで構築したウェブサイトにあるお問合せフォームですね。
ここから送られるメールに、送信ドメイン認証となるSPFやDMARCなどの送信者認証が記録されない。
このような問合せがお客様からきたのだけど、その理由がわからない、という質問でした。
その制作業者さんも、SPFやDMARCなどの送信者認証の事は知っていて、必要な設定はおこなっていたのです。
実際に動作確認をしようと、同じくフォームから送られるサンキューメールをサイト制作業者宛に送ったところ、今度は送信ドメイン認証がされていました。
でもお客様には送信ドメイン認証がされていない、という話です。
ここでピンときました。
お客様はレンタルサーバーが提供しているメールを使っていました。
つまりウェブサーバーと同じところにあるメールボックスからメールを受信していたわけです。
ローカル配送では送信ドメイン認証は行われない
この場合ローカル配送となりますから、送信ドメイン認証が行われません。
それを制作業者さんに説明し、お客様もそのこと説明してもらい、無事決着しました。
ポイントはメールの動作原理を知っている事
調べ方は色々あると思いますが、効率よく(時間をかけずに)解決するために必要な事は
「メールの動作原理を知っている事」です。
メールに限った話ではありません。
何事も動作原理を知っていれば解決に必要な事を思いつく事が出来るようになります。
これをやり方(解決方法)で覚えようとしてはいけない、という事です。
例えば、「メールが来なかったら、サーバーのメールアカウントを調べる」「SPFがつかなかったらローカル配送を疑え」といった覚え方です。
必ずしも間違いではありませんが、原因に対する答えはこれ一つだ、という話ではありませんから、違う原因だった場合にもう何もできなくなります。
また、「思い込み」(バイアス)が働き、覚えた事象にこだわり目の前にもしかしたら答えがあるにもかかわらず見逃してしまう事にもなりかねません。
だから必要な事は、「根本原理を知る」なのです。
エンジニアに対し私が一番言いたい事です。
お問い合わせ、ご相談を受け付けております
Webアプリケーションを構築、運用するにあたって、なんだかんだメールというものの存在はまだまだ無視できません。
Webアプリケーションに限らず、WebサイトをWordPressで構築する場合も同様です。
Webサイト、Webアプリの構築って、プログラムが出来ればOK、というものではありません。
今回はメールを例にしましたが、Web環境の土台となるインターネットについて幅広い知識を有する必要があります。
インターネット環境の事を十分理解しないまま、Webプログラミングが出来るだけでWebアプリケーションエンジニアと名乗って良いものではないと思っています。
このようなエンジニアは何か問題が起きた時に、「それはxxの問題だから解決できません」と間違った知識から違う回答を言いかねません。
回答したエンジニアはそれが「正しい」と思い込んでいる場合がありますから、それを聞いた依頼者も自信をもって回答されるから信じてしまいかねません。
でも結局解決に至らないから誰も幸せになっていないのです。
そういう不幸に遭わないためにも、医者と同様、ITエンジニアについてもセカンドオピニオンを受けられることをおすすめします。
そのために、「IT相談役」というサービスを行っています。
初回のお問い合わせやご相談は無料です。
何か少しでも気になる事があれば、お気軽にお問い合わせください。