Postfix(Maildir)+Dovecot(IMAP)の設定(on Fedora)



●メールサーバの構築

 メールサーバを構築する場合、送信メールサーバ(SMTPサーバ)と受信メールサーバ(POP/IMAPサーバ)の構築が必要となります。今回は、送信メールサーバにはPostfix、受信メールサーバにはDovecotを使用します。
 DovecotはPOP/IMAPサーバとして構築し、ユーザがPOPまたはIMAPを選択できるようにします。

●POPとIMAPサーバの違い

 IMAP(Internet Message Access Protocol。詳細は、『ウィキペディア(Wikipedia)』を参照してください。)というのはPOP(Post Office Protocol。詳細は、『ウィキペディア(Wikipedia)』を参照してください。)に代わるメール受信用プロトコルです。
 POP、IMAPともに、メールサーバに保管されているメールを読むという基本的な機能は共通していますが、それぞれに特徴を持っています。
 まずはPOPですが、正確には、POP3(RFC1939)を示します。POPは基本的に、メールサーバからメールを読むだけのプロトコルです。POPサーバはPOPクライアントであるメールソフトからの接続に対し、ユーザ−認証を行なったのちに、ユーザ−のメールボックスへのアクセスを許可します。
 ユーザ−認証後、POPクライアントが利用可能なサ−ビスとしては、メールボックスの一覧、メールの転送などが挙げられますが、基本的にはメールはすべてクライアントに転送してからクライアント側のメールソフトにその後の処理が委ねられます。高機能なPOPサーバでは、メールサーバにメールを残しておいた状態で、いくつか新着メールが届いても、新着メールだけをクライアントに転送する機能を持っています。さらにインタ−ネットのセキュリティが騒がれる昨今では、ユーザ−認証をより安全に機能拡張したAPOPや、メールを受けるだけではなく、送る機能を持ったPOPサーバも登場しています。
 続いてIMAPですが、ここでは、IMAP4 Rev1プロトコル(RFC2060)を前提に説明します。IMAPを利用するには、POPの場合と同様に、IMAPに対応するメールサーバとメールクライアントソフトが必要です。
 IMAPのもっとも大きな特徴は、メールを読むだけではなく、メールを検索することやフォルダの管理ができることです。このくらいならばPOP対応のメールソフトでも可能だと思われるかもしれませんが、POPとの大きな違いは、メールボックスをメールサーバに置いたままこれらの機能が利用できることです。ほかには、共有メールフォルダ機能があり、グル−プ内でのメールの回覧などの用途に利用することができます。
 最後に、POPとIMAPの比較検討をしてみたいと思います。
 POPがクライアント主導型なのに対し、IMAPはサーバ主導型といえます。IMAP サーバはその性格上、同時に複数のアクセスが発生します。ここまではPOPでも同様なのですが、IMAPではクライアントからのメールの検索やフォルダ管理などにも対応しなければいけませんので、POPよりも高い計算処理能力を求められます。さらに、IMAPではユーザ−のメールボックスをサーバに保管するため、POPよりも多くのディスク容量を必要とします。つまり、IMAPはPOPよりも多くのリソ−スが必要なサ−ビスといえます。しかし、 IMAPは、メールボックスをメールサーバに置くことによって、ユーザ−がどのクライアントマシンからアクセスしても、いつも同じメールボックスを提供することができます。例えば、職場(学校)、出先、自宅などで異なるパソコンを使っていても、同じメールボックスを利用することができるというわけです。ちなみに、POPの場合、メールをメールサーバに保存する設定を利用すれば異なる場所でも同じメールを読むことはできますが、未読管理はクライアントソフトに任されますので、同じメールをいくどとなく読まされることになります。また、メールをフォルダに仕分けする作業も、すべてクライアント側で行なわなければいけません。このような問題はIMAPを利用すれば一挙に解決します。
 以上のように、IMAPは異なる場所でメールサーバにアクセスしたり、一人で何台ものパソコンを利用している方にはとても有益です。
 今後は、メールボックスを管理するサーバ機能として、POPに代わってIMAPが利用されるケ−スが多くなっていくと思われます。また、IMAPにはメールだけでなくネットニュ−スやディレクトリサ−ビスなどとの連動という魅力的な機能もあります。しかし、まだクライアントソフトが充実していませんので、現状POPでこと足りているならば、あえて移行する必要はないでしょう。メールサーバにIMAPを導入しようとお考えの方は、それぞれの環境やメールクライアントソフトの機能を、よく吟味してからでも決して遅くないと思います。ちなみに、いちはやくIMAPに対応した定番メールソフトWinBiff の開発元オレンジソフトではIMAPに関する情報を集めたホームペ−ジ(http://imap4.orangesoft.co.jp/)を開設していますので、参考にされるとよいかもしれません。

●Postfixの設定

 SMTPsの設定は「●メールサーバのTLS化(SMTPs):2023年9月中旬以降採用」を参照してください。

 MTAをPostfixに設定します。
 この設定を最初に確認していなかったため、mail.cfを何度も確認するはめになりました。
# alternatives --config mta
3 プログラムがあり 'mta' を提供します。
  選択       コマンド
-----------------------------------------------
 + 1           /usr/sbin/sendmail.exim
*  2           /usr/sbin/sendmail.postfix
   3           /usr/sbin/sendmail.postfix
Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:2
 以下の箇所を変更及び追加しました。
vi /etc/postfix/main.cf
# メールサーバのホスト名
myhostname = mail.bigbang.mydns.jp
# ドメイン名
mydomain = bigbang.mydns.jp
# 差出人のメールアドレスに使用されるドメイン名
# システム発信等された場合、メールアドレスの@以降に補完される名称
myorigin = $myhostname
# 全てのインターフェースから受信する場合
inet_interfaces = all
# 特定のインターフェースからのみ受信する場合
inet_interfaces = 127.0.0.1, 192.168.0.20, 10.10.10.23
# メールサーバー自身に配送されたとみなすドメインのリスト
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
# メールのリレー(転送)を許可するネットワーク
mynetworks = 127.0.0.0/24, 1.0.0.0/24
# このシステムがメールをリレーしようとする配送先のドメイン(及びそのサブドメイン)
relay_domains = $mydestination
# ローカルメール以外をリレーさせる設定(SMTP over SSL対応)
relayhost = [smtpssl.odn.ne.jp]:465
  [hostname]のように、転送先ホスト名を[ ]で囲むとMX検索をしなくなる。
  複数行指定した場合、下の行が優先される。 
# Mailbox形式
home_mailbox = Maildir/
# procmailを使用したいので設定
mailbox_command = /usr/bin/procmail
※注意
ユーザ毎の設定時、環境変数に記載により正常にMailboxに取り込まれないことがありますので、その場合は下記を参照してください。
「Procmailとは?●全ユーザ共通設定」
「Procmailとは?●ユーザ毎の設定
# ESMTP unknownメールサーバソフト名の隠蔽化
smtpd_banner = $myhostname
# 送信するメールサイズを制限
message_size_limit = 13660000
      エンベロ−プ情報(送信者、受信者など) を含めた、Postfix キュ−ファイルの最大サイズの制限
      添付ファイルはbase64でエンコ−ドされるので、想定する制限の4/3倍するとよい
      約10Mまで有効
デフォルト(未指定)では10MByteに設定されています。
無制限にする場合
message_size_limit = 0
# メールボックスの容量設定
mailbox_size_limit = 102400000 ← メールボックス容量を100MBに制限
                                MailDir形式では有効にならない

Maildir形式でもサイズがmailbox_size_limitを超えた場合は、下記のメッセージが表示されます。
fatal: main.cf configuration error: mailbox_size_limit is smaller than message_size_limit
warning: process /usr/libexec/postfix/local pid 12685 exit status 1

# 当メールサーバでメール送信時の送信者アドレスを強制書き換え
sender_canonical_maps = hash:/etc/postfix/sender_canonical

  # /etc/postfix/sender_canonicalの内容
  @bigbang.dyndns.org		@mail.bigbang.mydns.jp
  @mail.bigbang.dyndns.org	@mail.bigbang.mydns.jp
  @mail.bigbang.mydns.bz	@mail.bigbang.mydns.jp
  @serverA.bigbang.dyndns.org	@mail.bigbang.mydns.jp

# SMTP over SSLでリレーホストに接続する場合の設定
smtp_tls_wrappermode = yes
smtp_tls_security_level = encrypt
smtp_sasl_password_maps = hash:/etc/postfix/odn_mail_pass

  ODNメールサーバ(465番ポート)を使用するためのハッシュファイルの作成
  # vi /etc/postfix/odn_mail_pass
  [smtpssl.odn.ne.jp]:465 ACCOUNT:password
   ↑ ODNアカウント(メールアドレス)、パスワードを記載
  # chmod 600 /etc/postfix/odn_mail_pass
  # postmap /etc/postfix/odn_mail_pass

# SMTP-AUTHを有効にする場合の設定
  # SASL認証の有効
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $myhostname
smtpd_recipient_restrictions =
    # mynetworksで指定されたネットワークからのリレーを許可
    permit_mynetworks
    # SMTP認証を通過したものは許可
    permit_sasl_authenticated
    # SMTP認証を通過しないものは拒否するが、relay_domainsにあるドメインへは許可
    # (これがないとローカルユーザにメールが配信されない)
    reject_unauth_destination
    # それ以外はすべて拒否
    reject
smtpd_sasl_security_options =
    # 匿名接続の拒否、クライアントはCRAM-MD5で認証
    noanonymous
    # PLAIN認証の拒否、クライアントはCRAM-MD5で認証
    noplaintext
  # アウトルック、Outlook Expressのログイン認証を利用するための設定
broken_sasl_auth_clients = yes

# リレーホストに対するSMTP over SSLの設定


●Maildir形式メールボックス作成

 Postfixのメール格納形式は共有ディレクトリ形式(「/var/spool/mail/ユーザ名」というファイルに全てのメールが蓄積されていく形式)だが、アクセス性能改善及びセキュリティ強化の観点から Maildir形式へ移行します。

【既存ユーザ対処】
 既存ユーザのホームディレクトリにMaildir形式のメールボックスを作成して、蓄積済のメールデータを当該メールボックスへ移行します。メールデータ形式の移行を参照

【新規ユーザ対処】
 新規ユーザ追加時に自動でホームディレクトリにMaildir形式のメールボックスが作成されるようにします。
# mkdir -p /etc/skel/Maildir/{new,cur,tmp}
 ← 新規ユーザ追加時に自動でMaildir形式メールボックス作成
# chmod -R 700 /etc/skel/Maildir/ ← メールボックスパーミッション設定
※メールデータ移行後メールサーバー再起動後したにもかかわらず、/var/spool/mail/ユーザ名」にメールが保存されてしまう場合、「全ユーザ共通設定」及び「ユーザ毎の設定」を参照して「/etc/procmailrc」を設定してください。

●Postfix起動


・sendmail停止
 デフォルトで起動しているSMTPサーバであるsendmailを停止します。
# systemctl stop sendmail
# systemctl disable sendmail
# systemctl status sendmail

or

# /etc/rc.d/init.d/sendmail stop
# chkconfig sendmail off ← sendmail自動起動設定解除
# chkconfig --list sendmail ← sendmail自動起動設定解除確認
sendmail        0:off   1:off   2:off   3:off   4:off   5:off   6:off
     ↑ 全ランレベルのoffを確認
・メールサーバ切替え
 システムで使用するメールサーバ機能をsendmailからPostfixに切り替えます。
# alternatives --config mta ← メールサーバ切り替え
2 プログラムがあり 'mta'を提供します。
  選択       コマンド
-----------------------------------------------
*+ 1           /usr/sbin/sendmail.sendmail
   2           /usr/sbin/sendmail.postfix
Enterを押して現在の選択[+]を保持するか、選択番号を入力します:2 ← 2を応答
・Postfix起動
# systemctl enable --now postfix
# systemctl status postfix

or

# /etc/rc.d/init.d/postfix start ← Postfix起動
# chkconfig postfix on ← Postfix自動起動設定
# chkconfig --list postfix ← Postfix自動起動設定確認
postfix         0:off   1:off   2:on    3:on    4:on    5:on    6:off
     ↑ ランレベル2〜5のonを確認
・ポート25番のOPEN
 ルーター側の設定でポート25番をOPENします。

●/etc/aliases

 解説には「aliases(5) はローカル受信者へのメールの宛名を書き換えるシステム全体に渡る機構を提供します。書き換えは Postfix local(8) 配送エージェントにより処理されます。通常、aliases(5) テーブルには postalias(1) コマンドへの入力に使われるテキストファイルが指定されます。dbm または db 形式でインデックス化された結果はメールシステムが高速に検索するために使われます。Postfix エイリアスデータベースを変更した後は、インデックスファイルを再構築するために newaliases コマンドを実行してください。」と記載されています。

 記載されている中にpostmasterやwebmasterがあります。
 デフォルトではrootに転送するように記載されています。
 インターネットに接続されているpostfixの場合、postmaster及びwebmaster宛にスパムメール等が届くと思います。
 これに対応するため、ちょっとした工夫をすることにより拒否することが出来るようになります。

 webmasterをコメントアウトしてみます。
 すると、下記のように拒否されるようになります。

2022/10/18 10:15:15 serverA postfix/smtpd[2035358]: connect from *****.odn.ne.jp[143.***.***.***]
2022/10/18 10:15:15 serverA postfix/smtpd[2035358]: discarding EHLO keywords: CHUNKING
2022/10/18 10:15:15 serverA postfix/smtpd[2035358]: NOQUEUE: reject: RCPT from *****.odn.ne.jp[143.***.***.***]: 550 5.1.1 <webmaster@mail.bigbang.mydns.jp>: Recipient address rejected: User unknown in local recipient table; from=<********@syd.odn.ne.jp> to=<webmaster@mail.bigbang.mydns.jp> proto=ESMTP helo=<cmsa102.odn.ne.jp>
2022/10/18 10:15:15 serverA postfix/smtpd[2035358]: disconnect from *****.odn.ne.jp[143.***.***.***] ehlo=1 mail=1 rcpt=0/1 rset=1 quit=1 commands=4/5


2022/11/07 03:38:41 serverA postfix/smtpd[483569]: NOQUEUE: reject: RCPT from unknown[117.69.188.103]: 550 5.1.1 <webmaster@mail.bigbang.mydns.jp>: Recipient address rejected: User unknown in local recipient table; from=<changeid@amazon.co.jp> to=<webmaster@mail.bigbang.mydns.jp> proto=ESMTP helo=<amazon.co.jp>
2022/11/07 04:26:50 serverA postfix/smtpd[483569]: NOQUEUE: reject: RCPT from unknown[60.23.118.76]: 550 5.1.1 <webmaster@mail.bigbang.mydns.jp>: Recipient address rejected: User unknown in local recipient table; from=<info@hotmail.com> to=<webmaster@mail.bigbang.mydns.jp> proto=ESMTP helo=<hotmail.com>
2022/11/07 04:28:30 serverA postfix/smtpd[524114]: NOQUEUE: reject: RCPT from unknown[175.150.96.28]: 550 5.1.1 <webmaster@mail.bigbang.mydns.jp>: Recipient address rejected: User unknown in local recipient table; from=<changeid@amazon.co.jp> to=<webmaster@mail.bigbang.mydns.jp> proto=ESMTP helo=<amazon.co.jp>


 webmasterを活かしたままスパムメールを拒否したい場合の一例は下記のとおりです。
 smtpd_sender_restrictionsを利用して設定した場合。
 記載方法は「●accessテーブルの使用」を参照。

2022/10/29 03:06:03 serverA postfix/smtpd[1690279]: NOQUEUE: reject: RCPT from unknown[27.184.133.218]: 450 4.1.8 <taf@pgnlk.net>: Sender address rejected: Domain not found; from=<taf@pgnlk.net> to=<webmaster@mail.bigbang.mydns.jp> proto=ESMTP helo=<pgnlk.net>
2022/10/30 04:23:34 serverA postfix/smtpd[3061631]: NOQUEUE: reject: RCPT from unknown[27.184.150.181]: 450 4.1.8 <is@xmvetnnew.org>: Sender address rejected: Domain not found; from=<is@xmvetnnew.org> to=<webmaster@mail.bigbang.mydns.jp> proto=ESMTP helo=<xmvetnnew.org>
2022/10/30 04:23:35 serverA postfix/smtpd[3061631]: NOQUEUE: reject: RCPT from unknown[27.184.150.181]: 450 4.1.8 <ejhmpyd@kynyqlto.net>: Sender address rejected: Domain not found; from=<ejhmpyd@kynyqlto.net> to=<webmaster@mail.bigbang.mydns.jp> proto=ESMTP helo=<kynyqlto.net>
2022/10/31 04:32:33 serverA postfix/smtpd[83272]: NOQUEUE: reject: RCPT from unknown[27.184.138.160]: 450 4.1.8 <mn@iuaz.net>: Sender address rejected: Domain not found; from=<mn@iuaz.net> to=<webmaster@mail.bigbang.mydns.jp> proto=ESMTP helo=<iuaz.net>


 

●accessテーブルの使用

 accessテーブルを利用すると、Postfixが受け入れるメールや送信するメールを制限することができます。accessテーブルで使用可能なパラメータには以下があります。

smtpd_client_restrictions
 このSMTPサーバに接続できるクライアントを制限します。デフォルトはどのクライアントからのSMTP接続も許可します

smtpd_helo_restrictions
 SMTPのHELOやEHLOコマンドで許可するホスト名を制限します。デフォルトでは全てを許可します。

smtpd_sender_restrictions
 SMTPのMAIL FROMコマンドでメールを送信できる送信者アドレスを制限します。

smtpd_recipient_restrictions
 SMTPのRCPT TOコマンドでメールを受信できる受信者アドレスを制限します。

 これらのパラメータの値に参照するaccessテーブルファイルを指定します。例えば、差出人のFROMアドレスでSPAMメールと判断し、メールの受信を拒否するのであれば、以下のようにsmtpd_sender_restrictionsパラメータを/etc/postfix/main.cf に追記し、変更を反映するためにPostfixを再起動します。
設定例
smtpd_sender_restrictions = hash:/etc/postfix/access,cidr:/etc/postfix/client.cidr reject
/etc/postfix/accessの内容
mail1.hoge.mail.co.jp     OK
mail2.hoge.mail.co.jp     OK
/etc/postfix/client.cidrの内容
127.0.0.1/8          OK
192.168.200.0/25     OK
 /etc/postfix/accessは、デフォルトで用意されているaccessテーブルファイルです。他のパラメータも指定するのであれば、それぞれ異なるaccessテーブルファイルを指定します。
 accessテーブルに拒否するメールのパターンを記述する場合は、以下のようにします。
設定例
smtpd_sender_restrictions = hash:/etc/postfix/access
/etc/postfix/accessの内容
spam@example.com     REJECT
example.com          REJECT
spam@                REJECT
192.168.0.1          REJECT
192.168.0            REJECT
192.168              REJECT
192                  REJECT
 このように、メールアドレス、IPアドレス、ドメイン名、ユーザー名を指定することができます。これに続きタブまたはスペースで区切り、REJECTと記述することで、マッチしたメールを拒否することができます。なお、ドメイン名を指定した場合は、そのサブドメインも拒否の対象となります。つまり、上記の例ではhoge.example.comやhogehoge.example.comからのメールも拒否されます。
 /etc/postfix/accessの編集後は、以下のようにpostmapコマンドを実行し、データベースファイルである/etc/postfix/access.dbを更新する必要があります。Postfixを再起動する必要はありません。
# postmap /etc/postfix/access
 「strings」コマンドを使用することで「access.db」の内容が確認できます。

●canonicalテーブルの使用

 内向けアドレス形式から外向けアドレス形式への変換時に使用されます。
 送信者および受信者アドレスに適用されます。
 デフォルトでは、すべてのヘッダとエンベロープのアドレスが書き換えられます。
 /etc/postfix/main.cfに下記を追記します。
# 送信者、受信者のアドレス書き換えに適用
canonical_maps = hash:/etc/postfix/canonical
# 書き換えるアドレスの対象
canonical_classes = envelope_sender, envelope_recipient, header_sender, header_recipient
送信者アドレスを書き換える場合
#sender_canonical_maps = hash:/etc/postfix/sender_canonical
受信者アドレスを書き換える場合
#recipient_canonical_maps = hash:/etc/postfix/recipient_canonical
適用の順序は、sender_canonical_maps,recipient_canonical_maps,canonical_maps
 /etc/postfix/canonicalの記載例を示します。
@bigbang.mydns.jp     @mail.bigbang.mydns.jp
@mail.bigbang.mydns.jp        @mail.bigbang.mydns.jp
test@mail.bigbang.mydns.jp    suzuki-t@mail.bigbang.mydns.jp
hoge    hoge.master
 変更後、下記を実行します。
設定変更の反映
# postmap /etc/postfix/canonical
postfix再読み込み
# systemctl reload postfix
マッピングの確認
# postmap -q @bigbang.mydns.jp /etc/postfix/canonical
@mail.bigbang.mydns.jp
# postmap -q @mail.bigbang.mydns.jp /etc/postfix/canonical
@mail.bigbang.mydns.jp
# postmap -q test@mail.bigbang.mydns.jp /etc/postfix/canonical
suzuki-t@mail.bigbang.mydns.jp
# postmap -q hoge /etc/postfix/canonical
hoge.master

●transportテーブルの使用

 transportテーブルを使用して、ドメインによるメールの配送経路を指定することができます。電子メールの送り先データ(MX)を無視して強制的に移送する時などに使うもので、例えば、メールゲートウェイ等で使うことがあります。MXはゲートウェイ、すなわち自分自身に向いているのでそれが利用できないためです。postfixの設定ファイルであるmain.cfに「transport_maps」項目を追加し、メールの配送経路指定を設定します。変更を反映するためにPostfixを再起動します。
設定例
transport_maps = hash:/etc/postfix/transport
hoge.net        smtp:192.168.1.1
.hoge.co.jp     smtp:mail1.sev.met
hoge1.net       smtp:[mail.server.com]
 「hoge.net」ドメイン宛てのみのメールについては、「smtpプロトコルにてIPアドレス「192.168.1.1」のサーバへ転送する」という設定です。
 「hoge.co.jp」のサブドメインを含むドメイン宛てのメールについては、「smtpプロトコルにて「mail1.sev.met」のサーバへ転送する」という設定です。
 「hoge1.net」のドメイン宛てのメールについては、「MXレコードを使用しないで「mail.server.com」のサーバへ転送する」という設定です。
 /etc/postfix/transportの編集後は、以下のようにpostmapコマンドを実行し、データベースファイルである/etc/postfix/transport.dbを更新する必要があります。Postfixを再起動する必要はありません。
# postmap /etc/postfix/transport
 「strings」コマンドを使用することで「transport.db」の内容が確認できます。

●virtualテーブルの使用

 管理していたドメインの利用を停止し、新たに別ドメインで運用をし始めた場合、メールドメインを切り替える必要があります。
 その場合、バーチャルドメインを利用することにより旧ドメイン宛のメールを受信することができるようになります。そのためには、バーチャルメールサーバを用意する必要がります。
 ただし、旧ドメイン宛のメールを受信するには、下記の条件が必要です。
 外部より受信するにあたり、新ドメイン・旧ドメインが外部のDNSサーバに登録されている事(名前解決できている事)。
 バーチャルメールサーバとは、複数のドメイン名宛へのメールアカウントをリアルドメインのメールアカウントで受信できる事です。
 例えば、当サイトのリアルドメインは『kajuhome.com』です。ご存知の方は少ないかも知れませんが、当サイト公開当時のドメインは『bigbang.dyndns.org』でサブドメインが『kaju』、即ち『kaju.bigbang.dyndns.org』で公開していました。
 当初の名残もあり、現在でも『kaju.bigbang.dyndns.org』でアクセス可能です。この『kaju.bigbang.dyndns.org』も以前は当然メールを使用していたので、『kaju.bigbang.dyndns.org』宛へのメールも受信する必要があります。
 よって、前述しましたが『kajuhome.com』がリアルドメイン、『kaju.bigbang.dyndns.org』がバーチャルドメインと言う位置付けとなっています。

●セカンダリメールサーバの設定

 メールサーバは24時間稼動することが要求されるサーバの1つです。障害発生時に備えてセカンダリメールサーバを用意しておけば、メール配送のトラブルを減らすことができます。セカンダリメールサーバは、プライマリメールサーバの代わりにメールをキューへ溜めておき、プライマリメールサーバの復旧後、一時的に受け取ったメールをプライマリメールサーバへ向けて配信する働きをします。
 セカンダリメールサーバとして機能させるために必要となる要件を以下に示します。
・DNSサーバのMXレコードにセカンダリメールサーバの設定を追加する
・受け取ったメールのローカル配信は行わずキューにためる
・プライマリメールサーバのドメイン宛のメールはリレーする
・プライマリメールサーバへ転送するときにMXレコードを参照しない
 ここでは、プライマリメールサーバをmailgw.hoge.co.jp、セカンダリメールサーバをmailgwbak.hoge.co.jpとして、セカンダリメールサーバを設定するための/etc/postfix/main.cfのパラメータについて解説します。
 最初にmydestinationパラメータを確認します。$mydomainが指定されているとプライマリメールサーバの停止中に受信したメールを取り込んでしまうため、プライマリメールサーバが復活しても転送されません。したがって、$mydomainが指定されている場合は削除します。
 次に、hoge.co.jpドメイン宛のメールを受け取ることができるように、relay_domainsパラメータにドメイン名を指定します。
relay_domains = hoge.co.jp
 MXレコードを参照せずにプライマリメールサーバへメールを転送するには、/etc/postfix/transportファイルにプライマリメールサーバを指定しておきます。
hoge.co.jp   smtp:[mailgw.hoge.co.jp]
 設定完了後は以下のコマンドを実行し、/etc/postfix/transport.dbファイルを更新する必要があります。
# postmap /etc/postfix/transport

●メールゲートウェイの設置

 メールサーバの構築においては、DMZ(非武装地帯)に設置した外部SMTPサーバ(メールエクスチェンジャ、メールゲートウェイ)が受信したメールをLAN内に設置した内部SMTPサーバへそのまま転送し、そのホストがメールスプールを持つといった2段構成もよくとられます。ここでは、メールゲートウェイとなる外部SMTPサーバをmailgw.hoge.co.jp、内部SMTPサーバをmail.hoge.co.jpとして各SMTPサーバの/etc/postfix/mail.cfのパラメータ定義について解説します。

mail.hoge.co.jp の設定

 内部のSMTPサーバを設定するために、先に解説した最も基本的なメールサーバと異なる点は、クライアントからのメールをメールゲートウェイであるmailgw.hoge.co.jp へそのまま転送することです。そのためには、relayhostパラメータを指定します。
relayhost = mailgw.hoge.co.jp
 これだけで、クライアントからのメールは、メールゲートウェイへ配送され、送信メールアドレスのドメイン名を処理するSMTPサーバへmailgw.hoge.co.jpにより配送されます。

mailgw.hoge.co.jpの設定

 メールゲートウェイを設定するために最低限必要な要件は、
・外部からのメールをmail.hoge.co.jpへ転送
することです。そのためには、transport_mapsパラメータを使用します。デフォルトのtransport_mapsパラメータは以下のように指定されています。
transport_maps = hash:/etc/postfix/transport
 ここで指定されている/etc/postfix/transportは、配送方法を指定するための設定ファイルです。つまり、このファイルにメールを転送するSMTPサーバとドメイン名とのマップを指定します。この例では、hoge.co.jpや.hoge.co.jpドメイン宛てのメールをmail.hoge.co.jpへ転送するために以下のように指定します。
hoge.co.jp         smtp:[mail.hoge.co.jp]
.hoge.co.jp        smtp:[mail.hoge.co.jp]
 設定完了後は、以下のコマンドを実行し /etc/postfix/transport.dbファイルを更新する必要があります。
# postmap /etc/postfix/transport
 これで、メールゲートウェイへ届いたhoge.co.jpドメイン宛てのメールは、mail.hoge.co.jpへ転送されるようになります。

●Postfixにおける制御

 下記のようなことを制御することが出来ます。
●ヘッダ及び本体のフィルタリングング

 スパム対策として以前はProcmailを利用していましたが、Postfixではあらかじめスパム対策用のパラメータが準備されており、それを利用することにします。主にheader_checks、body_checksを使用します。これらは設定次第でスパム対策だけでなく、さまざまなフィルタリングをすることも可能となります。
 header_checksはメッセージヘッダのコンテンツ検査を行うオプションの検索テーブルです。
 body_checksはメッセージ本体のコンテンツ検査を行うオプションの検索テーブルです。
 以下のようにheader_checks、body_checksパラメータを/etc/postfix/main.cfに追記し、変更を反映するためにPostfixを再起動します。
header_checks = regexp:/etc/postfix/header_checks
body_checks = regexp:/etc/postfix/body_checks
 それぞれの設定例を下記に示します。
 なお、「未承諾広告」という日本語文字をMIMEデコードに変換するには以下のようにします。
echo '未承諾広告' | nkf -jM
変換後:=?ISO-2022-JP?B?GyRCTCQ+NUJ6OS05cBsoQg==?=
 header_checks、body_checksを設定します。
# vi /etc/postfix/main.cf
#header_checks = regexp:/etc/postfix/header_checks
        ↓
header_checks = regexp:/etc/postfix/header_checks ← コメントを外す
#body_checks = regexp:/etc/postfix/body_checks
        ↓
body_checks = regexp:/etc/postfix/body_checks ← コメントを外す
# chmod 600 /etc/postfix/header_checks
# chmod 600 /etc/postfix/body_checks
 ヘッダチェックファイルの設定をします。
header_checksの設定例
header_checks = regexp:/etc/postfix/header_checks
#IPアドレスによる拒否設定
/^Received:.*\[211\.112\./ DISCARD
/^Received:.*\[218\.39\./ DISCARD
#ドメイン名による拒否設定
/^Subject:.*testtest/ REJECT
/^Received:.*.com\.tw/ REJECT
/^Received:(.from.a-net\.ne\.jp)/ REJECT
#その他
/^X-Mail-Agent:.*(BSMTP DLL)/ DISCARD
/^X-Mailer:(.AOL).*(for.Windows.US.sub)/ REJECT
#送信メールアドレスによる拒否設定
/^From:.*@yahoo\.fr/ REJECT
/^From:.*@yahoo\.ca/ REJECT
#送信宛先による拒否設定
/^To:.*undisclosed-recipients/ REJECT
#件名による拒否設定
/^Subject:(.Re:)$/ REJECT
/^Subject:(.Re:Re:)$/ REJECT
/^Subject:(.Re:Re:Re:)$/ REJECT
/^Subject:\ =\?ISO-2022-JP\?B\?GyRCTCQ\+NUJ6OS05cBsoQg==\?=.*/ REJECT ← 未承諾広告
#メールヘッダの隠蔽
#ローカルのみ有効
/^Received:/ IGNORE
設定前のヘッダ情報 Received: from bigbang.mydns.jp([***.***.***.***] [***.***.***.***]) by *****.*****.ne.jp with ESMTP id <20111007133537829.BNMG.4827.*****.*****.ne.jp@*****.*****.ne.jp> for <test@*****.*****.ne.jp>; Fri, 7 Oct 2011 22:35:37 +0900 Received: from mail(mail.bigbang.mydns.jp [192.168.0.54]) by bigbang.mydns.jp(Postfix) withSMTPid 4DE4A3D4029 for <test@*****.*****.ne.jp>; Fri, 7 Oct 2011 22:35:37 +0900(JST) Message-ID: <BC70BD4A5F574442A88CFD3281E780BE@bigbang.mydns.jp> From: "hoge HOGE" <hoge@bigbang.mydns.jp> To: =?iso-2022-jp?B?GyRCPEYhIUJuGyhC?= <test@*****.*****.ne.jp> Subject: TEST Date: Fri, 7 Oct 2011 22:35:33 +0900 設定後のヘッダ情報 Received: from bigbang.mydns.jp([***.***.***.***] [***.***.***.***]) by *****.*****.ne.jp with ESMTP id <20111007135640036.BOAT.4827.*****.*****.ne.jp@*****.*****.ne.jp> for <test@*****.*****.ne.jp>; Fri, 7 Oct 2011 22:56:40 +0900 Message-ID: <91515C3A33E54355839ED0552327424F@bigbang.mydns.jp> From: "hoge HOGE" <hoge@bigbang.mydns.jp> To: =?iso-2022-jp?B?GyRCPEYhIUJuGyhC?= <test@*****.*****.ne.jp> Subject: Date: Fri, 7 Oct 2011 22:56:39 +0900  ローカル部分のヘッダ情報がなくなっていることを確認できます。
body_checksの設定例 body_checks = regexp:/etc/postfix/body_checks #spam /^(|[^>].*)livedear.com/ REJECT #LogWatch if !/(reject: header|reject: body)/ /^(|[^>].*)sample.com/ REJECT /^(|[^>].*)http:\/\/[0-9a-zA-Z!-~]+\.ch/ REJECT /^(|[^>].*)http:\/\/[0-9a-zA-Z!-~]+\.example\.net/ REJECT end if *root宛てにLogWatchのメールを送っている場合、  body_checksでREJECTすると、LogWatchのメールもREJECTされ、  エラーメールで届いてしまうので、if文などで制御する *マニュアルではendifとなってるがendifだとpostmap時にエラーになる  end ifか何もかかないとエラーが出ず、一応動作する  if以降の行は、行頭にスペースやタブを入れない  スペースやタブは、前行の続きとみなされる 処理の方法について OK:受信する(Ver2.1以降はDUNNO推奨) IGNORE:一致した行をヘッダから削除 REJECT:受信拒否して、エラーメールを返す DISCARD:受信して破棄する
 /etc/postfix/header_checks、/etc/postfix/body_checksの編集後は、以下のようにpostmapコマンドを実行し、データベースファイルである/etc/postfix/header_checks.db、/etc/postfix/body_checks.dbを更新する必要があります。Postfixを再起動する必要はありません。
# postmap /etc/postfix/header_checks
# postmap /etc/postfix/body_checks


●postmapコマンドで生成した*.dbファイルの内容確認

  「strings」コマンドを使用することで「header_checks.db」「body_checks.db」の内容が確認できます。

●クライアントホスト名/アドレス制限

 SMTPサーバがクライアントからSMTP接続の要求を受けた際に適用する、オプションのアクセス制限で/etc/postfix/main.cfのsmtpd_client_restrictionsで設定します。デフォルトでは全ての接続要求を許可します。制限のリストをカンマまたは空白で区切って指定します。次の行を空白で始めることで長い行を継続します。制限は指定された順に適用されます。最初にマッチした制限が勝ちます。

文法
ゼロもしくはそれ以上の制限を空白またはカンマで区切って指定します。制限は指定された順に適用されます。最初にマッチした制限が勝ちます。クライアントのホスト名やIPアドレスに関する制限に加えて、HELO/EHLOコマンドや送信者アドレス、受信者アドレスで渡される情報に基づく制限を列挙することもできます。HELO/EHLOや送信者、受信者の制限はsmtpd_delay_reject = yesの時のみ課せられ、その場合全ての制限は RCPT TOコマンドの後で評価されます。
smtpd_client_restrictions = hash:/etc/postfix/access, reject_rbl_client relays.mail-abuse.org
smtpd_client_restrictions = hash:/etc/postfix/access, reject_rbl_client relays.ordb.org
smtpd_sender_restrictions = hash:/etc/postfix/access, reject_rhsbl_sender dsn.rfc-ignorant.org
smtpd_client_restrictions = permit_mynetworks, reject_unknown_client

 以下はクライアントホスト名またはクライアントネットワークアドレス情報に特有のものです。
check_client_access type:table
指定されたaccessデータベースでクライアントのホスト名や親ドメイン、クライアントのIPアドレス、重要でないオクテットをはぎ取ったネットワークを検索します。詳細はaccess(5)マニュアルページを参照してください。
permit_mynetworks
クライアントのIPアドレスが$mynetworksにリストアップされたネットワークのいずれかにマッチする場合、要求を許可します。
reject_rbl_client rbl_domain=d.d.d.d
逆にしたクライアントネットワークアドレスが\fIrbl_domain\fR以下のAレコード"\fId.d.d.d\fR"でリストアップされている場合に、要求を拒否します(Postfixバージョン2.1以降のみ)。"\fI=d.d.d.d\fR"が指定されていないと、逆にしたクライアントネットワークアドレスが rbl_domain以下のいずれかのAレコードでリストアップされている場合に、要求を拒否します。maps_rbl_reject_codeパラメータには要求を拒否する際の応答コードを(デフォルト: 554)、default_rbl_replyにはデフォルトのサーバ応答を、そして rbl_reply_mapsパラメータには rbl_domainでインデックス化されたサーバ応答を持つテーブルを指定します。この機能はPostfix2.0以降で使えます。
reject_rhsbl_client rbl_domain=d.d.d.d
クライアントのホスト名が\fIrbl_domain\fR以下のAレコード"d.d.d.d"でリストアップされている場合に、要求を拒否します(Postfixバージョンョン 2.1 以降のみ)。"=d.d.d.d"が指定されていないと、逆にしたクライアントネットワークアドレスがrbl_domain以下のいずれかのAレコードでリストアップされている場合に、要求を拒否します。さらなるRBL関連の設定パラメータについては、上のreject_rbl_clientの記述を参照してください。この機能はPostfix 2.0以降で使えます。
reject_unknown_client
クライアントのIPアドレスがDNSにPTRレコードを持たない場合や、そのPTRレコードがマッチするAレコードを持たない場合に、要求を拒否します。unknown_client_reject_codeパラメータには要求を拒否する際の応答コードを指定します(デフォルト:450)。一時的な問題によってホスト名の検索に失敗した場合、応答は常に450です。

 これに加えて、以下の 一般的な制限 を使えます。これらの制限はSMTPコマンドのどの場面にも適用できます。

check_policy_service servername
指定されたポリシーサーバに問い合わせます。詳細はSMTPD_POLICY_READMEドキュメントを参照してください。この機能はPostfix 2.1以降で使えます。
defer
要求を遅延します。クライアントは後で再び試すように言われます。この制限は、デフォルトのポリシーを明示的にするために制限リストの最後に置くと便利です。parameterパラメータにはSMTPサーバ応答コードを指定します(デフォルト: 450)。
defer_if_permit
以降の制限で結果が明示的もしくは暗黙のうちにPERMITアクションになる場合、要求を遅延します。これは一時的な問題でブラックリスト機能が失敗したときに便利です。この機能はPostfix 2.1以降で使えます。
defer_if_reject
以降の制限で結果がREJECTアクションになる場合、要求を遅延します。これは一時的な問題でホワイトリスト機能が失敗したときに便利です。この機能はPostfix 2.1以降で使えます。
permit
要求を許可します。この制限は、デフォルトのポリシーを明示的にするために制限リストの最後に置くと便利です。
reject_multi_recipient_bounce
エンベロープ送信者がnullアドレスで、かつエンベロープ受信者が複数の場合に要求を拒否します。これの使用は技術的には許されますが、正当なアプリケーションを持っていないように見えます。multi_recipient_bounce_reject_codeパラメータには要求を拒否する際の応答コードを指定します(デフォルト: 550)。この機能はPostfix 2.1以降で使えます。
reject_unauth_pipelining
前もってコマンドを送ることが許されない場所でクライアントがSMTPコマンドを前もって送ったり、Postfixが実際にSMTPコマンドパイプラインをサポートしているかどうかを知らずにクライアントが前もってSMTPコマンドを送った場合に、要求を拒否します。これは配送をスピードアップするためにSMTPコマンドパイプラインの間違った使い方をするバルクメールソフトウェアからのメールを止めます。
reject
要求を拒否します。この制限は制限リストの最後に置いて、デフォルトのポリシーを明示的にするのに便利です。reject_code設定パラメータには要求を拒否する際の応答コードを指定します(デフォルト: 554)。
warn_if_reject
次の制限の意味を変え、要求を拒否する代わりに警告をログに記録するようにします("reject_warning"を含むログファイルの記録を探してください)。これは動いている環境で、不用意にメールを失うリスクを冒さずに新しい制限をテストするのに便利です。

●HELO(EHLO)コマンドの要求

 smtpd_helo_requiredパラメータはクライアントがSMTPセッションのはじめにHELO(またはEHLO)コマンドを送らなければいけないかどうかを決定します。これを要求することで、止めることができるUCEソフトウェアもあります。
 デフォルトでは、Postfix SMTP serverはHELO(EHLO)の使用を要求しません。

文法
yesまたはnoを指定します。
smtpd_helo_required = yes

●HELO(EHLO)ホスト名制限

 デフォルトは設定されておらず、全てを許可します。smtpd_helo_restrictionsパラメータはHELO(EHLO)でクライアントが送れるホスト名を制限します。ここを厳密にすることで、止めることができるUCEソフトウェアもあります。
 デフォルトでは、この制限はクライアントがRCPT TOコマンドを送る時に適用されます。できるだけ早く制限の効果を出すためには、 smtpd_delay_reject = noをmain.cf設定ファイルで指定します。そうすると実装がまずいクライアントソフトウェアで予期しない結果を引き起こすかもしれません。
 デフォルトでは、SMTPサーバはHELO(EHLO)コマンドのいかなるガラクタも受け入れます。インターネット上には壊れたり設定が間違ったソフトウェアがたくさんあります。

文法
ゼロもしくはそれ以上の制限を空白またはカンマで区切って指定します。制限は指定された順に適用されます; 最初にマッチした制限が勝ちます。HELO(EHLO)コマンドパラメータに関する制限に加えて、クライアントのホスト名、クライアントのアドレス、送信者アドレス、受信者アドレスで渡される情報に基づく制限を列挙することもできます。送信者、受信者の制限はsmtpd_delay_reject = yesの時のみ課せられ、その場合全ての制限は RCPT TOコマンドの後で評価されます。
smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname
smtpd_helo_restrictions = permit_mynetworks, reject_unknown_hostname

 以下の制限は HELO または EHLO コマンドで受け取るホスト名情報に特有です。

check_helo_access type:table
指定されたaccess(5)データベースでHELOまたはEHLOホスト名や親ドメインを検索し、対応するactionを実行します。
check_helo_mx_access type:table
指定されたaccess(5)データベースでHELOまたはEHLOホスト名のMXホストを検索し、対応するactionを実行します。
注意: 安全上の理由から"OK"という結果は許されません。特定のホストをブラックリストから外すには、代わりにDUNNOを使ってください。この機能は Postfix 2.1以降で使えます。
check_helo_ns_access type:table
指定されたaccess(5)データベースでHELOまたはEHLOホスト名のDNSサーバを検索し、対応するactionを実行します。
注意: 安全上の理由から"OK"という結果は許されません。特定のホストをブラックリストから外すには、代わりにDUNNOを使ってください。この機能は Postfix 2.1以降で使えます。
reject_invalid_hostname
HELOまたはEHLOホスト名の文法が不正な場合に、要求を拒否します。
invalid_hostname_reject_codeには拒否された要求に対する応答コードを指定します(デフォルト:501)。
reject_non_fqdn_hostname
HELOまたはEHLOホスト名の文法がRFCで要求されているような完全修飾ドメイン形式ではない場合に、要求を拒否します。
non_fqdn_reject_codeパラメータには拒否された要求に対する応答コードを指定します(デフォルト:504)。
reject_unknown_hostname
HELOまたはEHLOホスト名のDNS AまたはMXレコードがない場合に、要求を拒否します。
unknown_hostname_reject_codeパラメータには拒否された要求に対する応答コードを指定します(デフォルト:450)。

●厳密なRFC 821形式のエンベロープアドレスの要求

 SMTP MAIL FROMおよびRCPT TOコマンドで受け取るアドレスが<>で括られていて、そのアドレスがRFC822形式のコメントやフレーズが含まれていないことを要求します。これは不完全に書かれたアプリケーションからのメールをブロックします。
 デフォルトでは、Postfix SMTPサーバはMAIL FROMおよびRCPT TOアドレスのRFC 822文法を受け入れます。

strict_rfc821_envelopes = yes

●送信者アドレス制限

 参照URL:迷惑メール対策 (Sender address reject)

 smtpd_sender_restrictions パラメータはMAIL FROMコマンドの送信者アドレスでこのシステムが受け取るものを制限します。
 デフォルトでは全てを許可します。
 制限のリストをカンマまたは空白で区切って指定します。次の行を空白で始めることで長い行を継続します。制限は指定された順に適用されます。最初にマッチした制限が勝ちます。

smtpd_sender_restrictions = reject_unknown_sender_domain
smtpd_sender_restrictions = reject_unknown_sender_domain,
                            check_sender_access hash:/etc/postfix/access
smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/reject_sender,
                            check_sender_access regexp:/etc/postfix/access


 以下の制限はMAIL FROMコマンドで受け取る送信者アドレスに特有です。

check_sender_access type:table
指定されたaccess(5)データベースでMAIL FROMアドレスやドメイン、親ドメイン、localpart@を検索し、対応するactionを実行します。
check_sender_mx_access type:table
指定されたaccess(5)データベースでMAIL FROMアドレスのMXホストを検索し、対応するactionを実行します。
 注意: 安全上の理由から "OK" という結果は許されません。特定のホストをブラックリストから外すには、代わりにDUNNOを使ってください。この機能はPostfix 2.1以降で使えます。
check_sender_ns_access type:table
指定されたaccess(5)データベースでMAIL FROMアドレスのDNSサーバを検索し、対応するactionを実行します。
 注意: 安全上の理由から"OK"という結果は許されません。特定のホストをブラックリストから外すには、代わりにDUNNOを使ってください。この機能はPostfix 2.1以降で使えます。
reject_authenticated_sender_login_mismatch
認証されたクライアントのみにreject_sender_login_mismatch制限を強制します。この機能はPostfix 2.1以降で使えます。
reject_non_fqdn_sender
MAIL FROMアドレスがRFCで要求されているような完全修飾ドメイン形式ではない場合に、要求を拒否します。
non_fqdn_reject_codeパラメータには拒否された要求に対する応答コードを指定します(デフォルト:504)。
reject_rhsbl_sender rbl_domain=d.d.d.d
MAIL FROMドメインがrbl_domain以下のAレコード"d.d.d.d"でリストアップされている場合に、要求を拒否します(Postfixバージョン 2.1 以降のみ)。"=d.d.d.d"が指定されていないと、逆にしたクライアントネットワークアドレスがrbl_domain以下のいずれかのAレコードでリストアップされている場合に、要求を拒否します。.br maps_rbl_reject_codeパラメータには要求を拒否する際の応答コードを(デフォルト:554)、default_rbl_replyにはデフォルトのサーバ応答を、そしてrbl_reply_mapsパラメータにはrbl_domainでインデックス化されたサーバ応答を持つテーブルを指定します。この機能はPostfix 2.0以降で使えます。
reject_sender_login_mismatch
$smtpd_sender_login_mapsがMAIL FROMアドレスの所有者を指定しているが、クライアントがMAIL FROMアドレスの所有者として(SASL)ログインしていない場合に、要求を拒否します。または、クライアントが(SASL)ログインしたものの、クライアントのログイン名が $smtpd_sender_login_mapsに一致するMAIL FROMアドレスを所有していない場合に、要求を拒否します。
reject_unauthenticated_sender_login_mismatch
認証されていないクライアントのみにreject_sender_login_mismatch制限を強制します。この機能はPostfix 2.1以降で使えます。
reject_unknown_sender_domain
MAIL FROMアドレスにDNS AまたはMXレコードがなく、Postfixがその送信者アドレスの最終配送先ではない場合に、要求を拒否します。
unknown_address_reject_codeパラメータには、拒否された要求に対する応答コードを指定します(デフォルト:450)。一時的なDNSエラーの場合には、応答は常に450です。
reject_unlisted_sender
MAIL FROMアドレスがドメインクラスに対する有効な受信者リストにない場合に、要求を拒否します。詳細は smtpd_reject_unlisted_senderの記述を参照してください。この機能はPostfix 2.1以降で使えます。
reject_unverified_sender
MAIL FROMアドレスがバウンスするとわかっている場合や、送信者アドレスの配送先に到達できない場合に、要求を拒否します。アドレス検証情報はverify(8)サーバによって管理されます。詳細はADDRESS_VERIFICATION_READMEファイルを参照してください。
unverified_sender_reject_codeパラメータには、アドレスがバウンスするとわかっている場合の応答を指定します(デフォルト:450、変えても安全だという自信がある場合には550に変えてください)。Postfix は一時的な問題でプローブが失敗した場合には450で応答します。この機能はPostfix 2.1以降で使えます。

●受信者アドレス制限

 smtpd_recipient_restrictionsパラメータはRCPT TOコマンドの受信者アドレスでこのシステムが受け取るものを制限します。
 デフォルトの設定は下記の通りです。
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination
 デフォルトでは、Postfix SMTP サーバは次のメールをリレーします。
  • IP アドレスが $mynetworks にマッチする信頼するクライアントからあらゆる目的地へのメール
  • 信頼しないクライアントから$relay_domainsやそのサブドメインにマッチする配送先へのメールで、アドレスに送信者指定ルーティング(user@elsewhere@domain) を含まないもの
 上記に加えて、Postfix SMTP サーバ はデフォルトで、その Postfixが最終配送先となる、次のメールを受け取ります。
  • $inet_interfaces にマッチする配送先へのメール
  • $mydestination にマッチする配送先へのメール
  • $virtual_alias_maps にマッチする配送先へのメール
  • $virtual_mailbox_maps にマッチする配送先へのメール

smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination

注意: 少なくとも次の一つの制限を指定しなければいけません。reject、defer、defer_if_permit or reject_unauth_destination。そうしないと Postfix はメールの受信を拒否します。

check_recipient_access type:table
指定されたaccess(5)データベースでRCPT TOアドレスやドメイン、親ドメイン、localpart@を検索し、対応するactionを実行します。 check_recipient_mx_access type:table
指定されたaccess(5)データベースでRCPT TOアドレスのMXホストを検索し、対応するactionを実行します。注意: 安全上の理由から "OK" という結果は許されません。特定のホストをブラックリストから外すには、代わりにDUNNOを使ってください。この機能はPostfix 2.1以降で使えます。
check_recipient_ns_access type:table
指定されたaccess(5)データベースでRCPT TOアドレスのDNSサーバを検索し、対応するactionを実行します。注意: 安全上の理由から "OK" という結果は許されません。特定のホストをブラックリストから外すには、代わりにDUNNOを使ってください。この機能はPostfix 2.1以降で使えます。
permit_auth_destination
以下のうち一つを満たした場合に、要求を許可します。
  • Postfixがメールを転送する場合: 解決されたRCPT TOアドレスが$relay_domainsまたはそのサブドメインにマッチし、送信者指定のルーティング(user@elsewhere@domain)を含まない場合。
  • Postfixが最終配送先の場合: 解決されたRCPT TOアドレスが$mydestinationや$inet_interfaces、$proxy_interfaces、 $virtual_alias_domains、$virtual_mailbox_domainsにマッチし、送信者指定のルーティング(user@elsewhere@domain)を含まない場合。
permit_mx_backup
ローカルメールシステムがRCPT TOアドレスのMXホストの場合に、要求を許可します。これはローカルメールシステムが最終配送先の場合も含みます。しかし SMTP サーバは、送信者指定のルーティング情報(例: user@elsewhere@domain)付きのアドレスを持つメールは転送しません。一次MXホストがネットワークブロックのリストにマッチすることを要求するには、オプションのpermit_mx_backup_networksを使ってください。
注意: Postfixバージョン2.0より前のバージョンでは、permit_mx_backupの使用は推奨されません: 一時的にDNS検索に問題があった場合にメールを拒否するかもしれません。
reject_non_fqdn_recipient
RCPT TOアドレススが RFC で要求されているような完全修飾ドメイン形式ではない場合に、要求を拒否します。
non_fqdn_reject_codeパラメータには拒否された要求に対する応答コードを指定します(デフォルト: 504)。
reject_rhsbl_recipient rbl_domain=d.d.d.d
RCPT TOドメインがrbl_domain以下のAレコード"d.d.d.d"でリストアップされている場合に、要求を拒否します(Postfixバージョンョン 2.1 以降のみ)。"=d.d.d.d" が指定されていないと、逆にしたクライアントネットワークアドレスがrbl_domain以下のいずれかのAレコードでリストアップされている場合に、要求を拒否します。.br maps_rbl_reject_codeパラメータには要求を拒否する際の応答コードを(デフォルト:554)、default_rbl_replyにはデフォルトのサーバ応答を、そしてrbl_reply_mapsパラメータにはrbl_domainでインデックス化されたサーバ応答を持つテーブルを指定します。この機能はPostfix 2.0以降で使えます。
reject_unauth_destination
以下のどれか一つに当てはまらない場合に、要求を拒否します。
  • Postfixがメールを転送する場合: 解決されたRCPT TOアドレスが$relay_domainsまたはそのサブドメインにマッチし、送信者指定のルーティング(user@elsewhere@domain) を含まない場合。
  • Postfixが最終配送先の場合: 解決されたRCPT TOアドレスが$mydestinationや$inet_interfaces、$proxy_interfaces、 $virtual_alias_domains、$virtual_mailbox_domainsにマッチし、送信者指定のルーティング(user@elsewhere@domain)を含まない場合。
relay_domains_reject_codeパラメータには、拒否された要求に対する応答コードを指定します(デフォルト:554)。
reject_unknown_recipient_domain
RCPT TOアドレススにDNSA またはMXレコードがなく、Postfixがその受信者アドレスの最終配送先ではない場合に、要求を拒否します。 unknown_address_reject_code パラメータには、拒否された要求に対する応答コードを指定します(デフォルト:450)。一時的なDNSエラーの場合には、応答は常に 450 です。
reject_unlisted_recipient(Postfix 2.0の名前:check_recipient_maps)
RCPT TOアドレススがドメインクラスに対する有効な受信者リストにない場合に、要求を拒否します。詳細は smtpd_reject_unlisted_recipientの記述を参照してください。この機能はPostfix 2.1以降で使えます。
reject_unverified_recipient
RCPT TOアドレススがバウンスするとわかっている場合や、受信者アドレスの配送先に到達できない場合に、要求を拒否します。アドレス検証情報はverify(8)サーバによって管理されます;。詳細はADDRESS_VERIFICATION_READMEファイルを参照してください。
unverified_recipient_reject_codeパラメータには、アドレスがバウンスするとわかっている場合の応答を指定します(デフォルト:450、変えても安全だという自信がある場合には550に変えてください)。Postfixは一時的な問題でプローブが失敗した場合には450で応答します。この機能はPostfix 2.1以降で使えます。

●ETRNコマンド制限

 smtpd_etrn_restrictionsパラメータはETRNコマンドで指定することができるドメインや、 ETRNコマンドを実行することができるクライアントを制限します。
 デフォルトでは、Postfix SMTPサーバ はあらゆるクライアントからのあらゆるETRNコマンドを受けます。

check_etrn_access maptype:mapname
maptype:mapname
指定されたaccess databaseからETRNコマンドで指定されたドメインやその親ドメインを検索します。結果がREJECT text...や "[45]XX text"であれば要求を拒否します。結果がOKやRELAY、または全て数字であれば要求を許可します。それ以外は、結果をUCE制限の他のリストとして扱います。access_map_reject_codeパラメータには拒否した要求に対するリザルトコードを指定します(デフォルト:554)。

●一般的な制限

 以下の制限はクライアントホスト名やアドレス、HELO (EHLO) ホスト名、送信者のメールアドレスおよび受信者のメールアドレスに使えます
 デフォルトでは、Postfix SMTPサーバ はあらゆるクライアントからのあらゆるETRNコマンドを受けます。

permit
要求を許可します。この制限はデフォルトのポリシーを明示的にするために制限リストの最後に置くと便利です。
defer
要求を遅延します。クライアントには後で再び試すよう伝えられます。この制限は、デフォルトのポリシーを明示的にするために、制限リストの最後に置くと便利です。
reject
要求を拒否します。この制限はデフォルトのポリシーを明示的にするために制限リストの最後に置くと便利です。reject_code設定パラメータには拒否した要求に対する応答コードを指定します(デフォルト:554)。
warn_if_reject
要求を拒否する代わりに警告をログに記録するため、次の制限の意味を変更します("reject_warning"を含むログファイルの記録を探してください)。これは新しい制限を "生きた" 環境で不必要なメールロスのリスクなしにテストするのに便利です。
reject_unauth_pipelining
Postfixが実際にSMTPコマンドパイプライニングをサポートしていることを知る前に、クライアントがSMTPコマンドを送ってきた場合に要求を拒否します。これは配送をスピードアップするために不正にSMTPコマンドパイプライニングを使うバルクメールソフトウェアからのメールを止めます。

●補助的な制御パラメータ

 SMTPクライアント要求がreject_rblまたはreject_rhsbl制限でブロックされた場合に使われる、デフォルトの応答テンプレート。以下に示すように、応答テンプレートは1レベルだけ$name クロ置換を受けます。smtpd_expansion_filter設定パラメータには$nameマクロ展開に使うことが許される文字セットを指定します。許可されたもの以外の文字は"_"で置き換えられます。

デフォルトの設定
default_rbl_reply = $rbl_code Service unavailable; $rbl_class [$rbl_what] blocked using $rbl_domain${rbl_reason?; $rbl_reason}

$name形式の代わりに${name}や$(name)を指定することもできます。

$client
name[address]という書式の、クライアントホスト名とIPアドレス。
$client_address
クライアントのIPアドレス。
$client_name
クライアントのホスト名または"unknown"。
$helo_name
HELOまたはEHLOコマンドで与えられたホスト名または空文字列。
$rbl_class
ブラックリストに掲載された円ティティの種類: クライアントホストやHeloコマンド、送信者アドレス、受信者アドレス
$rbl_code
maps_rbl_reject_code設定パラメータで指定された、数字のSMTP応答コード。
$rbl_domain
$rbl_whatをブラックリストに掲載しているRBLドメイン。
$rbl_reason
$rbl_whatがブラックリストに掲載されている理由、または空文字列。
$rbl_what
ブラックリストに掲載されているエンティティ(ブラックリストに掲載されているIPアドレスやホスト名、ドメイン名、Eメールアドレス)。
$recipient
受信者アドレスまたはnullアドレスの場合には<>。
$recipient_domain
受信者ドメインまたは空文字列。
$recipient_name
受信者アドレスのローカル部分またはnullアドレスの場合には<>。
$sender
送信者アドレスまたはnullアドレスの場合には<>。
$sender_domain
送信者ドメインまたは空文字列。
$sender_name
送信者アドレスのローカル部分またはnullアドレスの場合には<>
${name?text}
$nameが空でない場合には`text'に展開されます。
${name:text}
$nameが空の場合には`text'に展開されます。
$nameの代わりに${name}や$(name)も指定できます。


条件マクロ展開の文法
${name?text}
$nameが空でなければtextに展開されます。
${name:text}
$nameが空の場合、textに展開されます。

●EXPN/VRFYコマンドの拒否

 EXPN コマンドによってシステムアカウントの有無を確認することができます。
 また、VRFYはメールアカウントが存在するかどうかを確認するもので存在していればそのユーザー名を表示します。EXPN、VRFYを使うとアカウントの情報が外部から容易に確認することができてしまうので、このような情報はできるなら表示させないようにします。
# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.hoge.jp ESMTP Postfix
xEHLO localhost
250-mail.hoge.jp
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH LOGIN PLAIN OTP DIGEST-MD5 CRAM-MD5
250-AUTH=LOGIN PLAIN OTP DIGEST-MD5 CRAM-MD5
250-XVERP
250 8BITMIME
xVRFY hogehoge
252 hogehoge
 EXPN・VRFYコマンドを無効にするには、以下の行を追記します。
disable_vrfy_command = yes

●Postfixバージョンの非表示

 以下のようになっている行のコメントを削除することでPostfixのバージョンを非表示にすることができます。$mail_nameを削除してPostfixの名前すら表示させないようにすることも可能です。
smtpd_banner = $myhostname ESMTP

●ブラックリストの利用

 smtpd_client_restrictionsでは、送信者制限を行うことができます。自ネットワークは許可しておき、ブラックリストに登録された送信元からのメールは拒否するように設定しておきます。
 なお、受信者制限は、smtpd_recipient_restrictionsで行います。ここでは、中国・韓国(cn-kr)、ブラジル(brazil)、ロシア(russia)からのブラックリストに登録された宛先からのメールは全て拒否します。check_client_access では、ブラックリストに登録されていないIPアドレスからのメールを拒否する際に必要となる記述です。
 以下は、Postfix2用のmain.cfです。
smtpd_client_restrictions =
   permit_mynetworks,
   reject_rbl_client relays.ordb.org,
   reject_rbl_client spamcop.net,
   reject_rbl_client dynablock.wirehub.net,
   reject_rbl_client opm.blitzed.org,
   reject_rbl_client sbl.spamhaus.org,
   reject_rbl_client list.dsbl.org,
   reject_rbl_client cn-kr.blackholes.us,
   reject_rbl_client brazil.blackholes.us,
   reject_rbl_client russia.blackholes.us
   check_client_access hash:/etc/postfix/reject_client,
   reject_unknown_client, ← 逆引きができないホストの接続を拒否
   permit

●送信元クライアント(IPアドレス)による制限

 /etc/postfix/reject_clientは、ブラックリストには登録されていないIPアドレスを直接指定して受信を拒否するためのファイルです。デフォルトでは用意されていないので作成する必要があります。
# vi/etc/postfix/reject_client
10.10.10.10 REJECT
10.10.100 REJECT
 上記の設定を反映させるためにpostmapを実行します。postmapを実行すると、reject_client.dbというDBファイルが作成されるます。そのDBをPostfixに読み込ませるためにリロードを実行します。。
# /usr/sbin/postmap /etc/postfix/reject_client
# ls -la /etc/postfix/reject_client.db
-rw-r--r-- 1 root root 1272 Jan 25 10:46 /etc/postfix/reject_client.db
# service postfix reload

●送信元ドメインによる制限

 smtpd_sender_restrictionsパラメータはMAIL FROMコマンドの送信者アドレスを制限します。reject_unknown_sender_domainは、送信者メールアドレスがDNS AまたはMXレコードを持たない場合に、要求を拒否します。reject_non_fqdn_senderは、クライアントのMAIL FROMコマンドのアドレスがFQDN形式でない場合に要求を拒否します。
# vi /etc/postfix/main.cf
smtpd_sender_restrictions =
   hash:/etc/postfix/reject_sender
   reject_unknown_sender_domain,
   reject_non_fqdn_sender
 /etc/postfix/reject_senderを作成し、制限したいドメインを記述します。その後、postmapを実行し、hashを作成します。postfixをリロードさせて設定を反映させます。
# vi /etc/postfix/reject_sender
spam@spam.hoge.jp REJECT
spam.com REJECT
# ls -la /etc/postfix/reject_sender.db
-rw-r--r-- 1 root root 24454 Jan 25 10:51 /etc/postfix/reject_sender.db
# postfix reload 

●HELOコマンドの要求

 smtpd_helo_requiredパラメータは、SMTPセッションのはじめにHELO(またはEHLO)コマンドを要求するかどうかをクライアントに対して決定します。デフォルトでは、「no」に設定されており、HELOコマンドの使用を要求しません。HELOコマンドを要求するようにしておくことで止めることができるスパムメールもありますので、「yes」に設定しておきましょう。
smtpd_helo_required = yes
 また、HELO(EHLO)ホスト名を制限するために以下の記述も追加しておきます。reject_invalid_hostnameは、クライアントのHELOもしくはEHLOパラメータに間違った文法のホスト名があった場合に要求を拒否します。
smtpd_helo_restrictions =
   permit_mynetworks,
   check_helo_access hash:/etc/postfix/ok-ips,
   reject_invalid_hostname,
   reject_unknown_hostname,
   reject_non_fqdn_hostname,
   permit

◆補足
 smtpd_helo_restrictionsパラメータでreject_unknown_hostname等がある場合、HELOで渡すホスト名とDNSの実際のホスト名が違う場合に受信を拒否することができます。
 しかし、HELOホスト名がDNSのホスト名と異なるホストはかなり多いようです。したがって、このパラメータを設定することで必要なメールまでREJECTされてしまう可能性もあります。その場合は、/etc/postfix/ok-ipsというファイルを作成し、その中に「xxx.yyy.zzz.aaa OK」という1行を記述をしてあげればそのホストからのメールは受信することができるようになります。下記のSyslogの例では、実際のホスト名が「mail1.hoge.com」なのにHELOは「mailserver.hoge.com」を渡していますのでメールを受信することができなくなっています。実際に受信したメールのヘッダを閲覧してみると、「Received: from」の箇所にmail1.hoge.comとmailserver.hoge.comの2通りの記述が見られると思います。
例)Reject されてしまう例
# tail -1000 /var/log/maillog | grep -i reject
Jan 27 15:23:19 ns1 postfix/smtpd[4516]: 56FE42EB09: reject:
          / RCPT from mail1.hoge.com[10.10.1.29]: 450 <mailserver.hoge.com>:
          / Helo command rejected: Host not found; from=<user1@hoge.com>
          / to=<kororo@hoge.co.jp> proto=ESMTP helo=<mailserver.hoge.com>
 なお、このHELO ホスト名の値を変更するには、main.cf に「smtp_helo_name」のパラメータを付加します。デフォルトでは$myhostnameに設定されています。
# postconf -v | grep helo_name
smtp_helo_name = $myhostname
# vi /etc/postfix/main.cf
smtp_helo_name = abcd.kororo.jp
# postfix reload

●サイズ制限

 ひとりあたりのメールボックスの最大サイズ(デフォルト:10MB)を制限します。
mailbox_size_limit = 1024000
 エンベロープ情報 (送信者、受信者など) を含めた、Postfix キューファイルの最大サイズの制限。
message_size_limit = 1024000

●Receivedヘッダの削除

 main.cfを編集して、「header_checks = regexp:/etc/postfix/header_checks」を有効にします。その後、/etc/postfix/header_checks を作成し以下の行を追加します。
 なお、この設定はローカル情報の「Received」ヘッダに適用されます。
/^Received:/ IGNORE
 header_checks のパーミッションを600にしておきます。
# chmod 600 /etc/postfix/header_checks
 設定前後のヘッダー情報はここを参照してください。

●Dovecotの設定

 Dovecot 2.0の設定方法を参考にDovecotをインストールします。

 以下の箇所を変更しました。
vi /etc/dovecot.conf
protocols = imap imaps pop3 pop3s
mail_location = maildir:~/Maildir

●Dovecotの起動

# systemctl enable --now dovecot
# systemctl status dovesot

or

# service dovecot start
# chkconfig dovecot on ← Dovecot自動起動設定
# chkconfig --list dovecot ← Dovecot自動起動設定確認
dovecot         0:off   1:off   2:on    3:on    4:on    5:on    6:off
     ↑ ランレベル2〜5のonを確認
・ポート110番(POPの場合)または143番(IMAPの場合)のOPEN
 ルーター側の設定でポート110番(POPの場合)または143番(IMAPの場合)をOPENします。

●Dovecot-SieveによるMaildir形式の受信ボックス振り分け

 この機能はpostfixの場合、有効となります。
 Dovecotで受信したメールを件名等で指定のフォルダに振り分けるため設定をします。dovecot-sieveをインストールします。詳細については、http://Wiki.Dovecot.org/LDA/Sieveを参照してください。
# yum -y install dovecot-sieve
 今回の構成ではpostfixではVirtualを利用せずにlocalを利用しているので、local→dovecotのdeliverコマンドを利用するように修正しました。
# vi /etc/postfix/main.cf
mailbox_command = /usr/libexec/dovecot/deliver
 設定完了後、Postfixを再起動します。
# service postfix restart
  このままでは、deliverコマンドの実行時に/etc/dovecot.confが開けないというエラーがログに出力されますので、下記のように変更しました。
# chmod 644 /etc/dovecot.conf
 dovecotでsieveプラグインを利用するように設定します。
# vi /etc/dovecot.conf
protocol lda {
          :
  mail_plugins = sieve
          :
 設定完了後、Dovecotを再起動します。
# service dovecot restart
 フィルタ条件となるsieveの設定を記述します。/home/<ユーザ名>/.dovecot.sieveのように設置します。
require "fileinto";
if header :contains "subject" "Logwatch" {
  fileinto "logwatch";
} elsif header :contains "subject" "sshd" {
  fileinto "ssh";
} else {
  # The rest goes into INBOX
  # default is "implicit keep", we do it explicitly here
  keep;
}
 件名に「Logwatch」が含まれている場合は、受信フォルダ「logwatch」に保管、「sshd」が含まれている場合は、受信フォルダ「ssh」に保管、その他のメールはデフォルトの受信フォルダに保管されるという定義です。定義に問題が無ければ、メール配送時に.dovecot.sieveファイルがコンパイルされて、.dovecot.svbinファイルが作成されることでsieveが動作していることを確認できます。定義に問題があると、.dovecot.sieve.logが作成されますので、内容を確認して修正してください。

●DovecotでのQuota設定

 DovecotでIMAP用のQuota設定を有効にするため/etc/dovecot.confのprotocol imapに以下を追加します。
mail_plugins = quota imap_quota
 protocol ldaに以下を追加します。
mail_plugins = quota
上記のDovecot-Sieveと並用するときは下記のように記載する
mail_plugins = quota sieve
 Plugin settingsに以下を追加します。
mail_plugins = quota imap_quota
 pluginに以下を追加します。
quota = maildir:User quota
quota_rule = *:storage=100MB
quota_rule2 = Trash:storage=10M
quota_rule3 = INBOX:storage=10M
 設定完了後、Dovecotを再起動します。
# service dovecot restart
 quota_ruleの詳細については、Dovecot v1.1 quotaを参照してください。
 Plugin settingsにQuota Warningを設定します。パラメータ85及び95のどちらかのシェルが実行されます。
quota_warning = storage=95%% /usr/local/bin/quota-warning.sh 95
quota_warning2 = storage=85%% /usr/local/bin/quota-warning.sh 85
 /usr/local/bin/quota-warning.shの内容は以下のとおりです。必要に応じて修正してください。
#!/bin/sh
PERCENT=$1
FROM="postmaster@domain.org"
qwf="/tmp/quota.warning.$$"
echo "From: $FROM
To: $USER
To: postmaster@domain.org
Subject: Your email quota is $PERCENT% full
Content-Type: text/plain; charset="UTF-8"
Your mailbox is now $PERCENT% full." >> $qwf
cat $qwf | /usr/sbin/sendmail -f $FROM "$USER"
rm -f $qwf
exit 0
 上記スクリプト作成後に実行権を与えてください。

●DovecotでのExpire設定

 Expire pluginを使用して特定のメールボックス内のメールを自動削除するようにします。Expire pluginについてはExpire pluginを参照してください。
 プラグインExpireでMySQLを使用する場合の設定例です。
 dovecot-mysqlをインストールします。
# yum -y dovecot-mysql
 以下は、データベースにMySQLを使用するときの/etc/dovecot.conf設定例です。
protocol imap {
  mail_plugins = expire
}
protocol pop3 {
  mail_plugins = expire
}
protocol lda {
  # probably not necessary - just enables tracking messages on mailboxes
  # where messages are never saved via IMAP and never expunged
  mail_plugins = expire
}
dict {
  # NOTE: dict process currently runs as root, so this file will be owned as root.
  expire = mysql:/etc/dovecot-dict-expire.conf
}
plugin {
  # Trash and its children 7d, Spam 30d
  expire = Trash 7 Trash/* 7 Spam 30
  expire_dict = proxy::expire
  # If you have a non-default path to auth-master, set also:
  #auth_socket_path = /var/run/dovecot/auth-master
}
 設定完了後、Dovecotを再起動します。
# service dovecot restart
 MySQLにデータベース名「mails」を作成後、下記のテーブルを作成します。
 ただし、データベースの文字コードをUTF-8に設定しているため、緑色の箇所を追記して実行しないと「ERROR 1071(42000): Specified key was too long; max key length is 1000 bytes」というエラーが表示されます。
 この原因は、UTF-8の場合計算では(100+255)*3=1065となり、主キーの長さが1000バイトを越えているのが原因のらしいです。どうやらvarcharでは、1文字分を3バイトとカウントしているようです。UTF-8では、文字によって1バイト~4バイトありますが、漢字などのマルチバイト文字の多くは3バイトなので1文字を3バイトと計算しているのだろう。
# for v1.1 only:
CREATE TABLE expires(
  mailbox varchar(255) character set latin1 not null,
  expire_stamp integer character set latin1 not null,
  primary key(mailbox)
);
# for v1.2+:
CREATE TABLE expires(
  username varchar(100) character set latin1 not null,
  mailbox varchar(255) character set latin1 not null,
  expire_stamp integer not null,
  primary key(username, mailbox)
);
 作成したデータベースにアクセスするユーザ(sqluser)とパスワード(sqlpass)を設定します。
mysql> grant select,insert,update,delete
    -> on mails.*
    -> to sqluser@localhost
    -> identified by 'sqlpass';
mysql> flush privileges;
 /etc/dovecot-dict-expire.confを作成します。
connect = host=localhost dbname=mails user=sqluser password=sqlpass
# v1.1 only:
table = expires
select_field = expire_stamp
where_field = mailbox
username_field = not_used
# v1.2+ only:
map {
  pattern = shared/expire/$user/$mailbox
  table = expires
  value_field = expire_stamp
  fields {
    username = $user
    mailbox = $mailbox
  }
}


●SMTP-AUTHの設定

 /etc/postfix/main.cfの末尾に下記行を追記します。
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_local_domain = $myhostname
smtpd_recipient_restrictions =
    # mynetworksで指定されたネットワークからのリレーを許可
    permit_mynetworks
    # SMTP認証を通過したものは許可
    permit_sasl_authenticated
    # SMTP認証を通過しないものは拒否するが、relay_domainsにあるドメインへは許可
    # (これがないとローカルユーザにメールが配信されない)
    reject_unauth_destination
    # それ以外はすべて拒否
    reject
 Submissionポート(587番ポート)を設定します。
# vi /etc/postfix/master.cf
#
# Postfix master process configuration file.  For details on the format
# of the file, see the master(5) manual page (command: "man 5 master" or
# on-line: http://www.postfix.org/master.5.html).
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd
#smtp      inet  n       -       n       -       1       postscreen
#smtpd     pass  -       -       n       -       -       smtpd
#dnsblog   unix  -       -       n       -       0       dnsblog
#tlsproxy  unix  -       -       n       -       0       tlsproxy
submission inet n       -       n       -       -       smtpd
#  -o syslog_name=postfix/submission
#  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_tls_auth_only=yes
#  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
 SASLの設定をします。
# dnf install cyrus-sasl -y

# systemctl enable --now saslauthd
 SMTP認証を設定します。
# vi /etc/sasl2/smtpd.conf
pwcheck_method: auxprop
mech_list: cram-md5 plain login
※cram-md5認証が不要の場合、cram-md5を削除

※RockyやCentOS Streamでは下記のようにしました。
pwcheck_method: saslauthd
mech_list: plain login

# systemctl restart postfix
 submissionポートが開放されているか確認します。
# ss -atm|grep submission
LISTEN     0      100                  0.0.0.0:submission                  0.0.0.0:*
 上記のように表示されれば正常に開放されています。 
 他の端末からSubmission(587)ポートに接続できるように、Firewalldを設定します。
# firewall-cmd --add-port=587/tcp --permanent
success
# firewall-cmd --reload


●SMTP-AUTHの設定(内容古い)

 SMTP-AUTHを起動します。
# service saslauthd start
# chkconfig saslauthd on ← SMTP-AUTH自動起動設定
# chkconfig --list saslauthd ← SMTP-AUTH自動起動設定確認
saslauthd       0:off   1:off   2:on    3:on    4:on    5:on    6:off
     ↑ ランレベル2〜5のonを確認
 SMTP-AUTH用ユーザ名とパスワードの組み合わせをシステムのユーザ名とパスワードの組み合わせと別々にする場合は下記のようにします。
# vi /usr/lib/sasl2/smtpd.conf ← SMTP-AUTH認証設定ファイル編集
pwcheck_method: auxprop ← 「saslauthd」を「auxprop」に変更
mech_list: plain login cram-md5 digest-md5 ← この行は認証方法に合わせて変更
ん  パスワードを作成します。
# saslpasswd2 -u (ドメイン名) -c (ユーザー名)
# saslpasswd2 -u mail.bigbang.mydns.jp -c testuser
Password: ← SMTP-AUTHで使用するパスワードの入力
Again(for verification): ← 再度、SMTP-AUTHで使用するパスワードの入力
削除する場合は
# saslpasswd2 -u mail.bigbang.mydns.jp -d testuser
登録されているユーザを表示する場合は
# sasldblistusers2
 saslpasswd2で作成されたsasldb2のアクセス権限を変更します。
# chgrp postfix /etc/sasldb2
# chmod 640 /etc/sasldb2

●SMTP-AUTHのテスト
$ telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 hoge.hogehoge.com ESMTP Postfix
ehlo localhost ← 「ehlo localhost」と入力
250-hoge.hogehoge.com
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-auth plain LOGIN DIGEST-MD5 CRAM-MD5 ← これを確認
250-AUTH=PLAIN LOGIN DIGEST-MD5 CRAM-MD5
250 8BITMIME
quit ← 「quit」と入力すると終了する
 なお、Outlook Expressで使用する設定を行っている場合には「auth plain LOGIN DIGEST-MD5 CRAM-MD5」の下に「250-AUTH=PLAIN LOGIN DIGEST-MD5 CRAM-MD5」も表示されます。

確認ができたら一端「quit」で終了し、saslpasswd2で設定したパスワードをエンコードし、正しく認証が行われるかをチェックしよう。
# printf 'ユーザー名\0ユーザー名\0パスワード' | mmencode 
もしくは
# perl -MMIME::Base64 -e 'print encode_base64("ユーザー名\0ユーザー名\0パスワード");' 
 たとえば、テスト用に「ユーザー名:hoge」、「パスワード:hoge」でパスワードを作成してからテストする場合は、先ほど解説したように
# saslpasswd2 -c -u `postconf -h myhostname` hoge 
 そのあとユーザー名パスワードをエンコードします。
# printf 'hoge\0hoge\0hoge' | mmencode
aG9nZQBob2dlAGhvZ2U= 
Telnetでlocalhostのポート25番に接続し、ehloのあとに「auth plain エンコードしたユーザー名パスワード」を入力します。正しくないパスワードでのエンコードも行って正常に認証されるかテストします。
# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 hoge.hogehoge.com ESMTP Postfix
ehlo localhost ← 「ehlo localhost」と入力
250-zdnet.homelinux.org
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-auth plain LOGIN DIGEST-MD5 CRAM-MD5
250-AUTH=PLAIN LOGIN DIGEST-MD5 CRAM-MD5
250 8BITMIME
auth plain aG9nZQBob2dlAGhvZ2U= ← エンコードしたパスワードを入力
235 Authentication successful ← 認証が成功している
quit ← 「quit」と入力
念のため、間違ったパスワードを入力してテストしてみよう。
# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 hoge.hogehoge.com ESMTP Postfix
ehlo localhost ← 「ehlo localhost」と入力
250-zdnet.homelinux.org
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-auth plain LOGIN DIGEST-MD5 CRAM-MD5
250-AUTH=PLAIN LOGIN DIGEST-MD5 CRAM-MD5
250 8BITMIME
auth plain aG9nZQBob2dlAHRlc3Q=[ ← 間違ったパスワードを入力
535 Error: authentication failed ← 認証が失敗している
quit ← 「quit」と入力
テストが完了したらテスト用のアカウントを削除しておこう。
# saslpasswd2 -d -u `postconf -h myhostname` hoge 


●メールサーバSASL化後のメールクライアント設定

 メールクライアントからSubmission(587)ポートを採用したメールサーバにメールを送信する場合は、587番ポートあてにメールを送る必要があります。
 更に、ユーザ認証技術「SMTP AUTH」(SMTP authentication)が必須となります。
 このままでは暗号化されていませんので、メールクライアント(メーラ)側で暗号化するようにSTARTTLSを利用してください。

●メールサーバのTLS化(SMTPs):2023年9月中旬以降採用

 メール送受信用のPOP3/IMAP4/SMTPプロトコルは、メール本文や認証用パスワードが暗号化されないため、その対策としてTLSを導入します。
 ただし、暗号化される区間はユーザー・メールサーバ間のみであり、メールサーバと送信先メールサーバ間は暗号化されないので注意してください。

 SSL/TLSの設定(Let's Encryptを利用)

 参考URL:Mail サーバー : SSL/TLS の設定

 Let's Encrypt証明書を利用して設定します。証明書の設定は、●Let's Encrypt証明書の設定(Snapd)を参照し設定しておきます。
# vi /etc/postfix/master.cf
# 下記のように変更
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd
  :
(途中省略)
  :
submission inet n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
#  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_tls_auth_only=yes
  :
(途中省略)
  :
smtps     inet  n       -       n       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
(以下省略)

# vi /etc/postfix/main.cf
# 下記行をコメント化
#smtpd_tls_cert_file = /etc/pki/tls/certs/postfix.pem
#smtpd_tls_key_file = /etc/pki/tls/private/postfix.key

# 最終行に追記(証明書はLet's Encrypt証明書を利用)
smtpd_use_tls = yes
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
smtpd_tls_cert_file = /etc/letsencrypt/live/www.bigbang.mydns.jp/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/www.bigbang.mydns.jp/privkey.pem
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache

# SMTP認証設定
# smtp auth SASL認証有効化
smtp_sasl_auth_enable = yes
# SASL認証情報ファイル指定
smtp_sasl_password_maps = hash:/etc/postfix/smtp_pass
# 認証設定のセキュリティオプション指定
# anonymous(匿名)ユーザでのログインを許可しない設定とする。
# デフォルトの設定は「noanonymous,noplaintext」ですが、プロバイダが用意しているSMTPサーバでは「plain」(暗号化なし)での
# 認証が有効化されていることが多いため、「noplaintext」を記述しないことで「plain」(暗号化なし)での認証を許可した。
smtp_sasl_tls_security_options = noanonymous
# 認証方法の指定
smtp_sasl_mechanism_filter = plain,login

# 暗号化設定
# ODNのSMTPサーバから応答により(maillogで覚知)、「may」から「encrypt」に変更
smtp_tls_security_level = encrypt
# ODNのSMTPサーバから応答により(maillogで覚知)、設定
smtp_tls_wrappermode = yes
# 暗号化設定のログ出力設定
# 0 TLS関するログ記録を無効
# 1 TLSハンドシェイクと証明書情報をログに出力
# 2 TLSネゴシエーションの間のレベルをログに出力
# 3 TLSネゴシエーションプロセスの16進数とASCIIダンプをログに出力
# 4 STARTTLS以降の通信の16進数と完全なASCIIダンプをログに出力
smtp_tls_loglevel = 1
smtp_tls_CApath = /etc/pki/tls/certs
 上記設定は、/etc/pki/tls/certs/ca-bundle.crtにリンクされていることを要確認
 リンクされていない場合、下記の用に直接指定
smtp_tls_CApath = /etc/pki/tls/certs/ca-bundle.crt

# SMTP認証情報ファイル作成
形式:[相手先smtpサーバ]:465 ユーザID:パスワード
相手先smtpサーバは「/etc/postfix/main.cf」の「relayhost」で設定した内容と同じにします。

# SASL認証情報ファイルの作成
# vi /etc/postfix/smtp_pass
[smtpssl.odn.ne.jp]:465	ユーザID:パスワード

# パーミッションの変更
# chmod 600 /etc/postfix/smtp_pass

# 認証ファイルのhash化
# postmap /etc/postfix/smtp_pass

# 以下、Dovecotの設定
# vi /etc/dovecot/conf.d/10-ssl.conf
# 変更(SSLを必須にする場合はrequiredのまま)
ssl = yes

# Let's Encrypt証明書を指定
#ssl_cert = </etc/pki/dovecot/certs/dovecot.pem ← コメントアウト
#ssl_key = </etc/pki/dovecot/private/dovecot.pem ← コメントアウト
ssl_cert = </etc/letsencrypt/live/www.bigbang.mydns.jp/fullchain.pem ← Let's Encryptの証明書を設定
ssl_key = </etc/letsencrypt/live/www.bigbang.mydns.jp/privkey.pem ← Let's Encryptの証明書を設定

dovecot、postfixを再起動
# systemctl restart postfix dovecot
 必要に応じて、SMTPサブミッション(587/tcp)、SMTPs(465/tcp)、POP3s(995/tcp)、IMAPs(993/tcp)サービスを許可します。
# firewall-cmd --add-service={smtp-submission,smtps,pop3s,imaps} --permanent
# firewall-cmd --reload
 該当ポートが開放されているか確認します。
# ss -plnt


 サーバ証明書(オレオレ証明書)の作成

 CA認証局の構築については、●CA認証局の構築を参照してください。
 また、サーバ証明書にCAの署名を付加する方法については、●セキュア(SSL)なWebサーバの構築を参照してください。

 メールサーバ用の署名要求証明書を作成します。
# cd /etc/pki/tls/certs/

※postfixの場合
# openssl req -new -key server.key -out postfix.csr
※dovecotの場合
# openssl req -new -key server.key -out dovecot.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:空のまま「Enter」
Organization Name (eg, company) [Default Company Ltd]:BIGBANG
Organizational Unit Name (eg, section) []:空のまま「Enter」
Common Name (eg, your name or your server's hostname) []:www.bigbang.mydns.jp
Email Address []:webmaster@mail.bigbang.mydns.jp
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:空のまま「Enter」
An optional company name []:空のまま「Enter」
 サーバ署名要求証明書へCAの署名を付加します。
※postfixの場合
# openssl ca -config /etc/pki/tls/openssl.cnf -in postfix.csr -keyfile /etc/pki/CA/private/cakey.pem -cert /etc/pki/CA/cacert.pem -out postfix.crt
※dovecotの場合
# openssl ca -config /etc/pki/tls/openssl.cnf -in dovecot.csr -keyfile /etc/pki/CA/private/cakey.pem -cert /etc/pki/CA/cacert.pem -out dovecot.crt
Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for /etc/pki/CA/private/cakey.pem:パスワードを入力
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 9348937751764410297 (0x81be195a39281fb9)
        Validity
            Not Before: Mar  4 05:43:14 2016 GMT
            Not After : Mar  2 05:43:14 2026 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = BIGBANG
            commonName                = www.bigbang.mydns.jp
            emailAddress              = webmaster@mail.bigbang.mydns.jp
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Comment: 
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier: 
                C4:3F:……
            X509v3 Authority Key Identifier: 
                keyid:AF:CB:……
Certificate is to be certified until Mar  2 05:43:14 2026 GMT (3650 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
 また、ブラウザ(メーラー)インポート用にDERファイルを作成します。
※postfixの場合
# openssl x509 -in postfix.crt -out /var/www/html/postfix.der -outform DER
※dovecotの場合
# openssl x509 -in dovecot.crt -out /var/www/html/dovecot.der -outform DER

 SSL/TLSの設定(オレオレ証明書を利用)
# vi /etc/postfix/main.cf
以下を最終行に追加
# Server side TLS
smtpd_tls_CApath = /etc/pki/tls/certs
smtpd_use_tls = yes
smtpd_tls_ask_ccert = yes
smtpd_tls_received_header = yes
smtpd_tls_cert_file = /etc/pki/tls/certs/postfix.crt
smtpd_tls_key_file = /etc/pki/tls/certs/server.key
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
# Client side TLS
smtp_use_tls = yes
smtp_tls_key_file = /etc/pki/tls/certs/server.key
smtp_tls_cert_file = /etc/pki/tls/certs/postfix.crt
#smtp_tls_CAfile = /etc/ssl/private/cacert.crt
# Misc TLS
smtp_tls_loglevel = 1
smtpd_tls_loglevel = 1
#smtp_tls_session_cache_database = btree:/etc/postfix/smtp_tls_session_cache
#smtp_tls_session_cache_timeout = 3600s
#smtpd_tls_session_cache_database = btree:/etc/postfix/smtpd_tls_session_cache
#smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom

# vi /etc/postfix/master.cf
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#              (yes)  (yes)  (yes)  (never)(100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd
#smtps     inet  n       -       n       -       -       smtpd
 ↑ 行頭の#を削除(コメント解除)
#  -o smtpd_tls_wrappermode=yes ← 行頭の#を削除(コメント解除)
#  -o smtpd_sasl_auth_enable=yes ← 行頭の#を削除(コメント解除)

smtps     inet  n       -       n       -       -       smtpd
  -o smtpd_tls_wrappermode=yes
#  -o smtpd_sasl_auth_enable=yes
# /etc/rc.d/init.d/postfix restart ← Postfix再起動
 これで(sasl_auth_enable以外の2箇所の変更で)HTTPSと同じようにいきなりTLSセッションから始まるSMTPS通信を利用できるようになります。
 下記ポートを開けます。
# firewall-cmd --add-port=25/tcp --permanent
# firewall-cmd --add-port=587/tcp --permanent
# firewall-cmd --add-port=465/tcp --permanent
# systemctl restart firewalld
 smtpsで接続できるかどうか確認します。
# openssl s_client -connect mail.bigbang.mydns.jp:465
CONNECTED(00000003)
~中略~
    Verify return code: 18 (self signed certificate)
---
220 mail.bigbang.mydns.jp ESMTP Postfix unknown
→ コマンド入力待ち状態
 自己証明書ということで怒られますが、接続確認ができました。なお、
# openssl s_client -connect mail.bigbang.mydns.jp:465 -CAfile <認証局証明書>
で認証局の証明書を指定した場合は
Verify return code: 0 (ok)
の応答があります。商用CAの証明書であれば問題ないはずです。
 Submissionポート(TCP587)の設定をします。OP25Bの回避策として使われるSubmissionではSTARTTLSでの設定になります。STARTTLSはは、EHLO後、セッションの途中からTLSに切り替える通信方法です。
# vi/etc/postfix/master.cf
submission inet n - n - - smtpd
と
-o smtpd_tls_security_level=encrypt
のコメントをはずしましょう。
 このsmtpd_tls_security_levelですが、設定値を

 encrypt

にしてしまうと、クライアントから接続時に

 530 5.7.0 Must issue a STARTTLS command first

と必ずSTARTTLSをしてから送れ、と言われてしまいます。条件にもよるのですが、暗号化を必須としない場合
-o smtpd_tls_security_level=may
にしておいたほうが良いかもしれません。

 Dovecotの設定
# vi /etc/dovecot/conf.d/10-ssl.conf
# SSL/TLS support: yes, no, required.
ssl = yes
# サーバ証明書の指定、下記2行
ssl_cert_file = /etc/pki/tls/certs/dovecot.crt
ssl_key_file = /etc/pki/tls/certs/server.key
# /etc/rc.d/init.d/dovecot restart ← dovecot再起動
 ポート995番(POPの場合)または993番(IMAPの場合)を開けます。
 SSLを利用したIMAPでの接続時に、接続できずに下記のようなエラー表示される場合があります。
Error: SSL: Stacked error: error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca: SSL alert number 48
 このため、CA認証局ではないサーバで下記の対策を施しました。

 CA秘密鍵(/etc/pki/CA/private/cakey.pem)のリモートサーバへのコピー
 CA証明書(/etc/pki/CA/cacert.pem)のリモートサーバへのコピー
# scp /etc/pki/CA/cacert.pem root@mercury:/etc/pki/CA
# scp /etc/pki/CA/private/cakey.pem root@mercury:/etc/pki/CA/private
 CA証明書のderファイルを作成し、他のサーバからアクセスしやすい場所に保存します。
# openssl x509 -inform pem -in /etc/pki/CA/cacert.pem -outform der -out /var/www/html/cacert.der
 これによりエラーは表示されなくなりましたが、IMAPに接続(CentOS 7はOK、Fedora 22は2016.03.14現在×)できません。

 メーラ(Outlook Express)の設定

メニューの「ツール」→「アカウント」→「メール」タブ→設定するアカンウトの選択→「プロパティ」をクリック→「詳細設定」でメールの設定を行います。

 「このサーバはセキュリティで保護された接続(SSL)が必要」を送信メール、受信メールともにチェックします。
 「サーバのポート番号」、「送信メール」に「465」と入力します。
 「サーバのポート番号」、「受信メール」に「993」と入力します(自動で変更される)。
 なお、受信メールにPOPを使用している時、上記は、「995」が自動的に変更されます。



 サーバ証明書のインポート

 メーラからメールサーバへアクセスするたびに以下のような警告ウィンドウが表示されて煩わしいので、サーバ証明書をクライアントへインポートすることにより、警告ウィンドウが表示されないようにします。



 クライアントへのインポート用サーバ証明書を作成します。
# cd /etc/pki/tls/certs/
# openssl x509 -in mail.pem -outform DER -out mail.der ← インポート用サーバ証明書作成
 ※mail.derというファイル名でインポート用サーバ証明書が作成されるので、クライアント側へコピーします(コピーする手段は利用者が限られた仲間内の場合はフロッピー、メール等でもいいですが、利用者が不特定多数の場合はWeb上で公開すればいい)。 当サイトのサーバ証明書は、ここからダウンロード出来ます。
サーバ側からコピーしてきたインポート用サーバ証明書(server.der)をダブルクリックします。

 「証明書のインストール」をクリックします。


 「次へ」をクリックします。


 「次へ」をクリックします。


 「完了」をクリックします。


 「はい」をクリックします。


 「OK」をクリックします。


 もし、下記のようなウィンドウが表示された場合は、サーバ証明書作成時に入力した「Common Name(eg, your name or your server's hostname) []:」の箇所とメーラの送信メールまたは受信メールの設定とが一致しているかどうか確認してください。


 例えば、Outlook Expressの場合、「Common Name(eg, your name or your server's hostname) []:」で「mail.bigbang.mydns.jp」と入力したにもかかわらず、下記のように「受信メール」及び「送信メール」の設定をIPアドレスで入力している場合、上記の警告ウィンドウが表示されます。


 その場合は下記のように、「受信メール」及び「送信メール」の設定を「mail.bigbang.mydns.jp」としてください。


●メール送信テスト

 オプションは以下のとおりです。

-v 詳細情報を表示する
-b 指定したアドレスをBCC宛てにする
-c 指定したアドレスをCC宛てにする
-s タイトル名 タイトル名がメールの表題になる

 簡単な例は以下のようです。

mail -s 件名 宛先

 実際には以下のように実行します。件名にスペースやドット等が入る場合は「""」で囲んでください。
$ mail -s "This is TEST" To@mail.com ← 「リターンキー」を押下
TEST ← 本文を記載後、「Ctrl」+「D」を押下
Cc: ← が表示されるので、もう一度「Ctrl」+「D」を押下
$ ← プロンプトが表示されたらメールが送信されます。
 送信先のメールを確認してください。テストで送ったメールが届いていると思います。
「-s "This is TEST"」はタイトルを設定しています。この例だと、メールのタイトルは「This is TEST」で届きます。

 覚えておくと便利なテクニック

 コマンドでメールを送信するには下記のように実行します。
$ cat $BODY | mail -s $SUBJECT $TO
$BODY:メール本文
$SUBJECT:件名
$TO:宛先
$ vi message ← 「message」ファイル作成
 ファイルに定型メッセージ書くとこんなことができます。 ← 作成した文書
 ↑メッセージはなんでもいいんですが、今回は
  「ファイルに定型メッセージ書くとこんなことができます。」
 と入力しました。
$ cat message | mail -s testmail To@mail.com
 上記のコマンドは「cat message」の結果をメールの本文にして、「mail」コマンドで送信する方法です。こうすることで、定型のメッセージを送れるようになります。
 ただし、この場合は大抵メーラ側で日本語が文字化けします。これはmailコマンドを使用して送信する場合、どのような文字コードを示すHeaderが無いためです。これを回避するには「cat」コマンドではなく、「nkf」コマンドを利用します。

 nkfコマンドの主な文字コードのオプションは下記の通りです。

-j JISコードを出力する(デフォルト)。
-e EUCコードを出力する。
-s Shift_JISコードを出力する。
-w8 UTF8コードを出力する。

 ですので、UTF8コードを使用したい場合は下記のように実行します。
$ nkf -w8 < message | mail -s testmail To@mail.com
 これを応用すると、いくつか定型文を書いたファイルを用意しておいて、シェルスクリプトの処理結果によって、送信するメッセージを変えるということもできます。他にメッセージだけじゃなく、システムログやファイルの内容をメールで送るなんてこともできます。
# nkf -w8 < /var/log/messages | mail -s log To@mail.com
 上記はLinuxサーバのメッセージログを、メールで送信しています。
 ※注意
  ・送る内容はセキュリティーの面から気をつける必要があります。
  ・サイズがあまり大きいものを送るのは止めましょう!
  ・環境によっては上記をcronで実行すると読み込んだファイルがメール本文ではなく、添付ファイルになってしまう場合があります。
   この場合、下記のようにすると改善するかもしれません。
    * * * * * LANG=ja_JP.uft8 [Script Source]
    * * * * * LC_CTYPE=ja_JP.UTF-8 [Script Source]
    * * * * * /usr/local/bin/nkf -w [読み込み対象ファイル] [Script Source]
    * * * * * /usr/local/bin/nkf -jM [読み込み対象ファイル] [Script Source]

 メールのFromを指定する

 メールのFromを指定するには下記のようにします。
$ mail -r From@yahoo.co.jp -s testmail To@mail.com
 ただし、下記の記載ではうまく送信出来ませんでした。
 $ mail -s testmail To@mail.com -r From@yahoo.co.jp
 「-r」も「From@yahoo.co.jp」も宛先のアドレスと解釈されてしまう。
 受信側ではToに以下のようにアドレスに記載されていました。
 From@yahoo.co.jp, -r@yahoo.co.jp, To@mail.com


 s-nailパッケージのmailコマンドでメールのFromを指定する

 s-nailパッケージのmailコマンドでFromを指定するには下記のようにします。

 参考URL:CentOS 9 でmailコマンドを使う
 参考URL:S-nail

$ vi .mailrc
set mta=smtp://<メールサーバのIPアドレス>:25

$ echo "TEST" | mailx -r FROM@mail.bigbang.mydns.jp -s testmail TO@mail.bigbang.mydns.jp
 しかし、下記のようなエラーが表示されメールを送信することが出来ませんでした。
s-nail: Obsoletion warning: Use of old-style credentials, which will vanish in v15!
s-nail:   Please read the manual section "On URL syntax and credential lookup"
 https://access.redhat.com/solutions/7007021 に対処方法がありました。
1.Please add v15-compat=yes -Ssmtp-auth=none options in the command for non-authentication.

# echo "TEST `date`" | mail -s "Test mail from RHEL9-01" -S v15-compat=yes -Ssmtp-auth=none --debug -S mta=smtp://127.0.0.1:25 root@localhost
「--debug」を削除することで送信できるようになります。

2.If you want to send mail via authentication, please refer to below command.

# echo "TEST `date`" | mail -s test -S v15-compat=yes -S smtp-use-starttls -S smtp-auth=login -S mta=smtp://USER:PASSWORD@XXX.XXX.xx.xx:587 -r XXXX@uu.yy.xx


●メール送信用シェルスクリプト

 以下は、件名及び本文共に日本語を利用して送信テストを行うためのシェルスクリプトです。(2017.2.9シェルスクリプト更新)

 参考URL:bash で メールヘッダを編集してEメールを送る

 RFC違反にならないようメールヘッダを記述しています。メールヘッダを記述するためmailコマンドではなくsendmailコマンドを使用しています。
#!/bin/bash
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin
# このスクリプトの保存ディレクトリ
DIR=`dirname $0`
# nkfコマンド
NKF=`which nkf`
NKFJ="$NKF -j"
NKFJM="$NKF -jM
# sendmailコマンド
SENDMAIL=`which sendmail`
SENDMAIL="$SENDMAIL -t"
# メールヘッダ
MAIL_HEADERS='Content-Type: text/plain; charset="ISO-2022-JP"
Content-Transfer-Encoding: 7bit
MIME-Version: 1.0'
# 送信元
FROM="soushinmoto@mail.bigbang.mydns.jp"
# 宛先
TO="atesaki@mail.aaa.bbb.jp
# 件名
SUBJECT="メール送信試験"
# 件名の文字コードをエンコード
SUBJECT=`echo $SUBJECT | $NKFJM`
# 本文
BODY="これはメール送信試験です。"
# 本文の文字コードをエンコード
BODY=`echo $BODY | $NKFJ`
echo "$MAIL_HEADERS
Subject: $SUBJECT
From: $FROM
To: $TO
$BODY" | $SENDMAIL
#!/bin/sh
#----------------------------------------
#メール送信テスト
#----------------------------------------
#初期設定(宛先、件名、本文またはコマンド)
address="宛先"
subject="メール送信テスト"
messages="これはメール送信テストです。\n件名及び本文の日本語が文字化けしないかの確認です。"
cmd="df -h"
#件名の文字コードをShift_JISに変換
subject=`echo $subject | nkf -s`
#メール送信(本文の文字コードをShift_JISに変換)
mail -s "$subject" $address << HONBUN
`echo -e $messages | nkf -s`
`$cmd | nkf -s`
HONBUN
#終了
exit


●メールキュー

 参考URL:Postfixのキューが詰まった時の対処

 Postfixのメールキューを確認、削除する方法を記載します。

# postqueue -p

-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
EC7FF818C538 320 Mon Feb 13 09:34:14 hoge-san@yahoo.co.jp
(connect to mailsv1.hoge.co.jp[xxx.xxx.xxx.xxx]:25: Connection timed out)
XXXXX@mail.domain.co.jp

-- 3 Kbytes in 1 Requests.

# mailq

-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
EC7FF818C538 320 Mon Feb 13 09:34:14 hoge-san@yahoo.co.jp
(connect to mailsv1.hoge.co.jp[xxx.xxx.xxx.xxx]:25: Connection timed out)
XXXXX@mail.domain.co.jp

-- 3 Kbytes in 1 Requests.


 キューに入っているメールの内容を確認するには、下記のようにします。
$ postcat -q [Queue ID]
 キューに入っているメールの内容を確認(その2)するには、下記のようにします。

$ for qid in $(ls /var/spool/postfix/hold/); do postcat -q $qid | grep '^sender: \|^recipient: ' | xargs echo -n; echo; done > /tmp/queue.txt

--------------------
sender: hoge@hoge.com recipient: foge@foge.com


 特定のメールキューを削除するには、下記のようにします。
# postsuper -d [Queue ID]
 すべてのメールキューを削除するには、下記のようにします。
# postsuper -d ALL
 ちなみに、キューに溜まったメールを強制再送するには、下記のようにします。
キューを指定
$ postqueue -i [Queue ID]
保留キュー全再送
$ postfix flush
または
$ postqueue -f


●不正リレーのチェック

 下記のサイトを利用できます。

 Anonymous Relay Test
 open relay checker

 fail2banを利用している場合、ブロックされてしまいチェックが途中でできなくなりますので、一時的に停止させてください。

●/etc/aliases.dbが存在しない

 maillogに下記のようなエラーが出力され、postfixが動作していませんでした。
 error: open database /etc/aliases.db: No such file or directory
 上記の場合は、下記コマンドを実行してください。
# postalias /etc/aliases
 /etc/aliasesを変更した場合、必ずnewaliasesコマンドを実行してください。
# newaliases
 この時点でpostfixには新しいaliases情報が反映されますが思った転送をしない場合は、aliasesファイルの再確認し、postfixを再起動してください。

●statistics: max connection rate 1/60s for (smtp:IPアドレス)

 /var/log/maillogに下記のようなログが記録されていました。

May 8 19:27:39 server postfix/anvil[29610]: statistics: max connection rate 1/60s for (smtp:::1) at May 8 19:17:39
May 8 19:27:39 server postfix/anvil[29610]: statistics: max connection count 1 for (smtp:::1) at May 8 19:17:39
May 8 19:27:39 server postfix/anvil[29610]: statistics: max cache size 1 at May 8 19:17:39


 原因は、一定時間内に同一クライアントから接続できる回数を上回っていることです。
 対策としては2つあります。

 対策1:接続上限数を緩和する

 /etc/postfix/main.cf ファイルの smtpd_client_connection_rate_limit に大きな値を設定します。
 または、anvil_rate_time_unit の時間を短くします。デフォルトは、smtpd_client_message_rate_limit = 60sであるので、smtpd_client_message_rate_limit = 10sなどに変更します。

 補足1
 改善されない場合は、同時接続数の上限設定smtpd_client_connection_count_limitの値を見直します。

 補足2
 メールが送信できない場合は、smtpd_client_message_rate_limitの値も見直します。

 対策2:接続元のネットワークを制限対象から外す

 /etc/postfix/main.cfファイルに下記のように記載し制限対象から除外します。
smtpd_client_event_limit_exceptions = 127.0.0.0/8
または
smtpd_client_event_limit_exceptions = $mynetworks


●454 4.7.1 Relay access denied

 仮想IPを切り替えたところZabbixからメール送信ができなくなってしまいました。
 Postfixの場合、大抵、下記、2つの設定値に問題があることが多い。
  • mynetworks
  • smtpd_relay_restrictions
 smtpd_relay_restrictionsは、メールをリレーをする際の制限ルールを記載します。デフォルトではpermit_mynetworks、 permit_sasl_authenticated、defer_unauth_destinationが設定されています。
  • permit_mynetworks
    mynetworksに記載されたネットワークからのメールリレーを許可
  • permit_sasl_authenticated
    SASLで認証されたメールのリレーを許可
  • pdefer_unauth_destination
    不明な宛先からのメールリレーを一時的なエラーコード(4xx)で拒否
 上記の3つのルールは先頭から順番に処理されるようです。
 今回の場合、mynetworksにメールクライアントのネットワークアドレスを設定しなかったのが原因でした。
 したがって、エラーを回避するためにメールクライアントのネットワークアドレスをmynetworksに追記します。
# vi /etc/postfix/main.sf
mynetworks = 127.0.0.0/8, 192.168.0/24, 172.16/16

# systemctl restart postfix
 以上で、設定は完了です。

●inet_protocols: disabling IPv6

 参考URL:CentOS7のIPv6無効化設定

 /var/log/maillogに下記のようなメッセージが大量に記録されていました。

Jan 30 03:23:01 node1 postfix/sendmail[2166796]: warning: inet_protocols: disabling IPv6 name/address support: Address family not supported by protocol
Jan 30 03:23:01 node1 postfix/postdrop[2166810]: warning: inet_protocols: disabling IPv6 name/address support: Address family not supported by protocol
Jan 30 03:23:01 node1 postfix/postdrop[2166810]: warning: unable to look up public/pickup: No such file or directory
Jan 30 03:24:01 node1 postfix/sendmail[2167833]: warning: inet_protocols: disabling IPv6 name/address support: Address family not supported by protocol
Jan 30 03:24:01 node1 postfix/postdrop[2167843]: warning: inet_protocols: disabling IPv6 name/address support: Address family not supported by protocol
Jan 30 03:24:01 node1 postfix/postdrop[2167843]: warning: unable to look up public/pickup: No such file or directory
Jan 30 03:25:01 node1 postfix/sendmail[2168952]: warning: inet_protocols: disabling IPv6 name/address support: Address family not supported by protocol
Jan 30 03:25:01 node1 postfix/postdrop[2168973]: warning: inet_protocols: disabling IPv6 name/address support: Address family not supported by protocol
Jan 30 03:25:02 node1 postfix/postdrop[2168973]: warning: unable to look up public/pickup: No such file or directory
Jan 30 03:26:01 node1 postfix/sendmail[2170229]: warning: inet_protocols: disabling IPv6 name/address support: Address family not supported by protocol
Jan 30 03:26:01 node1 postfix/postdrop[2170238]: warning: inet_protocols: disabling IPv6 name/address support: Address family not supported by protocol
Jan 30 03:26:01 node1 postfix/postdrop[2170238]: warning: unable to look up public/pickup: No such file or directory
Jan 30 03:27:01 node1 postfix/sendmail[2171209]: warning: inet_protocols: disabling IPv6 name/address support: Address family not supported by protocol
Jan 30 03:27:01 node1 postfix/postdrop[2171217]: warning: inet_protocols: disabling IPv6 name/address support: Address family not supported by protocol
Jan 30 03:27:02 node1 postfix/postdrop[2171217]: warning: unable to look up public/pickup: No such file or directory
Jan 30 03:28:01 node1 postfix/sendmail[2172232]: warning: inet_protocols: disabling IPv6 name/address support: Address family not supported by protocol
Jan 30 03:28:01 node1 postfix/postdrop[2172252]: warning: inet_protocols: disabling IPv6 name/address support: Address family not supported by protocol
Jan 30 03:28:01 node1 postfix/postdrop[2172252]: warning: unable to look up public/pickup: No such file or directory

 当該ホストではIPv6を使用しないこととしたために生じた影響です。
 問題を解消するため下記のように対応しました。
# vi /etc/postfix/main.cf
※下記のように変更
# Enable IPv4, and IPv6 if supported
#inet_protocols = all ← 行頭に#を付加
 ↓
inet_protocols = ipv4
# postfix check
# systemctl restart postfix
 この作業によりエラーが出力されなくなりました。

●SSL alert number 42

 ※2022.05.06追記
 「SSL alert number 42」となりthunderbirdのIMAPSの接続が拒否されるのは、オレオレ証明書を利用している場合や正式なSSL証明書でもFQDNが異なっている場合で、セキュリティ強化による影響のようです。
 ローカルネットワークからのメール受信サーバへの接続をこれまでIMAPSで問題なく接続できていたのですが、何度トライしてもIMAPSで接続できなくなってしまいました。
 (後日dovecotの設定を確認したところ、/etc/dovecot/conf.d/10-ssl.confのssl_cert及びssl_keyの設定がデフォルトのままでした。Let's Encrypt証明書に置き換えて問題解消しました。)
 仕方ないので、IMAPS(993)での接続をやめてIMAP(143)で接続することにより問題を解消させました。

 普段Thunderbirdを利用しているのですが、突然サーバ(送受信とも)に接続できなくなりました。
 /var/log/maillogを確認してみると、下記のようなエラーが記録されていました。

Feb 8 09:36:32 serverA dovecot[2096]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=<クライアントIP>, lip=<受信メールサーバIP>, TLS handshaking: SSL_accept() failed: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate: SSL alert number 42, session=<hwGi6HbHYofAqCDB>

 /etc/postfix/main.cf、/etc/dovecot/conf.d/10-ssl.confの設定に問題ありませんでした(問題発生の前後で設定変更した記憶なし)。
 Thunderbirdの設定を確認したところ、SMTPサーバ及びIMAPサーバの「サーバー名」の設定をIPアドレスで指定していました(これまでは、この設定で利用できていた。2022年2月7日時点)。
 そこで、IPアドレスからホスト名(SSL証明書で指定しているFQDN)に変更したところ正常に接続できるようになりました。

Feb 9 13:35:26 serverA dovecot[442589]: imap-login: Login: user=<ユーザ名>, method=PLAIN, rip=<クライアントIP>, lip=<受信メールサーバIP>, mpid=471034, TLS, session=<N+PWXI7XV/TAqABo>
Feb 9 13:44:03 serverA dovecot[442589]: imap-login: Login: user=<ユーザ名>, method=PLAIN, rip=<クライアントIP>, lip=<受信メールサーバIP>, mpid=471035, TLS, session=<vN/WXI7XVvTAqABo>

 その後、ホスト名からIPアドレスに戻しても正常に接続できるようになりました。一体何が原因だったのだろうか・・・。

●SSL alert number 42(その2)

 インターネット経由で接続していたメールサービス(IMAPS)に接続てきていないことが分かりました。
 ログ(/var/log/maillog)を確認したところ、下記のようなエラーが記録されていました。

Jan 15 22:36:39 tk2-235-27182 dovecot[2950]: imap-login: Disconnected: Connection closed: SSL_accept() failed: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate: SSL alert number 42 (no auth attempts in 0 secs): user=<>, rip=<クライアントIP>, lip=<受信メールサーバIP>, TLS handshaking: SSL_accept() failed: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate: SSL alert number 42, session=<W8ehGVXydvg8TE2h>
 /etc/dovecot/conf.d/10-ssl.confの設定を確認したところ、ssl_certの指定が間違っていました。
 これを修正(fullchain.pem → cert.pem)し、Dovcotを再起動したところ正常に接続できるようになりました。
 今まで問題なく接続できていたことが、問題なような気がしますが・・・。

●status=deferred

 突然、プロバイダのメールサーバとの送受信が出来なくなりました。

2022/11/15 12:08:02 serverA postfix/smtp[2353447]: connect to smtpssl.odn.ne.jp[143.***.***.***]:25: Connection refused
2022/11/15 12:08:02 serverA postfix/smtp[2353447]: 83AF130B16C9D: to=<uhouho@***.***.ne.jp>, relay=none, delay=0.38, delays=0.3/0.02/0.06/0, dsn=4.4.1, status=deferred (connect to *****.odn.ne.jp***[143.***.***.***]:25: Connection refused)
2022/11/15 12:08:02 serverA postfix/smtp[2353447]: 83AF130B16C9D: to=<nikoniko@***.***.ne.jp>, relay=none, delay=0.38, delays=0.3/0.02/0.06/0, dsn=4.4.1, status=deferred (connect to *****.odn.ne.jp***[143.***.***.***]:25: Connection refused)

 以前、deferredになった時はプロバイダのメールサーバが変更になったことに気が付かずpostfixを運用していたためでした。
 この時は、relayhostを設定変更することにより正常に戻りました。

 今回は、maillogを確認すると直前までメールの送受信が出来ていることを確認しました。
 インターネット側から、および、イントラネット側からメール送信試験をしましたが、どちらも失敗しました。
 原因が不明のため、サーバを再起動しましたが問題は解消されませんでした。

 もう少しmaillogを確認します。
 すると下記のようなログを発見しました。

2022/11/16 09:31:55 serverA postfix/smtpd[75727]: warning: connect to Milter service unix:/var/run/milter-manager/milter-manager.sock: No such file or directory
2022/11/16 09:32:55 serverA postfix/smtpd[75727]: warning: connect to Milter service unix:/var/run/milter-manager/milter-manager.sock: No such file or directory
2022/11/16 09:33:38 serverA postfix/smtpd[75727]: warning: connect to Milter service unix:/var/run/milter-manager/milter-manager.sock: No such file or directory
2022/11/16 09:33:55 serverA postfix/smtpd[75727]: warning: connect to Milter service unix:/var/run/milter-manager/milter-manager.sock: No such file or directory
2022/11/16 09:34:55 serverA postfix/smtpd[75727]: warning: connect to Milter service unix:/var/run/milter-manager/milter-manager.sock: No such file or directory

 下記を実行したところ、インターネット側からメールを受信できるようになりました。
# systemctl start milter-manager
# systemctl restart postfix
 ただし、イントラネット側からの送信(2022.11.20 04:58:09から送信不能に)はまだてきていません。
 これまではプロバイダのメールサーバの25番ポートを指定していました。
 これまで利用できていた25番ポートが空いているか確認してみます。
# telnet smtpssl.odn.ne.jp 25
Trying 143.***.***.***...
telnet: connect to address 143.***.***.***: Connection refused
 25番ポートが閉じられて接続が出来ないようなので465番ポート(SMTP over SSL)を使用するように変更します。
ODNメールサーバ(465番ポート)を使用するための準備
# vi /etc/postfix/odn_mail_pass
[smtpssl.odn.ne.jp]:465 ACCOUNT:password
 ↑ ODNアカウント(メールアドレス)、パスワードを記載

# chmod 600 /etc/postfix/odn_mail_pass
# postmap /etc/postfix/odn_mail_pass

# vi /etc/postfix/main.cf

※変更箇所のみ
relayhost = [smtpssl.odn.ne.jp]:465 ← 変更
smtp_tls_wrappermode = yes ← 追加
smtp_tls_security_level = encrypt ← 追加
smtp_sasl_password_maps = hash:/etc/postfix/odn_mail_pass ← 追加

# systemctl restart postfix
 これで465番ポートを使用してメール送信できるようになりました。