sendmailで送信したメールが迷惑メールフォルダに入ってしまうときの対応

最近は、SendGridなどのメール配信サービスを使うことが多くなり、
自前でのメールサーバやsendmailを利用したメール送信は少なくなっているかもしれませんが、
先日別件でメール配信周りで対応が必要だったのでその時の備忘録を！

# メールが届かない、迷惑メールフォルダに入ってしまう

とある案件のお手伝いをしている際に、Amazon LinuxのサーバからPHPで処理した結果をmb_send_mail()を使ってメールを飛ばす処理が組み込まれていました。

配信先は、Yahoo!やGmailなどのフリーメールアドレスだけでなく、
docomo,au,souftbankといったキャリアのメールアドレスに対しても送信されていたのですが、
フリーメールアドレスだと「迷惑メールフォルダに必ず入ってしまう」
キャリアメールだと「そもそも届かない」
という問題が発生しており、なんとか届くように修正したいとの要望を受け調査することにしました。

# なぜ迷惑メールに入ってしまうのか

私自身もメール配信についてはそこまで詳しくないので、
まずはネットで調べて調査することにし、
下記の記事などはとても分かりやすい内容だなと感じました。

- [迷惑メール判定されないための善き送信プラクティス](https://sendgrid.kke.co.jp/blog/?p=4698)


なお、フリーメールアドレスの場合は、迷惑フォルダに入ってしまったとしても
ユーザの操作で「非迷惑メールとして報告」などを行えば、
次回以降の受信では正常に受信BOXに入ってくれることも多いですが、
キャリアメールにはそもそも届かない（キャリア側で迷惑メールとして判断して飛ばさないようになっていそう）のは流石に困ってしまうので、更に調査を進めることに...

# 中継や受信メールサーバーの制限を確認

下記の記事が非常に分かりやすかったのでまずは読んでみることをおすすめします！

- [Amazon EC2 Eメール送信ベストプラクティス](https://dev.classmethod.jp/cloud/aws/ec2-send-email-best-practice/)


送信元のIPアドレスがブラックリスト登録されてしまっている場合は、AWSに申請して対応を行わないといけないですが、今回の案件ではブラックリストには登録されておりませんでした。
そのため下記2点に注目して対応を行いました。


## 「SPF」(SPF(Sender Policy Framework)/Sender ID)

> 「このIPアドレスからのメールは正当です！」ということを示す専用のDNSレコードを、DNSサーバーに登録する手法です。受信メールサーバーはDNSサーバーにSPFレコードを問い合わせ、レコードに記載された送信メールサーバーのIPアドレスとメールヘッダにあるIPアドレスが異なる場合、メールを破棄することがあります。
> (引用元: https://dev.classmethod.jp/cloud/aws/ec2-send-email-best-practice/ )

送信しているメールアドレスのドメインが、DNSサーバにSPFレコードとして登録されているかを確認し、
登録されたIPアドレスの場合は問題なし、別のIPアドレスからの場合はなりすましかもと判断され迷惑メールフォルダに入ってしまうことがあります。


今回は送信元が1台だけだったので、DNSの設定で下記のように指定して登録しました。

```
"v=spf1 ip4:IPアドレス -all"
```

AWSのRoute53を利用している場合は下記のようにすれば良さそうです！

<img width="406" alt="DNSの設定.png" src="https://qiita-image-store.s3.amazonaws.com/0/17346/ddbf6f0f-338f-0dbc-0b49-0c3d9f6d9767.png">

（ドメインは送信したいメールアドレスの@より右側なので、例えば「no-reply@sample.co.jp」でメールを送信したい場合は、「sample.co.jp」で設定する必要があります）
（ドメインを持っていない方は、まずはお名前.comなどで独自ドメインを取得されることをおすすめします）



- 参考
   - [Amazon EC2 Eメール送信ベストプラクティス](https://dev.classmethod.jp/cloud/aws/ec2-send-email-best-practice/)
   - [SPF（Sender Policy Framework） : 迷惑メール対策委員会](http://salt.iajapan.org/wpmu/anti_spam/admin/tech/explanation/spf/)



## 「DNSレコードの整合性」

> 「正規の送信メールサーバーであれば、真っ当なDNS設定になっているだろう」という仮定で、受信メールサーバーがDNSサーバーに問合せを行います。送信メールサーバーのホスト名とIPアドレスを対応づけるDNSの正引き(A)レコードと逆引き(PTR)レコードの内容が合致しないと、メールを破棄することがあります。
> (引用元: https://dev.classmethod.jp/cloud/aws/ec2-send-email-best-practice/ )

地味にハマったポイントでもあったのですが、**「送信メールサーバーのホスト名とIPアドレスを対応づける」**必要があるようです。

メールサーバのホスト名は

```
hostname
```

などのコマンドを実行すると確認できるかと思います。
このホスト名を先程SPFで登録したドメインと同様のものに設定している方が良さそうです。（※ 別に必要ないかもしれないですが...）

下記の記事などが参考になるかと思います。

- 参考
   - [AmazonLinuxのホスト名を変更するには](https://qiita.com/Ksaka9821/items/8cfdc9a174ba2b7b19a1)
   - [CentOS 6 でホスト名を確認・変更する手順](https://weblabo.oscasierra.net/hostname-centos6/)


### sendmailの設定

なにも設定を行っていないデフォルトの状態の場合、Fromのメールアドレスを指定して送信したとしても
到着したメールアドレスは、「no-reply@localhost.localdomain」などのように、
ドメイン名が**localhost.localdomain**になってしまいます。

これは、sendmailの設定(/etc/mail/sendmail.mc)を修正する必要があります。

念のためバックアップを取得

```
$ sudo su
$ cp /etc/mail/sendmail.mc /etc/mail/sendmail.mc.org
```

該当箇所を修正

```/etc/mail/sendmail.mc
## dnl MASQUERADE_AS(`mydomain.com')dnl のdnlを削除し、SPFで登録したドメインに設定する
MASQUERADE_AS(`sample.co.jp')dnl

## dnl FEATURE(masquerade_envelope)dnl のdnlを削除
FEATURE(masquerade_envelope)dnl

## それぞれ先頭のdnlを削除し、MASQUERADE_ASへ変換するドメインのリストを書き出す
MASQUERADE_DOMAIN(localhost)dnl
MASQUERADE_DOMAIN(localhost.localdomain)dnl
```

編集後、m4コマンドを利用してsendmail.mcをsendmail.cfに変換する必要がある。

```
$ m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
```

もしm4のコマンドが入っていない場合には下記でインストール可能

```
$ yum install sendmail-cf
```

作成が完了すればsendmalを再起動してメールを送信すればOK

```
$ /etc/init.d/sendmail restart
```

- 参考
   - [sendmailで送信元のドメイン名(デフォルトはlocalhost.localdomain)を変更する](http://d.hatena.ne.jp/rx7/20081121/p3)


上記のような対応をいれることで、これまで迷惑メールフォルダに入っていたメールが正常にBOXに入るようになりました！！！

# ヘッダー情報を比べる

念のため迷惑メールフォルダに入ったメールと正常なBOXに入ったメールのヘッダー情報を確認してみましょう。

Gmailを利用している場合、各メールの右端にある下矢印を押し「メッセージのソースの表示」を押すと確認することが出来ます。


## 迷惑メールに入っていたヘッダー情報

```
Return-Path: <apache@localhost.localdomain>
Received: from sample.co.jp (xxxxxxxxxxxxxxx])
        by mx.google.com with ESMTPS id YYYYYYYYYYYYYYYYY
        for <送信先のメールアドレス>
Received-SPF: neutral (google.com: 送信元IPアドレス is neither permitted nor denied by best guess record for domain of apache@localhost.localdomain) client-ip=送信元IPアドレス;
```

## 正常に受信BOXに入っていたメールのヘッダー情報

 「SPF」と「DNSレコードの整合性」の対応後のヘッダー情報

```
Return-Path: <apache@sample.co.jp>
Received: from sample.co.jp (xxxxxxxxxxxxxxx])
        by mx.google.com with ESMTPS id YYYYYYYYYYYYYYYYY
        for <送信先のメールアドレス>
Received-SPF: pass (google.com: domain of apache@sample.co.jp designates 送信元IPアドレス as permitted sender) client-ip=送信元IPアドレス;
```


見比べると**「Return-Path」**が意図したものになっているのと、
**「Received-SPF」**がneutralではなくpassになっているかと思います。

「pass」は認証が成功しており、「neutral」はSPFレコードが送信サーバーとマッチはしていないことを表しており迷惑メールフォルダに入りやすい状態を示しています。
実際には、「Received-SPF」が「neutral」の時は迷惑メールフォルダに分類されていましたが、「pass」になった途端受信BOXに正常に分類されるようになりました。


- 参考
   - [SPF（Sender Policy Framework） : 迷惑メール対策委員会](http://salt.iajapan.org/wpmu/anti_spam/admin/tech/explanation/spf/)
   - [TXTレコードが正しく登録できていないのでSPF認証が失敗で迷惑メールになっちゃうよ](http://ashyktj.hatenablog.com/entry/2015/04/17/TXT%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%8C%E6%AD%A3%E3%81%97%E3%81%8F%E7%99%BB%E9%8C%B2%E3%81%A7%E3%81%8D%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%81%AE%E3%81%A7SPF%E8%AA%8D%E8%A8%BC%E3%81%8C)


# まとめ

sendmailでメール送信する際には、**「SPFの設定」**と**「DNSレコードの整合性」**については忘れずに対応を！！