Amazon SESでメールを送ったときにGmailでvia email-bounces.amazonses.comって表示されないようにする

久しぶりの更新です。すごくハマってだいぶ調べたので同じことで悩む誰かの助けになればとまとめておきます。

Amazon SESを使って普通にメールを送ると以下のように受け取った側のGmailでvia email-bounces.amazonses.comと表示されてしまいます。

Gmailでは送信元アドレスのドメインとメールサーバーのドメインが違う場合には、ドメインを詐称してメールを送っている場合があるので、それをabc@co-meeting.com via example.comと送信元アドレスとメールサーバーのドメインを両方表示します。
これは格好悪いですし、スパム扱いされる危険性があります。

Gmailのヘルプ(Why am I seeing extra information next to the sender’s name? - Gmail Help)を読むと、SPFレコードを設定するか、DKIM署名を付けると、表示しないようにできるよと書かれています。
しかし、SPFレコードを設定するだけではだめのようです。なので、SESで送るメールにDKIM署名をつけてみました。

DKIMの詳細についてはこちら(電子署名方式の最新技術「DKIM」とは − @IT −)が詳しいです。今回は理屈は他の記事に譲り、とにかくSESでDKIM署名付きメールを送る方法を書きます。

1. 公開鍵と秘密鍵を作成します。

以下のコマンドで作成します。

>openssl genrsa -out ses.key.pem 1024
>openssl rsa -in ses.key.pem -out ses.key.pub -pubout -outform PEM

2. DNSレコードを追加します。

うちで使っているDNS管理サービスDozensの場合は以下のように設定します。

Record Name:ses._domainkey.co-meeting.com
Type:TXT
Content:v=DKIM1; k=rsa; t=y; p=HD83kFU9dkFDAP...


ses._domainkey.co-meeting.comのsesはDKIMのselectorと呼ばれるものです。後でプログラムで指定します。
Contentのpには作成した公開鍵から改行やスペースを削除した文字列を指定します。

3. SESの管理画面でメールアドレスの承認を行う

AWS Management Consoleで、メールアドレスの承認を行います。
サンドボックスモードでは、送信元メールアドレスと受信先メールアドレスの両方のアドレスを登録しないと、SESはメールを送ることができません。

「Verify a new sender」ボタンから両方のアドレスを登録してください。確認のメールが送られてきますので、メール内のリンクをクリックします。

4. メール送信プログラムのためにGemをインストール

Rubyでは、aws-sesというAmazon SESを使うためのGemとdkimというDKIM署名をつけるGemがあります。インストールしましょう。

>gem install aws-ses
>gem install dkim

5. メール送信プログラム

以下のように書きます。
access_key_idとsecret_access_keyはセキュリティ証明書 - Amazon Webサービスから取得してください。
ses.key.pemは1.で作成した秘密鍵です。

require 'aws/ses'
require 'dkim'

ses = AWS::SES::Base.new(
	:access_key_id => 'key',
	:secret_access_key => 'secret'
)

Dkim::domain            = 'co-meeting.com'
Dkim::selector          = 'ses'
Dkim::private_key       = open("ses.key.pem").read

# Don't sign certain headers.
# See: http://docs.amazonwebservices.com/ses/latest/DeveloperGuide/DKIM.html
Dkim::signable_headers  = Dkim::DefaultHeaders - %w{Message-Id Resent-Message-ID Date Return-Path Bounces-To}

mail = <<eos
To: reciever@co-meeting.com
From: info@co-meeting.com
Subject: SES Test

It is #{Time.now.strftime("%Y-%m-%d %H:%M:%S")} now.
eos

mail_signed = Dkim.sign(mail)

ses.send_raw_email(mail_signed)

6. 実行すると以下のようなメールが届きます


via email-bounces.amazonses.comが表示されなくなっており、signed-byにco-meeting.comが追加されています。
さらにメールのソースを見ると、「Authentication-Results」に「dkim=pass」と書かれていると思います。これで正しく署名がついていることがわかります。
よかったよかった。


順番おかしいですけど、この後、

  • Herokuでメール送信する方法の比較
  • Amazon SESの使い方
  • HerokuからAmazon SESを使う方法

とか書いてみようかなと思っています。


追記 2011/11/25 15:48
やっぱりv=DKIM1は大文字みたいです。DNSのキャッシュでちょっと古いのがうまく動いてたようです。修正しました。