前提
メールシステム移転のため、現行メールサーバに届いたメールのコピーを、次期メールサーバにも転送しなければならない(並行配送しなければならない)ことになりました。
まず、次期メールサーバでは alice@example.jp
だけでなく alice@migration.example.jp
でもメールを受け取るように設定しました。後は、現行メールサーバに届いた、alice@example.jp
宛のメールのコピーを alice@migration.example.jp
にも送信するように設定すれば良いだけです。
案①転送用 LDAP 属性を新設する
本学のメールシステムでは、各利用者のメール転送先アドレスは ~/.forward ではなく LDAP で管理されています。
myhostname = old-mail-server.example.jp
mydomain = example.jp
mydestination = $myhostname, $mydomain
alias_maps =
hash:/etc/postfix/aliases
ldap:/etc/postfix/forward.cf
server_host=ldap.example.jp
server_port=389
timeout=20
search_base=ou=users,dc=example,dc=jp
scope=one
query_filter=(uid=%u)
result_attribute=examplePersonMailForward
したがって、各ユーザに LDAP 属性を追加すれば、まったく難しいことはなかったんです。例えば、次のように属性を追加して、
dn: uid=alice,ou=users,dc=example,dc=jp
examplePersonMailForward: alice-mobile@docomo.ne.jp
examplePersonMailMigrationAddress: alice@migration.example.jp
以下のように、LDAP の検索で2つの属性の値を両方返すように設定する。
server_host=ldap.example.jp
server_port=389
timeout=20
search_base=ou=users,dc=example,dc=jp
scope=one
query_filter=(uid=%u)
result_attribute=examplePersonMailForward, examplePersonMailMigrationAddress
ところが、どんな場合でも、やむを得ない事情というのは存在するものです。例えば、メールサーバと LDAP サーバを管轄している業者が違うとか、LDAP サーバを含む認証基盤システムについても設定変更が予定されていて LDAP サーバの急な設定変更(上記はスキーマの変更を必要としますから)が難しいとか、メールシステム移転までの残日数が少なくて LDAP サーバの設定変更が待てないとか…
案②canonical_maps と virtual_alias_maps を使う
というわけで、代替案です。qmgr(8) および local(8) の段階で並行配送できないならば、その前段階である cleanup(8) の段階で並行配送するしかありません。しかし、動作テストが大変になるので、mydomain パラメータや mydestination パラメータは変更したくありません。というわけで、以下のような案が考えられます。
↓
+-----------+
| smtpd |
+-----------+
↓
+-----------+ ①canonical_maps を使って、alice@example.jp 宛メールを一旦、alice@migration-forward.example.jp 宛に書き換える。
| cleanup | ②virtual_alias_maps を使って、alice@migration-forward.example.jp 宛のメールを
+-----------+ alice@example.jp 宛と alice@migration.example.jp 宛に書き換える。
↓
+-----------+
| qmgr |
+-----------+
↓
しかし、実際には、現行メールサーバでは既に virtual_alias_maps パラメータにかなり面倒な設定が作り込まれているために、上記のように単純に変更することはできませんでした…
現実:content_filter と canonical_maps と virtual_alias_maps を使う
というわけで、現実の経路は、以下のようになります。scansmtpd と scancleanup は、この設定のために新設したサービス名です。
↓
+-----------+
| smtpd |
+-----------+
↓
+-----------+
| cleanup | canonical_maps と virtual_alias_maps は既存システムが利用している
+-----------+
↓ content_filter パラメータを使って、全てのメールを localhost:10025 に転送
+-----------+
| scansmtpd | localhost:10025 で待受
+-----------+
↓
+-----------+ ①canonical_maps を使って、alice@example.jp 宛メールを一旦、alice@migration-forward.example.jp 宛に書き換える。
|scancleanup| ②virtual_alias_maps を使って、alice@migration-forward.example.jp 宛のメールを
+-----------+ alice@example.jp 宛と alice@migration.example.jp 宛に書き換える。
↓
+-----------+
| qmgr |
+-----------+
↓
設定としては、高度なコンテンツフィルタを使う設定を少しアレンジした形になります。まず、必要なサービスを作ります。
scan unix - - n - 64 smtp
-o syslog_name=postfix/scan
-o smtp_send_xforward_command=yes
-o smtp_enforce_tls=no
10025 inet n - n - 64 smtpd
-o syslog_name=postfix/scan
-o content_filter=
-o smtpd_helo_restrictions=
-o smtpd_client_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
-o cleanup_service_name=scancleanup
scancleanup unix n - - - 0 cleanup
-o syslog_name=postfix/scan
-o canonical_classes=envelope_recipient
-o canonical_maps=hash:/etc/postfix/migration_rewrite
-o virtual_alias_domains=migration-forward.example.jp
-o virtual_alias_maps=tcp:localhost:10003
scan は localhost:10025 で待ち受けている smtpd に配送するための特別な配送経路で、content_filter パラメータに指定します。
content_filter = scan:localhost:10025
localhost:10025 で待ち受けている smtpd(図では scansmtpd と記載)は、並行配送を行うための特別な cleanup プロセス(図では scancleanup と記載)を呼び出すための特別な smtpd です。そのために、/etc/postfix/master.cf
では、明示的に cleanup_service_name を書き換えています。
scancleanup が実際の並行配送のためのアドレス書き換えを行います。
@example.jp @migration-forward.example.jp
というようなファイルを用意して、
$ sudo postmap hash:/etc/postfix/migration_rewrite
データベースを作成しておきます。scancleanup 配送はまず、canonical_classes と canonical_maps の指定にしたがって、配送先メールアドレスの alice@example.jp
を alice@migration-forward.example.jp
に変換します。
その次に、virtual_alias_domains と virtual_alias_maps の指定により、実際に並行配送したいアドレスに変換します。scancleanup 配送に関する設定は、以下の通り(再掲)です。
scancleanup unix n - - - 0 cleanup
-o syslog_name=postfix/scan
-o canonical_classes=envelope_recipient
-o canonical_maps=hash:/etc/postfix/migration_rewrite
-o virtual_alias_domains=migration-forward.example.jp
-o virtual_alias_maps=tcp:localhost:10003
ここで、virtual_alias_domains が migration-forward.example.jp
となっていることがポイントです。このドメインに属するアドレス、例えば alice@migration-forward.example.jp
宛のメールの宛先は、TCP アドレス変換サーバに問い合わせを行うようになっています。この部分についての詳細は、「任意のスクリプトを使ってアドレス変換を行う」を参照してください。