Ubuntu

Ubuntu20.04 Mailman3でマルチドメインなメーリングリスト 後編

前編でMailman3をインストールしたが、サーバーからの連絡が英語なので、これを日本語にする。
また、メーリングリストを運用したい各ドメインからのメール転送を設定する。



広告


ついでに、テスト環境のPostfixでSMTP認証を行う方法についても書いてみた。

メールメッセージの日本語化

国際化についてはこちらに説明があり、誰でも参加が可能とされている。
Internationalization(i18n)

また、各種通知のメールは、こちらにあるものをすべて翻訳して、マージリクエストすれば反映してもらえるかもしれない。
https://gitlab.com/mailman/mailman/-/tree/master/src/mailman/templates/en

ここでは、これら正規の貢献ではなく、オリジナルの通知メールを日本語で書いてみる、という方法を試す。
Mailman 3 Core REST API / Templated texts

※ローカライズについて探していたときに見つけたアーカイブ。前向きな感じ。
lists.mailman3.org / spanish localization

テンプレート

メールのテンプレートは mailman-coreの中、/usr/lib/python3.8/site-packages/mailman/templates/en に入っていた。
(dockerのイメージが0.3から0.4になったら、jaのディレクトリもできていて、そこにファイルを入れておけば動きそうな気配)

テンプレートはWeb UIからドメイン単位で作ることができ、さらに、メーリングリストに個別の設定をすることもできる。
GNU Mailman / Templated texts

名前説明(原文)説明(DeepL先生の翻訳)
[list:admin:action:post]Sent to the list administrators when moderator approval for a posting is required.投稿に対してモデレーターの承認が必要な場合に、リスト管理者に送信されます。
[list:admin:action:subscribe]Sent to the list administrators when moderator approval for a subscription request is required.購読リクエストに対するモデレーターの承認が必要な場合に、リスト管理者に送信されます。
[list:admin:action:unsubscribe]Sent to the list administrators when moderator approval for an unsubscription request is required.購読解除リクエストに対するモデレーターの承認が必要な場合に、リスト管理者に送信されます。
[list:admin:notice:subscribe]Sent to the list administrators to notify them when a new member has been subscribed.新しいメンバーが登録されたことを通知するために、リスト管理者に送信されます。
[list:admin:notice:unrecognized]Sent to the list administrators when a bounce message in an unrecognized format has been received.認識できない形式のバウンスメッセージを受信した場合に、リスト管理者に送信されます。
[list:admin:notice:disable]Sent to the list administrators to notify them when a member’s delivery is disabled due to excessive bounces.過剰なバウンスによりメンバーの配信が停止した際に、リスト管理者に通知するために送信されます。
[list:admin:notice:unsubscribe]Sent to the list administrators to notify them when a member has been unsubscribed.会員が退会したことを通知するために、リスト管理者に送信されます。
[list:member:digest:footer]The footer for a digest message.ダイジェストメッセージのフッターです。
[list:member:digest:header]The header for a digest message.ダイジェストメッセージのヘッダです。
[list:member:digest:masthead]The digest “masthead”; i.e. a common introduction for all digest messages.ダイジェストの「マストヘッド」、つまり、すべてのダイジェストメッセージのための共通の紹介文です。
[list:member:regular:footer]The footer for a regular (non-digest) message.通常の(ダイジェストではない)メッセージのフッターです。
[list:member:regular:header]The header for a regular (non-digest) message.通常の(非ダイジェスト)メッセージのヘッダです。
[list:user:action:subscribe]The message sent to subscribers when a subscription confirmation is required.購読確認が必要な場合に購読者に送られるメッセージ。
[list:user:action:unsubscribe]The message sent to subscribers when an unsubscription confirmation is required.購読解除の確認が必要な場合に、購読者に送信されるメッセージです。
[list:user:action:invite]The message sent to subscribers when they are invited to join a list.購読者がリストに招待されたときに送られるメッセージ。
[list:user:notice:goodbye]The notice sent to a member when they unsubscribe from a mailing list.会員がメーリングリストの登録を解除する際に送られる通知。
[list:user:notice:hold]The notice sent to a poster when their message is being held for moderator approval.投稿者のメッセージがモデレーターの承認のために保留されているときに送信される通知です。
[list:user:notice:no-more-today]Sent to a user when the maximum number of autoresponses has been reached for that day.その日の自動応答の最大数に達したときにユーザーに送信されます。
[list:user:notice:post]Notice sent to a poster when their message has been received by the mailing list.投稿者のメッセージがメーリングリストで受信されたときに送られる通知。
[list:user:notice:probe]A bounce probe sent to a member when their subscription has been disabled due to bounces.バウンスが原因で会員の購読が無効になった場合に、会員に送信されるバウンスプローブです。
[list:user:notice:refuse]Notice sent to a poster when their message has been rejected by the list’s moderator.投稿者のメッセージがリストのモデレーターによって拒否されたときに送られる通知。
[list:user:notice:rejected]Notice sent to a poster when their message has been rejected automatically.投稿者のメッセージが自動的に拒否されたときに送られる通知。
[list:user:notice:welcome]The notice sent to a member when they are subscribed to the mailing list.メンバーがメーリングリストに登録されたときに送られる通知。
[list:user:notice:warning]The notice sent to a member when their membership has been disabled due to excessive bounces.過剰なバウンスにより会員資格が無効になった際に会員に送られる通知。

