【AWS SES, Lambda, API Gateway】実装編:サーバーレスでメール配信APIを作る
はじめに
Webサービスやアプリケーション開発において、メール配信機能はとても重要です!例えば、以下のようなユースケースが考えられます。
- ユーザー登録時の確認メール送信
- パスワードリセットの案内メール送信
- ニュースレターやお知らせの配信
- お問い合わせへの自動返信
- システムからのアラート通知
AWS SESとLambda、API Gatewayを活用すれば、これらのメール配信機能をサーバーレスで簡単に実装できます!
この記事では、具体的な実装手順を通して、AWSのサーバーレスサービスによる効率的なメール配信システムの構築方法を解説します。
設計編はこちら↓
前提条件
- AWSアカウントを持っていること
2. SESの初期設定
まず、SESの初期設定が必要です。
AWS SESのサービスページに遷移して、以下の内容をセットアップしていきましょう。
- メールアドレスを検証
- 送信ドメインを検証
- 本番アクセスをリクエスト
2-1. メールアドレスの検証
SESコンソールから、送信元として使用するメールアドレスを登録・検証します。確認メールが届くので、メール内のリンクをクリックして検証を完了します。
2-2. 送信ドメインを検証
SESを通してメールを送信するには、送信元のドメインが必要です。Amazon Route53などのドメイン取得サービスを用いてドメインを取得します。
2-3. 本番アクセスをリクエスト
初期状態では、送信できるメール数や送信先アドレスに制限があります。
AWS SESのサンドボックス環境では、検証済みのメールアドレスにしかメールを送信できません。
本番環境で運用したい場合は、AWSサポートに送信制限の解除を申請してください。
3. Lambda関数の実装
3-1. 必要なIAMロールの設定
Lambda関数がSESを利用するためには、AWSのリソースにアクセスするための権限を設定する必要があります。この権限はIAMポリシーを通じて付与されます。
以下の手順で、Lambda関数がSESを利用するために必要なIAMロールを設定します。
- IAMコンソールを開く: AWSマネジメントコンソールでIAMのサービスページを開きます。
- 新しいロールを作成: 「ロール」-> 「ロールの作成」を選択します。
- ロールの種類を選択: 「AWSサービス」を選択し、ユースケースで「Lambda」を選択します。
- アクセス権限を設定: ポリシーをアタッチします。「AmazonSESFullAccess」ポリシーを検索してアタッチします。「確認」をクリックします。
-
ロール名と説明を入力: ロール名(例:
lambda-ses-role
)と説明を入力し、「ロールの作成」をクリックします。
3-2. Lambda関数を作成
- Lambdaコンソールを開く: AWSマネジメントコンソールでLambdaのサービスページを開きます。
- 関数の作成: 「関数の作成」ボタンをクリックします。「一から作成」のオプションを選択します。
-
基本情報の設定:
-
関数名: 任意の名前(例:
send-email-api
)を入力します。 - ランタイム: Node.js 22.x を選択します。
- アーキテクチャ: x86_64 を選択します。
-
アクセス権限: 実行ロールで「既存のロールを使用する」を選択し、先ほど作成したIAMロール(例:
lambda-ses-role
)を選択します。
-
関数名: 任意の名前(例:
- 「関数の作成」をクリックします。
3-3. メール送信機能の実装
Lambda関数に以下のコードを記述します。
import { SESClient, SendEmailCommand } from "@aws-sdk/client-ses";
const ses = new SESClient({ region: "ap-southeast-2" }); // リージョンは適宜変更
export const handler = async (event) => {
let requestBody;
try {
if ((event.body) && (typeof event.body === 'string')){
requestBody = JSON.parse(event.body);
} else {
requestBody = event;
}
} catch (error) {
console.error("リクエストボディのパースエラー:", error);
return { statusCode: 400, body: JSON.stringify({ error: "不正なリクエストボディです" }) };
}
const { to, subject, messageBody } = requestBody; // messageBodyを使用
// 入力値検証
const missingFields = [];
if (!to) missingFields.push("to");
if (!subject) missingFields.push("subject");
if (!messageBody) missingFields.push("messageBody");
if (missingFields.length > 0) {
return {
statusCode: 400,
body: JSON.stringify({
error: "必須項目が不足しています",
missing_fields: missingFields // 不足しているフィールド名を配列で返す
})
};
}
const toAddresses = Array.isArray(to) ? to : [to]; // to を配列に変換
const sourceEmailAddress = process.env.FROM_EMAIL; // 環境変数名を FROM_EMAIL に変更
const command = new SendEmailCommand({
Destination: { ToAddresses: toAddresses },
Message: {
Body: { Text: { Data: messageBody } }, // HTMLメールの場合は Html: { Data: body } を使用
Subject: { Data: subject },
},
Source: sourceEmailAddress,
});
try {
const response = await ses.send(command);
console.log("メール送信成功:", response);
return { statusCode: 200, body: JSON.stringify({ message: "メールを送信しました", messageId: response.MessageId }) };
} catch (error) {
console.error("メール送信失敗:", error);
return { statusCode: 500, body: JSON.stringify({ message: "メール送信に失敗しました", error: error.message }) }; // エラー内容を返す
}
};
環境変数の設定手順
- 設定タブを選択: 「設定」タブをクリックします。
-
環境変数を追加:
- 「環境変数」セクションで「環境変数を追加」をクリック。
-
キーに
FROM_EMAIL
、値に SESに登録したドメインに基づくメールアドレスを入力します。
- 保存: 変更を保存します。
3-4. Lambda関数内でテストする
-
テストイベントの設定:「テスト」タブを選択し、「新しいイベントを設定」をクリックします。
-
イベントJSONの編集: イベントJSONを以下のように編集します。
to
,subject
,messageBody
にはテスト用の値を入力してください。to
には配列で複数のメールアドレスを指定することも可能です。
{
"to": ["example1@gmail.com", "example2@gmail.com"],
"subject": "テストメール",
"messageBody": "これはLambdaを通じて送信されたテストメールです。"
}
⚠️ 注意: 送信先のメールアドレスは適宜変更してください。
-
テストの実行: イベントJSONを編集後、「保存」をクリックし、次に「テスト」ボタンをクリックします。
-
結果の確認: 実行結果が表示されます。
statusCode
が 200 であれば成功です。ログ出力も確認し、エラーが発生していないか確認しましょう。
4. API Gateway を利用したAPI構築
API Gateway を利用することで、Lambda 関数をよりセキュアかつ高機能な API として公開できます。ここでは、API Gateway を利用したAPI構築の手順と、テスト方法について解説します。
4-1. API Gateway の設定
- API Gateway のコンソールを開く: 新しい REST API を作成します。
-
API 名を指定: (例:
send-email-api
) -
リソースを作成: (例:
/send
)このとき、「CORS (クロスオリジンリソース共有)」にチェックを入れます。 - POST メソッドを作成: Lambda 関数との統合を設定します。統合対象には、3章で作成した Lambda 関数を指定します。
- CORS を有効化: 作成したリソースから「CORS を有効化」を押し、「Access-Control-Allow-Methods」で「POST」を選択し、使用したいアプリのオリジンを許可するように設定してください。
-
API をデプロイ: ステージ名(例:
dev
)を指定します。
4-2. API キーの作成 (推奨)
API キーを作成し、API へのアクセスを制限することで、セキュリティを強化し、API の使用量を制御できます。
- 使用量プランを作成: API Gateway のコンソールから使用量プランを作成します。
- API キーを作成: API Gateway のコンソールからAPI キーを作成します。
- API キーを使用料プランに追加: 作成したAPI キーのページから「使用料プランに追加」で関連付けます。
- API キーの使用を必須に設定: リソースのPOSTメソッドでメソッドリクエストの設定の「編集」から、「API キーは必須です」にチェックを入れます。
- API を再デプロイ: API を再デプロイして更新を有効にします。
- 使用料プランと紐づけ: 作成した使用料プランのページから「ステージを追加」でデプロイしたステージを関連付けます。
また、Cognitoと連携することでAPIの利用制限をかけることもできます。
4-3. APIのテスト
API Gateway のコンソールから、作成した API をテストできます。
- 作成したAPIの「POST /send」メソッドを選択します。
- 「テスト」をクリックします。
- リクエストボディに、下記のようなJSONを入力します。
{
"to": ["example1@gmail.com", "example2@gmail.com"],
"subject": "テストメール",
"messageBody": "これはAPI Gatewayを通じて送信されたテストメールです。"
}
5. Reactアプリからの呼び出しテスト
5-1. Reactアプリの修正
Axiosライブラリを使ってReactアプリからAPI Gateway経由でLambda関数を呼び出し、メール送信機能をテストします。
Axiosを使ってAPIを呼び出すReactアプリのコンポーネントを作成します。
import React, { useState } from 'react';
import axios from 'axios';
const EmailSender = ({ apiUrl, apiKey }) => {
const [email, setEmail] = useState('');
const [subject, setSubject] = useState('');
const [messageBody, setMessageBody] = useState('');
const [messageId, setMessageId] = useState('');
const [error, setError] = useState('');
const [message, setMessage] = useState('');
const handleSubmit = async () => {
const emailArray = email.split(',').map(e => e.trim()); // カンマ区切りで分割し、トリムする
try {
const response = await axios.post(
apiUrl,
{
to: emailArray, // 配列として指定
subject: subject, // subjectを直接指定
messageBody: messageBody // messageBodyを直接指定
},
{
headers: {
'Content-Type': 'application/json',
'x-api-key': apiKey // APIキーをプロパティから取得
}
}
);
console.log("sending email:", response);
// response.data.bodyをJSONとしてパース
const responseBody = JSON.parse(response.data.body); // JSONパース
// パースしたデータからmessageIdとmessageを取得
setMessageId(responseBody.messageId);
setMessage(responseBody.message); // メッセージを取得してステートに設定
setError('');
} catch (error) {
console.error("Error sending email:", error);
setError(error.response?.data?.error || 'メール送信に失敗しました'); // エラーメッセージを抽出
setMessageId('');
setMessage('');
}
};
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
<input
type="email"
value={email}
onChange={e => setEmail(e.target.value)}
placeholder="送信先メールアドレス"
/>
<input
type="text"
value={subject}
onChange={e => setSubject(e.target.value)}
placeholder="件名"
/>
<textarea
value={messageBody}
onChange={e => setMessageBody(e.target.value)}
placeholder="本文"
/>
<button
onClick={handleSubmit}
style={{ alignSelf: 'flex-start' }} // ボタンの幅を自動に設定
>
メール送信
</button>
{messageId && <p>メッセージID: {messageId}</p>}
{message && <p>メッセージ: {message}</p>}
{error && <p style={{ color: 'red' }}>{error}</p>}
</div>
);
};
export default EmailSender;
呼び出し箇所
EmailSender
コンポーネントを使用するには、まず必要なプロパティ(API GatewayのURLとAPIキー)を指定して呼び出します。以下のコードは、App
コンポーネント内で EmailSender
を呼び出す例です。
import React from 'react';
import EmailSender from './EmailSender'; // EmailSenderコンポーネントをインポート
function App() {
return (
<div>
<h1>メール送信アプリ</h1>
<EmailSender
apiUrl="YOUR_API_GATEWAY_URL" // API GatewayのURLを指定
apiKey="YOUR_API_KEY" // APIキーを指定
/>
</div>
);
}
export default App;
この例では、App
コンポーネント内に EmailSender
コンポーネントを配置しています。apiUrl
と apiKey
の値を適切に設定することで、メール送信機能を持つフォームが表示されます。ユーザーがメールアドレス、件名、本文を入力し、「メール送信」ボタンをクリックすると、指定されたAPI Gatewayを通じてメールが送信されます。
CORS (Cross-Origin Resource Sharing) について
CORSは、異なるオリジン(ドメイン、プロトコル、ポート)を持つWebページからのリソースへのアクセスを制御するセキュリティメカニズムです。ReactアプリとAPI GatewayのURLが異なるオリジンを持つ場合、CORSの設定が正しく行われていないと、ブラウザがAPIリクエストをブロックします。
API GatewayでCORSを有効化し、Reactアプリのオリジンを許可するように設定することで、この問題を解決できます。設定方法は4章で説明した通りです。
5-2. テストの実行
- Reactアプリを起動します。
- メールアドレス、件名、本文を入力し、送信ボタンをクリックします。
- メールが送信されること、そしてReactアプリにエラーメッセージが表示されないことを確認します。
- 必要に応じて、ブラウザの開発者ツールでネットワークリクエストを確認し、レスポンスヘッダーに
Access-Control-Allow-Origin
が含まれていることを確認します。
Reactからメール送信APIを利用してメールを送信することができました!
これで、Axiosを使ったReactアプリからのメール送信テストが完了です。
まとめ
この記事では、AWS SESとLambdaを使用して、スケーラブルでコスト効率の良いメール配信APIを構築する方法について解説しました。
参考資料
- AWS SES ドキュメント
- AWS Lambda ドキュメント
- API Gateway ドキュメント
- Lambda と Amazon SES を使用して E メールを送信する方法
- チュートリアル: API Gateway で Lambda を使用する
- Cognitoオーソライザーの設定
お疲れ様でした!
この記事は以上になります。お疲れさまでした。
Discussion