マルチドメインなPostfix + Dovecot + MariaDB with lmtp環境でメール転送を行う
家ではマルチドメインなメールサーバーをPostfix + Dovecotで建てて、sasl認証にはDovecotのlmtpを利用しています。構築当初から、以前のmacos serverではできていた、メールアドレスは作るが、受信については別のメールアドレスに集約させるということがうまくできませんでした。a@mitsugi.jpというアカウントを作成して使うけれど、内部的にはb@mitsugi.jpに転送させておいて、メーラーではb@mitsugi.jpでしか確認しない、みたいな感じです。別にa@mitsugi.jpでアクセスすればいいだけの話なのですが、これが数あると面倒なのです。設定的にはマニュアル通りに行って問題ないはずなのに、メールサーバーのログを見ると、a@mitsugi.jpなんてユーザーは存在しないと言ってエラーになってしまう。仕方ないのでしばらくはa@mitsugi.jpで受信させてsieveなんかで転送させていました。最近、Alma LinuxからUbuntuに移行させることを見越してこのあたりを再度きちんと調べたところ、下記のような感じで実現できましたので、あまりニーズはないかと思いますが備忘録的に記載しておきます。なお、私の環境ではMaria DBをメールアカウント管理用に使用していて、DBのテーブル構成・構造についてはpostfixadminのものを参考に必要な部分のみ手動管理しています。postfixadminだとテーブル構造的に外部制約入れたりしてるんですが、個人メールサーバーではそこまでしなくても問題ないので、あえてシンプルな構造にしています。DBについては基本的に関連するテーブルはmailboxテーブルとaliasテーブルの2つだけで、これは標準のpostfixadminのテーブル構造と同じような感じです。
MariaDB [user]> DESC mailbox;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(128) | NO | UNI | NULL | |
| password | varchar(150) | NO | | NULL | |
| maildir | varchar(128) | NO | | NULL | |
| local_part | varchar(128) | NO | | NULL | |
| domain | varchar(128) | NO | | NULL | |
| is_active | tinyint(1) | NO | | 1 | |
+------------+--------------+------+-----+---------+----------------+
MariaDB [user]> DESC alias;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| address | varchar(128) | NO | UNI | NULL | |
| goto | text | NO | | NULL | |
| domain | varchar(128) | NO | | NULL | |
| sendonly | tinyint(1) | NO | | 0 | |
| is_active | tinyint(1) | NO | | 1 | |
+-----------+--------------+------+-----+---------+----------------+
基本的にこれで、postfix側の設定ファイルmain.cfでvirtual_alias_maps・virtual_mailbox_mapsでaliasテーブルおよびmailboxテーブルのクエリーとを記載しておけばよしなにしてくれるはずと思っていたのですが、これだけではダメでした。後、lmtpを利用した認証なのでDovecot側の設定ファイルにパスワード用のクエリー文を記載するのですが、そこで単純にmailboxテーブル宛のクエリーを書くだけではなく、aliasテーブル宛のクエリーをUNIONで繋げてやる必要があるようです。パスワード用のクエリーを下記のような感じで設定することでうまくいきました。
$ cat /etc/dovecot/dovecot-sql.conf.ext
--------------------- snip ---------------------
password_query = \
SELECT \
username AS user, \
password \
FROM \
mailbox \
WHERE \
username = '%u' \
AND is_active = '1' \
UNION \
SELECT \
username AS user, \
password \
FROM \
mailbox \
WHERE \
username = ( \
SELECT \
goto \
FROM \
alias \
WHERE \
address = '%u' \
AND is_active = '1')
--------------------- snip ---------------------
改行を入れまくっているのは単に見やすさの問題でそうしているだけなので、別に必要はありません。
また、同時に送信専用アカウントも実装させています。aliasテーブルのsendonlyカラムで管理するようにしていて、私の環境ではここを1にしてやると送信専用扱いとしています。クエリー文を例えば /etc/postfix/recipient_sendonly.cfとして、
$ cat /etc/postfix/recipient_sendonly.cf
user = <DB認証用ユーザー>
password = <DB認証用ユーザーのパスワード>
hosts = <DB address>
dbname = <DB name>
query = SELECT 'REJECT Sorry this address is sending only.' as action FROM alias
WHERE address='%s'
AND sendonly = '1'
AND is_active = '1'
のようにして、あとはこのファイルをpostfixのmain.cfのsmtpd_recipient_restrictionsの先頭に下記のように加える感じです。
smtpd_recipient_restrictions = check_recipient_access mysql:/etc/postfix/recipient_sendonly.cf,