プレースホルダー

テンプレートの中では、以下のプレースホルダーを書いておくと、対応する情報に変換してくれる。
特定のテンプレートだけで置き換わるプレースホルダーもある。

プレースホルダー内容
$listname完全なメーリングリストの名前ml-theme@rohhie.net
$list_idメーリングリストIDml-theme.rohhie.net
$display_name設定→List Identity→Display NameMl-theme
$short_listnameメーリングリストのローカル部分ml-theme
$domainメーリングリストのドメイン部分rohhie.net
$description設定→List Identity→information技術テーマについて語ろう!
$request_emailリクエスト用のメールアドレスml-theme-request@rohhie.net
$owner_email管理者用のメールアドレスml-theme-owner@rohhie.net
$site_emailサイト管理者のメールアドレスsiteowner@rohhie.net
$languageメーリングリストで好まれる言語ja
$subjectメールの件名Your confirmation is needed to join the ml-theme@rohhie.net mailing list.
※購読開始メールに返送された確認メールの例
$token確認用のトークンa7e67ffab3a881c060181b3a850b577de6bc4b28
※購読開始メールに返送された確認メールの例
$confirm_email確認メールの返送先
Reply-Toに設定される
ml-theme-confirm+a7e67ffab3a881c060181b3a850b577de6bc4b28@rohhie.net
※購読開始メールに返送された確認メールの例
$user_email確認メールの宛先kanri@myhome.local
※購読を申し込んだときに使用したメールアドレス
等々他のプレースホルダーはマニュアルを参照

ドメイン単位のテンプレート例

実際に購読開始の際のメッセージテンプレートを、ドメインに登録してみた。

[list:user:action:subscribe]

メールアドレス登録確認

$domain のメーリングリスト管理サーバーからのお知らせです。

この度は、メーリングリストの購読依頼をいただきまして、
ありがとうございます。

購読にあたり、このメールアドレスがあなたのものであることを
確認させてください。

    $user_email

確認には、このメッセージをそのまま返信するか、
$request_email に

    確認コード $token

を含めたメールを送ってください。

もし、このメーリングリストの購読を希望していない場合には、
このメールを無視してください。

ご質問がありましたら、以下のメールアドレスにご連絡ください。

    $owner_email

ml-theme-joinにメールを送るとこのようなメールが届く。ヘッダーにList-ほにゃほにゃがあって、mailtoが書かれている。

Return-Path: <ml-theme-bounces@rohhie.net>
<省略>
X-Mailman-Version: 3.3.3
Precedence: list
List-Id: =?utf-8?b?5oqA6KGT44OG44O844Oe44Gr44Gk44GE44Gm6Kqe44KN44GG77yB?= <ml-theme.rohhie.net>
List-Help: <mailto:ml-theme-request@rohhie.net?subject=help>
List-Owner: <mailto:ml-theme-owner@rohhie.net>
List-Subscribe: <mailto:ml-theme-join@rohhie.net>
List-Unsubscribe: <mailto:ml-theme-leave@rohhie.net>

メールアドレス登録確認

rohhie.net のメーリングリスト管理サーバーからのお知らせです。

この度は、メーリングリストの購読依頼をいただきまして、
ありがとうございます。

購読にあたり、このメールアドレスがあなたのものであることを
確認させてください。

    hogehoge@myhome.local

確認には、このメッセージをそのまま返信するか、
ml-theme-request@rohhie.net に

    確認コード f1bb260422eeb1ca741d36df3edba03425361b9c

を含めたメールを送ってください。

もし、このメーリングリストの購読を希望していない場合には、
このメールを無視してください。

ご質問がありましたら、以下のメールアドレスにご連絡ください。

    ml-theme-owner@rohhie.net

テンプレートをしっかり作り込めば、ユーザーには親切だろうなと思う。

テンプレートの登録先

メールテンプレートを探し回っていたとき、登録したテンプレートがデーターベースに登録されていることを確認したのでメモ。

$ sudo docker exec -u 0 -it docker-mailman_database_1 /bin/bash --login
root@fc36f30e1c97:/# mysql -umailman -hlocalhost -pmailmanpass

