AWS Lambdaで遊ぼう #3 LambdaからSNSでメール送信
もくじ
はじめに
こんにちは。 中村です。
今回は、LambdaからSNSへ連携してメール送付する手順を紹介します。
SNSとは
AWS様の直引用ですみません。m(___)m 以下の通りです。
Amazon Simple Notification Service (Amazon SNS) は、アプリケーション対アプリケーション(A2A)間と、アプリケーション対個人(A2P)間の両方の通信に使用できる、フルマネージド型メッセージングサービスです。
A2A での pub/sub 機能により、分散型システムやマイクロサービス、そして、イベント駆動型のサーバーレスアプリケーションにおいて、高スループットでプッシュベースの、多対多メッセージングをトピックで利用できるようになります。Amazon SNS トピックを使用することで、パブリッシャーシステムは、Amazon SQS キュー、AWS Lambda 関数、HTTPS エンドポイント、および Amazon Kinesis Data Firehose などの多数のサブスクライバーシステムに対しメッセージをファンアウトし、並列処理を行えます。A2P 機能を使用すると、SMS、モバイルプッシュ、E メールなどを介して、大量のユーザーに対しメッセージを送信できるようになります。
Amazon SNS
AWSリソースからSMSやEメールが送れる感じですね ( ・ ∀ ・ )っ💌
構成図
こんな感じのものを作ります。

前提条件
- AWSアカウント作成ずみである事
手順
① SNSトピック作成
AWSコンソール画面の検索窓に「sns」と入力し、SNSを選択する

左メニューの「トピック」をクリック、「トピックの作成」を実施する

タイプに「スタンダード」を選択し、SNSトピック名を入力する

画面一番下の「トピックの作成」をクリックする

トピックが作成されました。 続いて送信先を設定します。「サブスクリプションの作成」をクリックする

プロトコルに「Eメール」を選択する
エンドポイントにメールアドレスを入力する

画面一番下の「サブスクリプションの作成」をクリックする

ここまででSNSトピックの画面を見ると、サブスクリプションが登録され、ステータスが「保留中の確認(?)」となります。

サブスクリプションを登録すると、登録したメアド宛に確認メールが届きます。
「Confirm subscription」をクリックする

ブラウザに遷移し、この画面が表示されればOK

ステータスが「確認済み」になっている事を確認します。

少し余談ですが、サブスクリプション確認メールのリンクから、サブスクリプション解除も容易にできてしまいます。例えばメーリングリストを登録している場合、メーリスに入っているメンバーであれば誰でも解除できてしまいます。
サブスクリプションの誤解除を防ぐための手順も紹介されているので、必要な方は以下をご確認ください。
① Lambda関数作成
Lambda関数を作成します。作り方はこちら
IAM設定
LambdaくんがSNSを操作できるように権限を追加してあげる必要があります。
AWSコンソール画面の検索窓に「iam」と入力し、IAMを選択する

左メニューから「ポリシー」を開き、「ポリシーを作成」をクリックする

「サービス」を展開し、検索窓に「sns」と入力。ヒットした「SNS」を選択する

「アクション」→「書き込み」と展開し、「Publish」にチェックを付ける

「リソース」は「すべてのリソース」を選択する

ここまでで「JSON」タブを開くと、権限情報がJSON形式で記載されています。
得意な人はこっちでJSONで書くのもアリですね

一番下の「次のステップ: タグ」をクリックする

タグは今回は特に不要なので、「次のステップ: 確認」をクリックする

ポリシー名を入力して「ポリシーの作成」をクリックする

Lambdaの画面へ行き、「設定」タブから「アクセス権限」を開く。 Lambdaに付いているロールをクリックする

ロールの画面に遷移するので、「ポリシーをアタッチします」をクリックする

先ほど作成したポリシー名を選択して、「ポリシーのアタッチ」をクリックする

ポリシーがアタッチされればOK

Lambdaソースコードを更新
さてさて、ここからプログラムを書いて行きますぞ!
Node.jsとPythonの両方を用意しました。 とにかく最もシンプルな書き方にしているので、プログラミングが得意な方はガンガンにカスタマイズしちゃってください。
パラメータ定義や、SNS連携の部分は関数で外だししてあげが方が良いでしょうし、 arnなどの特定情報は環境変数に入れてあげる方が良いでしょうし。 Lambda環境変数の活用については、また別途記事を書こうと思います。
Node.js 14.xの場合
const AWS = require('aws-sdk');
const sns = new AWS.SNS();
exports.handler = async (event) => {
let params = {
TopicArn: 'arn:aws:sns:ap-northeast-1:999999999999:sns-topic-name',
Subject: 'Subject Lambda(node) -> SNSでメール送ったよ',
Message: 'Message\n\nLambda -> SNSでメール送ったよ\n届いた?'
};
await sns.publish(params).promise();
};
Python 3.9の場合
import boto3
client = boto3.client('sns')
def lambda_handler(event, context):
params = {
'TopicArn': 'arn:aws:sns:ap-northeast-1:999999999999:sns-topic-name',
'Subject': 'Subject Lambda(python) -> SNSでメール送ったよ',
'Message': 'Message\n\nLambda -> SNSでメール送ったよ\n届いた?'
}
client.publish(**params)
AWS SDK
Lambdaから他のAWSリソースへアクセスするにはAWS SDKというものが必要になります。言語ごとにAWS-SDKのAPIリファレンスがあるのでそちらを参考にしつつ、コードを書いて行きます。全部英語なので、気合入れて行きましょうwww
また、Nodeで書く場合はAWS SDK for JavaScriptを使うのですが、v2とv3があるようです。新しいv3が推奨されているようですが、情報量的にはv2の方が圧倒的に多いので、どっちを使うか悩ましいところですね( ´Д`)y━・~~ 本記事ではv2を使っています。v3にも慣れていかねば。。。
SNSトピックARNを確認する
上記ソースコードのSNSトピックARNの部分は実際に作ったSNSのARNに書き換えます。
SNSトピックの画面からARNを確認してください

③ 動作確認
よし!じゃあLambdaを動かしてみましょう!
「テスト」タブから「テスト」をクリックして動かします。

Lambdaは成功しましたね!

メールもちゃんと届きました!

念のため、CloudWatchLogsでエラー等出てないか確認しましょう。うん。大丈夫そうですね。

さいごに
LambdaとSNSの連携方法を紹介しましたが、SNSを作るのはそんなに難しくは無かったですね。
そして今回、IAMの設定手順が登場しました。Lambdaに限らずですがAWSを触っていると、とにかくIAMとの戦いになる気がしています。 たくさん触れば慣れてくるかと思います。
それでは左様なら( ・ ∀ ・ )ノシ
ベンジャミンのサーバレス開発サービス
ベンジャミンではAWS Lambdaを使ったサーバーレス開発サービスを提供しております。詳細は以下リンクをご確認ください