猫でもわかるWeb開発・プログラミング

本業エンジニアリングマネージャー。副業Webエンジニア。Web開発のヒントや、副業、日常生活のことを書きます。

アプリケーションにメール送信機能を実装するにあたって - AWS SES と SPF, DKIM

メール送信の実装は簡単ではない

メール送信の実装は思ったほど簡単ではありません。AWS SES などの登場によってかなり実装しやすくはなりましたが、それでも考えなければいけないことが色々あります。

メール送信のどこが大変なのか

メールは送信元を簡単に偽装できてしまいます。

メールの From に記載されているメールアドレスは、誰でも好き勝手に名乗ることができます。他人のメールアドレスを使って勝手にメールを送信することができるのです。

郵便を送るときと同じで、 From に他人の名前を書くことができるのです。

最近はスパムメールが飛び交っており、勝手に自分のメールアドレスを From に記載されることは良いことではありません。

そこで登場したのが SPF / DKIM / DMARC といった技術です。この記事ではこれらの技術について簡潔に書きます。わかりやすさを重視するため多少正確性を犠牲にする部分がありますがご容赦ください。

メールを受ける側も気をつけなくてはいけない

メールを受ける側も手口や対策について理解しておくことでスパムメールに引っかからないように気をつけることができます。

SPF (Sender Policy Framework)

メールが送信されたサーバーが正規のサーバーなのか確認するための技術です。

メールの送信に利用するメールサーバーの情報を DNS に登録し公開しておくことで、メール受信者は正しいメールサーバーから送られた物なのか判定できるようにします。

From に no-reply@qr-talk.com というアドレスを使いたい場合、 qr-talk.com の DNS に v=spf1 include:amazonses.com -all のような TXT レコードを登録しておきます。

  • v=spf1 は SPF のバージョンを表していますが、現状は spf1 以外のバージョンはありません。
  • include:amazonses.com は、 AWS SES からのメールを送信することを表しています。AWS SES 以外から送られてきた qr-talk.com のメールは偽装ということになります
  • -all は、それ以外のサーバーは許可していませんという意味です

include:amazonses.com を指定すると、AWS SES を使えば他の人が From qr-talk.com のメールアドレスを送れてしまいそうですが、そこは AWS 側で認証がされているので問題ありません。

AWS SES を使わず自前でメールサーバーを持っている場合など、 IP アドレスで指定したい場合は ip4:203.0.113.10 のように書きます。

Gmail など各メールサービスが SPF を確認してくれます。SPF に違反したメールは警告が表示されたり、迷惑メールに分類されたりします。

CDK での実装例

const hostedZone = route53.HostedZone.fromLookup(
  this,
  'QrTalkHostedZone',
  {
    domainName: 'qr-talk.com',
  },
);

const emailIdentity = new ses.EmailIdentity(
  this,
  'QrTalkEmailIdentity',
  {
    // メールの From に no-reply@qr-talk.com を使う場合は qr-talk.com を指定
    identity: ses.Identity.domain('qr-talk.com'),

    // SPF が参照する MAIL FROM ドメイン
    mailFromDomain: 'bounce.qr-talk.com',
  },
);

// bounce.qr-talk.com の SPF レコード
new route53.TxtRecord(this, 'SesMailFromSpfRecord', {
  zone: hostedZone,
  recordName: 'bounce',
  values: ['v=spf1 include:amazonses.com ~all'],
});

AWS SES が参照する MAIL FROM ドメインは実際にメールに付与される From ドメインと違ってややこしいのですが、ここでは詳しく説明しません。実装の詳細については調べてください。

DKIM (DomainKeys Identified Mail)

DKIM は、メールが送信後に改ざんされていないことを確認できるようにする仕組みです。どうやって改ざんすんねん、という話は省略します。

メールに電子署名を付与することで改ざんを検知できるようにします。電子署名についても詳しく説明しません。改ざんを検知できるようになる仕組みです。

実装

AWS SES を利用する場合、電子署名が自動で付与されます。電子署名を検証するための公開鍵の情報を DNS に登録します。

AWS CDK + Route 53 を使っている場合の実装はこれだけです

const hostedZone = route53.HostedZone.fromLookup(
  this,
  'HostedZone',
  {
    domainName: 'qr-talk.com',
  },
);

new ses.EmailIdentity(this, 'Identity', {
  identity: ses.Identity.publicHostedZone(hostedZone),
});

DMARC (Domain-based Message Authentication, Reporting, and Conformance)

DMARC は上記2つと少し毛色が違います。DMARC は、SPF, DKIM の検証に失敗したメールをどのように扱うかを記載します。厳密には違いますが、わかりやすさ重視でざっくりこのようにします。不正なメールをどのように扱うべきかを記載するという点が重要です。

例えば、このような DNS レコードを登録します。

"v=DMARC1; p=quarantine"

  • V=DMARC1 は DMARC のバージョンです。現在は DMARC1 しかありません
  • p は、 SPF や DKIM に引っかかったメールをどう処理して欲しいかを記載します。以下のいずれかを指定できます
    • none 何もしない(レポートのみ)
    • quarantine 迷惑メールとして扱う
    • reject 受信を拒否する

さいごに

今回は SPF, DKIM, DMARC を説明しましたが、これ以外にも、メールは到達確認が困難だったり、バウンス(メール送信が失敗した時の対応)の問題などがあります。

一方、AWS SES の登場によりかなり改善された面もあります。

アカウント登録などでメール送信を実装するアプリも多いかと思いますが、「メール送信なんて実装するだけでしょ」とは思わず、色々考慮することが重要です。