この記事はWHITEPLUSのカレンダー | Advent Calendar 2018 - Qiita 2日目になります。
こんにちは、WHITEPLUSのサーバーサイドエンジニア仲見川です。 リネットのフロントエンドから社内イベントのシステム開発まで幅広く携わってます。
さて、最近は個人間では余りメールしなくなってはいますが、Webサービスの登録はやはりメールアドレスという事が多いですよね。
ちょっとしたサービスを作るにあたってメールアドレス認証をしたい、みたいな事もあるかと思います。
しかし、そのためにSMTPサーバーを用意してーとか考えるととても面倒くさくなります。
そこで、登場するのがSendGrid。
SendGridはクラウド型のメールサービスで、SMTPやAPIによりメールの送受信が可能となっています。 MarketingCampaignという機能により管理画面からメールマガジンの配信なども行えます。
SendGridは送信通数に制限はあるものの。基本的な機能については無料から使用することができます。
今回はHeroku&SendGridでAPIとWebhookを用いたメール送受信をご紹介します。 HerokuであればSendGridをAdd-onとしてHerokuのコンソールから追加できてお手軽に試すことができます。
SendGridの準備
今回はHerokuのAdd-onですが、SendGridのコンソールは同じなので普通にSendGridを登録しても同じ手順でできます。
Herokuでアプリを作成したらResourcesの「Find more add-ons」からAdd-onを検索して追加。 ※クレジットカードの登録が無いとAdd-onの追加できないかも。
SendGridで検索するとMarketingCampaignというのもありますがなにもない方を選びます。
「Install SendGrid」を押すと追加されます。
追加するとAdd-onsの所に表示が追加され、
SettingsのConfig Vars(環境変数)にIDとパスワードが追加されます。
このIDパスワードを使ってAdd-onsに追加されたSendGridのリンクからSendGridのコンソールにログインできます。
APIキーの払い出しはSettingsの「API Keys」からできます。 実運用時は権限をきちんと考えないと行けませんが、今回はFull Accessで作ってしまいます。
いったんここまでで、SendGridを用いてメール送信する準備はできました。
メールの受信
本題のメール受信ですが、ドメインのDNS設定と、SendGrid側でもう少し設定が必要になります。
仕組みは以下の通り簡単です。
- ドメインを取得
- SendGridをメールサーバーとして設定する(DNSのMXレコード設定)
- SendGridのWebhookを設定するInbound Email Parse Webhook - ドキュメント | SendGrid
- Webhookを受け取るWebアプリケーションを作成
今回はドメインの取得は割愛します。
SendGridをメールサーバーとして設定する
SettingsからSender Authenticationを選びDomain Authenticationで自分の所有するドメインとSendGridを繋ぎます。
DNS Hostの所は選択肢に存在するDNSサービスの場合は該当のサービスを選択。 存在しない場合(お名前.comとか)は一番下にOtherがあるので、それを選択してDNSサーバーを入力します。
②のYes,NoはLink Tracking設定(トラッキング用のドメインとして使うかどうか)なので今回はNoのままにします。
進むと、DNSにCNAME登録してねーと言われるので。言われるがままDNSにCNAMEを設定したらVerifyします。
このようにVerifiedになれば大丈夫です。
Webアプリの作成
今回はHerokuで気軽に動かす為、 Node.js + Expressを前提にします。
expressのインストール方法、プロジェクト作成はわからない場合調べてもらうとして。
npmで以下をインストール
@sendgrid/mail // メールの送信 body-parser // POSTパラメータの取得 multer // POSTパラメータの取得
コード自体は手抜きです。 Expressで生成されるApp.jsに以下のコードを追加
var bodyParser = require('body-parser'); var multer = require('multer'); var upload = multer(); app.use(bodyParser.json({ type: 'application/*+json' })); app.use(bodyParser.urlencoded({ extended: false, type: 'application/x-www-form-urlencoded' })); app.use(upload.array()); app.use('/getmail', (req, res, next) => { console.log(req.body) if (!req.body['from']) { res.send('notting from'); return } const sgMail = require('@sendgrid/mail'); sgMail.setApiKey(process.env.SENDGRID_API); const msg = { to: req.body['from'], from: 'info@npathfinder.info', replyTo: req.body['from'], subject: req.body['subject'], text: `from MailAddress: ${req.body['from']} ${req.body['text']}`, }; sgMail.send(msg); res.send('ok'); });
getmailというendpointにWebhookがPOSTされたら(SendGrid経由でメールを受信したら)オウム返しに送信者へメールとサブジェクト、本文などがメールで送られます。
実際にはここで内容をパースして目的に合わせた処理を実装することになります。
この時点でアプリをHerokuにデプロイしておきます。
Webhookの設定
SettingsのInbound Parseを開きます。
Add Host & URLから登録します。
Receiving Domainのsubdomainは任意です。 ドメインは今回で言うと「npathfinder.info」なのでDomain欄にはこれを記載します。
Destination URLというのがWebHook送信先となります。 これは独自ドメインでは無く、Heroku自体のURLが良いです。(Herokuの有料Dynoを使っている場合は独自ドメインで問題ありません。)
今回ので言えば↓のような形
https://wp-mail-register.herokuapp.com/getmail
Webhook登録時に定義したエンドポイントが存在しないと追加が完了できません。
ここで、ドメイン宛てにメールを送信するとwebhookがSendGridからPOSTされます。 ロジックとしては難しくないのですが。SendGridからのPOST内容がてっきりJSONだと思ってたのですがmultipart/form-dataで送信されるという落とし穴があります。
最初なにも考えずにJSONだと思って受け取れないなーと悩んでいました・・・ そこだけ注意すれば難しいことはありません。
最後に
明日は弊社人事、髙見さんによる新人エンジニアへのインタビュー「僕がホワイトプラスを選んだ理由<まっすー編>」です!
そして、WHITEPLUSでは一緒に働く仲間を募集しています。