Post Fixの最近のブログ記事

久々にメールアドレスでも新しく作ろうと思って、nologinで新規ユーザ作成してみた。

thunderbirdでちゃちゃちゃとアカウント設定して、いざ受信って思ったら、
「接続:ホストにログイン情報を送信しています・・・」
のまま音沙汰なし。

パスワードとかいろいろ確認しても特におかしくないので、とりあえずmaillogを確認したら、こんなメッセージが。

-----------------------------------------------------------------------------------------
dovecot.... mail_location not set and autodetection failed: Mail storage autodetection failed with home=......
-----------------------------------------------------------------------------------------

うーん、これはなんだろう。

なんか雰囲気的に、メールボックスの場所が指定されてないから、メールを取りにいけません的な感じだろうか・・・

おかしいなあ、前までは普通にユーザ作成してメーラーの設定するだけですぐにいけたんだけどなあ・・・
と思いつつ、とりあえず問題ありそうな「/etc/dovecot.conf」を確認。

ってゆうか、このファイル一回も中身見たことないし〜。

メールサーバ入れたときもdovecotの設定なんか一回もやんなかったのに・・・
デフォルトでいままでいけてたんですけどね。


でもなんかこの辺が臭かったので、

-------------------------------------------------------------------------------------------
# Location for users' mailboxes. This is the same as the old default_mail_env
# setting. The default is empty, which means that Dovecot tries to find the
# mailboxes automatically. This won't work if the user doesn't have any mail
# yet, so you should explicitly tell Dovecot the full location.
#
# If you're using mbox, giving a path to the INBOX file (eg. /var/mail/%u)
# isn't enough. You'll also need to tell Dovecot where the other mailboxes are
# kept. This is called the "root mail directory", and it must be the first
# path given in the mail_location setting.
#
# There are a few special variables you can use, eg.:
#
# %u - username
# %n - user part in user@domain, same as %u if there's no domain
# %d - domain part in user@domain, empty if there's no domain
# %h - home directory
#
# See for full list. Some examples:
#
# mail_location = maildir:~/Maildir
# mail_location = mbox:~/mail:INBOX=/var/mail/%u
# mail_location = mbox:/var/mail/%d/%1n/%n:INDEX=/var/indexes/%d/%1n/%n
#
#
#
#mail_location =
-------------------------------------------------------------------------------------------

google様で直訳してみると、locationの設定は必須ですよ〜みたいな感じなのかな?

とりあえず例のまんま設定してみる。

-------------------------------------------------------------------------------------------
mail_location = mbox:~/mail:INBOX=/var/mail/%u
-------------------------------------------------------------------------------------------

てなかんじ。

すると・・・おお!メーラーがちゃんとメールを読みに行った!

なんじゃそりゃ。


ユーザディレクトリにも「mail」ディレクトリが作成されてる。
さっきまで無かったのに・・・
この「mail」ディレクトリって何なのかわかんなかったけど、dovecotが勝手に作ってるんですね・・・


とりあえずpopはOKそうなので、ついでにSMTP(postfix)の方も確認。
/etc/postfix/main.cfを開いて、それっぽい部分を見てみると、

-------------------------------------------------------------------------------------------
# DELIVERY TO MAILBOX
#
# The home_mailbox parameter specifies the optional pathname of a
# mailbox file relative to a user's home directory. The default
# mailbox file is /var/spool/mail/user or /var/mail/user. Specify
# "Maildir/" for qmail-style delivery (the / is required).
#
#home_mailbox = Mailbox
#home_mailbox = Maildir/
-------------------------------------------------------------------------------------------

どうやら、デフォルトのメールボックスは/var/spool/mail/userか、 /var/mail/userで、何もいじらないとここにメールを届けに行くらしい。
というわけで、さっきのdovecotの設定とつじつまがあってるのでOK。

まあ、ちゃんとした人たちはMaildir形式にちゃんと設定してるんだろうけど、横着な私はこれで問題無し。


一応確認のためにpostfixから送信して、dovecotで取りに行ってちゃんと読めたのでめでたし。

しかし軽く7時間かかったのは痛かった。


サーバ立ち上げた時から今まで問題なかったのに、いつからdovecotのデフォルト設定変わったの?って感じ。

アップデートなんてまったくやってないのに。

・・・よくわからないなー
同じサーバでメインのドメイン以下サブドメインを複数運用しているが、そのうちの一つでメールが送れない現象が発生。