MariaDB [(none)]> use mailmandb
MariaDB [mailmandb]> charset utf8
MariaDB [mailmandb]> select * from postrius_emailtemplate;

※ユーザー、ホスト、パスワードは docker-compose-mysql.yml で定義したもの。

テンプレートファイルを作ってみる

元のメールが分からないと、日本語のテンプレートなんか作れないな…ということで探し回り、ようやくテンプレートのありかを発見。
mailman-core:/usr/lib/python3.8/site-packages/mailman/templates

テンプレートが入っているディレクトリの中身は本家から提供され、システムのデフォルトになる。当然、docker-composeでvolume指定されておらず、イメージを差し替えると本家提供のものに置き換えられる。

そこで、英語版のテンプレートをDockerイメージから取りだし、日本語に翻訳して、その結果をDockerイメージの中に置く方法を取る。良い翻訳ができたなら、マージリクエストしてみたら、ひょっとしたら採用していただけるかもしれない。

まずは、英語版と日本語版を取り出す。

$ sudo docker cp mailman-core:/usr/lib/python3.8/site-packages/mailman/templates/en ./
$ sudo docker cp mailman-core:/usr/lib/python3.8/site-packages/mailman/templates/ja ./
$ sudo chown -R rohhie:rohhie *

※オーナーは適宜作業用のものに。変えなくても良いけれども、作業するのに扱いやすいかなと。

さしあたり、 購読開始の際のメッセージテンプレートを編集してみる。

$ cp en/list\:user\:action\:subscribe.txt ja/

ja/list:user:action:subscribe.txt

メールアドレス登録確認

$domain のメーリングリスト管理サーバーからのお知らせです。

この度は、メーリングリストの購読依頼をいただきまして、
ありがとうございます。

購読にあたり、このメールアドレスがあなたのものであることを
確認させてください。

    $user_email

確認には、このメッセージをそのまま返信するか、
$request_email に

    確認コード $token

を含めたメールを送ってください。

もし、このメーリングリストの購読を希望していない場合には、
このメールを無視してください。

ご質問がありましたら、以下のメールアドレスにご連絡ください。

    $owner_email

作ったテンプレートを配置。
ファイル名にコロンを含んでいるが、docker cpはこれをエスケープ処理できないようなので、シンボリックリンクを作って、それをコピーする。
Github / docker / for-linux / Error “copying between containers is not supported” when trying to copy to local path containing “:” #565

$ ln -s list\:user\:action\:subscribe.txt ja/list-user-action-subscribe.txt
$ sudo docker cp -L ja/list-user-action-subscribe.txt mailman-core:/usr/lib/python3.8/site-packages/mailman/templates/ja/list\:user\:action\:subscribe.txt

これでテンプレートが適用されると思ったら…メーリングリストの推奨言語を日本語にしておく必要があった。
メーリングリストの設定で List Identity → 推奨言語 を Japanese に設定。

これで日本語のメールが届くようになる。

なお、件名については別の言語ファイルで定義されているようで英語のままだった。
中身が日本語だからどうにかなるだろう、ということで割り切って、ここで調査終了。

メール転送設定

こんな構成でメーリングリストを運用しようとしている。

  [Internet]                                        [Internet]
      │                                                │
┌──┴───┐┌──────────────┐┌───┴──┐
│ rohhie.net ││work.hogeserver.hogeddns.jp ││myhome.local│
│* Web       ├┤* Mailman3                  ├┤* Web       │
│* SMTP      ││* Web/SMTP                  ││* SMTP      │
└──────┘└──────────────┘└──────┘
ml-theme@rohhie.net                          ml-info@myhome.local
[メーリングリスト]                            [メーリングリスト]
               https://work.hogeserver.hogeddns.jp
                      [Mailman3のWeb UI]

※work.hogeserver.hogeddns.jpとmyhome.localはマスクしたドメイン。

work.hogeserver.hogeddns.jpはウチの中で勝手に名前解決ができるようにしているだけで、ウチの中で閉じてある。

その上で、Mailman3からインターネットにメールを転送することを想定して、インターネット向けのメールを myhome.local に転送している。
work.hogeserver.hogeddns.jp: /etc/postfix/main.cf

relayhost = [myhome.local]

メーリングリストにまつわるアドレス

ml-info@myhome.localとml-theme@rohhie.netを登録したところ、Mailman3は以下のメールアドレスを自分に引き込むように設定していた。

ml-info@myhome.local
ローカルパート
ml-theme@rohhie.net
ローカルパート
機能
ml-infoml-themeメーリングリストの宛先。
ml-info-bounces(+.*)?ml-theme-bounces(\+.*)?非アクティブになったメンバーを無効化または削除する。
メールロボットが処理する。
ml-info-confirm(+.*)?ml-theme-confirm(\+.*)?購読要求や購読解除要求を処理する。
メールロボットが処理する。
ml-info-joinml-theme-join購読をリクエストする。
ml-info-leaveml-theme-leave購読解除をリクエストする。
ml-info-ownerml-theme-ownerメーリングリストのオーナへの連絡。
ml-info-requestml-theme-requestメールロボットにあてたメール。
ml-info-subscribeml-theme-subscribeml-theme-joinと同じ機能。
ml-info-unsubscribeml-theme-unsubscribeml-theme-leaveと同じ機能。

