SendGridのInbound Parseでメール受信をトリガーに処理を実行する
「メール受信をトリガーになんらかの操作をしたい」ときに調べたときの調査結果
やりたいこと
メール受信をトリガーになんらかの操作をしたい
実現方法
SendGrid
SendGridでメールを受信することはできますか? – サポート
- Parse Webhookを利用して、指定したドメイン宛のメールを指定したURLにPOSTできる。
- POSTには受信したメールのヘッダ、本文、添付ファイルなどの情報が含まれる。このPOSTをアプリケーション側で受けることにより、メール受信をトリガとした処理を実行できる。
- Parse Webhookを利用するには、Domain Whitelabel設定を行った上でメールを受信するドメインのDNSのMXレコードの修正が必要
SendGrid設定方法
- SendGrid登録
- Domain Whitelabel
- MX/CNAMEレコードを追加
- Inbound Parse設定
- POSTリクエストを受け取るアプリケーションを用意
- メール送信
1. Send GridのFreeプランを登録する(私の場合、Azureから登録しました)
2. [Send Grid] Domain Whitelabel 設定
Parse Webhook(Inbound Parse)を利用するためには、まずDomain Whitelabel設定が必要のため、以下の通りサブドメインを登録します。
3. [ドメイン設定] MXレコードとCNAMEを追加する。
Domain Whitelabl登録時に表示されるCNAMEと、MXレコードをご自身のドメイン管理サイト(お名前.com)に、以下3レコードを追加します。
はじめ、Domain Whitelabel設定を行ったときに、これを登録しろと言われるCNAMEを全部登録した後にMXレコードを追加しようとしたが、お名前.com側で追加できなかった。
CNAMEに登録するのは、s1._domainkey.XXXX, s2._domainkey.XXXXの2つだけでよい。
livedoor Techブログ : CNAMEの間違った使い方
4. [Send Grid] Inbound Parse設定
Settings > Inbound Parse 対象ドメインのメール受信後にどのURLに対してPOSTするかを設定する。
subdomainの部分は、「2.」で登録したドメインを登録する。
Destination URL
にはPOST先のURLを指定する。
テスト時は後述するRequestBin
やngrok
のURLを指定した。
5. POSTリクエストを受け取るアプリケーションを用意
Node.js(Express)の場合。
server.js
const express = require('express');
const cors = require('cors');
const port = 4000;
const app = express();
const multer = require('multer');
let upload = multer();
app.use(cors());
// HTTPリクエストを受け取る
app.post('/incoming', upload.fields([]), function (req, res) {
console.log(req.body.subject);
console.log(req.body.text);
res.sendStatus(200);
});
// サーバーを起動する部分
const server = app.listen(port, function () {
var host = server.address().address;
console.log('Example app listening at http://%s:%s', host, port);
});
node server.js
6.メール送信
例えば、sub.hoge.com
とした場合、[email protected]にメール送信する。
確認方法
以下のリンクで紹介されているRequestBin
というWebサービスを利用するのがよいです。
その後、ローカルデバッグしたい場合は、ngrok
を利用する。
ハマった点
multipart/form-data
として扱わなければならないところを扱っていなかったため、request.body
が取得できなかった。
今までrequestのデータが取れない場合は、だいたいbodyParserで解決していたので、今回も同様に考えていたらハマった。上記で紹介しているRequestBin
を試してみたところ、multipart/form-data
で送られてきていたので判明した。
https://stackoverflow.com/questions/24543847/req-body-empty-on-posts
https://stackoverflow.com/questions/37630419/how-to-handle-formdata-from-express-4
Node.jsではmulter
というライブラリを使うのが通例(?)っぽいので試してみたところ解決した。
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const port = 4000;
const app = express();
const multer = require('multer');
let upload = multer();
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
// HTTPリクエストを受け取る部分
app.post('/incoming', upload.fields([]), function (req, res) {
console.log(req.body.subject);
console.log(req.body.text);
res.sendStatus(200);
});
// サーバーを起動する部分
const server = app.listen(port, function () {
var host = server.address().address;
console.log('Example app listening at http://%s:%s', host, port);
});
ngrok
$ ngrok 4000
Session Status online
Version 2.2.8
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://xxxxxxxx.ngrok.io -> localhost:4000
Forwarding https://xxxxxxxx.ngrok.io -> localhost:4000
Connections ttl opn rt1 rt5 p50 p90
29 0 0.00 0.00 0.02 0.56
HTTP Requests
-------------
POST /incoming 200 OK
参考
Related contents
TECH
2017.10.21
TECH
2020.04.17
TECH
2020.02.02
TECH
2016.09.03
TECH
2016.08.28
TECH
2016.08.27
TECH
2016.08.24
TECH
2016.05.11