Help us understand the problem. What is going on with this article?

迷惑メールにならないためのエンジニアにできる最大限の対応。php mb_send_mailからSPFとDKIMとDMARC

CentOS7 nginx postfix phpという環境でWebからメール送信する仕組みを構築

環境は、
CentOS7 nginx postfix php7 opendkim といったところです。Amazon Linux 2でも同じやり方でできました。

SendGridのブログに、世の中の主要なメールサーバーの受信するメールの95%は迷惑メールだというデータがあるようです。正しい設定をしていても、誤って迷惑メールに判断されないように、最大限の対応はしておきたいですね。

ここではエンジニアとしての最大限のできることをまとめています。それでも迷惑メールになる場合は、メールの文章に問題があると思ってください。

総務省が出しているメールの文章の書き方についてもあります。
http://www.soumu.go.jp/main_sosiki/joho_tsusin/d_syohi/pdf/m_mail_081114_1.pdf
以下抜粋。
FireShot Capture 27 -  - http___www.soumu.go.jp_main_sosiki_joho_tsusin_d_syohi_pdf_m_mail_081114.png

ちなみに、受信側が迷惑メールとして判断する方法として
迷惑メール相談センターにEメールヘッダ情報の確認方法があります。
https://www.dekyo.or.jp/soudan/contents/ihan/header.html

ということは、この対策は最低限しておかないとメールサーバーは迷惑メールとして判定されやすいと思ったらいいですね。

では、以下、サーバーの設定からメールヘッダの書き方まで説明します。

pstfix null client

送信するだけのメールサーバーのことをnull clientといいます。

こちらの方の設定でばっちりです!

NullクライアントのPostfix環境の作成(Qiita)

SPF

Sender Policy Framework(SPF)は、SMTPを利用したインターネット電子メールの送受信において送信者のドメインの偽称を防ぎ、正当性を検証する仕組みのひとつとして元Pobox社のMeng Wong氏により提唱された送信ドメイン認証方式である。(迷惑メール対策委員会より)

SPFはDNSに設定するものである。正しい設定方法は各DNSプロバイダに聞くのもよいし、検索してみましょうね。
参考

dns
example.jp.  IN SPF "v=spf1 ip4:192.0.2.1 -all"

192.0.2.1は、Web Serverからメール送信の仕組みを入れる場合は、そのWeb ServerのIPアドレスに書き換えてください。

DKIM

DKIM (Domainkeys Identified Mail) : 迷惑メール対策委員会

これは、証明書を作成してそれをDNSに登録します。メールを送信するWeb ServerとDNS間でDNSが言っていることは正しいということを証明するためのものです。

opendkim インストール

opendkimはepel repoにあります。

#(root)
yum -y install epel-release

yum info opendkim
yum -y install opendkim

暗号化キー保存用ディレクトリの作成

複数ドメイン運用を考慮してドメイン毎に暗号化キーの保存ディレクトリを作成します。

mkdir /etc/opendkim/keys/sample.com

暗号化キーの作成

[opendkim-genkey]
http://www.opendkim.org/opendkim-genkey.8.html

/usr/sbin/opendkim-genkey -D /etc/opendkim/keys/sample.com/ -d sample.com -s default

Ownerの変更

Ownerを変更します。またdefault.privateが秘密鍵、default.txtがDNSに設定する公開鍵になります。

chown -R opendkim:opendkim /etc/opendkim/keys
ls -l /etc/opendkim/keys/sample.com/
-rw------- 1 opendkim opendkim 887 May  8 16:25 default.private
-rw------- 1 opendkim opendkim 317 May  8 16:25 default.txt

opendkim.confの設定

/etc/opendkim.confShell

/etc/opendkim.conf
vi /etc/opendkim.conf

Mode sv
#KeyFile /etc/opendkim/keys/default.private
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
InternalHosts refile:/etc/opendkim/TrustedHosts

Socket  inet:8891@localhost # ここほ確認だけ。localhostで8891ポートで動作することを確認。

KeyTableの設定

複数ドメイン運用の場合にはこのファイル/etc/opendkim/KeyTableに暗号化キー情報を追加していきます。

/etc/opendkim/KeyTable

/etc/opendkim/KeyTable
vi /etc/opendkim/KeyTable

default._domainkey.sample.com sample.com:default:/etc/opendkim/keys/sample.com/default.private

TrustedHostsの設定

/etc/opendkim/TrustedHosts

/etc/opendkim/TrustedHosts
vi /etc/opendkim/TrustedHosts

127.0.0.1
::1
smtp.sample.com

SigningTableの設定

署名するドメイン情報を/etc/opendkim/SigningTableに追加します。