※メールアドレスを分けて呼ぶ場合は local-part@domain となる。

こんなに種類があって、しかもbouncesとかconfirmは都度変わりそうだと思案していたところ、正規表現を使ったテーブルの書き方があることを教えてもらった。色々なシーンで柔軟に設定ができてありがたい。
ngyukiの日記 / Postfix で 正規表現で From を書き換え

これらのメールをMailman3に届ければ、メーリングリストが機能するはずだ。

  • ml-info@myhome.local宛のメール
    Internet → [myhome.local] → [work.hogeserver.hogeddns.jp] → [Mailman3]
  • ml-theme@rohhie.net宛のメール
    Internet → [rohhie.net] → [work.hogeserver.hogeddns.jp] → [Mailman3]

以降でml-theme@rohhie.netの転送方法を3つ記すが、Mailman3にメールが届けばどの方法でも良い。

そのまま転送

自分のサイトに届いた、特定のアカウントへのメールだけを、よそのホストに転送する。
こんな転送できるの?と思ったのだが、[work]→[Mailman3]の転送がそれをやっていて、同じことをすれば良かった。

[Internet                   ]
 ↓
 ↓ ml-theme@rohhie.net
[rohhie.net                 ] ※特定のメールアドレスのものを転送
 ↓
 ↓ ml-theme@rohhie.net
[work.hogeserver.hogeddns.jp]
 ↓
 ↓ ml-theme@rohhie.net
[Mailman3                   ] ※正規のドメインで受信

rohhie.netで、メーリングリストとして受け取りたい、というメールアドレスをファイルに書く。
メールアドレスが存在することだけが分かれば良いので、テーブルを成立させるためだけに ${1} ではなく a とか適当なのを書いてもOK。

rohhie.net: /etc/postfix/mailman3 ※新規作成、名前は何でもOK

/(^ml-theme.*@rohhie\.net)$/ ${1}

ローカルパートがメーリングリストのものだったら、そのメールを転送するテーブルを書く。
今回の件で色々と探していく中で、ほとんどの場合transportファイルを書いて、postmapでtransport.dbを作っているケースがほとんどだった。
その場合は、元々のtransportファイルの中身を正規表現の形式に書き換える。

rohhie.net: /etc/postfix/transport ※新規作成、名前は何でもOK

# Internal
/myhome\.local$/ smtp:[mail.myhome.local]
/work\.hogeserver\.hogeddns\.jp$/ smtp:[work.hogeserver.hogeddns.jp]

# for Mailman3
/^ml-theme.*@rohhie\.net$/ smtp:[work.hogeserver.hogeddns.jp]

※最初の2つはローカルのメールをローカルでやりとりするための指定。

これらのテーブルをmain.cfに取り込む。

rohhie.net: /etc/postfix/main.cf

local_recipient_maps = regexp:/etc/postfix/mailman3
transport_maps = regexp:/etc/postfix/transport

※元々の定義を壊さないように慎重に追加。

ウチの場合は、Kopanoをメールサーバーとして使わせてもらっていて、これがマルチドメイン対応なのでvirtualな感じでメールを受け取っているので、local_recipient_mapsはこの設定で良いのだけれど、そうじゃない場合は、こんな設定になるかもしれない。

local_recipient_maps = proxy:unix:passwd.byname $alias_maps regexp:/etc/postfix/mailman3

これを反映させれば転送されるようになる。

$ sudo systemctl reload postfix

regexpの使い方が分かったことで、かなり柔軟なリストが書けるようになった。
Postfix Lookup Table Overview

ハッシュとregexpのどちらの方が負荷が軽いのか…ハッシュの方が早いだろうけれども、一応探して見つからず。
ウチの場合は、そもそも取り扱うメールの数が少ないので、たいした差にはならないだろうし、必要なんだからこの設定でいくしかないなと。

エイリアスドメインに転送

Mailman3にはエイリアスドメインという機能があって、メーリングリスト宛てのメールを受け取るためだけのエイリアスドメインを定義することができる。
今回の場合は…

[Internet                   ]
 ↓
 ↓ ml-theme@rohhie.net
[rohhie.net                 ] ※宛先ドメインを書き換え
 ↓
 ↓ ml-theme@work.hogeserver.hogeddns.jp
[work.hogeserver.hogeddns.jp]
 ↓
 ↓ ml-theme@work.hogeserver.hogeddns.jp
