2011/08/31

SendmailからSendGridへリレーする4つの方法

SendGridの紹介SendGridを使ってテストメールを送った話の続きです。SendGridにSMTPでメールをリレーするには、SMTP認証が必須です。なので毎回opensslで認証用文字列を作るのは面倒ですし、Mail.appやOutlook Express, ThunderbirdなどのMUAから[送信]ボタンを押して送るのは、機械的にメール送信する上では非現実的です。

という事で、通常メールをリレーする場合はMTAを使います。PerlのNet::SMTPやEmail::Senderを使って送るのもよいですが、ここではSendmailに渡したメールをSendGridにリレーする話を書きます。Twitterのタイムラインでは毎日誰かがSendmailを罵倒してますが、僕はSendmailが好きなのでSendmailでやります。

MTAからのリレーが役立つケース

結論から先に書くと、自前のMTAからどうしても送信できない(SMTP接続が拒否されるなど)場合や遅延した場合のバックアップ用MTAとして、SendGridのような配信ASPにリレーするとよいって話です。

Webサイトを運営している場合、メールマガジンをやっていなくても、ユーザ登録のメールを送るなど大量ではないメール送信は少なからず在るでしょう。多くの場合はWebサイトが動いているサーバ自身からメールを発信したり、別に立てたメールサーバにリレーして送信します。

ユーザがWebサイトに登録するメールアドレスはちゃんと正当なものであるかどうかをチェックする、一度でもバウンスした(宛先不明)アドレスには二度と送らないのは当然として、メール送信でどうしても送れないケースというのも存在します。

メールが送信できないケース

  • 自分のMTAに逆引きがない&&逆引き設定できないのでAOLから拒否される
  • 自分のMTAに割り当てられたIPアドレスが相手側のブラックリストに載ってる
  • いつも遅延するメールは決まっていて配信の最後まで遅延してしまう

ブラックリストに載っているという状況は、自分がスパムまたはそれに類する行為を行っていたのであれば自業自得です。

しかし、過去にそのIPアドレスからスパムが発信されていた、大量に発生するバウンスを放置していた、近隣のIPアドレスがブロックされる巻き添えで自分もブロックされている、などの理由で特定の相手から接続を拒否されるというケースがたまーにあります。

同じ理由でSpamhausなどのDNSベースのブラックリストに載っている事もあります。

予備・バックアップ・FallbackとしてもSendGrid

IPアドレスを変更する事やブラックリストの解除を相手にお願いする事が困難である場合、その相手に送る時に限り別のMTAからメールを送る必要があります。そこで自前のMTAからSendGridを経由して送信するという手段が浮上します。

0. authinfo: SMTP認証の事前準備

0.1 sendmail.cf

SendGridへリレーするにはSMTP認証が必要です。Sendmailが自動的にSMTP認証を経由してリレーできるようにauthinfoを有効にしたsendmail.cfを作ります。元になるsendmail.mcはLinuxでパッケージから入れた場合は/usr/share/sendmail-cf/cfの中に、ソースビルドした場合はsendmail-8.14.5/cf/cfで見つかるでしょう。

FEATURE(`authinfo')
sendmail.mcに上記のFEATUREを書いて、sendmail.cfをmakeして、/etc/mail/sendmail.cfとしてインストールするとよいです。/etc/mail/sendmail.cfを上書きする前にバックアップを忘れずに。
# cp /etc/mail/sendmail.cf /etc/mail/sendmail.`date '+%F'`.cf⏎
# cp ./sendmail.cf /etc/mail/sendmail.cf

0.2 /etc/mail/authinfo.db

次にSMTP認証用のユーザ名とパスワードを設定します。内容は/etc/mail/accessに書いてもよいのですが、SMTP認証のパスワードを生で書くので別ファイルに書いてパーミッションを厳しくしておいた方が合理的です。

# cd /etc/mail⏎
# vi ./authinfo
AuthInfo:smtp.sendgrid.net "U:SMTP認証のユーザ名" "P:パスワード" "M:PLAIN"
# makemap hash authinfo.db < authinfo⏎
# chown root ./authinfo*⏎
# chmod 0600 ./authinfo*⏎
# kill -HUP `head -1 /var/run/sendmail.pid`
/etc/mail/authinfoファイルを作って、makemapして、念のためauthinfoを組み込んだsendmail.cfがちゃ〜んと動くかの確認という事でsendmailを再起動しています。

RedHatな人なら/etc/rc.d/init.d/sendmail restartでもよいです。

1. define(`SMART_HOST',`smtp.sendgrid.net')

