概要
Sendgridの機能でInbound Parse Webhookというものがあります
これは受信したメールの内容を指定したURLにPOSTしてくれる機能です
sendgridはHTTPステータスコード200 OKまで再送し続けてくれるのでセカンダリのメールサーバーに使えそうです
ということでこの機能を使ってセカンダリのメールサーバを作ってみます
構成はこんな感じ
Inbound Parse Webhook でPOSTされる値を Cloud functions で受け取ってプライマリのメールサーバに届けます
構築
まず、以下のようなスクリプトを書いて、cloud functions関数を作成します
今回はすべての同じドメインの全てのアドレスを受け取り、ヘッダを含むメッセージをそのまま流しています
宛先のチェック、SPAMチェック等をする場合はここでチェックして破棄すると良いと思います
転送先のアドレスは25番ポート以外にしてください( GCE同様25番はブロックされているため )
また、SMTP AUTH, STARTTLS等の送信設定に関してはプライマリのメールサーバに合わせて適宜変更します
サンプルコードはこちら
https://github.com/yaasita/inbound_parse_receive
以下のようにdeployします
git clone https://github.com/yaasita/inbound_parse_receive.git
cd inbound_parse_receive
vim index.js # 適宜修正
# ローカルでテスト
npm run start
# multipart/form-dataで送る あと、 Content-Type: application/octet-stream をつけない
curl -X POST -F "email=<test.eml" http://localhost:8080/
# deploy
gcloud functions deploy webhook-receive --gen2 --runtime=nodejs16 \
--region=asia-northeast1 --entry-point=handler \
--trigger-http --allow-unauthenticated
次に、sendgridの管理画面から、Settings
-> Inbound Parse
と進み、ドメインを追加します
URLに先程作ったcloud functions関数のURLを指定します
今回はメッセージをそのまま転送するため、POST the raw, full MIME message
にもチェックを入れておきます
ちなみに、Check incoming emails for spamにチェックすると、Spam reportとSpam Scoreもパラメータに付与してくれます(詳細は後述)
あとはDNSサーバーのMXレコードを編集すればOKです
設定例
example.net. 60 IN MX 10 example.net.
example.net. 60 IN MX 20 mx.sendgrid.net.
その他細かいこと
以下は公式情報ではない部分があります
時期や、アカウントによって変わる可能性があります
あくまで一例という事でお願いします
※2020年4月に調べた情報です
メッセージサイズの上限は?
20MBらしいです
The total message size limit, including the message itself and any number of attachments, is 20MB.
ただ、試してみたところ、142MB程度まで、送ることができました・・・何でですかね?
143MBあたりから以下のエラーが出るようになりました
'552 5.3.4 Error: message file too big'
今回の場合はCloud FunctionsのHTTPリクエストサイズ上限が10MBなのでそちらが先に制限に達すると思います
POST the raw, full MIME messageにチェックしないと?
text
というパラメータで本文だけがPOSTされますが、このチェックを付けると、email
となって、ヘッダ+本文がまとめて取得できます
今回はそのまま転送するのでチェックしています
Spam reportってどんな感じ?
先ほどのsendgrid設定画面でCheck incoming emails for spam
にチェックすると、Spam reportとSpam ScoreもPOSTするパラメータに付与してくれます
内容はSpamAssassinのレポートみたいです
spam report
Spam detection software, running on the system "xxx.sendgrid.net", has
identified this incoming email as possible spam. The original message
has been attached to this so you can view it (if it isn't spam) or label
similar future email. If you have any questions, see
@@CONTACT_ADDRESS@@ for details.
Content preview: xxxxxxxxxxxxxxxxxx [...]-
Content analysis details: (0.0 points, 5.0 required)
pts rule name description
---- ---------------------- --------------------------------------------------
0.0 FREEMAIL_FROM Sender email is freemail (xxxxxx[at]example.com)
0.0 TVD_SPACE_RATIO TVD_SPACE_RATIO
0.0 T_TO_NO_BRKTS_FREEMAIL T_TO_NO_BRKTS_FREEMAIL
spam_score
0.012
再送の頻度は?
試してみると以下のようにリトライしてくれました。
https://gist.github.com/yaasita/16ab255370363f6620c10d47e090b4b8
6回目までは5分後にリトライ, 7回目は10分後, 8回目は15分後, 9回目は30分後, 10回目は1時間後, 11回目以降は3時間後みたいに長くなっていくみたいです
postfixのように、すぐ再送間隔が倍になることはないみたいですが、時間が経つと再送間隔が長くなっていくのは同じみたいです
再送処理は3日経つまで繰り返してくれます
DMARCに対応してる?
対応してないみたいです
ポリシーがp=rejectでも、指定したURLにPOSTされました
DMARCのレポートも送信されませんでした
bounceはする?
bounceはしないです
3日間の再送処理の後は静かにメッセージが消えるだけでした
postfixみたいにbounce_queue_lifetimeを越えたら送信元にエラーメッセージが届くわけではなさそう
Mail Settings
のForward Bounce Messages
も関係なかったです
再送処理中に送信先URLは変更できる?
APIを使用して変更できました
コマンド例
curl -s \
-X "PATCH" "https://api.sendgrid.com/v3/user/webhooks/parse/settings/example.net" \
-H "Authorization: Bearer xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.net/newurl", "spam_check": false, "send_raw": true }'
タイムラグはありますが新しいURLに向き先が変わります。
POST受信側で対応が難しい場合にURLを変更して対応することも可能です
(今回の例だと、cloud functions側の制限を超える20MBのメールを受信したい場合など)
zapierでも出来る?
今回は、セカンダリのメールサーバーとして使いたかったので、cloud functionsを使いましたが本文を見るだけならzapierの方が確認かと思います
(WebhooksはPREMIUMアプリなのでなのでStarterプラン以上が必要です)
ただし、DKIM署名や、Fromアドレスは書き換わってしまいます