最近BINDの設定をちゃちゃっと済ませていたので、メールログの内容をもよく見ないで、BINDの設定を間違ってると勝手に思い込んでいた。

zone設定ファイルと延々とにらめっこするも、決定的な原因見つからず・・・

$ nslookup -type=MX xxxx.jp

のコマンドは正常にMXが引けているし、named.confの設定も何回も見直したがどこもおかしくない。
ってゆうか、他のサブドメインと設定は一緒で、それらは問題なくメールの送受信ができてるのになぜ?みたいな感じになって頭を抱えていたら、maillogに
「・・・loops back to myself・・・」
というエラー文を発見。(遅っ!)

よくみたらバウンスメールにも書いてあるし・・・


・・・ということは、postfixのせいか?

ということでpostfixのmain,cfファイルをみてみたら、なんと

mydestination = の項目に、当該ドメインを指定し忘れている!!

やっちまったー、正味5時間の無駄。
指定した後は何ら問題なく送受信ができるようになりました。


というわけで、今日は、先入観を持たずに、常にmaillogを見るくせをつけようという教訓を得ました・・・

前回の応用編として、バウンスされたエラーアドレスを、メルマガごとに処理してみる。
(過去記事:「メルマガのエラーアドレスやバウンスメールを自動的に処理する方法(PostFix)」)
(環境:fedora9、postfix2.23以降、perl5.8.X)

まず、VERPを利用の際に、sendmailパスを以下のようにしてみる。

sendmail -XV -f bounce+$magazine_name

もちろん$magazine_nameにはメルマガ名とかメルマガ番号とかが格納されてること。



次に、/etc/postfix/main.cf の設定は前回と同じ。




次に、バウンスメール処理用のプログラム(perl)を以下のようにカスタマイズする。
(設置場所は前回同様、/home/owner/に設置)

例:process_bounce.cgi(705 or 755)


#!/usr/bin/perl -w

my ($magazine_name, $deadadd);

#バウンスメールのヘッダ及び本文を標準入力から取得
while(<>){
    #最初に出てきたTo行から宛先を取得
    if ($_ =~ /^To: "?bounce\+(.+?)\+(.+?)\=(.+?)"?\@mydomain.jp\n$/){
        $magazine_name = $1;            #最初に設定した$magazine_nameが取得できる
        $deadadd = $2."@".$3;            #ここでエラーアドレスを取得
        last;
    }
}


#
#
#このあたりで、mysqlに接続するなどして、不逹アドレスを削除する処理
#
#取得した$magazine_nameの値を利用して、読者削除したい対象のメルマガが指定可能
#

exit;


※こうすることによって、データベース処理が楽になる。
※もう一つ前回と違う点は、ペーストする正規表現を、

  /^To: "?bounce\+(.+?)\+(.+?)\=(.+?)"?\@mydomain.jp\n$/

としたところ。

これは、相手先MTAが、バウンズを返すエンベローブアドレスを""でくくってよこす場合があるので、そのための対処。





postfixなどで、送信時にホストに接続できなかったりして再配送処理(deferやdeferred)に廻ってしまったメールキューは、手動で削除しない限り、デフォルトの5日間は数分おきに延々と再配送処理を繰り返す。
main.cfの設定でこの期間を短縮することは可能だが、ウザいので手っ取り早く消してしまいたいときは、管理者権限からエディタ(gedit)を起動して、

/var/spool/postfix/defer/メールIDの最初の1文字/メールID

のファイルを抹消すれば良い。

コマンドラインから行うときは、

# postsuper -d ALL defer (or deferred)

で実行可能。
ディレクトリを指定しない場合は、/var/spool/postfix/ 以下のすべてのキューが削除される。

command not found となってしまうときは、管理者権限を得るときに、
su じゃなくて、 su - で上位ディレクトリから行うとできるはずです。


なぜこの作業が必要かというと、前回の記事でバウンスメールの処理を行うにあたり、バウンスが返ってこなければ削除が行われないということに起因する。

deferが繰り替えされる要因としては、
1.ホスト名の解決はできたが、そのホストのDNSサーバに接続できずMXレコードが引けず、Connection timed out になるため、postfixは再送を試みる。
2.同じく、DNSサーバで名前解決はしたが、接続されるはずのメールサーバがダウンしている、もしくは存在しないため Connection timed out となり、postfixは再送を試みる。

これらが大半を占めると思われる。

