Azure でメールを受信するには
はじめに
アプリケーションの利用者との追加のコミュニケーションチャネルとしてメールを使用することが良くあると思います。Azure の標準機能ではメールの送受信のサービスを提供していませんので、Office 365 等の外部メールサービスを別途利用する必要があります。しかし本格的なメールサービスを利用するのは大げさすぎるということであれば、 SendGrid を使用することで簡易的に実現することが可能です。SendGrid はその名前からメール送信用のサービスに見えるのですが、実は受信することも可能になっています。
アーキテクチャ
まずはメールの受信やアプリケーションに使用される独自ドメインが必要になります。Azure DNS でホストしていただくのがもちろん理想ですが、一般的な DNS サービスであれば問題ありません。次に SendGrid では Domain White Label および Inbound Parse と呼ばれる機能が提供されていますのでそちらを有効にします。最後に DNS サービス側でメールを受信したいドメインの MX レコードを mx.sendgrid.net に向けてやります。SendGrid の詳細な構築手順はこちらなどをご参照ください。
ここで注意したいのは、SendGrid はメールを受信してくれますが、メールボックスを提供しているわけではないということです。このため POP3 や IMAP 等のプロトコルを用いて取得できるわけでもありません。独自ドメイン宛てに送信されたメールは、MX レコードの記述に従って SendGrid サービスにリレーされるのですが、SendGrid は受信したメール情報を Webhook として指定した URL に送信してくるので、それを受け付けるアプリケーションを用意しておく必要があります。
Webhook を Functions で受け付ける
SendGrid の Inbound Parse Webhook はメールデータを multipart/form-data として HTTP で POST してきますので、それを受け付けるアプリを用意する必要があります。これ自体は Web アプリが作れる方であれば比較的容易に作成できると思いますが、任意の POST リクエストを受け付ける URL を用意するのはとても不安な気持ちになりますので、何らかの認証機構を持たせたいところです。ただ Inbound Parse の設定は下図のようにいたってシンプルで、認証するパラメータとして設定できそうなのは URL に含まれるクエリ文字列くらいしかありません。
というわけで以下の理由から Azure Functions の出番です。
- アプリとしての機能自体はとてもシンプル
- URL に埋め込んだ API キーを使用した認証機構も持っている
- 出力バインディングが豊富に用意されているので後続の処理につなげやすい
- メール受信頻度に合わせてスケールするサーバーレスモデルが選択可能
- PaaS なので運用が楽、可用性も安心
C# Script のサンプル
HTTP Trigger を使用したデフォルトのテンプレートを若干カスタマイズしただけではありますが、以下にサンプルコードを公開しておきました。
https://github.com/ayuina/sendgrid-inbound-parse-by-functions
ポイントは HttpRequestMessage から ReadAsMultipartAsync メソッドを使用して MultipartMemoryStreamProvider クラスのオブジェクトを取り出すところになります。この Provider クラスを利用するとリクエストボディに含まれる各パートを1つ1つ処理することが出来ます。
またサンプルでは単にログ出力しているだけですが、“text” パートから本文を取り出して AI で解析、その結果を ”from” パートの送信元アドレスに自動応答するとか、いろいろ応用が考えられます。実際にどんな構成のメッセージが送信されてくるかはこちらに記載されていましたので、あわせてご参照ください。
備考
本ブログでは SendGrid を使用する方法を解説していますが、Azure にこだわらなければ Office 365 を使用する等の別の方法も当然ありえます。
また、以前から Azure 仮想マシンから SMTP 送信をすることはサポートされていなかったのですが、現在では一部の条件に合致するお客様は SMTP によるメール送信が制限される場合がありますのでご注意ください。