sendmailでaliasesが効かない

sendmailでaliasesが効かない現象に遭遇。私が管理している環境ではインタネットからのメールはsendmailで受け取り、その後Dominoへ転送しています。

特定のアドレスに送信されたメールに対して特定の処理をする必要があり、以下のようなaliasesを記述。

hoge:        "|/export/home/hoge/hoge.pl"

newaliases実行後、sendmail -bv で確認。

# /usr/lib/sendmail -bv hoge
"|/export/home/hoge/hoge.pl"... deliverable: mailer prog, user |/export/home/hoge/hoge.pl

しかしながら、smtpで接続してメールを送信してみても期待された結果が得られない。以下の例だとNG。

# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 mail.example.com ESMTP Sendmail 8.14.4/8.14.3; Thu, 16 Feb 2012 15:30:15 +0900 (JST)
EHLO www
250-mail.example.com Hello localhost [127.0.0.1], pleased to meet you
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-8BITMIME
250-SIZE
250-DSN
250-ETRN
250-DELIVERBY
250 HELP
mail from:hoge@example.com
250 2.1.0 hoge@example.com... Sender ok
rcpt to:hoge.example.com
250 2.1.5 hoge@example.com... Recipient ok
data
354 Enter mail, end with "." on a line by itself
this is test
.
250 2.0.0 q1G6URG8011039 Message accepted for delivery

いろいろ試していると、rcpt toのところが 'hoge@example.com'ではなくて、'hoge'のみだと期待される動作、つまりaliasesでパイプ指定したプログラムが動作することがわかりました。

なんでだろ

さてなんでだろうと考える。ドメイン付きのアドレスと、なしのアドレスでなにが違うのかをsendmailデバッグモードで調べてみる。メールアドレスがどう解釈されているかですね。

まず、ドメインなしアドレスの場合。

# /usr/lib/sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> 3,0 hoge
canonify           input: hoge
Canonify2          input: hoge
Canonify2        returns: hoge
canonify         returns: hoge
parse              input: hoge
Parse0             input: hoge
Parse0           returns: hoge
ParseLocal         input: hoge
ParseLocal       returns: hoge
Parse1             input: hoge
Parse1           returns: $# local $: hoge
parse            returns: $# local $: hoge

次にドメイン付きのアドレス。

> 3,0 hoge@example
canonify           input: hoge @ example . com
Canonify2          input: hoge < @ example . com >
Canonify2        returns: hoge < @ example . com . >
canonify         returns: hoge < @ example . com . >
parse              input: hoge < @ example . com . >
Parse0             input: hoge < @ example . com . >
Parse0           returns: hoge < @ example . com . >
ParseLocal         input: hoge < @ example . com . >
ParseLocal       returns: hoge < @ example . com . >
Parse1             input: hoge < @ example . com . >
MailerToTriple     input: < > hoge < @ example . com . >
MailerToTriple   returns: hoge < @ example . com . >
Parse1           returns: $# esmtp $@ example . com . $: hoge < @ example . com . >
parse            returns: $# esmtp $@ example . com . $: hoge < @ example . com>

それぞれの一番最後の行が最終的に解釈されたトリプレット。配信エージェントが$#の次に書かれているもので、それぞれlocalとesmtpとなっています。

配信エージェントが違う

配信エージェントが違うことがわかりました。つまりドメインなしのアドレスの場合はlocalで処理して、ドメイン付きのアドレスの場合はesmtpで別のサーバに転送するってことです。この環境の場合はDominoへ転送しているんですね。
で、配信エージェントにかんするところを少々調べてみる。参考図書はこちら。

sendmail 第3版〈VOLUME2〉設定編

sendmail 第3版〈VOLUME2〉設定編

これの133ページあたりに配信エージェントのフラグ(F=)に関する記述があります。その中にAliasに関するものは。。ありました。'A'というオプションがあると、その配送エージェントではアライアスを展開するようです。
localhost,esmtpそれぞれの配信エージェントはこうなっています。

Mlocal,         P=/usr/lib/mail.local, F=lsDFMAw5:/|@qfSmn9, S=EnvFromL/HdrFrom
Mesmtp,         P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\
r\n, L=990,

なるほど。localhostのFにはAがあるけれども、esmtpにはありませんね。

ということで

ということで原因がわかったので、以下のように設定。

sendmail.cfのMesmtpのF=にAを追加。
Mesmtp,         P=[IPC], F=mDFMuXaA, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\
r\n, L=990,(以下略)
aliasesを以下に
hoge@example.com:        "|/export/home/hoge/hoge.pl"
newaliasesを実行
# newaliases

これで期待したとおりの動作が得られました。よかった。