なので、大量のメールアドレスを扱うメルマガ配信システムを持ってる場合等は、一日一回はメールキューの処理を行なったほうがいいかもしれない。
ただし、メールキューを削除すると、メールアドレスは正常であるにもかかわらず何らかの理由でdeferなどに一時的にまわったキューも削除されてしまうので注意。


「n回以上 Connection timed out になったキューは自動的に管理者にバウンスを返す」
みたいな設定ができればいいんだけどな・・・
もしかするとマニュアルをよく読めばできるのかな・・・

どなたかお知恵を貸してください。
おそらく、この世にメルマガ配信システムはたくさんあるので、この方法は
広く使われていると思うのだが、いくら検索しても具体的に説明されてるサイトが
ないので、忘れないようにメモ。
(環境:fedora9、postfix2.23以降、perl5.8.X)

まず、VERPを利用するので、sendmailを使う場合はパス指定時に、

sendmail -XV -f bounce

と指定。
※postfixのバージョンが2.2以前の場合は -XV じゃなく -V 。
※bounceの部分は別にhogeでも何でもよい。
※sendmailを使わない場合(SMTPに直接送るときとか)は、別にVERPを使わなくても、
エンベロープMailFromに
"バウンスを受けたい架空のアカウント"+"送信先のアカウント"="送信先ドメイン"@"自ドメイン"の形で指定できればOK。


次に、/etc/postfix/main.cf に以下を追記

recipient_delimiter = +
propagate_unmatched_extensions = canonical, virtual

※1行目は、送られてくるバウンスメールの宛先アドレスは、「+」で区切りますよ、とpostfixに教えている。
※2行目は、デリミタ以降(extensions)は、エイリアスに展開する際、無視しますよということをpostfixに教えている。
※これらの変数や定義値は、postfixのデフォルトなので、変更していればそれに合わせてください。


次に、バウンスメール処理用のプログラムをperlで作成。(ここでは/home/owner/に設置)

例:process_bounce.cgi(705 or 755)


#!/usr/bin/perl -w

my ($bouncetxt, $deadadd);

while(<>){    #バウンスメールのヘッダ及び本文を標準入力から取得
    #最初に出てきたTo行から不逹の宛先を取得
    if ($_ =~ /^To: bounce\+(.+?)\=(.+?)\@mydomain.jp\n$/){
        $deadadd = $1."@".$2;
        last;
    }
}

#
#
#このあたりで、mysqlに接続するなどして、不逹アドレスを削除する処理
#
#
#

exit;

※これは別にperlじゃなくても、CでもJavaでもshellでもなんでもいい。
※ポイントは標準入力からメール内容を受け取れるということ。



次に、/etc/aliases (OSやpostfixのヴァージョンによっては、 /etc/postfix/aliases とか)に以下を追記。

bounce:     |/home/owner/process_bounce.cgi

※エイリアスで、さっき書いたメール内容を処理するプログラムのコマンド(場所)をパイプで指定する。
※もし、セキュリティ上smrshなどの影響で、コマンドを渡せない場合は、コマンドラインから
# cd /etc/smrsh
# ln -s /home/owner/process_bounce.cgi process_bounce.cgi
などと打って対処する。



最後にエイリアスデータベースを初期化&postfix再起動

# newaliases
# /etc/init.d/postfix restart


これで、リターンメールやバウンスメールを受信する度にスクリプトが起動して、
死にアドレスを自動でデータベースから削除してくれるので、次回送信時から無駄な
送信負荷がなくなる。

ここでちょっと気になるのが、パイプでコマンドに渡されたメールキューは
どこにいくのかということだが、maillogを確認したところ、コマンドに渡した直後に
勝手にremoveされていたので一安心。
/var/spool/postfix をのぞいてみたらちゃんと削除されていた。


また、ホスト名が解決できない場合のバウンス(host not found)はすぐに返ってくるので、メルマガ送信後すぐに削除処理されるが、実在するホストの場合、アカウントが存在しなくてもホストのMTAによっては送信リトライを繰り返すような場合がある。
この場合、deferedフォルダにキューが溜まってしまうが、いずれアカウントが見つからない
といったバウンスが返ってくるので、24時間後とかに処理さる場合もあると思う。
(まだ未確認)

また、当たり前だが、相手先のMTAがアカウント不明の受信メールはすべて破棄し、バウンスを返さない設定になっていればこの方法は使えない。



このアーカイブについて

このページには、過去に書かれたブログ記事のうちPost Fixカテゴリに属しているものが含まれています。

前のカテゴリはPHPです。

次のカテゴリはサーバ構築です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

Powered by Movable Type 4.22-ja