[Mailman3                   ] ※エイリアスドメインで受信

という形で届けることができる。

エイリアスドメインはMailman3のWeb UIで設定変更することができる。
設定は即座には反映されず、mailman-coreの再起動や、メーリングリストの追加・削除のタイミングで反映されるので注意。
(反映されたかどうか/opt/mailman/core/var/data/postfix_lmtpを見て確認)

エイリアスドメインが設定できたら、rohhie.netでml-themeで始まるメールアドレスの宛先を書き換える設定を書く。
記憶では、ユーザーを作って.forwardを定義すればメール転送はできたはずだけれど、ユーザーを作らずにやるなら?と探していたら到達。
BinaryTides / Setup mail forwarding in postfix on Ubuntu or Debian

rohhie.net: /etc/postfix/va_maps ※新規作成、名前は何でもOK

/^(ml-theme.*)@rohhie\.net$/ ${1}@work.hogeserver.hogeddns.jp

書き換え設定をmain.cfに取り込む。

rohhie.net: /etc/postfix/main.cf

virtual_alias_maps =
    mysql:/etc/postfix/mysql-aliases.cf
    regexp:/etc/postfix/va_maps

※元々Kopanoのために定義があったので、その定義の後に追加。

これを反映させれば、宛先が書き換えられて転送されるようになる。

$ sudo systemctl reload postfix

alias_mapsとvirtual_alias_mapsのどちらに設定すべきか?というところで、どちらでもできそうな気がするが…
ウチの場合、ドメイン管理の都合上、myhome.local側のサーバーの/etc/hostnameが “hoge” と定義されているので、alias_mapsに/etc/aliasesを指定しても機能しない(ローカルのやりとり、つまり、ml-info@hogeでないとaliasesが機能しない)。このような場合は、virtual_alias_maps 一択となる。
serverfault / Confused about alias_maps and virtual_alias_maps

ドメイン書き換え・書き戻しで転送

メール転送のたびにドメインを書き換えるやり方で転送する。
この方法だと、書き換えが2回行うのでメンテナンスが大変だから、Mailman3にはエイリアスドメイン機能があるのだろう。

[Internet                   ]
 ↓
 ↓ ml-theme@rohhie.net
[rohhie.net                 ] ※宛先ドメインを書き換え
 ↓
 ↓ ml-theme@work.hogeserver.hogeddns.jp
[work.hogeserver.hogeddns.jp] ※宛先ドメインを書き戻し
 ↓
 ↓ ml-theme@rohhie.net
[Mailman3                   ] ※正規のドメインで受信

rohhie.net側の書き換え処理は先程のものと変わらないが、書き戻しのためにちょっと工夫。

rohhie.net: /etc/postfix/va_maps ※新規作成、名前は何でもOK

/^(ml-theme.*)@rohhie\.net$/ ${1}.rohhie.net@work.hogeserver.hogeddns.jp

rohhie.net: /etc/postfix/main.cf

virtual_alias_maps =
    mysql:/etc/postfix/mysql-aliases.cf
    regexp:/etc/postfix/va_maps

反映。

$ sudo systemctl reload postfix

work.hogeserver.hogeddns.jpでは、メールアドレスの宛先を書き戻す。

work.h.h.jp: /etc/postfix/va_maps ※新規作成、名前は何でもOK

/^(.*)\.rohhie\.net@work\.hogeserver\.hogeddns\.jp$/  ${1}@rohhie.net
/^(.*)\.myhome\.local@work\.hogeserver\.hogeddns\.jp$/ ${1}@myhome.local

※ここにMailman3宛てのメールが集まるので、もう1つのml-info@myhome.localの定義もしている。
※雑な書き換えだけれども、メーリングリストを追加するたびに工事する必要がなくなる。

これらのテーブルをmain.cfに取り込む。
work.h.h.jp: /etc/postfix/main.cf

virtual_alias_maps = regexp:/etc/postfix/va_maps

※元々定義されているときは、その定義を壊さないように慎重に追加。

これを反映させれば、宛先が書き戻されてMailman3に転送されるようになる。

$ sudo systemctl reload postfix

手間が掛かるし、2回も書き換えるのが運用時に邪魔っぽい感じがするのでオススメはしないが、こんなやり方でもメールは転送ができるんだな、と。

Postfixのあれこれ

デバッグ

転送設定を色々試していると、思い通りにメールが届かないこともあった(今思うと、元々あったサーバー達の設定がイケてなかった)。
そんなときにはデバッグログを出力させて、丹念に追っていけば対応できると思う。

/etc/postfix/main.cf

debug_peer_list = 192.168.0.3
debug_peer_level = 3

これで、192.168.0.3との間のやりとりが詳細にログ出力されるようになる。
宛先を複数指定するには空白で区切り、範囲指定したいならCIDR形式で指定が可能。
Postfix Configuration Parameters

