mail-relay - UNIXからメールを送る際に、接続先SMTPサーバを指定したい
目的
以下の条件に合うように、
- 特定ドメインのアドレス(jp.example.com)宛のメールはサーバ1に送る。
- それ以外のメールはサーバ2に送る。
以下のメールサーバ(MTA)で、メール送信時のSMTP接続先を指定したい。
※なぜこの3つかというと、RHELが想定しているMTAがこの3つだから(参考: Product Documentation for Red Hat Enterprise Linux 8 - Red Hat Customer Portal; system-switch-mail コマンドで切り替え可能)。
結果
MTAの設定変更で実現できた。
MTA | 特定ドメインのアドレスの接続先 | それ以外のメールの接続先 |
---|---|---|
sendmail(FC使用) | mailertableファイルで設定 | sendmail.mcファイルのSMART_HOSTで設定 |
postfix | transportファイルで設定 | relayhostファイルで設定 |
exim | (未調査) | (未調査) |
注意:メールのFromかToどちらかが自社の有効なメールアドレスでないと、SMTPサーバがメールを無視してしまう場合があるので、気をつける。
これをlocalhostへの送信時に判別できるようにする方法も試みたが、うまくいかず断念。
以下、詳細。
背景と動機
例えば、社内の情報システムの設定が不思議なポリシーに従っていて、「社内LANからのDNSのMXレコードの問い合わせには、SMTPを受けつけないホストのIPアドレスを返す」という場合がある(なぜこういう設定なのか、意図がわからない…)。
この設定だと、社内の自分のメールアドレスへのメール送信すらできない。
具体的には、以下のような状況:
# MXレコードはとあるサーバを指している % dig gmail.com MX ... ;; ANSWER SECTION: gmail.com. 86223 IN MX 200 bluejays.examle.com. ... ;; ADDITIONAL SECTION: bluejays.example.com. 43200 IN A xxx.xxx.xxx.xxx ... # このサーバのSMTPポートにアクセスできない % telnet bluejays.example.com smtp Trying xxx.xxx.xxx.xxx... telnet: connect to address xxx.xxx.xxx.xxx: No route to host # pingも通らない(昨日は通ったような気がするが…) % ping -c1 xxx.xxx.xxx.xxx PING xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx) 56(84) bytes of data. ... 1 packets transmitted, 0 received, 100% packet loss, time 0ms
この状況でUNIXマシンからmail(1)やsendmail(8)ではメールを送信すると、コマンドは終了するので一見メールが送れたように思えるが、実際はlocalhostでキューイングしているだけ、相手にはいつまでたっても届かない。
実際にメールを送ってみる(失敗編)
今、yamada.taroh@jp.example.com に送ることにする。
以下は、sendmailの場合を記述(コマンドの使い方は、postfixでもeximでも同じ)。
mail(1)の場合:
% printf "Subject: test mail\nFrom: yamada.taroh@jp.example.com\nTo: you\n\n" | mail -v yamada.taroh@jp.example.com yamada.taroh@jp.example.com... Connecting to [127.0.0.1] via relay... ...
sendmail(8)の場合:
% printf "Subject: test mail\nFrom: me\nTo: you\n\n" | sendmail -v -f yamada.taroh@jp.example.com yamada.taroh@jp.example.com yamada.taroh@jp.example.com... Connecting to [127.0.0.1] via relay... ...
どちらも、一見成功したように見えるが、メールのキューを確認してみると:
# さっき送ったはずのメールが、localhostのキューにたまっている % sudo mailq m385ZkxJ027070 7 Tue Apr 8 14:35(Deferred: Connection timed out with smtp.example.com.) .... # 再送しても、失敗する % sudo sendmail -q -v Running /var/spool/mqueue/m386bs3I027745 (sequence 2 of 2) ... Connecting to bluejays.example.com. via relay... ... Deferred: Connection timed out with bluejays.example.com.
このままでは、メールは届かない。
設定方法
以下のサーバに繋ぎに行くように設定したい:
- jp.example.com宛のメールは 10.71.199.3 のIPアドレスに送る(社内メールの配送サーバ)
- それ以外のメールは、mail.jp.example.com に送る
(以降に具体的に設定を書いたが、http://www.networkworld.jp/server/-/23261.html を見た方が早いかもしれない)
sendmail の場合
RHELではCFが使われているので、その設定に従う。
- 特定ドメイン宛メールの設定
- /etc/mail/mailertbleに以下の行を追加する
jp.example.com smtp:[10.71.199.3]
※/etc/mail/sendmail.mc にて、access_db と mailertable のFEATURE が有効になっている(行が存在し、行頭にdnlが付いていない)ことを確認すること。
- それ以外のメールの設定
- /etc/mail/sendmail.mc の以下の行を編集
define(`SMART_HOST',`mail.jp.example.com')dnl
※もし行頭の "dnl"(m4のコメントマーク)が付いていたら削除する。
- 設定更新
- rootで以下を実行する
# cd /etc/mail # make
- デーモン再起動
- rootで実行
# /etc/init.d/sendmail restart
postfixの場合
jp.example.com smtp:[10.71.199.3]
※/etc/mail/sendmail.mc にて、access_db と mailertable のFEATURE が有効になっている(行が存在し、行頭にdnlが付いていない)ことを確認すること。
- それ以外のメールの設定
- /etc/postfix/main.cfに以下の行を追加する
relayhost = [mail.jp.example.com]
- 設定更新
- rootで実行
# cd /etc/postfix # postmap transport
- デーモン再起動
- rootで実行
# /etc/init.d/postfix restart
実際にメールを送ってみる(成功編)
今度は成功するはず。
mail(1)の場合:
% printf "Subject: test mail\nFrom: yamada.taroh@jp.example.com\nTo: you\n\n" | mail -v yamada.taroh@jp.example.com yamada.taroh@jp.example.com... Connecting to [127.0.0.1] via relay... ...
sendmail(8)の場合:
% printf "Subject: test mail\nFrom: me\nTo: you\n\n" | sendmail -v -f yamada.taroh@jp.example.com yamada.taroh@jp.example.com yamada.taroh@jp.example.com... Connecting to [127.0.0.1] via relay... ...
ここまでは先ほどと同じだが、メールのキューはからになっている:
# さっき送ったはずのメールが、localhostのキューにたまっている % sudo mailq /var/spool/mqueue is empty Total requests: 0
あとは、実際にメールを取り込んで確認する。
再度注意
社内LANからアクセスするSMTPサーバは、FromかToのいずれかが社内の有効なメールアドレスでないと、送信メールを無視してしまう。
「拒否」ではなく「無視」なのが分かりにくいところで、「コミットメールが届かない!」などの問題が起きたら、これを疑ってみること。