ラベル ses の投稿を表示しています。 すべての投稿を表示
ラベル ses の投稿を表示しています。 すべての投稿を表示

Gmailでカスタムドメインのメールアドレスを送受信する

自ドメインをメールサーバー無しで送受信するためのアーキ


登場人物

  1. Gmail カスタムドメイン宛メールの受信メールボックスおよび、SMTPクライアントとして
  2. → GoogleWorkspaceは使わない。一般アカウント。

  3. improvmx カスタムドメイン宛メールをGmail転送するためのMXサーバーとして
  4. SES カスタムドメインでメール送信するためのSMTPサーバーとして(GMailでもよい)
  5. Route53 カスタムドメインのDNSとして

カスタムドメインから受信

Gmail


カスタムドメイン宛メールの受信メールボックスとして

  • 受信専用であれば追加設定は不要。

Improvmx


https://improvmx.com/

カスタムドメインのMXサーバーとして

  • Improvmxは転送専用であり、メールボックス実態は存在しない。転送先メアドのエイリアスとして利用する。
  • SMTP機能は有料オプションなので使わない。

カスタムドメインと転送先メアドを設定して登録開始


転送先メアドで認証プロセスを終えると、ひとまずドメイン未検証の状態でダッシュボードがオープンし、転送ルールと、MX・SPFレコードが払い出される。


上記、SETTINGS > DNS settingsに表示されるるMX・SPFレコードをDNSに登録後、DNS検証が完了するとセッティングがアクティベートされる。 ※なお、SMTPは使わないんだけど、アクティベートにはSPF(TXT)レコードの定義も必須。


  • Email forwarding activeになったらTESTで検証メールを送信させて、無事にGmailメールボックスに届いたら完了。


カスタムドメインから送信

Gmail


SMTPクライアントとして

1. プロフィールとSMTPサーバーを追加する

Gmailアカウントに以下の設定を組んだら、カスタムドメインをFROMアドレスとして利用可能となる。

  1. カスタムドメインのFROM送信者名とメアド
  2. SMTPサーバ

Gmail > 設定 > アカウントとインポート > 名前 | 他のメールアドレスを追加

を開いて、カスタムドメインの送信者名とメアドを指定する。 ここに追加したメールアドレスはGASのMailAppでもメールFROMとして利用可能となる


2. SMTPサーバーの指定

SMTPサーバーとしてGmailとSESを比較

最も手軽なのは検索でよく出てくる自GmailアカウントのSMTPを利用する方法。 カスタムドメインの名前&メアドをFROMにしつつ、SMTPはGmailドメインで送信者認証もサポートしてくれるのでカジュアルな送信基盤としては問題はなさそう。

一方、SESをSMTPにする場合は、カスタムメールFROM機能でカスタムドメイン(サブドメイン)から送信されるため、 GmailではエンベロープFROMヘッダにGmailメアドが露出するのに対して、SESはカスタムドメイン(サブドメイン)となる。 (厳密にはGmailの追加ヘッダX-Gmail-Original-Message-IDなど付記される。)

その他にも、送信クウォータとかレピュテーション要件などそれぞれ要件が異なるため、適宜選択というイメージ。今回はSESで構築する。

SMTPサーバーにGMailを使う場合


FROM(表示名)=mail@domain.to.path エンベロープFROM(実際送信元)={アカウント}@gmail.com

  • カスタムドメインをメールFROMにして、GmailアカウントのSMTPから送信者認証つきで送信できる。
  • もっとも簡単だけど、ヘッダのエンベロープFROMにGmailアドレスが受信者に露出する。

注意事項としては、SMTPサーバーのパスワードはGoogleアカウントのパスワードではなく、アプリパスワードだ。 アプリパスワードの発行のためにはアカウントに二段階認証プロセスの設定が必要。

SMTPサーバーにSESを使う場合

FROM(表示名)=mail@domain.to.path エンベロープFROM(実際送信者)=XXXXXXXXXXXXXXXX-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX-XXXXXX@mail.domain.to.path

  • カスタムメールFROMで指定したサブドメイン(mail.domain.to.path)から送信者認証つきで送信できる。
  • カスタムメールFROMのセッティングは必要だけど、Gmailアドレスが受信者に露出することはない。

SESでは以下、設定済のこと

  • カスタムドメインのID検証、SPF、DKIM、DMARCレコード
  • サンドボックス解除
  • SMTP設定


送信テスト

カスタムドメインからメールを送信し、SPF、DKIM認証をパスできているか確認する。 テスターmail-tester.comを使うと、問題点をリスト化してくれるのでさらに捗る。

SESのバウンスメールをウェブフック


SESでバウンスレート由来のレビュー・配信停止を抑止するために、SNSのhttpsサブスクリプションでアプリケーションをフックするアーキ

ハードバウンスはSESがアカウントレベルのサプレッションリストに入れたあと、90日間の再送が抑止されるが、アプリケーション層でもレビュー対象として管理し、送信管理、ユーザへの修正依頼に利用する。 Amazon SESアカウントレベルのサプレッションリストの使用 - Amazon Simple Email Service

SES(ID) → ( バウンス/苦情フィードバック) → SNSトピック → (httpsウェブフック) → アプリケーション でフラグを立てる 


サブスクライブ認可