ログレベルについては0~3とのこと。
ダメ出し Blog / Postfix の詳細ログを採取する – Postfix Advent Calendar 2014

設定の確認

Postfixの設定値はこれで確認できる。

$ postconf -p ※現在の設定値
$ postconf -d ※デフォルト値

デバッグログを見ながら、元々の設定を壊していないか、設定値は結局どうなっているのか、といったあたりを確認していくと、問題解消できるかなと。

ローカルのメール配送

インターネット向けのメールは、プロバイダーのメールサーバーに依頼して送ってもらっている(OP25Bされているため)。
だけれども、よく見ると、ローカルにある別ドメイン向けのメールもプロバイダーに依頼していた…

これは、直送に修正しなければ。

/etc/postfix/transport ※新規作成

rohhie.net smtp:rohhie.net

このファイルはハッシュにして使うそうなので、以下を実行。

$ sudo postmap /etc/postfix/transport

/etc/postfix/main.cf

transport_maps = hash:/etc/postfix/transport

※hash: 指定をしていると、実際には/etc/postfix/transport.dbが参照される。

最終的には、正規表現でtransportテーブルを設定していくことにして、同じ指定をしている。

EHLOで示すホスト名

メールをリレーするとき、相手のサーバーに伝える自分の名前をこれで指定できる。
myhome.local側のサーバーが “hoge” と名乗ってしまう問題を解決できた。

/etc/postfix/main.cf

myhostname = work.hogeserver.hogeddns.jp
smtp_helo_name = $myhostname ← postconfで確かめたデフォルト値がこれ

SMTP認証でメール送信

テスト用のサーバーを立てた時、簡単だから25番ポートを開けていたのだが、サブミッションポートでメールを送信する形を覚えたいと思った。
SMTP認証はSASL認証にして、SASL認証のバックエンドはPAM認証にする。

SASL認証の為のアプリケーションをインストールし、一旦停止。

$ sudo apt install sasl2-bin
$ sudo systemctl stop saslauthd

デフォルトでは起動時に自動起動してこないので、自動起動するように設定。
また、Postfixからアクセスができるように、chrootされた場所にファイルを動かす。
serverfault / Postfix SMTP+saslauthd autentication failure
serverfault / Postfix: SASL authentication failure: cannot connect to saslauthd server: Permission denied

/etc/default/saslauthd

…
# Should saslauthd run automatically on startup? (default: no)
START=yes
…
# Other options (default: -c -m /var/run/saslauthd)
# Note: You MUST specify the -m option or saslauthd won't run!
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd"

ファイルを移動させて、サービスを起動。

$ sudo adduser postfix sasl
$ sudo mkdir -p /var/spool/postfix/var/run
$ sudo mv /var/run/saslauthd /var/spool/postfix/var/run/
$ sudo systemctl start saslauthd

Postfix側にSASL認証を設定していく。
わすれないうちにメモしよう / debian postfix + dovecot + sasl(PAM)

sasl2-binはplainとloginのみに対応している。
/etc/postfix/sasl/smtpd.conf ※新規作成

pwcheck_method: saslauthd
mech_list: plain login

SASL認証を求めるのだが、mua_client_restrictionsというところに設定している。
これは、master.cfから参照する。
/etc/postfix/main.cf

# 正式な証明書があればそれを設定。なければsnakeoilをとりあえず使う。
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
# SASL認証されればクライアントになれる
mua_client_restrictions = permit_sasl_authenticated,reject

Submission(587)とSMTPS(465)を有効にする。
/etc/postfix/master.cf ※コメントになっているものを有効にする。

…
submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_tls_auth_only=yes
#  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
#  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
#  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
…

Postfixの設定を再読込する。

$ sudo systemctl reload postfix

これで、

  • 587 SMTP認証 + STARTTLS
  • 465 SMTP認証

でメールが送信できるようになった。

やったこと

Dovecot

日頃、Kopanoを利用しているので、Dovecotはあまり触ったことがないのだが…とても簡単にPOP3サーバーをインストールできる。

$ sudo apt install dovecot-core dovecot-pop3d

メールクライアントソフトでは、POP over SSLで証明書を検証しないような設定にしておけば、とりあえずは動作する。

Mailman3のインストール(失敗)

Mailmanのインストール方法は、DockerやVirtualenv等も用意されているが、Ubuntuのパッケージを入れてみることにする。

Mailman3のインストール

mailmanは2.xのブランチらしく、最新はmailman3ですよ、とされていた。
(mailmanをインストールしてみて、READMEを見たらそう書かれていた)

ということで、mailman3-fullをインストールしていく。途中の問い合わせはDeepL先生に翻訳してもらったもの。

$ sudo apt install mailman3-full