SendmailのSMART_HOSTを使います。

外部システム宛のメールは全てSMART_HOST(sendmail.cfではSマクロ)で指定したホストにリレーされますので、全てのメール送信をSendGridに任せるならSMART_HOSTを使うのがよいでしょう。

似たような機能にnullclientとMAIL_HUBがありますが、これらはローカルホスト宛のメール中継の動作が微妙に異なるので、SMART_HOSTを使います。

SMART_HOSTの設定は、sendmail.mcに下記のような定義をして、sendmail.cfを作るだけです。
define(`SMART_HOST',`smtp.sendgrid.net')

作り直したsendmail.cfは/etc/mail/sendmail.cfとしてコピーして、次のような感じでテストします。ここではメールサーバのホストはmx.example.jpとします。
%  sendmail -bv azuma@example.jp⏎
azuma@example.jp... deliverable: mailer local, user azuma
↑自分のホスト宛はそのままローカルのメールボックスに配信
% sendmail -bv az@example.com⏎
az@example.com... deliverable: mailer relay, host smtp.sendgrid.net, user az@example.com
↑外部ホスト宛はSMART_HOSTで定義したサーバにリレーされる

リレー先のホストにsmtp.sendgrid.netと表示されていればOKです。新しいsendmail.cfでSendmailを再起動して、テスト送信をして、ログを見て確認です。
# hostname | mail -s 'TEST' az@example.jp⏎
# tail /var/log/maillog⏎
Aug 31 19:30:05 nijo sm-mta[10162]: p812U5tl022457: to=, ctladdr= (0/0), delay=00:00:01, xdelay=00:00:01, mailer=relay, pri=120498, relay=smtp.sendgrid.net. [174.36.32.204], dsn=2.0.0, stat=Sent (Delivery in progress)

2. mailertable

特定のホスト・ドメイン宛のメールだけをSendGridへリレーするのであればmailertableが最適です。sendmail.cfにmailertableを組み込んでいない場合は、下記の定義をsendmail.mcに書いてsendmail.cfを作り直します。
FEATURE(`mailertable',`hash -o /etc/mail/mailertable')dnl
宛先ドメインとリレー先のDBマップとなるファイル/etc/mail/mailertableを次のような内容で作ります。ここではGmail,AOL,BIGLOBE宛は全てSendGridにリレーする事にします。
gmail.com          relay:smtp.sendgrid.net
aol.com            relay:smtp.sendgrid.net
.biglobe.ne.jp     relay:smtp.sendgrid.net
mailertableはSMTPのルーティングテーブルとして動作するので、上記のような内容を書くと、****@gmail.com, ****@aol.com, ****@***.biglobe.ne.jp宛のメールだけSendGridにリレーされます。
# makemap hash mailertable.db < mailertable⏎
# kill -HUP `head -1 /var/run/sendmail.pid`
配送テストは「sendmail -bv メールアドレス」で確認するとよいでしょう。ちなみにmailertableは前述のSMART_HOSTよりも先に処理されるので、SMART_HOSTに何か定義してある状態でもmailertableの定義が優先して処理されます。

3. FallbackMXhost

FallbackMXhostは、宛先メールサーバに接続できなかった場合に接続を試みるホストを定義するものです。これは相手側メールサーバから拒否された場合、FallbackMXhostに定義したホストにメールをリレーして、そのホストから送信を試みるという使い方が出来ます。

ここではsmtp.sendgrid.netをFallbackMXhostに設定してみます。
define(`confFALLBACK_MX',`smtp.sendgrid.net')
いざという時の浮輪

上記のような定義を追加したsendmail.mcからsendmail.cfを作ってSendmailを再起動します。こうする事によって最初は直接相手側のMXになっているサーバに接続し、送信できなかった場合はSendGridにリレーして、SendGridのサーバから配送が行われます。 

FallbackMXhostはその名の通り、複数台のメールサーバでFallbackMXhostを多段構成になるように設定しておくと、かなり遅延が減少します。

4. 独自メーラの定義: 587番ポートへの中継

これまで書いてきた方法はどれもsmtp.sendgrid.netの25番ポートへリレーするものでした。しかし、何故かメールサーバがOP25Bの影響下にあるなんて場合は、SendGridの587番ポート(Submission)にリレーするとよいでしょう。

4.1 sendgrid587.m4

25番ポート以外にリレーするには、下記のようなSendGridへリレーする専用のメーラーを定義したsendgrid587.m4というファイルを作ります。 ディレクトリは、Sendmailをソースからビルドした人はsendmail-8.14.5/cf/mailer, Linuxのパッケージでいれた人は/usr/share/sendmail-cf/cf/mailer です。
# cd /usr/local/src/sendmail-8.14.5/cf/mailer⏎
# vi ./sendgrid587.m4


中身はrelayメーラーを少し変えただけのものです。sendgrid587.m4の中身を直接sendmail.mcに書いてもOKですが、別ファイルに描いてsendmail.mcから呼び出した方が合理的です。

4.2 sendmail.mc

続いてsendmail.mcに下記の様な記述をしてsendgrid587.m4を読込ませます。
define(`SMART_HOST',`sendgrid587:smtp.sendgrid.net')
mailer(`sendgrid587')
外部宛メールを全てSendGridの587番ポートにリレーするなら一行目のSMART_HOSTをメーラーの指定つきで書きます。特定の宛先だけSendGridの587番ポートにリレーするなら、一行目のSMART_HOSTは書かずに後述のmailertableを使います。 そして、これまでと同じく、sendmail.cfを作り直して、Sendmailを再起動します。

4.3 mailertable

SMART_HOSTを使わず、特定の宛先だけSendGridにリレーするなら、下記のような内容をmailertableに書いてmakemapするとよいでしょう。
gmail.com          sendgrid587:smtp.sendgrid.net
aol.com            sendgrid587:smtp.sendgrid.net
.dti.ne.jp         sendgrid587:smtp.sendgrid.net

4.4 ログの確認

SMART_HOSTでもmailertableでも、sendgrid587メーラーでSendGridの587番にリレーできたら次のようなログが確認できます。
# tail /var/log/maillog⏎
Aug 31 20:00:01 nijo sm-mta[10730]: p81301Xg022951: to=<*****@mars.dti.ne.jp>, ctladdr= (0/0), delay=00:00:00, xdelay=00:00:00, mailer=sendgrid587, pri=120531, relay=smtp.sendgrid.net. [174.36.32.204], dsn=2.0.0, stat=Sent (Delivery in progress)

まとめ

SendGridのアフィリエイト(僕)と
新規ユーザの割引リンク
SendGridを使ったリレー方法を四つ紹介しましたが、SendGridに限らずどのようなメールサーバでも使える方法です。配信量が多くなると調整が難しい携帯電話宛のメールだけ商用のリレーサーバを使いたいというケースなどで有用でしょう。

Sendmailの運用については、Sendmailを深く知るなら二冊組のコウモリ本は書かせない物です。しかし日々の運用におけるよくある設定を行うのであれば、「sendmailクックブック」が薄くて使いやすい設定例集としてお薦めです。

No comments:

Post a Comment