SNSトピックにhttpsプロトコルでサブスクリプションを作成すると、エンドポイントに次のhttpsリクエストが入るのでSubscribeURLを叩いて、承認を完了する。 エンドポイントで応答する実装を組んでもいいし、コピペしてブラウザUAからリクエストしても良い。

{
  "Type" : "SubscriptionConfirmation",
  "MessageId" : "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "Token" :"xxx...",
  "TopicArn" : "arn:aws:sns:ap-northeast-1:{AWSアカウントID}:{SNSトピック名}",
  "Message" : "You have chosen to subscribe to the topic arn:aws:sns:ap-northeast-1:{AWSアカウントID}:{SNSトピックID}.¥nTo confirm the subscription, visit the SubscribeURL included in this message.",
  // これ 
  "SubscribeURL" : "https://sns.ap-northeast-1.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:ap-northeast-1:{AWSアカウントID}:{SNSトピックID}&Token=xxx...",
  "Timestamp" : "2024-10-16T05:07:58.589Z",
  "SignatureVersion" : "1",
  "Signature" : "xxx...==",
  "SigningCertURL" : "https://sns.ap-northeast-1.amazonaws.com/SimpleNotificationService-xxx.pem"
}

認可完了のレスポンス

<ConfirmSubscriptionResponse>
  <ConfirmSubscriptionResult>
    <SubscriptionArn>
      arn:aws:sns:ap-northeast-1:{アカウントID}:{SNSトピック名}:{サブスクリプションID}
    </SubscriptionArn>
  </ConfirmSubscriptionResult>
  <ResponseMetadata>
    <RequestId>{レスポンスID}/RequestId>
  </ResponseMetadata>
</ConfirmSubscriptionResponse>

フィードバック

SESからSNSトピックにフィードバック通知を組む。


SESバウンストピックの受信

バウンスメールが発生したとき、エンドポイントに次のようなPOSTリクエストが入る。 Messageオブジェクトにバウンスまたは苦情メールのプロパティがjson文字列として入っている。

SESでバウンスなテストメールを発信する

{
  "Type" : "Notification",
  "MessageId" : "79a880a8-d9ea-538d-9f74-df218c1aa5f0",
  "TopicArn" : "arn:aws:sns:ap-northeast-1:{AWSアカウントID}:{SNSトピックID}",

  "Message" : "{¥"notificationType¥":¥"Bounce¥",¥"bounce¥":{¥"feedbackId¥":¥"0106019293deea0f-19d2444a-7a3a-4e40-a632-8b776bd2202d-000000¥",¥"bounceType¥":¥"Permanent¥",¥"bounceSubType¥":¥"General¥",¥"bouncedRecipients¥":[{¥"emailAddress¥":¥"bounce@simulator.amazonses.com¥",¥"action¥":¥"failed¥",¥"status¥":¥"5.1.1¥",¥"diagnosticCode¥":¥"smtp; 550 5.1.1 user unknown¥"}],¥"timestamp¥":¥"2024-10-16T05:48:32.000Z¥",¥"remoteMtaIp¥":¥"18.139.69.138¥",¥"reportingMTA¥":¥"dns; e234-11.smtp-out.ap-northeast-1.amazonses.com¥"},¥"mail¥":{¥"timestamp¥":¥"2024-10-16T05:48:32.056Z¥",¥"source¥":¥"ses@hoge.jp¥",¥"sourceArn¥":¥"arn:aws:ses:ap-northeast-1:{AWSアカウントID}:identity/hoge.jp¥",¥"sourceIp¥":¥"121.117.160.85¥",¥"callerIdentity¥":¥"ms-ohashi¥",¥"sendingAccountId¥":¥"{AWSアカウントID}¥",¥"messageId¥":¥"0106019293dee7b8-dc011c08-e485-4f71-bf91-e8b7d0542aa1-000000¥",¥"destination¥":[¥"bounce@simulator.amazonses.com¥"],¥"headersTruncated¥":false,¥"headers¥":[{¥"name¥":¥"From¥",¥"value¥":¥"ses@hoge.jp¥"},{¥"name¥":¥"To¥",¥"value¥":¥"bounce@simulator.amazonses.com¥"},{¥"name¥":¥"Subject¥",¥"value¥":¥"test bounce¥"},{¥"name¥":¥"MIME-Version¥",¥"value¥":¥"1.0¥"},{¥"name¥":¥"Content-Type¥",¥"value¥":¥"multipart/alternative;  boundary=¥¥¥"----=_Part_1489259_127934103.1729057712056¥¥¥"¥"}],¥"commonHeaders¥":{¥"from¥":[¥"ses@hoge.jp¥"],¥"to¥":[¥"bounce@simulator.amazonses.com¥"],¥"subject¥":¥"test bounce¥"}}}",

  "Timestamp" : "2024-10-16T05:48:32.836Z",
  "SignatureVersion" : "1",
  "Signature" : "xxx==",
  "SigningCertURL" : "https://sns.ap-northeast-1.amazonaws.com/SimpleNotificationService-xxx.pem",
  "UnsubscribeURL" : "https://sns.ap-northeast-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:ap-northeast-1:{AWSアカウントID}:{SNSトピックID}:xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

データボディの仕様 Amazon の Amazon SNS通知コンテンツ SES - Amazon Simple Email Service