■Configuring mailman3
mailman3 パッケージは、使用する前にデータベースをインストールして設定する必要があります。
これはオプションで dbconfig-common で処理できます。
もしあなたが上級のデータベース管理者で、この設定を手動で行いたいことがわかっている場合や、
すでにデータベースがインストールされて設定されている場合は、このオプションを拒否してください。
何をしなければならないかの詳細は、おそらく /usr/share/doc/mailman3 に記載されているはずです。
そうでなければ、このオプションを選択すべきでしょう。
dbconfig-common で mailman3 のデータベースを設定しますか?
→ Yes

■Configuring mailman3-web
<先程と同じことを聞かれる。>
→ Yes

Webサーバーはインストールしていなかったが、Apacheが選択されていた。
先にNginXをインストールしている場合には、何も起きないのではないかと思われるが、/etc/mailman3ディレクトリにはnginx.confが含まれており、サポートされている模様。

Postfixの設定

/usr/share/doc/mailman3/README.Debian を読んでみると、Postfixの設定について書かれている。

/etc/postfix/main.cf

owner_request_special = no
transport_maps = hash:/etc/postfix/transport hash:/var/lib/mailman3/data/postfix_lmtp
local_recipient_maps = proxy:unix:passwd.byname $alias_maps hash:/var/lib/mailman3/data/postfix_lmtp
relay_domains = ${{$compatibility_level} < {2} ? {$mydestination} : {}} hash:/var/lib/mailman3/data/postfix_domains

※transport_mapsは、宛先ドメインと転送プロトコル、転送先サーバーを定義したファイルで、ローカル配送用に定義済みだったので、空白で区切って追記している。

MariaDBの設定

/usr/share/doc/mailman3/README.Debian を読んでみると、 データベースはSQLite3が使われているそうだ。

また、業務利用するなら、PostgreSQLやMySQLを使うべきだとされていて、dbconfig-pgsqlやdbconfig-mysqlをインストールして、dpkg-reconfigure mailman3を実行することで自動設定できるとのこと。

ウチではだいぶ大げさだけれども、MariaDBをインストールして設定してみよう。

$ sudo apt install mariadb-server dbconfig-mysql python3-pymysql
$ sudo dpkg-reconfigure mailman3

■Configuring mailman3
mailman3を再設定しているので、使用しているデータベースも再インストールしたいと思うかもしれません。
mailman3のデータベースを再インストールしたい場合は、このオプションを選択してください。
そうしたくない場合(無関係な理由でパッケージを再設定する場合)は、このオプションを選択しないでください。
警告: データベースの再インストールを選択し、既に存在する名前でインストールした場合、
古いデータベースは問答無用で削除されます。その場合、元のデータベースのバックアップが /var/tmp/ に作成されます。
警告:データベースの名前を変更しても、古いデータベースは削除されません。
データベースに接続するユーザーの名前を変更しても、元のユーザーの権限は取り消されません。
mailman3のデータベースを再インストールしますか?
→ Yes

■Configuring mailman3
mailman3パッケージでは、いくつかのデータベースタイプのうちの1つを使用するように設定することができます。
以下に、利用可能な選択肢が示されています。
mailman3 がサポートしているにも関わらず、ここに表示されていない他のデータベースタイプがある場合、
対応する dbconfig-<データベースタイプ> パッケージがインストールされていないことが原因です。
サポートされている他のデータベースタイプを使用したいことがわかっている場合、最良の選択肢は、
dbconfig-commonの質問から手を引き、このパッケージに対するdbconfig-commonの支援を今のところ
オプトアウトすることです。パッケージの依存関係にあるリストから
お好みの dbconfig-<データベースタイプ> オプションをインストールし、"dpkg-reconfigure mailman3" で選択してください。
mailman3で使用するデータベースタイプ:
→ mysql

■Configuring mailman3
デフォルトでは、mailman3はローカルのUnixソケットを介してMySQLサーバーを使用するように設定されています
(これは最高のパフォーマンスを提供します)。別の方法で接続したり、まったく別のサーバーに接続するには、
ここにある選択肢から適切なオプションを選択してください。
mailman3のMySQLデータベースへの接続方法:
→ Unix socket

■Configuring mailman3
データベースのユーザアカウントは、MySQLでの認証にさまざまなプラグインを使用するように設定できます。
サーバのデフォルトがこのアプリケーションで動作しない場合は、動作するものを指定する必要があります。
利用可能なプラグインのリストから1つ選択してください。選択肢を元の値に設定したままにしておくと、
リモートサーバーが予測不可能なデフォルトを使用していない限り動作するはずですが、
他のオプションは mailman3 でサポートされていない可能性があります。問題が発生した場合は、
パッケージのドキュメントがヒントを与えてくれるはずです; /usr/share/doc/mailman3/ を参照してください。
オプションは以下の通りです。
 * default - サーバーで決められたデフォルトを使用します。
 * mysql_native_password - MySQL認証プラグインを使用しません。
 * sha256_password - より安全なパスワード暗号化アルゴリズムを使用します。
 * caching_sha2_password - SHA2に加えて、インメモリの認証キャッシュを使用します。
