はじめに
EC2からメールを送信する方法はいくつかあります。
自分用メモとして、その中でも一番メジャーであろうSESを使ったメール送信について残しておきます。
ドメインの取得
メールを送信するためにはドメインが必要となります。(~@mail.comの部分ですね)
こちらは以下のサイト参照で取得しておきましょう。
Route53から直接購入する場合
「ドメインのRoute 53への登録」までですね。
https://dev.classmethod.jp/articles/relaxing-send-limit-and-removing-sandbox-restriction-in-ses/
他のサービスを使う
ドメインはRoute53で買わずとも、他のドメイン登録サービスを使うこともできます。
有名なのはお名前.comですね。
先にドメインを取得しておいて、お名前.comの設定ページのネームサーバー欄にRoute53のNSレコードを貼り付けたら完了です。
お名前.comで取得するとキャンペーンとかで安くなる事が多いのでおすすめです。
こちらもDevelopersIOさんのサイトを貼っておきますね。
https://dev.classmethod.jp/articles/route53-domain-onamae/
Django側
django-sesのインストール
ドメインの取得ができたら次はDjango側での作業です。
DjangoではDjango-sesをインストールすることで簡単にDjangoからSESを操作する事ができます。
pip install django-ses
django-sesではbotoというpythonライブラリとAWSサービスをつなぐものを必要としますので、こちらもインストールが必要です。
pip install boto3
これにより、Djangoの標準からSESを使う事ができるようになりました。
setting.pyの修正
setting.pyを開いて以下のように修正しましょう。
なお、...は省略の意味です。
INSTALLED_APPS = [
...
'django_ses' #追加する
]
...
AWS_SES_REGION_NAME="ap-northeast-1" #追加する
AWS_SES_REGION_ENDPOINT="email.ap-northeast-1.amazonaws.com" #追加する
EMAIL_BACKEND="django_ses.SESBackend" #追加する
DEFAULT_FROM_EMAIL = "no-reply@mail.com" #追加する、@の後ろは取得したドメイン
各項目について簡単にメモしておきます。
とは言っても名前でなんとなくわかりますけどね。
AWS_SES_REGION_NAME
SESを動かしているリージョンを選択します。東京リージョンなら例の通りです。
AWS_SES_REGION_ENDPOINT
SESのエンドポイントです。Djangoはここにアクセスします。
似たようなものにSMTP endpointがあります。こちらではないのでご注意ください。
自分の認識だと、AWSサービスとしてではなくシンプルにSMTPサーバーとしてSESを使いたいときに使うものだと思ってます。
EMAIL_BACKEND
その名の通り、Django内でEmailサービスの根幹となるアプリケーションを選択します。
デフォルトでは以下の様になっていると思います。
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
これはSMTPサーバーを指定してDjangoからメールを送るときのデフォルトのバックエンドです。
setting.py内でSMTPサーバーの設定をすれば、このデフォルトのバックエンドでメール送信をする事ができますが、今回はdjango-sesのバックエンドを指定しておきましょう。
DEFAULT_FROM_EMAIL
メールの送信元を設定します。
これを設定しないとデフォルトでwebmaster@localhostが送信元に設定されてしまいます。
SESにlocalhostのドメインはないのでエラーが出ます。
Django側の設定は以上で終了です。
EC2側
続きましてEC2側の設定です。
Djangoが動いているEC2とSES間の認証にはIAMロールを使用します。
先程のsetting.py内に
AWS_ACCESS_KEY_ID = "***********************"
AWS_SECRET_ACCESS_KEY = "***********************"
のようにIAMユーザーのアクセスキーとシークレットアクセスキーを入力することでも認証することは可能です。
ただ、環境変数ならまだしもアクセスキーをプログラム中に書くのはまずいのでIAMロールを使用します。
ポリシーを作成する
IAMのコンソール画面からポリシーをクリックして、ポリシーを作成をクリックしましょう。
ポリシーを入力
ビジュアルエディタから入力しても良いですが、とくにこだわりがなければJSONでこの3つを書いておけばいいかと思います。
↓コピー用
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SESSendMail",
"Effect": "Allow",
"Action": [
"ses:SendEmail",
"ses:SendRawEmail",
"ses:GetSendQuota"
],
"Resource": "*"
}
]
}
GetSendQuotaですが、SESには送信できる上限値があって、GetSendQuotaで知ることができるみたいです。
そのためロールにこれがないとエラーとなります。
https://docs.aws.amazon.com/ja_jp/ses/latest/dg/manage-sending-quotas-monitor.html
あとは画面にしたがって進んでいきましょう。
途中で名前を設定する画面がありますが、この名前はあとで使うので覚えておきましょう。
これでポリシーは完成しました。
ポリシーをアタッチしてIAMロールを作成
次にいま作成したポリシーをIAMロールを作成してアタッチします。
ロールをクリックしましょう・
ロールを作成をクリック
エンティティ選択
今回はAWSサービスにIAMロールをつけるので、AWSサービスを選びます。
ユースケースはEC2を選んで次へいきましょう。
アタッチするポリシーを選択
続いて作成中のロールにアタッチするポリシーを選択します。
ここには自分が作ったポリシーだけでなく、AWS側で最初から用意されているポリシーも表示されています。
先ほどポリシー作成時につけた名前「SES_SendMail」で検索しましょう。
名前を入力して作成完了
最後にこのロールの名前を入力して作成ボタンを押しておきましょう。
EC2にアタッチ
ここまでくればあともう少しです!
IAMロールを変更をクリック
ロールを選択して保存
ここで先程作成したロールを選択してください。
もし、さきほどロールを作成する先にエンティティでEC2を選んでないとここに表示されないので注意しましよう。
Django側の設定
こんな関数を作っておいて、呼び出してやればメールを送る事ができます。
from django.core.mail import EmailMultiAlternatives
def send_email(subject,text_content,html_content,from_email,to_emails):
msg = EmailMultiAlternatives(subject, text_content, from_email, [to_emails])
msg.attach_alternative(html_content, "text/html")
msg.send()
https://docs.djangoproject.com/ja/4.0/topics/email/
詳しくは、Djangoの公式ドキュメントに書いてありますが簡単に説明しますと、
subject:メールタイトル
text_content:プレーンテキストのメール本文(受信者がHTMLメールに対応してない場合に表示する用)
html_content:HTMLで書かれたメール本文
from_email:送信元
to_emails:送信先(リストで指定できます。)
ちなみに試してはいませんが、HTMLメールを送る必要がない場合はこれだけでも送れるみたいです。
from django.core.mail import send_mail
send_mail(
'Subject here',
'Here is the message.',
'from@example.com',
['to@example.com'],
fail_silently=False,
)
まとめ
いかがでしょうか。
AWSではEC2にメールサーバーを建てなくても、マネージドサービスで簡単にメールを送信することができます。
しかも、今回のようにEC2にホストされているアプリケーションからSESを使ってメール送信した場合には、62,000通/月まで無期限無料枠があるので個人開発だとほぼ無料枠に収まるのではないでしょうか。