sendmailを使うとアフリカがさらに遠くなる闇への防衛術

## 井の中の蛙(海外経験なし)、アフリカがらみの仕事でテンパるの巻

みなさんはアフリカ行ったことがございますでしょうか。私がアフリカはおろか、日本国内から海外に行ったことがありません。そんな、**井の中の蛙にアフリカがらみの仕事が来てテンパった闇のお話です。**

※sendmail詳しくないので、もし間違っていたら指摘ください💦
※数字は適当にぼかしています
※18年前のことなので、今はだいぶ事情が違うはずです。はず……

# 何が起きたか

18年前あるお仕事があり
- ふじた🐱が書いたバッチ処理で
- インターネットメールを
- NGOと交流している海外現地のみなさんに
- 日本国内のお客様が用意したサーバーから
- SMTPで送る

ということがありました。こういう構成です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314396/ef1ffecb-4a8b-aa62-98a8-160f88a36951.png)

sendmail-(SMTP)→インターネットは並列処理になっているので、バッチ処理は送信対象に対して並列処理不要と考えていました。バッチ処理-(SMTP)→sendmail は同じセグメントなんだし、0.5秒くらいで1通渡せる。1時間あれば~~18,000~~ (訂正)7,200通をお客様のsendmailに渡す。そこから海外あて送信だから多少の遅延があるだろうけど、並列処理の恩恵を受けるだろう、と。

お客様がたててあるsendmailに中継許可を依頼し、結合試験・総合試験を実施したのち、さて本番の送信を迎えました。

## アフリカは遠いのだろうが、予想より遠い。しかも国内の通信ですでに遅い❓❓❓

バッチが動いて、NGOと交流している海外現地のみなさんにメールを送りました。バッチは地域別に実行します。

1000件送ったときの処理時間を表にするとこうでした。

| 宛先地域 | バッチ処理に要する時間 | sendmailが95%送り終わるまでの時間 |
|:-:|:-:|:-:|
| 東アジア、東南アジア | 600秒 | 1100秒 |
| 南アジア、西アジア | 500秒 | 600秒 |
| ヨーロッパ・CIS | 600秒 | 700秒 |
| 北アメリカ | 400秒 | 500秒 |
| 南アメリカ | 600秒 | 600秒 |
| オセアニア | 500秒 | 500秒 |
| アフリカ | **3000秒** | 3500秒 |

お客様とふじた🐱で「（アフリカの3500秒を指さして）アフリカは回線不安定で、1000通送るのに1時間強もかかるんだね～」と話し、そうだねこれは予想の範囲と思い、「バッチ処理に要する時間」を見るとおかしい。アフリカだけ、バッチ処理が異様に時間かかっています。
予想していなかったことに、宛先の地域によって、sendmail側ではなく、バッチ処理の処理速度が大きく異なるのです。

アフリカあてのメール送信で時間を要している要因のかなりは、国内データセンターの隣のラックと隣のラックの通信なのです。なぜ、アフリカだけ バッチ処理→sendmail で時間がかかるのか、謎でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314396/70beb1d2-6f0c-e618-2d4c-3b1715765b34.png)

# その sendmail はメールを受けつけてキューに入れるときに宛先を名前解決してた

手をこまねいていても仕方ないので、再度、同じ宛先にバッチ処理でメールを送るとき
- sendmailでパケットキャプチャ取得（お客様と一緒に）
- バッチ処理のスレッドダンプ取得

を行いました。

すると、お客様の sendmail 、メールをSMTPで受け取る＝キューに入れるときに、宛先ドメインを名前解決していました。ここで時間を要しています。



SMTP は大雑把にはこんな感じで通信を行いますが、この「RCPT TO:<alice@foo.com>」でバッチ処理が宛先をsendmailへ通信したとき、sendmailが foo.com を名前解決しているのです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314396/2d527153-e69e-c5a7-75db-a1efe5c3c3bb.png)

https://ja.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol より

### 名前解決のどこが遅い？→現地にある DNSサーバー が遅い

アフリカは国が沢山あり、見たことない ccTLD が送信先に多数ありました。

<table>
        <thead>
            <tr>
                <th>国名</th>
                <th>ccTLD</th>
            </tr>
        </thead>
        <tbody>
            <tr><td>アルジェリア</td><td>.dz</td></tr>
            <tr><td>アンゴラ</td><td>.ao</td></tr>
            <tr><td>ベナン</td><td>.bj</td></tr>
            <tr><td>ボツワナ</td><td>.bw</td></tr>
            <tr><td>ブルキナファソ</td><td>.bf</td></tr>
            <tr><td>（以下略）</td><td>計53個ある</td></tr>
        </tbody>
</table>