MySQLデータベース用の認証プラグイン:
→ default

■Configuring mailman3
mailman3で使用するMySQLデータベースの名前を入力してください。
mailman3のMySQLデータベース名:
→ mailman.db

■Configuring mailman3
mailman3がデータベースサーバーに登録するためのMySQLユーザー名を入力してください。
特にデータベースがリモートサーバーにある場合、MySQLユーザーは必ずしもシステムログインと同じではありません。
このユーザーは、このインストールで作成されるデータベース、テーブル、その他のオブジェクトを
所有するユーザーです。このユーザーは、データベースへのデータの挿入、変更、削除を自由に行うことができます。
ユーザー名に@が含まれている場合は、ドメインも指定する必要があります(下記参照)。
高度な使い方:ユーザーがログインするドメインを定義する必要がある場合は、「username@domain」と書くことができます。
mailman3のMySQLユーザー名:
→ mailman3@localhost

■Configuring mailman3
mailman3がデータベースサーバーに登録するためのパスワードを入力してください。
空欄の場合は、ランダムなパスワードが生成されます。
mailman3のMySQLアプリケーションパスワード:
→ パスワードを入力
パスワードの確認:
→ パスワードを入力

■Configuring mailman3
このパッケージが管理操作を行うべきアカウントの名前を入力してください。
このユーザは、新しいデータベースユーザを作成する権限を持っています。
MySQL では、ほとんどの場合、これは「root」です。これは、Unix の
ログイン名「root」とは異なることに注意してください。
データベースの管理ユーザーの名前。
→ root

■Configuring mailman3
Mailman3は、HyperKittyアーカイバにメッセージを送信するために、mailman.cfgに追加の設定が必要です。
この設定は現在、自動的に追加できます。
/usr/share/mailman3/mailman_cfg_hyperkitty_snippet.cfg の内容が
/etc/mailman3/mailman.cfg に追加されます。
mailman.cfgにHyperKittyの設定を追加しますか?
→ Yes

■Configuring mailman3
データベースのインストール中にエラーが発生しました。
mysqlは言いました: ERROR 1064 (42000) at line 3: SQL構文にエラーがあります。
1行目の「.* TO 'mailman3'@'localhost' 」付近で使用する正しい構文については、
MariaDBサーバのバージョンに対応するマニュアルを確認してください。
オプションは以下のとおりです。
* abort - 操作を失敗させます。このパッケージを継続して使用するためには、ダウングレード、
          再インストール、再設定など、手動で介入する必要があります。通常、インストールの
          失敗が解決するまで、他のパッケージのインストールにも影響が出ます。
* retry - すべての設定に関する質問 (debconf の優先度設定によって見落としたものも含む) を
          もう一度尋ね、操作の実行を再度試みます。
* retry (skip questions) - すべての質問をスキップして、すぐに操作を再試行します。
          これは通常、エラーが発生した後に根本的な問題を解決した場合にのみ有効です。
* ignore - dbconfig-commonエラーを無視して操作を続行します。これは通常、
          このパッケージには機能的なデータベースがないままになります。
データベースインストールの次のステップ:
→ abort

まだ、何も設定をしていない段階なので、データベースを再インストールするオプションを選択している。

中止をさせたけれども、中途半端にファイルが残される。
サービスは立ち上がったままなので、何も動作が変わっていない…という状態に。

成功事例はあるようなんだけれど…
Mailman3 on Ubuntu 20.04 LTS – Best Installation Method?

これを解決しようとする過程で情報を探していたところ、こんな情報に遭遇。
Installing mailman3 from Ubuntu 20.04 repository

不具合の報告はされているけれども修正されていない、Dockerを使って振り返るな、ということなので、その方向に軌道修正。

さいごに

ここまで記事が長くなることを想定していなかったのだが、実際に運用を意識すると作業量が結構あった。
この記事に着手した後にSPFやDKIM、DMARCを整理したりして、これがまたなかなかに歯ごたえがあり、時間が経過…

でも、そのおかげでメールの仕組みの理解が少しだけ進んで、Mailman3は新しい技術にもしっかり対応していることが分かったり、新しいバージョンのDockerイメージが作られていたりと、良いことが多かった。

それにしても、Postfixは難しかったなぁ。これでなんとか設定くらいはできるようになってきた。
ちょっとした機能を足したいと思っているけれども、そんなのいつになることやら。

コメントはこちらから お気軽にどうぞ ~ 投稿に関するご意見・感想・他