フレッツADSL導入日誌

home / adsl / qmail / remove-prepend-v2 remove-prepend (V2) for qmail

導入編
FreeBSDルーター編
ローカルDNSサーバー
フレッツADSLで固定IP
ドメイン取得とDNS運用
>>> メールサーバー / remove-prepend-V2パッチ
Webサーバー
10 Jun 2017 新規作成。

 古いタイプ(qmail-localにパッチを当てるタイプ)、qmail-localとの戯れ方はこちらです。 remove-prepend for qmail

 netqmail-1.06用のパッチです。 仮想ドメインを使ったときに-ownerアドレスに仮想ドメインプレフィックスがついてしまう不具合の修正を行います。 ついでに、virtualdomains vs. VERP and Delivered-Toのパッチも入ってます。

このソフトウェアは現状のまま提供されるものであり、このソフトウェアを使用した結果生じた直接的・間接的な、あるいはその他のいかなる損害に対しても、作者は責任を負いません。

BEFORE using the following patch, READ preamble of the patch.

netqmail-1.06-removeprepend2-0.1.patch

 ~user/.qmailで転送を指示した場合に、~user/.qmail-ownerがあると、表書き差出人がuser-owner@example.jpの形に書き換えられます。 このアドレスは~user/.qmail-ownerの配送指示に従いますが、このファイルがあるからこのアドレスが生成されたので、必ず配送が可能です。

 一方、user@virtual.domaincontrol/virtualdomainsに合致するとprepend-プレフィックスが付けられて配送されます。 これはユーザーprependに配送され、~prepend/.qmail-user の配送指示に従います。

 もし、~prepend/.qmail-userで転送が指示されていて、~prepend/.qmail-user-ownerが存在すると、表書き差出人はprepend-user-owner@virtual.domainに書き換えられますが、このアドレスにメールを差し出すとcontrol/virtualdomainsによりさらにプレフィックスが付けられてしまい、prepend-prepend-user-owner@virtual.domain宛に配送されることになります。 このアドレスは~prepend/.qmail-prepend-user-ownerの配送指示に従いますが、普通このようなファイルはありませんから、このメールは正しく配送されません。

 また、prepend-というのは一種の内部情報で、外に漏れて欲しくない場合もあるでしょう。

 prepend-を付けているのはqmail-sendです。 表書き差出人を書き換えているのはqmail-localです。 qmail-sendからqmail-localを呼び出すまでの間で、prepend-を削ればより望ましい動作になるでしょう。 以前は一生懸命qmail-localで削除していましたが、このパッチではqmail-sendでprepend-を付けるときに、内部では-:にしておき、qmail-localを呼び出すまでの間で:より前を削除することで実現しています。

 qmail-localは削られたアドレスしか受け取らないので、Delivered-To:ヘッダフィールドにもprepend-を削ったアドレスが出力されます。 .qmailから起動されるコマンドに渡される環境変数NEWSENDERLOCALRECIPIENTも、prepend-を削ったものが渡されます。 LOCALRECIPIENTについては以前のバージョンと動作が異なりますので注意してください。

 制御ファイルは使用しません。 コロンが特殊文字扱いになりますが、変えたい人はビルドする前にvdom-sep.hの中身を書き換えてください。

 副作用として、ログファイルへの受取人アドレスの出力で、prepend-の最後のハイフンがコロンになります。 また、prepend-がない場合も、先頭にコロンが付きます。

 このパッチを当てなくても、~prepend/.qmail-userでqmail-injectの-fオプションで表書き差出人アドレスを差し替えれば解決します。 複数の宛先に転送したい場合は、qmail-injectで表書き差出人アドレスを書き換えた上で配送用のローカルなアドレスにメールを投げ、そのアドレスに転送先のアドレスを並べればOKです。 要するにメーリングリストと同じ要領です。

home / adsl / qmail / remove-prepend-v2 内部構造

 qmail-sendがキューからメールを取りだすと、まず、rewrite関数でlocalsvirtualdomainsにヒットするかどうかを調べます。 localsにヒットすればそのままローカル配送、virtualdomainsにヒットすればアドレスの前にprepend-を付加してローカル配送、それ以外の場合はそのままリモート配送になります。

 このとき、virtualdomainsにヒットした場合に付加するprepend-を、後ろをコロンにしてprepend:にします。 その他の場合は先頭にコロンを付けておきます。 これでprependそれ自身にハイフンが含まれていても、どこまでがprependかはっきり分かります。 また、先頭がコロンならばprependがないこともすぐに分かります。

 続いて、qmail-lspawnあるいはqmail-rspawnに対して、パイプ経由でコマンドが渡ります。 このふたつのプログラムは構造がちょっと特殊で、main関数がどちらもspawn.cの中にあり、そこからspawn関数を呼び出すようになっています。 この関数がqmail-lspawn.cとqmail-rspawn.cの中にあり、どちらをリンクするかで実際の動作が決まるようになっています。

 で、spawn.cのdocmdでそれぞれのspawn関数を呼び出しているため、この部分はlspawnとrspawnで処理が共通になっていないと面倒です。 先ほど、リモート配送の場合も先頭にコロンを付けていましたが、それはdocmd関数がローカルとリモートで共通になっているからです。 spawn関数を呼び出すときにprependの後ろのコロンをハイフンに戻し、さらに、今までの引数に追加してprepend-の文字数をspawn関数に渡します。 これで簡単にprepend-を外すことができます。

 qmail-lspawnではnughde_get関数(name, uid, gid, home, dash, ext、のことらしい)で配送先ユーザーを決めていますが、ここではコロンをハイフンに置き換えた(prepend-を外す前の)受取アドレスを使います。 最終的にspawn関数からqmail-localあるいはqmail-remoteをexecしますが、コマンドラインを作るときにprepend-を外してしまいます。 これでqmail-localにはprepend-がやって来ませんから、Delivered-To:も環境変数も、転送時のownerも、一切prepend-が付くことはありません。

 qmail-remoteはprepend-は関係ないのですが、先ほど説明したように、spawn関数の呼び出し側がlocalと共通になっているので、qmail-localと同様にprepend-を外すコードを一応入れてあります。 prepend-がなければコロンは外された状態で飛んでくるので放っておいても大丈夫なはずですが。

 なお、バウンスを発生させるときはqmail-sendがprepend-を外しています。 この時に呼び出すstripvdomprependも何かごちゃごちゃやっていますが、prependのデリミタをコロンに変えてしまったので、ばっさり書き換えてあります。


Copyright (C) 2017 You SUZUKI

$Id: remove-prepend-v2.htm,v 1.4 2018/10/27 05:39:36 you Exp $