いま、手元で「アルジェリア」の大学を調べると、[Algiers 1 University (univ-alger.dz)](http://www.univ-alger.dz/) というものがありました。例えば、このメールの宛先であるサーバー(MXレコードを調べるには)

1. ルートサーバーに .dz のネームサーバーを尋ねる
1. .dz のネームサーバーに univ-alger.dz のネームサーバーを尋ねる
1. univ-alger.dz のネームサーバーにMXレコードを尋ねる

という順序を経ます。
※DNSSECとか18年前なので忘れて💦

上の「ルートサーバー」は欧米や日本・アジアなど応答が速いところにあるのですが、「.dz のネームサーバー」「univ-alger.dz のネームサーバー」の応答が遅い。「サーバーはどこにあるの？」と調べると
- **「.dz のネームサーバー」などアフリカ各国のccTLDのDNS権威サーバー → アフリカ現地にあり遅い**
- **「univ-alger.dz のネームサーバー」などアフリカ各国のccTLD配下のドメインDNS権威サーバー → アフリカ現地にあり遅い**
- 「univ-alger.dz のメールサーバー」などアフリカ各国のccTLD配下のドメインのメールサーバー → 欧米圏のVPSが多く、SMTPでの通信は速い 

という傾向がつかめました。

- お客様の立てた sendmail が
- バッチ処理からのSMTPを受けるとき（国内同DC内通信）
- 宛先ドメインのアフリカccTLD以下の名前解決を行い（対アフリカ通信）
- 異様に時間がかかる

こういうことです。起きていることは分かりましたが、不思議なことがあります。「なぜ sendmail は受け取るときに名前解決するんだ？」
※ postfix ではこういうことよっぽど変な設定を書かないと起きません。

メールサーバーのキューに限りませんが、処理をキューを挟んで構成するのは、キューに入れた（キューイング）タスク（この例ならメール送信）が、重たかったり、時間がバラバラだからですよね。
アプリケーションの生成結果をキューイングして、また別の処理（だいたい並列処理とか得意なもの）がキューからとって処理する。そういうものなのに、**キューイングで名前解決して時間を要されては、キューを挟む意味が減ってしまいます。**

### sendmail の canonify,nocanonify 

正直 sendmail には詳しくないのですが、nocanonify という設定項目が sendmail にはあります。

[cf/README for sendmail 8.12.3](https://www.sendmail.org/~ca/email/doc8.12/cf/m4/features.html#nocanonify)

sendmailの既定の動作は foo@bar という宛先を foo@bar.example.com と完全修飾、正規化し処理するのですが、nocanonify を指定すると、それをしない。既定の動作では、**メールアドレスのドメインを完全修飾、正規化するときに名前解決を行う** とあります。
たしかに、メールサーバーが自ホストあてのメールか、中継してどこかに送るメールか判断するとき、宛先を完全修飾したい気持ちは分かります。postfix だと mydomain という設定値で宛先を完全修飾するとき名前解決しないのですが、sendmail は完全修飾するとき名前解決しますよ、と。

# そうして(18年前)新たな闇が生まれてふじた🐱が死んだ

- バッチ処理からのメール送信で
- sendmailのキューを挟んだのに
- キューイングで名前解決して
- 名前解決先のアフリカに ccTLD や 配下のドメイン の応答が遅い
- ゆえ、バッチ処理が予定より時間かかる

まとめるとこうです。

# たぶん、いまはもうこんなことないはず

**これ18年前のことなのでさすがにもうこんなことはないと思います。** あと、メールを送信するサービスを使ったり、メールサーバーをなにがしかの事情で立てるときもまずは postfix を使えばいいのだと思います。

そうそう、sendmail とても取っつきにくい、というか私もなるべく触りません。だって、大変なんですもの。あるところから、sendmail の第4版(日本語未翻訳) の画像を持ってきましたが、火曜サスペンス劇場で凶器にできるような重さです。

![89_p_1767455_0.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314396/2a0b3e70-36bb-40af-55c4-61b2ab493a60.jpeg)



**sendmail の第3版は、上巻下巻で**
[sendmail 第3版 VOLUME 1](https://www.oreilly.co.jp/books/4873111765/)
[sendmail 第3版 VOLUME 2](https://www.oreilly.co.jp/books/4873111803/)
と 808ページ＋628ページ、 **計1,436ページ です。** ふじた🐱はこの闇に触れた後、全然分からん……という顔をしながら、新宿の紀伊国屋書店に吸い込まれ、気が付くとこの2冊を買い「くそ重い……」としかめっ面しながら会社に持ち帰った記憶があります。**完全なインターネット老人会ですね**

### で、防衛術は？

- 昨今、メールサーバーを立てるのは難しい。メールを送信するサービスを使おう。
- もしメールサーバーを立てるとき、経験がないのなら間違っても sendmail は使うな。・

の2点です。

# おわりに

ここまで、ご高覧ありがとうございました。何かご指摘やご存知のことありましたら、何かコメントいただけると嬉しいです。

今年は別のアドベントカレンダーでこんなのも書いてます。良ろしければお立ち寄りください。

https://qiita.com/nfujita55a/items/770054874086bd86f0ea

https://qiita.com/nfujita55a/items/49eda31786516ffd1ea9