/etc/opendkim/SigningTableShell

/etc/opendkim/SigningTable
vi /etc/opendkim/SigningTable

*@sample.com default._domainkey.sample.com

DNSの設定

公開鍵をDNSのzoneファイルに設定します。当然外部からの問い合わせに応答するためにインターネット公開用Zoneファイルに/etc/opendkim/keys/sample.com/default.txtの内容をそのままコピーします。またキーとは別にDKIMポリシーも追記します。
「"」から「”」までをTXTに。「”」も含めて。
2レコード追加ですよ

default._domainkey      IN      TXT     ( "v=DKIM1; k=rsa; "
          "p=MIGf............................" )  ; ----- DKIM key default for sample.com

_adsp._domainkey.sample.com IN TXT "dkim=unknown"

postfixの設定

postfixにopendkimを使用するように設定追加します。
milterとは、postfixの Mail Filterという意味。opendkimの動作しているIP:portを指定する。

/etc/postfix/main.cf
vi /etc/postfix/main.cf

smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters
milter_default_action = accept

opendkimの有効、起動

systemctl enable opendkim
systemctl start opendkim
systemctl status opendkim

postfixのreload

systemctl reload postfix
or 
postfix reload

DMARC設定

DNSにTXTレコードを追加です。最小設定

_dmarc.sample.com TXT  "v=DMARC1; p=none;"

php側の設定

php mb_send_mail関数でメール送信する際の注意点

php.iniの設定がJapaneseとUTF-8になっているか確認する

php.ini
[mbstring]
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8

もし、変更できないならメール送信処理前に以下を書いてもOK

mb_language("ja");
mb_internal_encoding("UTF-8");

mb_send_mailは、第5引数が大事らしい。
ここに

-ffrom@sapmle.com

という-fからスペースなしでfromメールアドレスを記述するパラメータを付与する必要がある。
ここではちょっとややこしいけど、from@sample.comからメールを送っているとする。
これは、メールエンベローブであり、メールヘッダーのReturn-Pathで指定されるものとは別。
メールヘッダーで指定するFromやReturn-PathとエンベローブのReturn-Pathが異なることで迷惑メールに分類される可能性があるとの記事もあったので設定しておくとよいです。

※メールのエンベロープとメールのヘッダーの2か所にReturn-Pathがあることを知っておくこと。

-fを指定しないとウェブサーバーのメールアドレスになる
Return-Path: <nginx@sample.com>
mb_send_mail
$param = "-ffrom@sample.com;
// 送信者情報の設定
$headers = '';
$headers .= "Content-Type: text/plain \r\n"; // HTML メールなら text/htmlで
$headers .= "Return-Path: from@sample.com \r\n";
$headers .= "From: " . mb_encode_mimeheader($name) . " " . "<from@sample.com> \r\n";
$headers .= "Sender: " . mb_encode_mimeheader($name) . " " . "<to@sample.net> \r\n";
$headers .= "Reply-To: from@sample.com \r\n";
$headers .= "Organization: " . mb_encode_mimeheader($name) . " \r\n";
$headers .= "Precedence: bulk \r\n"; // 大量メール送信時にはあったほうがよい
$headers .= "X-Sender: from@sample.com \r\n";
$headers .= "X-Priority: 3 \r\n";

// 送信先
$to = "to@sample.net";

//
$body = "本文書いて下しされ";

// メール送信します。
mb_send_mail($to, $subject, $body, $headers, $param);

同じメールをたくさんの人に送るときは、とりあえず、bulkメールですよって教えてあげると、安全かも。
似たようなメールをたくさんの人に送るわけだし、宛先違っても似たようなメールを複数受け付けると怪しまれれる=迷惑ーメールに思われる可能性もありそうなので、HeaderにPrecedence: bulkを追加してあげるとよいです。
もひとつついでに、X-Priority: 3くらいで。普通のメールですよと。ここまで設定して迷惑メールに入るとするならば、文章中に、外部(他ドメイン)リンクたくさんあったり、あやしいスクリプトが埋め込まれてたり、いろんなひとが迷惑メールとして報告してたりする可能性しかないのかなと。

主要なメールサーバーは、95%が迷惑メール扱いするという昨今なので、5%のメールを目指すためすくなくとも上記の対策はやっておきたいところですね。

Precedence: bulk
f_uto
株式会社クオリアシステムズのCTO&COOをしております。 新体制になりまして、エンジニア毎月1名程度募集してます。SESのような責任のない契約形態は基本NGです。お仕事は責任持って業務委託、請負で行いますし、行っていただきたい。 ※SES業界に疲れたエンジニアの方はぜひ、声かけてください。
http://staff.qualias.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした