はじめに
SendGridのメールサービスを触ってみた。
今回は、SendGridのSMTPリクエストとSendGrid EventWebhookを使いAWS側で受け取るところまでを紹介します。(ほんとは分析ようにKibanaまで行きたかったので、それは別で書こうと思います(*^_^*)
SendGridとは
SendGridは月間200億通を超えるメール配信を行い、世界のメール業界を支えています。
ただ大量の配信をするだけでなく、配信したメールのアナリティクス機能も提供しています。
トランザクションメールなんかも送れるので、利用の幅は広いですね。
フロー
実装
SendGrid SMTP APIを使ったリクエスト
SMTP APIではX-SMTPAPIヘッダを利用してメールのカスタム処理を指定できる。
{
"minimum-stability" : "dev",
"require": {
"sendgrid/smtpapi": "~0.5",
"swiftmailer/swiftmailer": "@stable"
}
}
<?php
date_default_timezone_set('Asia/Tokyo');
require_once dirname( __FILE__ )."/lib/vendor/autoload.php";
use Smtpapi\Header;
// カスタムヘッダ例 名前の埋め込み
$to = array('kazuki.mitani+01@nijibox.co.jp', 'kazuki.mitani+02@nijibox.co.jp');
$from = "smtp-testmail@nijibox.co.jp";
$subject = "お久しぶり";
$body = <<<EOF
%how%さんこんにちは! \r\n
最近元気ですか?
EOF;
$substitution = array('三谷', '伊藤', '吉田');
//
$message = new \Swift_Message();
$message->setTo($to);
$message->setFrom($from);
$message->setSubject($subject);
$message->setBody($body);
// SMTP サーバーとの接続設定
$transport = \Swift_SmtpTransport::newInstance('smtp.sendgrid.net', 587);
$transport->setUsername('SENDGRID_USER');
$transport->setPassword('SENDGRID_PASS');
$mailer = \Swift_Mailer::newInstance($transport);
// ヘッダーの設定
$header = new Header();
$header->addSubstitution('%how%', $substitution);
$message_headers = $message->getHeaders();
$message_headers->addTextHeader(HEADER::NAME, $header->jsonString());
// 送信
try {
$response = $mailer->send($message);
print_r($response);
} catch(\Swift_TransportException $e) {
print_r($e->getMessage());
}
DynamoDBの作成
DynamoDB
↓
テーブル作成
テーブル名:SendGridEvents
プライマリーキー:sg_event_id 文字列
で作成。
Lambdaの設定
受け取ったWebhookのポストをパースしてDynamoDBに入れるためのLambda Functionを作ります
AWS Lambda
↓
Create a Lambda function
↓
元に使えそうなblueprintを選択。
今回は、microserice-http-endpointを選択しました
↓
設定
name:SendGrid-EventWebhook
Description:ダイナモDBに入れる
Runtime:NodeJS
↓
コードを書く
var doc = require('dynamodb-doc');
var dynamo = new doc.DynamoDB();
exports.handler = function(event, context) {
function logArrayElements(element, index, array){
var params = {
TableName: 'SendGridEvents',
Item:element
};
dynamo.putItem(params, function (err, data) {
if (err) {
console.log(err, err.stack);
} else {
console.log(data);
}
});
}
event.forEach(logArrayElements);
};
API Gatewayの設定
SendGridから飛んでくるWebhookの受け場所を作ります。
AWS API Gateway
↓
Create API
↓
Create Method
↓
POSTを選択
Integration type:Lambda Function
Lambda Region:ap-northeast-1(作製したLambdaのRegion)
Lambda Function:SendGrid-EventWebhook(作製したLambdaのFunction名)
EventWebhook到達確認
INTEGRATION TESTING TOOL
AWS側の設定はここまでで終了したので、疎通確認を行います。
SendGridでは実際にメールを送らず、受け取り側のテストだけ行える”INTEGRATION TESTING TOOL”を提供しています。
SendGrid
↓
ログイン
↓
ダッシュボード
↓
Mail Settings
↓
Event Notification
↓
HTTP POST URL:API GatewayのURL
↓
SELECT ACTIONSのすべてにチェックを付ける
↓
保存してTestYourIntegrationをクリック。
↓
DynamoDBの格納確認が出来たら成功!
SMTPAPIを使った疎通確認
先に作成したphpを実行して、メールリクエストを送ることで実際のWebhookを受け取れるか確認する。
$ php sendMail.php
↓
メールが届く
↓
でもWebhookは届かない!!!
状況確認
1.INTEGRATION TESTING TOOLでは動く。
↓AWSは悪くない。
2.SendGridのEventWebhookがそもそもAPIGatewayに到達していない。
↓SendGrid側が怪しい。
3.ngrokを使ってEventWebhookのPOSTをローカルで受け取れた。
↓Webhookは送られている。
結果:SendGridのWebhookの挙動が怪しい。
ここで天から舞い降りた鶴の一声でAWS API GatewayのCustom Domain Namesを使用してみることに。
※https通信するためにAWSにCertificate body, Certificate private key, Certificate chainを登録する必要がある。
AWS API Gateway
↓
Custom Domain Names
↓
Base path:api-gateway
API:SendGrid-EventWebhook
Stage:なし
↓
https://使いたいドメイン/BasePath/Stage名/API名
例: https://DOMAINNAME/api-gateway/prod/SendGrid-EventWebhook
↓
SMTPAPIテスト
↓
メールが届く
↓
DynamoDBにデータが入る!成功!!
まとめ
SendGridと、使ってみたかったAWSに触れてみました。
全く理解不能なところで詰まったり、悩んでた割にすんなりと設定出来たりといろいろ経験が出来ました。
おわり