AmplifyからFunctions(Lambda)経由でSESを使いメールを送信する方法
2023/7/22 2023/7/22 システム
はじめに
AWSのAmplify、便利ですよね。
Auth(Cognito)を使った認証や、API(GraphQL API)、Storageなどを簡単に結合することができます。
上記のような一般的な処理の他にも、定時処理やプッシュ通知、外部APIを叩くときなんかはFunctions(Lambda)を使うことで機能を拡張することができます。
今回は、アプリケーションからなんらかの処理をした際に、任意のユーザーにメールを送信したい場合の実装方法のサンプルをご紹介します。
実装方法の大まかな流れは以下となります。
- Amazon SESの準備
- Functionsの実装
- アプリからの呼び出し
早速一つ一つ記載していきたいと思います。
Amazon SESの準備
まず初めに、AWSのサービスを用いてメール送信をするためには検証済みIDが必要となります。
AWSのコンソールからSESのページを開き、IDの作成から送信元となるメールアドレスを登録します。
登録したメールアドレス宛に届いたリンクをクリックすることでステータスが「検証済み」となりますが、これだけでは不完全で、この時点ではsandboxが自由に使える状況で、Lambdaから呼び出そうとするとエラーが起きてしまいます。
そのため、同じくSESの画面から「送信制限を解除し本番アクセスを有効にする」申込を行います。
ユースケースの説明として、どういった状況で利用するために必要か説明を書く必要があります。
私の場合、一度承認されませんでしたが、非承認の案内に返信する形で「メールを送信する頻度、メール内容のサンプル」を追記して再度申請すると、数分以内に承認の案内が届きました。
ここまでで、SESの準備は完了となります。
Functionsの実装
続いて、メール送信を行うLambdaを作成します。
まずはコンソールから以下のコマンド
amplify add function
Lambda functionを選択します。
パッケージ等をまとめて一つで管理してLambdaを使いたい場合はLayerを使うのも有りです。
function nameはsendMailとしました。
また、今回はNodeJS、Hello Worldのテンプレートを使用しています。
Functionsの追加ができましたら、{function name}-cloudformation-template.jsonにSESの権限を付与します。今回の場合「sendMail-cloudformation-template.json」ですね。
追加する箇所は以下です
Resources > lambdaexecutionpolicy > Properties > PolicyDocument > Statement
最初からログに関する定義が記載されているので、その上あたりに追加しましょう。
"Statement": [
// 追加
{
"Effect": "Allow",
"Action": [
"ses:SendEmail",
"ses:SendRawEmail"
],
"Resource": "*"
},
// ここまで
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
続いて、このfunctionにawsのsdkを追加します。
cd amplify/backend/functions/sendMail/src
yarn add @aws-sdk/client-ses
続いて処理を行index.jsを記述します。
/* Amplify Params - DO NOT EDIT
ENV
REGION
Amplify Params - DO NOT EDIT */
const {SESClient, SendEmailCommand} = require('@aws-sdk/client-ses');
/**
* @type {import('@types/aws-lambda').APIGatewayProxyHandler}
*/
exports.handler = async event => {
const to = event.arguments.data.to;
const from = event.arguments.data.from;
const sesClient = new SESClient({
region: 'ap-northeast-1',
});
const sendEmailCommandInput = {
Source: 'from',
Destination: {
ToAddresses: to,
},
Message: {
Subject: {Data: 'ここにメールの件名'},
Body: {
Text: {
Data: `ここにメールの本文`,
},
},
},
};
const sendEmailCommand = new SendEmailCommand(sendEmailCommandInput);
const sendEmailCommandOutput = await sesClient.send(sendEmailCommand);
return {
statusCode: 200,
body: sendEmailCommandOutput.MessageId,
};
};
ここまでできたら、amplify pushでクラウドに反映させます。
また、Lambda自体が動作していることを確認するには、Amplify mock functionでもできますし、AWSコンソールのLambdaのページからテストを行うこともできます。
テストに利用するevent.jsonは以下のようにします
ここまで完了したら、最後にアプリから呼び出す処理を追加します
アプリからの呼び出し
アプリから先ほどのLambdaを呼び出すには、AmplifyのAPIを使うことで簡単に呼び出しができます。
まずはAPIで利用しているschema.graphqlに以下を追加します。
sendMail(data: EmailData!): String @function(name: "sendMail-${env}")
input EmailData {
from: String!
to: [String]
}
追加をしたらクラウドに反映させたいので、amplify pushでアップデートしましょう。
その後は、任意の場所で関数を呼び出すだけです!
以下はあくまでも呼び出しサンプルなので、プロジェクトに合わせた実装をしてください。
await sendMail({
from: user?.mail,
to: mailAddresses,
});
export async function sendMail(data: any): Promise<any> {
const res = await API.graphql(
graphqlOperation(sendMail, {
data: data,
}),
);
return res;
}
さいごに
今回はAWSのAmplifyを使い、Functions(Lambda)でSESを使ってメール送信をするための方法をご紹介しました。最後まで閲覧いただきありがとうございました。