(ヽ´ω`) < 助けてほしいマン

わからないことを助けてほしいマンが書くブログ

(ヽ'ω`) < Mailmanのconfig_listコマンドの使用方法と一括設定について

(ヽ´ω`) < config_listコマンドの役割

bin/config_listコマンドでは、コンソールからリストの各種設定を変更できる。

システム管理者がコマンドの実行を行う事を想定されているようで、パスワード等による認証は不要。

単一のリストだけの設定変更であれば、WebUIからのほうが手軽だが、運用形態の変化によるmm_cfg.pyの変更などが発生した場合、複数のリストに対して一括して処理を行うことができる。(繰り返しになるが、mm_cfg.pyを変更しても、既に作成されたリストの設定には影響がない)

(ヽ´ω`) < いくつかの注意点

面倒なことに、config_listコマンドでは、予め変更したい設定内容を記述したファイルを別個に用意してやらないといけない。

このファイルはPythonのスクリプトそのもので、config.pck内の変更したい変数への代入文を記載する。

例としてアーカイブの設定を変更するための設定ファイルは以下の通り

$ vi /tmp/archive_config.py

archive = True
archive_private = 1
archive_volume_frequency = 2

ここで注意したいのが、このファイルに記載されている変数名がmm_cfg.pyでの名前と違う(WebUIやconfig.pckファイルのダンプでの変数名と同じ)であること。

これまでの記事で何度も繰り返しているが、mm_cfg.pyはあくまでもテンプレートであり、実際のリスト毎の設定はリスト作成時にconfig.pckファイルとして出力される。今ここで変更しようとしているのはconfig.pckなので、config.pckの変数名を記述する。

(ヽ´ω`) < config.pck内変数名の取得

実際に入力となる設定変更用のファイルを書く前に、設定を行う変数名を調べておく必要がある。

config.pck内で使用されている変数名は以下の2通りの方法で確認ができる。

WebUIからの確認

WebUIの各設定項目に太字で記載されている、"◯◯◯の詳細"というリンク文字列の"◯◯◯"が対応する変数名となる。

f:id:tsugi-hagi:20141216164422p:plain

処理対象のリストが1つだけであれば、変数名を確認したこの画面から、そのまま変更してしまったほうが早い。

dumpdbコマンドからの確認

コンソールからbin/dumpdb <config.pckファイルの場所>を実行することで、config.pckの中身をテキストで確認することができる。

[root@d09f4ab28203 mailman]# bin/dumpdb lists/mailman/config.pck
[----- pickle ファイル開始 -----]
<----- 1 番目のオブジェクト ----->
{   'accept_these_nonmembers': [],
    'acceptable_aliases': '\n',
    'admin_immed_notify': True,
    'admin_member_chunksize': 30,
    'admin_notify_mchanges': False,
    'admin_responses': {   },
    'administrivia': True,
    'advertised': True,
    'anonymous_list': False,
    'archive': True,
    'archive_private': 0,
    'archive_volume_frequency': 1,
(以下省略)

ここでは各行の:より左側の部分、accept_these_nonmembersacceptable_aliasesが変数名となる。

(ヽ´ω`) < mm_cfg.py内の変数とconfig.pck内の変数の対応付けはどうやるの?

どこかに文章としてあるのかもしれないが、今のところ見当たらないです(ヽ´ω`)

ほとんどの場合はprefixとしてDEFAULT_が付いているかどうかなので、なんとなくはわかるかと。

(ヽ´ω`) < 設定ファイルの形式

変数名がわかったら、それに対する代入文を記述したPythonファイルを作成する。

基本的には下記の通り変数名 = 値を1行ずつ書いて行く。

archive = No
max_num_recipients = 10

値として使用可能なものは以下の通り

  • 数字
  • 文字列(シングルクォーテーションで囲む)
  • 真偽値(True, False)
  • 上記の値を含む配列
  • 上記の値を含む辞書

数字、文字列、真偽値は特に問題なく記述ができるはず。

配列・辞書

配列は複数の値を取りうる変数で、値は"[]"で囲まれる。

典型的な例としては、リストの管理者で、これは変数名ownerで設定される。

# bin/dumpdb lists/mailman/config.pck | grep "'owner'"
    'owner': ['ml-admin@hoge.com', 'john@foo.net', 'take@bar.jp'],

WebUI上で表示は以下の通りとなる。

f:id:tsugi-hagi:20141216164355p:plain

WebUIでの設定時は、指示通りテキストボックスに改行区切りで値を入れていく。

config_listコマンドで設定する場合、入力ファイルを以下のように作成する。

owner = ['ml-admin@hoge.com', 'john@foo.net', `take@bar.jp']

その他の形式にも言えることだが、入力ファイルには`bin/dumpdb'コマンドの出力そのまま

'owner': ['ml-admin@hoge.com', 'john@foo.net', 'take@bar.jp']

のように記述してはいけない。必ず変数名 = 値の形式で書くこと。

時間関係の関数

Defaults.pyの最上部に以下の定義がされている

def seconds(s): return s
def minutes(m): return m * 60
def hours(h): return h * 60 * 60
def days(d): return d * 60 * 60 * 24

これを見ると分かる通り、時間指定のベースは秒単位であり、minutes(), hours(), days()の関数が使用できる。

# 会員権停止の警告メールを3日おきに送信する
bounce_you_are_disabled_warnings_interval = days(3)

真偽値のエイリアス(Yes, On, No, Offの関係)

これまたDefaults.pyの最上部に以下の定義がある。

# Some convenient constants
try:
    True, False
except NameError:
    True = 1
    False = 0

Yes = yes = On = on = True
No = no = Off = off = False

真偽値のYes, yes, On, on, TrueNo, no, Off, off, Falseはそれぞれ同じ意味になるように定義されている。

更に

]# python
Python 2.6.6 (r266:84292, Jan 22 2014, 09:42:36)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> True == 1
True
>>> True == 0
False
>>> False == 0
True
>>> False == 1
False

より、Yes, yes, On, on Trueは1とNo, no, Off, off Falseは0と同値となる。つまり、Yesの代わりに1を使用したり、Offの代わりにnoを使うこともできる。

tryでTrueとFalseの名前を確認しているのは、Pythonの実装系によって定義されていない可能性を考慮しているものと思われる。

(ヽ´ω`) < 実際にやってみる

以上の内容を元に、実際にファイルの作成からコマンドの実行までを行う。 設定内容は以下の通り

  1. 通常のメーリングリストから、Aliasesのようなリストに役割を変更する
  2. Subjectのprefixを無しにする
  3. 配送メールの返信先を、元メールの送信者宛にする
  4. 非メンバーからの投稿を有効にする
  5. 管理者のアドレスを変更する(admin1@hoge.com, admin2@foo.net)
$ vi /tmp/aliases_settings.py

# 2) Subjectのprefixを無しにする
subject_prefix = ""

# 3) 配送メールの返信先を、元メールの送信者宛にする
reply_goes_to_list = 0

# 4) 非メンバーからの投稿を有効にする
generic_nonmember_action = 0

# 5) 管理者のアドレスを変更する(admin1@hoge.com, admin2@foo.net)
owner = ['admin1@hoge.com', 'admin2@foo.net']

3と4の値については、Defautls.pyに値の意味が記載されている。

# Mailman can be configured to "munge" Reply-To: headers for any passing
# messages. One the one hand, there are a lot of good reasons not to munge
# Reply-To: but on the other, people really seem to want this feature. See
# the help for reply_goes_to_list in the web UI for links discussing the
# issue.
# 0 - Reply-To: not munged
# 1 - Reply-To: set back to the list
# 2 - Reply-To: set to an explicit value (reply_to_address)
DEFAULT_REPLY_GOES_TO_LIST = 0

# What shold happen to non-member posts which are do not match explicit
# non-member actions?
# 0 = Accept
# 1 = Hold
# 2 = Reject
# 3 = Discard
DEFAULT_GENERIC_NONMEMBER_ACTION = 1

設定内容を記述したファイルができたので、これをリストに適用する。

# /opt/mailman/bin/config_list --inputfile=/tmp/aliases_settings.py <リスト名>

初めて設定した時は、WebUIやdumpdbコマンドで変更が正しく適用されているかを確認したほうが良い。

(ヽ´ω`) < 全てのリストに対して処理を行う

さて、ようやく本題。

単一のリストの設定を変更するだけであれば、わざわざ変数名を探してファイルを作って…という面倒な手順をふまずに、WebUIで変更を行ったほうが良い。

長々と前振りをしてまで、config_listの使い方を説明したのは、このコマンドを使用し全てのリスト(あるいは特定の複数)に対して、処理を行うケースを想定してのこと。

config_listコマンドに渡すリスト名のパラメータに、ワイルドカードが使えれば楽なのだが、残念ながらそうはなっていない。

ということで、以下の様な単純なスクリプトを作ってぶん回す。

#!/bin/bash

# Mailmanのインストールパス
MAILMAN_PATH=/opt/mailman

# 変更する設定内容
INPUT_FILE=/tmp/aliases_settings.py

# 処理対象のリスト
TARGET_LISTS=`ls $MAILMAN_PATH/lists`
# 特定のリストをファイル記述して処理
## TARGET_LISTS=`cat /tmp/target_lists.txt`

for list in $TARGET_LISTS;
do
    echo $list
    $MAILMAN_PATH/bin/config_list -v --inputfile=$INPUT_FILE $list
done

TARGET_LISTSの中の値で、任意のリストを指定できるので、

# "external-"から始まるリスト全てを処理対象とする
TARGET_LISTS = `ls $MAILMAN_PATH/lists/external-*`

単純なスクリプトなので、これをベースに目的に合わせて作りなおすと吉。

(ヽ´ω`) < withlistってコマンドが全リスト対象のオプションもあって便利そうなんだけど、コレじゃダメなの?

bin/withlistコマンドはPythonを使える人向けに、Mailman操作のプログラムインターフェースを提供するものなので、既に他の人が作成したスクリプトで設定を行うのには便利だけど、そうじゃないケースでは使いにくいかと。

(ヽ´ω`) < 運用計画はしっかりと

というわけで、config_listコマンドの使用方法はそこまで難しくはない。

が、変更を行うときに、単一のファイルで設定を完結できないのは少し面倒くさい。

可能な限りこの作業を繰り返さないために、Mailmanの構築時にしっかりと運用計画とmm_cfg.pyの内容を作成するのが良いです。

(ヽ'ω`) < Mailmanの設定ファイル、Defaults.pyとmm_cfg.py, config.pckの関係について

(ヽ´ω`) < 3つもあるからわかりにくい

Mailmanの細かい設定パラメータについて解説する前に、

既にインストールの段階で説明したとおり、Mailmanの設定はMailman/mm_cfg.pyMailman/Defaults.pyのデフォルト設定を上書きする形で行われる。

それでは、Mailmanに関する全ての設定がこの2つのファイルだけで行われているかというと然にあらず。実はMailmanの設定には「全体設定」と「リスト毎の設定」がある。

各リストのデフォルト設定はDefaults.pymm_cfg.pyで設定した値、つまりシステム管理者が設定した値となるが、多くの設定に関しては、リストの管理者が変更可能である。

この変更はリストの管理者がWebUIから行うことができるが、

  • リスト管理者のメールアドレス
  • リストから配送されるメールのSubjectに付与するPrefix
  • メンバー登録時のWelcomeメッセージの内容

のようなリスト固有のものもあれば、

  • メンバー以外からメールを受信した際の挙動(配送、破棄、保留)
  • アーカイブ化処理の有無
  • エラーメールの処理方法

などと、Mailmanのコアな部分の挙動についても制御が可能となっている。

「リスト毎の設定」はlists/<リスト名>/config.pckというファイルに保存される。この拡張子pckのファイルはPickleファイルと言い、Pythonに標準で添付されているオブジェクトシリアライズのためのフォーマットとなる。バイナリファイルなので、中身を見たい場合にはbin/dumpdbコマンドを使用する。

Defaults.py, mm_cfg.py, config.pckそれぞれの関係をまとめると以下のようになる。

ファイル名 役割 変更方法 変更者 ファイル形式
Defaults.py Mailmanデフォルトの設定を記載
各パラメータの役割についてのコメント有
基本的に変更しない システム管理者 Pythonスクリプト
mm_cfg.py Mailmanのシステム全体に渡る設定を記載 ファイルを直接編集 システム管理者 Pythonスクリプト
config.pck 各リスト毎の個別・固有の設定を記載 WebUI(リスト管理者、システム管理者)、bin/config_listコマンド(システム管理者) 主にリスト管理者 Pickle形式(バイナリファイル)

(ヽ´ω`) < 設定内容の移譲について

上記の図を見てわかるとおり、config.pckはリスト作成時に作成されるため、リスト作成後にmm_cfg.pyの内容を変更しても、その内容は既存のリストには反映されない。既存のリストへ設定を反映させるには、個別にbin/config_listコマンドで設定を流しこんでやる必要がある。(この方法については後述する)

ApacheやPostfixなどの一般的なサーバアプリケーションでは、設定ファイルを書き換えてサーバをリロードすれば設定が反映されるが、Mailmanではここが特殊でハマりやすい。

(おーい、未承認メールの保留期間を2週間にしておいてくれー)
(ヽ´ω`) < はいはい、mm_cfg.pyでDEFAULT_MAX_DAYS_TO_HOLDを14に設定っと…
3週間後
(オラァ! 2週間って言っただろうが! 全然消えてねぇぞ!![※デフォルトでは未承認メールは自動削除されない])
(;ヽ´ω`) < えぇ…
(;ヽ´ω`) < スンマセン、今WebUIで変更しました!
(チッ)
(ヽ´ω`) < と言うか自分でWebUIから変更してくれればよかったんじゃ…

というのが実体験に基づくかどうかは置いておいて、この特徴をしっかりと覚えておくためには、Defaults.pymm_cfg.pyを"設定ファイル"と考えずに "テンプレート" として考えると良い。

Defaults.pymm_cfg.pyはテンプレートで、設定ファイルはconfig.pckのみと覚えておけば、設定を変更するには、当然設定ファイルであるconfig.pckを操作しないといけない、となる。

(ヽ´ω`) < 「固有設定」と「個別設定」について

config.pckファイルの中身、リスト毎の設定には「固有設定」と「個別設定」がある。それぞれの区別は以下の通り。

言葉 定義 設定は必須か?
固有設定 リストの名前や管理者のメールアドレスなどの、そのリスト自身の独立性を表す設定。
リスト作成時にinputとして渡す。
必須
個別設定 Defaults.py, mm_cfg.pyから引き継がれ、必要に応じて上書きされた、メーリングリストシステムとしての挙動を制御する設定。 必要に応じて。設定しない場合はシステム管理者が設定した値が使用される。

実際のファイルの中身に明確な区別があるわけではなく、概念として2つの設定があるということを留意してもらいたい。

繰り返しになるが、個別設定は「mm_cfg.pyのものが使用される」のではなく、「mm_cfg.pyから生成される」ということを覚えておくこと。

(ヽ´ω`) < config.pckファイルの変更方法

config.pckファイルの中身を変更するには2つの方法がある。

1つめはWebUIからの変更。これはリスト管理者がログインして行うことができるし、システム管理者がマスターパスワード(bin/mmsitepassで作成したパスワード)でWebUIにログインすることでも変更が可能。

(ちなみに、アクセス対象のWebUIのURLはどちらの場合でも同じ。つまり、WebUIにログインする際には、リスト個別のパスワードとマスターパスワードの2つが利用可能となる。)

もう1つが先程から何度か出ているbin/config_listコマンドである。

これはサーバのスクリプトファイルなので、当然、サーバのコンソールを触れる人間、通常はシステム管理者のみが使用できるコマンドとなる。

bin/withlistというコマンドもあるのだが、これはかなりPythonプログラマに寄ったコマンドなので、Pythonに馴染みのない管理者にはとっつきにくい。

(ヽ´ω`) < config_listコマンドの使用方法

長くなるので次のエントリで

(ヽ'ω`) < わかりにくい 図を使え 人に伝える気があるのか

(ヽ'ω`) < そ、そのうち追加します

(ヽ'ω`) < Mailmanを"まずは動くまで"設定

(ヽ´ω`) < インストールの続き

前回までで、Mailmanを使うためのファイルの配置と、Postfix, Apacheの連携ソフトウェアの設定を行った。

かなり長い手順となったが、今回はMailman自身の設定を行っていく。

  • Mailmanの初期設定
    1. mm_cfg.pyの設定
    2. aliasesファイルの仮作成
    3. 管理ML(mailman)作成
    4. マスターパスワード設定
  • 動作を確認
    1. 投稿確認
    2. Gmailからの投稿確認

(ヽ´ω`) < Mailmanの初期設定

以下の手順を行い、Mailmanが正常に起動するまでもっていく。ここでは、個別のカスタマイズについては触れない。設定項目があまりにも多いため、別のエントリで逆引き形式で解説を行う。

mm_cfg.pyの設定

Mailmanでは、あらゆるシステムのデフォルト設定値がMailman/Defaults.pyというファイルに記載されている。

このファイル自身は、拡張子を見て分かる通りpythonスクリプトそのものとなっているが、ApacheやPostfixの設定ファイルと同じように

変数名 = 値

の形式で設定を入れているだけなので、読んでいく分にはあまり問題がないと思う。

各変数名(設定項目)がどういう働きをするのかも、このファイルに記載されているので、このファイルを参照すればどのような設定が行えるかがわかるようになっている。

で、システムの設定をデフォルトから変更したい時、

例えば、デフォルトではMailmanから配送されたメールの返信先は、送信者のアドレスとなっているが、これをメーリングリストのアドレスに変更したい、という場合

Defaults.pyDEFAULT_REPLY_GOES_TO_LISTの値を0から1に変更する、のではなく

同じディレクトリ(Mailman/)のmm_cfg.pyというファイルに、設定を記述する。

# Mailman/Defaults.pyの以下の記述はそのままで
DEFAULT_REPLY_GOES_TO_LIST = 0

# Mailman/mm_cfg.pyに以下の記述を追加する
DEFAULT_REPLY_GOES_TO_LIST = 1

これはシステムの正常性を保つのに非常に便利な話で、Defaults.pyに記載されているデフォルト値は変更されないので、不都合が発生して、その原因が不明な場合はmm_cfg.pyの内容を削除してしまえば、元の状態に戻すことができる。

本来であれば、ここでメーリングリストの基本的な設定を記述してくことになるのだが、まずは最低限の記載のみを行う。

# 1) 連携するMTAの名前を指定
MTA = 'Postfix'

# 2) WebUIからアクセスする際のFQDN
DEFAULT_URL_HOST = 'mailman-ui.tsugihagi.net'

# 3) メーリングリストアドレスの@以降の部分
DEFAULT_EMAIL_HOST = 'ml.tsugihagi.net'

# 4) 上記のDEFAULT_*_HOSTを変更した場合、
#    下記の通りadd_virtualhostメソッドを呼び出す
add_virtualhost(DEFAULT_URL_HOST, DEFAULT_EMAIL_HOST)

各項目についての説明

  1. 連携するMTAの名前を指定
    ここではPostfixを使用するので、値にはPostfixを指定。他にはMailman/MTA/ディレクトリ以下のクラスの名前が使用可能とのことだが…ManualPostfixしか無い。完全にPostfixとの連携が前提なんですかね。
  2. WebUIからアクセスする際のFQDN
    Mailmanが提供するWebUIのURL内の、ホスト名部分を指定する。ここでは
    http://mailman-ui.tsugihagi.net/mailman/
    というURLで提供することを想定。URL内の斜体の部分が対象の値となる。
  3. メーリングリストアドレスの@以降の部分
    各メーリングリストのアドレスが
    hogehoge@ml.tsugihagi.net
    となるとして、斜体の部分。もしも foobar@tsugihagi.net
    とした場合はDEFAULT_EMAIL_HOST = 'tsugihagi.net'となる。
  4. add_virtualhostの呼び出し
    DEFAULT_URL_HOSTとDEFAULT_EMAIL_HOSTの値を変更した時には、必ずこのメソッドを呼び出す必要がある。ここはMailmanをバーチャルホストで運用した場合の話もからんでくるのだが、とりあえずおまじない的に覚えておく。

mm_cfg.pyについて補足しておくと、このファイルの内容がそのまま、各メーリングリストの設定として扱われるわけではない。

このファイルの内容を読み取って、各メーリングリストの設定内容がconfig/<メーリングリスト名/config.pckというファイルに書き出される。

この辺りの細かい話は、メーリングリストのカスタマイズに関連して、別エントリで解説を行う。

aliasesファイルの仮作成

下記のコマンドでaliasesファイルを作成する。このファイルはメーリングリストの作成・削除を行う度に更新されるので、ここでは問題なく作成できるかをだけを確認する。

# /opt/mailman/bin/genaliases

上記コマンド実行後に、data/以下にaliases, aliases.dbと2つのファイルが作成されている事を確認しておく。

[root@d09f4ab28203 data]# ls -l
total 36
-rw-rw---- 1 root mailman   351 Dec 15 06:07 aliases
-rw-r----- 1 root mailman 12288 Dec 15 06:07 aliases.db
-rw-r--r-- 1 root mailman    10 Dec 15 05:51 last_mailman_version
-rw-r--r-- 1 root mailman 14100 Dec 15 05:51 sitelist.cfg

[root@d09f4ab28203 data]# cat aliases
# This file is generated by Mailman, and is kept in sync with the
# binary hash file aliases.db.  YOU SHOULD NOT MANUALLY EDIT THIS FILE
# unless you know what you're doing, and can keep the two files properly
# in sync.  If you screw it up, you're on your own.

# The ultimate loop stopper address
mailman-loop: /opt/mailman/data/owner-bounces.mbox

管理ML(mailman)作成

Mailmanではシステムの管理のために、1つのメーリングリスト('site-wide mailing list')が必要となる。

パスワードリマインダー等は、このメーリングリストのアドレスから届くことになる。他にも色々なところで使われる…っぽいのだが、あんまり見たことがない。

このメーリングリストはデフォルトではmailmanという名前となる。(もしもこの名前が気に喰わない場合は、mm_cfg.pyMAILMAN_SITE_LISTという名前の変数を設定することで変更が可能)

メーリングリストの作成は、bin/newlistコマンドを使用する。このコマンドの引数は以下の通り。

newlist <メーリングリスト名> <管理者のメールアドレス> <管理パスワード>

ここではmailmanという名前のメーリングリストを作成するので、

# /opt/mailman/bin/newlist mailman ml-admin@tsugihagi.net sOme_PA$$W0RD

上記コマンドで、mailman@ml.tsugihagi.netというメーリングリストが作成された。

コマンド実行時に、エンターを押すと管理者にメールを送信した旨のメッセージが表示されるが、実際にはMailmanのサービスはまだ実行されていないので、送信は行われない。

実際にmailmanというメーリングリストが作成されたことを、システム上で確認してみる。

まずは、lists/ディレクトリにmailmanというディレクトリが存在しているか。

[root@d09f4ab28203 mailman]# pwd
/opt/mailman
[root@d09f4ab28203 mailman]# cd lists
[root@d09f4ab28203 lists]# ls -l
total 4
drwxrwsr-x 2 root mailman 4096 Dec 15 06:11 mailman

次に先ほどgenaliasesで作成されたdata/aliasesファイルにエントリが追加されているか。

[root@d09f4ab28203 lists]# cat /opt/mailman/data/aliases
# This file is generated by Mailman, and is kept in sync with the
# binary hash file aliases.db.  YOU SHOULD NOT MANUALLY EDIT THIS FILE
# unless you know what you're doing, and can keep the two files properly
# in sync.  If you screw it up, you're on your own.

# The ultimate loop stopper address
mailman-loop: /opt/mailman/data/owner-bounces.mbox

# STANZA START: mailman
# CREATED: Mon Dec 15 06:10:11 2014
mailman:             "|/opt/mailman/mail/mailman post mailman"
mailman-admin:       "|/opt/mailman/mail/mailman admin mailman"
mailman-bounces:     "|/opt/mailman/mail/mailman bounces mailman"
mailman-confirm:     "|/opt/mailman/mail/mailman confirm mailman"
mailman-join:        "|/opt/mailman/mail/mailman join mailman"
mailman-leave:       "|/opt/mailman/mail/mailman leave mailman"
mailman-owner:       "|/opt/mailman/mail/mailman owner mailman"
mailman-request:     "|/opt/mailman/mail/mailman request mailman"
mailman-subscribe:   "|/opt/mailman/mail/mailman subscribe mailman"
mailman-unsubscribe: "|/opt/mailman/mail/mailman unsubscribe mailman"
# STANZA END: mailman

この2点で正常にメーリングリストが作成されたどうかを判別できる。(実際に問題なく配送されるかは別だが)

マスターパスワード設定

マスターパスワードという名前は勝手につけた名前で、公式ドキュメントでは'site password'と表記されている。

このパスワードはMailmanに関する全ての操作を行うためのパスワードで、Linuxシステムでのrootパスワードと、ほぼ同じとなる。

以下のコマンドで作成する。

# mmsitepass <パスワード>
# /opt/mailman/bin/mmsitepass My-$lt3-p@$sW0rD

当然、取り扱いには最大限の注意を

(ヽ´ω`) < 動作を確認

これでようやく設定は完了。実際にMailmanの動作を確認する。

と、その前にMailmanのサービスが起動していないので起動してやる。 CentOS6で使用できるSysVinit用のサービス起動スクリプトが、script/mailmanにあるので、それを/etc/init.d/にコピーして起動する。

# cp /opt/mailman/script/mailman /etc/init.d/
# chkconfig --add mailman
# service mailman start

投稿確認

早速投稿確認を行う。

現在の状態で、システムにはmailman@ml.tsugihagi.netというメーリングリストが1つだけ存在するので、そこにユーザを追加して、投稿が配送されるかを確認する。

今回はサーバ側の解説がメインなので、この辺りの操作は、実際の運用で作成された手順書等を参考にしてもらいたい。「Mailman 運用」でググると山ほど手順書が引っかかる。

mailman 運用 - Google 検索

Gmailからの投稿確認

Gmailでは同一のMessage-IDを持つメールを重複メールとして扱う、という仕様がある。

Message-IDはメールの送信時に決定されるが、GmailからMailmanに投稿を行った場合、送信は問題なく行われるが、"自分宛に配信されたメール"と"自分が送ったメール"は同一のMessage-IDを持つ。

そのため、Mailmanから送信されたメッセージは、Gmailの受信トレイをスキップして、そのままアーカイブされる(自分が送ったメールが自分へと配信されていないように見える現象が起こる)

Gmail ヘルプ

これはMailmanに限った話ではなく、送信元のMessage-IDを保持するポリシーのメーリングリストシステム全般に起こりうる問題となる。

MailmanのMLではMessage-IDを書き換えるか否かについて、散々に議論された結果、書き換えを行わないという方針となっている。将来的に方針が変更される可能性があるかもしれないが、少なくとも現状ではシステム側・あるいは運用面で対応する必要がある。

運用で対応する場合は「Gmailからの投稿については、送信者へ配送されません」とアナウンスを行えば良いだけなのだが…、新規ではなくリプレース(Majordomoなど)の場合、混乱が起こる可能性がある。

オリジナルのソースに手を加えるリスクを取るか、運用面での手間を取るかはケースバイケースだが、今回の解説では上記の問題に対応した+jバージョンをtarballからインストールすることで、システム側での対応を行った。

実際にGmailアカウントから投稿を行うと、自分が送信したメッセージがちゃんと受信トレイに表示されると思う。

(ヽ´ω`) < ここまでが初期設定

以上でMailmanのインストール部分については完了。

このままの状態で使い続けられるような環境ならば良いんだけど、殆どの場合はそうじゃないはず。

先ほど例でも上げたとおり

  • 投稿の返信先を送信者ではなく、メーリングリストにしたい
  • 返信時の「Re:」の付く場所を変更したい
  • Subjectに自動的に付与される文字列を変更したい
  • WebUIがあるからメールコマンドを無効化したい

など、いろいろな要望があるかと予想されるので、カスタマイズの方法や、運用面でのトラブルシュート、ログの見かたなどを書いていく予定。

(ヽ´ω`) < インストール手順のページは山ほどあるから、どちらかというと、そっちのほうがメインコンテンツですかね。

(ヽ'ω`) < Mailmanをしっかり理解しながらインストール

(ヽ'ω`) < しっかり理解とは?

Mailmanのインストールから実際の運用まで、(可能な限り)コマンドの羅列ではなく、なぜこの設定が必要なのかというところを含めて解説していきたい。というより、忘れないように作業メモを清書しておく。

他のインストール解説ページと比べて冗長な部分が多々あるので、必要のない部分は読み飛ばしてくださいな。

(ヽ'ω`) < 想定環境

ザックリと以下の環境を想定。

対象 環境
OS CentOS 6.5(システムの文字コードEUC-JP)
Python python2.6
Mailman 2.1.14+j7(tarball)
HTTPd Apache2.2 yumでインストール済

(ヽ'ω`) < EUC-JP? UTF-8じゃなくて?

Mailmanの日本語対応にあたって、内部で使用される文字コードはEUC-JPで固定されている。 UTF-8環境での運用も不可能ではないが、コマンドを実行した時など、ふとした時に悩まされることがあるので、Dedicatedなサーバならシステムの文字コードをEUC-JPにしておいたほうが楽

使ったことはないのだが、ハックのためのスクリプトが存在する模様。

python-nkf/mailman-ja-utf8ize.sh at master · fumiyas/python-nkf · GitHub

(ヽ´ω`) < なんでtarballなの? yumとかaptじゃだめなん?

Mailmanの日本語カスタム版がtarballの形式でしか配布されていないため。

素のMailmanでも日本語には対応しているが、以下のように細かなFixが行われている。

Mailman はそのままでも日本語で利用することができますが、それは文字コード 集合についての規則 (JIS) を守っている場合であって、機種依存文字の使用な どでエラーになったり不具合も残っています。このあたりは、日本人でも正確に 問題を把握している人は少なく、その事情を本家の開発者に伝えるのも結構大変です。

そこで、Mailman に少々手を加えて、日本語メールで機種依存文字を使われても、 文字コード集合の規則にかなったメールを配信できるようにしたものを +j バー ジョンとして作成しました。

(ヽ´ω`) < インストールの流れ

インストールは以下の流れで行っていく。

  • Mailman本体のインストール
    1. mailmanユーザとグループの作成
    2. ディレクトリの準備
    3. パッケージのダウンロードと解凍
    4. ファイルのインストール
    5. アイコンファイルのコピー
  • Postfix側での設定
    1. Postfixでaliasesファイルの場所を指定
    2. aliasesファイル内forward, includeでのコマンド実行許可を設定
    3. mynetworksへのIPv6ループバックアドレスの追加
    4. Postfix再起動
  • ログやcronなどの周辺環境の設定
    1. ログローテーションの設定
    2. 定期処理をcrontabへ追加
  • Apacheとの連携設定
    1. AddDefautCharsetの変更
    2. WebインターフェースのためのScriptAlias設定
    3. PipermailのためのAlias設定
    4. アクセスコントロール
    5. Apache再起動

ここまでやって、ようやくMailmanの設定に入れる

  • Mailmanの初期設定
    1. mm_cfg.pyの設定
    2. aliasesファイルの仮作成
    3. 管理ML(mailman)作成
    4. マスターパスワード設定
  • 動作を確認
    1. 投稿確認
    2. Gmailからの投稿確認

(ヽ´ω`) < Mailman本体のインストール

まずはMailmanをインストールするためのユーザ・グループ、ディレクトリを作成。その後、Mailmanのパッケージを取得し、ファイルシステム上へ配置していく

mailmanユーザとグループの作成

Mailmanで使用するユーザとグループを作成する。名前はそのものズバリのmailman

ログインシェルは必要ないので/sbin/nologinにしておく。

# groupadd mailman
# useradd -s /sbin/nologin -g mailman mailman

ディレクトリの準備

Mailmanをインストールするディレクトリを作成する。

ここで悩ましいのが、/usr/local以下に配置するか、/optのようなそれ以外の場所に配置するか。

デフォルトのインストールでは/usr/local/mailmanへの配置となるのだが、それにしてもmakeで自動的に作成されるわけではなく、./configureより事前に作成しておく必要がある。作成されていない場合は./configureが失敗する。

また、ディレクトリ構成も

[root@486497a9e830 mailman]# pwd
/usr/local/mailman
[root@486497a9e830 mailman]# tree -L 1 ./
./
|-- Mailman
|-- archives
|-- bin
|-- cgi-bin
|-- cron
|-- data
|-- icons
|-- lists
|-- locks
|-- logs
|-- mail
|-- messages
|-- pythonlib
|-- qfiles
|-- scripts
|-- spam
|-- templates
`-- tests

18 directories, 0 files

このように、binディレクトリも含め、全てを自分のディレクトリの中に持つような形なので、ディレクトリの役割的には/usr/lib/optに配置するのが正しいかなと思う。

参考

というわけで、/optにディレクトリを作成。

# mkdir /opt/mailman

ディレクトリのグループをmailmanに設定して、パーミッションを02775に設定する。

# chgrp /opt/mailman mailman
# chmod 02775 /opt/mailman

パッケージのダウンロードと解凍

下記URLからMailmanの+jバージョンを取得し、展開したものを、適当なディレクトリ(/usr/local/src)に置く。

リリース情報 — Mailman日本語情報

2014/11/13現在で、最新のものは mailman-2.1.14+j7 となっている。

Mailman公式では2.1系の最新バージョンは mailman-2.1.18-1 になっており、どちらを使うか悩ましいところ。

1.14から1.18までのRelease notesとChangelogを見てみると、結構な数の新機能とバグフィックスが含まれている様子なので、可能であれば1.18-1を使用したほうが…と思いつつ、このメモを作成した時は1.14+j7が最新だったのでとりあえず今回の解説は1.14+j7をベースに行っていく。

2.1.15 : Series 2.1 : GNU Mailman 2.1.16 : Series 2.1 : GNU Mailman 2.1.17 : Series 2.1 : GNU Mailman 2.1.18 : Series 2.1 : GNU Mailman 2.1.18-1 : Series 2.1 : GNU Mailman

# cd /usr/local/src
# wget http://docs.python.jp/contrib/mailman/_static/mailman-2.1.14+j7.tgz
# tar xvzf mailman-2.1.14+j7.tgz

ファイルのインストール

解凍して作成されたディレクトリで./configure, make, make installを行っていく。

まずは./configure * prefixオプションは、先ほど作成した/opt/mailmanを渡す * with-cgi-gidでApacheの実行グループ名を渡す

mailmanではWeb管理画面を提供しているため、Apacheとの連携のために、Apacheの実行グループ名を、with-cgi-gidオプションで渡してやる必要がある。Apache以外のHTTPdサーバについては未調査(ヽ´ω`)

CentOS6のyumでインストールした場合のユーザ名はapacheとなるが、Debianなんかだとwww-dataになるし、指定しないとnobodyが値として使われる。

その他のオプションは以下のページを参照

3.1 Run configure

# cd /usr/local/src/mailman-2.1.14+j7
# ./configure --prefix=/opt/mailman --with-cgi-gid=apache

この時点で、mailman, apacheユーザが作成されていなかったり、インストール先ディレクトリが存在しない・パーミッションが適切でない場合はエラーが発生する。

問題なく終了したら、次はmakemake install。これに関しては特に注意点は無いかと。

# make
# make install

ファイルが配置されたら付属のbin/check_permスクリプトでパーミッションの確認を行う。問題がある場合はメッセージが表示されるので、適時修正して問題が出なくなるまでその作業を繰り返す。

このコマンドはカレントディレクトリをbinに変更してから実行する。

# cd /opt/mailman/bin
# ./check_perm -f

Dockerで実際に上記チェックスクリプトを実行したところ、下記のエラーが発生した。

[root@d09f4ab28203 bin]# ./check_perms -f
directory permissions must be 02775: /opt/mailman/templates/gl (fixing)
directory permissions must be 02775: /opt/mailman/templates/ru (fixing)
directory permissions must be 02775: /opt/mailman/templates/fi (fixing)
directory permissions must be 02775: /opt/mailman/templates/lt (fixing)
directory permissions must be 02775: /opt/mailman/templates/da (fixing)
directory permissions must be 02775: /opt/mailman/templates/it (fixing)
directory permissions must be 02775: /opt/mailman/templates/pt (fixing)
directory permissions must be 02775: /opt/mailman/templates/de (fixing)
directory permissions must be 02775: /opt/mailman/templates/cs (fixing)
directory permissions must be 02775: /opt/mailman/templates/pt_BR (fixing)
directory permissions must be 02775: /opt/mailman/templates/zh_TW (fixing)
directory permissions must be 02775: /opt/mailman/templates/pl (fixing)
directory permissions must be 02775: /opt/mailman/templates/uk (fixing)
directory permissions must be 02775: /opt/mailman/templates/sk (fixing)
directory permissions must be 02775: /opt/mailman/templates/sr (fixing)
directory permissions must be 02775: /opt/mailman/templates/el (fixing)
directory permissions must be 02775: /opt/mailman/templates/zh_CN (fixing)
directory permissions must be 02775: /opt/mailman/templates/fr (fixing)
directory permissions must be 02775: /opt/mailman/templates/eu (fixing)
directory permissions must be 02775: /opt/mailman/templates/en (fixing)
directory permissions must be 02775: /opt/mailman/templates/hu (fixing)
directory permissions must be 02775: /opt/mailman/templates/es (fixing)
directory permissions must be 02775: /opt/mailman/templates/sl (fixing)
directory permissions must be 02775: /opt/mailman/templates/ar (fixing)
directory permissions must be 02775: /opt/mailman/templates/ro (fixing)
directory permissions must be 02775: /opt/mailman/templates/ast (fixing)
directory permissions must be 02775: /opt/mailman/templates/no (fixing)
directory permissions must be 02775: /opt/mailman/templates/ko (fixing)
directory permissions must be 02775: /opt/mailman/templates/ca (fixing)
directory permissions must be 02775: /opt/mailman/templates/sv (fixing)
directory permissions must be 02775: /opt/mailman/templates/vi (fixing)
directory permissions must be 02775: /opt/mailman/templates/nl (fixing)
directory permissions must be 02775: /opt/mailman/templates/tr (fixing)
directory permissions must be 02775: /opt/mailman/templates/ja (fixing)
directory permissions must be 02775: /opt/mailman/templates/he (fixing)
directory permissions must be 02775: /opt/mailman/templates/et (fixing)
directory permissions must be 02775: /opt/mailman/templates/hr (fixing)
directory permissions must be 02775: /opt/mailman/templates/ia (fixing)
directory permissions must be 02775: /opt/mailman/messages/gl (fixing)
directory permissions must be 02775: /opt/mailman/messages/ja_JP.UTF8 (fixing)
directory permissions must be 02775: /opt/mailman/messages/ru (fixing)
directory permissions must be 02775: /opt/mailman/messages/fi (fixing)
directory permissions must be 02775: /opt/mailman/messages/lt (fixing)
directory permissions must be 02775: /opt/mailman/messages/da (fixing)
directory permissions must be 02775: /opt/mailman/messages/it (fixing)
directory permissions must be 02775: /opt/mailman/messages/pt (fixing)
directory permissions must be 02775: /opt/mailman/messages/de (fixing)
directory permissions must be 02775: /opt/mailman/messages/cs (fixing)
directory permissions must be 02775: /opt/mailman/messages/pt_BR (fixing)
directory permissions must be 02775: /opt/mailman/messages/zh_TW (fixing)
directory permissions must be 02775: /opt/mailman/messages/pl (fixing)
directory permissions must be 02775: /opt/mailman/messages/uk (fixing)
directory permissions must be 02775: /opt/mailman/messages/sk (fixing)
directory permissions must be 02775: /opt/mailman/messages/sr (fixing)
directory permissions must be 02775: /opt/mailman/messages/el (fixing)
directory permissions must be 02775: /opt/mailman/messages/zh_CN (fixing)
directory permissions must be 02775: /opt/mailman/messages/fr (fixing)
directory permissions must be 02775: /opt/mailman/messages/eu (fixing)
directory permissions must be 02775: /opt/mailman/messages/hu (fixing)
directory permissions must be 02775: /opt/mailman/messages/es (fixing)
directory permissions must be 02775: /opt/mailman/messages/sl (fixing)
directory permissions must be 02775: /opt/mailman/messages/ar (fixing)
directory permissions must be 02775: /opt/mailman/messages/ro (fixing)
directory permissions must be 02775: /opt/mailman/messages/ast (fixing)
directory permissions must be 02775: /opt/mailman/messages/no (fixing)
directory permissions must be 02775: /opt/mailman/messages/ko (fixing)
directory permissions must be 02775: /opt/mailman/messages/ca (fixing)
directory permissions must be 02775: /opt/mailman/messages/sv (fixing)
directory permissions must be 02775: /opt/mailman/messages/vi (fixing)
directory permissions must be 02775: /opt/mailman/messages/nl (fixing)
directory permissions must be 02775: /opt/mailman/messages/tr (fixing)
directory permissions must be 02775: /opt/mailman/messages/ja (fixing)
directory permissions must be 02775: /opt/mailman/messages/he (fixing)
directory permissions must be 02775: /opt/mailman/messages/et (fixing)
directory permissions must be 02775: /opt/mailman/messages/hr (fixing)
directory permissions must be 02775: /opt/mailman/messages/ia (fixing)
Warning: Private archive directory is other-executable (o+x).
         This could allow other users on your system to read private archives.
         If you're on a shared multiuser system, you should consult the
         installation manual on how to fix this.
Problems found: 76
Re-run as mailman (or root) with -f flag to fix
[root@d09f4ab28203 bin]# ./check_perms -f
Warning: Private archive directory is other-executable (o+x).
         This could allow other users on your system to read private archives.
         If you're on a shared multiuser system, you should consult the
         installation manual on how to fix this.
No problems found

表示の通りfixingと表示されていたので、もう一度実行するとエラーは自動で修正されていた。

Private archive directoryに関するWarningが出ているが、これはDedicated(専有)サーバでない(一般のユーザが自由にログイン可能)場合、そのユーザたちがPrivateなアーカイブを閲覧できてしまうという警告。専有サーバであっても、そのまま放置するのも気味が悪いので変更しておく。

# chmod o-x /opt/mailman/archives/private/
# ./check_perms -f
No problems found

アイコンファイルのコピー

WebUIのためのアイコン画像が<インストール先ディレクトリ>/icons/に入っている。このファイルをhttp://<ホスト名>/icons/から参照できるようにコピーする。yum経由でhttpdをインストールした場合は、/var/www/icons/になるので、

# cp /opt/mailman/icons/* /var/www/icons/

とする。

以上でファイルの配置は完了。次はMailman本体の設定、と行きたいところだが、その前に連携するMTA側の設定を行う。

(ヽ´ω`) < Postfixの設定

MTAとしてPostfixを例に設定を行っていく。

(ヽ´ω`) < というかsendmailが魔窟過ぎて…

aliasesファイルの場所を追加

Mailmanはメーリングリストのサーバではあるものの、実際にメールを受け取るのはMTA(Postfix)の仕事になる。Postfixは受け取ったメールが、メーリングリスト宛のメールであれば、Mailmanのプログラムにそのメールを転送する。

Postfixがメーリングリスト宛かどうかを判断するのが、aliasesファイルとなる。

Mailmanはメーリングリストの作成・削除を行う度にdata/aliasesというファイルを作成する。このファイルをPostfixがaliasesファイルとして読みこむように、以下の設定を追加する。

PostfixをCentOS6のyumでインストールした場合、編集するファイルは/etc/postfix/main.cfとなる。

# 以下の内容がPostfixのデフォルト値
#alias_maps = hash:/etc/aliases
#alias_database = hash:/etc/aliases
# 以下のように追記
alias_maps = hash:/etc/aliases, hash:/opt/mailman/data/aliases
alias_database = hash:/etc/aliases, hash:/opt/mailman/data/aliases

aliasesファイル内includeでのコマンド実行許可を設定

Postfixのデフォルトでは、メールをコマンドに渡すのをaliasesとforwardでしか許可をしていない。

local(8) が外部コマンドへメールを配送するのを制限します。 デフォルトでは :include: ファイルでの "|command" への配送を認めません (この用例を定義している文章は aliases(5) を参照してください)。

Postfix 設定パラメータ

:include:でもコマンドを実行するのを許可するために、以下の設定を/etc/postfix/main.cfに追加。

allow_mail_to_commands = alias,forward,include

ただ、これMailmanのインストール手順に書いてあるけど、Mailmanが作成するaliasesファイルに:include:が含まれてないんですよね。なんなんだろう?(ヽ´ω`)

mynetworksへのIPv6ループバックアドレスの追加

環境依存の問題なのかは不明だが、mynetworksへIPv6のループバックアドレスを追加しないと、外部へのメール配送が上手くいかない。

Bug #676777 “need to add Ipv6 localhost address in /etc/postfix/...” : Bugs : ubuntu-docs package : Ubuntu

/etc/postfix/main.cfmynetworksに値を追加

mynetworks = [既存の値], [::1]/128

Postfix再起動

設定を書き換えたので再起動。

説明は端折ってあるが、そもそものPostfixの基本的な設定はしっかりできていることが大前提。再起動後に、Mailmanは置いておいて正常にメールの送受信ができるかを確認する。

(ヽ´ω`) < ログやcronなどの周辺環境の設定

ここまでやっても、未だMailman本体の設定には入らない。我慢していくスタイル。

続いてMailmanのログローテーションの設定と、定期処理のためのCron設定を行う。

ログローテーションの設定

ログのローテーションはlogrotateコマンドに任せることになるが、syslog経由で吐き出されるログじゃないので、ローテーション実行時の再読み込み処理が独自のコマンドとなる。

4.07 How can I rotate my Mailman logs? - Documentation - Confluence

上記URLによると(また、コマンドのヘルプでも確認できたが)、以下のコマンドを実行することで、ログが再オープンされる。

# bin/mailmanctl reopen 

ということで、/etc/logrotate.d/mailmanファイルを新規に作成して、以下の内容を記述する。

/opt/mailman/logs/bounce
/opt/mailman/logs/mischief
/opt/mailman/logs/error
/opt/mailman/logs/post
/opt/mailman/logs/smtp
/opt/mailman/logs/smtp-failure
/opt/mailman/logs/qrunner
/opt/mailman/logs/locks
/opt/mailman/logs/fromusenet
/opt/mailman/logs/subscribe
/opt/mailman/logs/vette
{
    sharedscripts
    postrotate
        /opt/mailman/bin/mailmanctl reopen > /dev/null 2>&1 || true
    endscript
}

対象ファイルの指定で/opt/mailman/logs/*じゃダメなの? と思うかも知れないが、

(ヽ´ω`) < マジで死ぬ。というか死んだ。

Mailmanは関係のない話になるが、ローテーション後のxxxxx.xのファイルもローテーションの対象になってエライことになる。

定期処理をcrontabに追加

Mailmanではメールの配送以外で、以下の様な処理をcronで定期実行している。

  • 保留中の処理やパスワード変更に関する通知
  • リストのメール書庫の圧縮
  • その他、ユーザへの情報通知やキューの掃除など

これらの処理はcron/ディレクトリにスクリプトとして用意されている。

この処理をシステムのcronへ登録するために、以下のコマンドを実行する。

# crontab -u mailman cron/crontab.in

上記のコマンドの-uオプションからも分かる通り、これらの処理はmailmanユーザの権限で実行される。

追加される内容はcron/crontab.inに記載されている。実際に中身を見てもらえればわかるが、これ本当に必要か? と思う処理もいくつかある(コメントにも"必要ないならコメントアウトしてね"って書いてあるものもある)
この辺りの調整は、運用ポリシーなどの問題もあるのでここでは触れずに、別エントリで考える。

(ヽ´ω`) < Apacheとの連携設定

先述の通り、Mailmanでは各リストの管理にWebインターフェースを提供している。Webサーバ機能は内蔵していないため、ApacheのようなHTTPdサーバとの連携が必要となる。 また、Mailmanではやりとりされたメールをアーカイブ化して、Webから閲覧可能にするPipermailという機能を持っている。そこでも連携設定が必要となる。

とは言っても、そこまで面倒な設定が必要なわけではなく、Apache側でAliasを張るだけ。

下記2つの設定は、httpd.confの中に追加してもいいし、/etc/httpd/conf.d/mailman.confのようなファイルを新規に作成して、その中で記述するのもOK。Debianならmods-availableの中にmailman.confを作成して、mods-enabledにSymlinkを張るという形か。

AddDefaultCharsetのOff

Mailmanに限った話ではないが、ApacheではAddDefaultCharsetディレクティブで、サーバがtext/plainやtext/htmlな種類のファイルを応答する際に、任意の文字コードを指定してHTTPヘッダに挿入することができる。

core - Apache HTTP サーバ バージョン 2.2

CentOS6のyumでインストールできるApacheでは、デフォルトでutf-8が指定されている(2014/11/14)。のだが、Mailmanが生成する日本語のページのエンコーディングは、全てEUC-JPとなっている。

そのため、デフォルトのApacheのままでは日本語のページを表示させた時に、文字化けが発生する。

個々のHTMLページ内に記載されるmetaタグ内のContent-Typeは、優先順位の関係で無視される。

Javaの文字化け対策FAQ(1):Webブラウザが文字コードを判定する基準は? - @IT

まずは、Webにおける文字コードの扱いをおさらいしておこう。HTML 4.01仕様では、Webブラウザが以下の優先順位で文字コードを決定することを規定している。

  1. HTTPにおけるContent-Typeヘッダのcharsetパラメータ
  2. HTML文書内のMETA宣言およびhttp-equiv属性で設定された、Content-Typeヘッダのcharsetパラメータ
  3. HTML文書内の各要素のcharset属性

というわけで、Apacheの設定でhttpd.conf内にAddDefaultCharsetというディレクティブがあるはずなので、それを探して値をEUC-JPにする。

AddDefaultCharset EUC-JP

これで文字コードの判別は個々のHTMLファイルまたはレスポンスの中のmetaタグから行われる。もしもmetaタグでの定義がされていない場合は、ブラウザの文字コード判別アルゴリズムに則って決定される。

WebインターフェースのためのScriptAlias設定

Mailmanが提供するWebインターフェースの機能はcgi-bin/ディレクトリ内のCGIによって実装されている。

なので単純にApacheの設定に以下の内容を追加してやればいい。

Alias元の/mailman/は任意の値が設定可能だが、とりあえずmailmanとしておく。

ScriptAlias /mailman/ /opt/mailman/cgi-bin/

PipermailのためのAlias設定

これも単純に、ファイルがarchives/publicディレクトリに作成されるので、以下の内容を追加。/pipermail/の部分の値は任意のもので。

Alias /pipermail/ /opt/mailman/archives/public/

リスト毎の設定で、アーカイブを公開(public)にするか否か(private)を設定できる。
archives/ディレクトリにはpublicprivateディレクトリが作成されるため、公開する分はpublicにAliasを張っておく。

アクセスコントロール

上記設定で、Webインターフェースでのエントリポイントが2つ作成された。

これらに対して、無条件でアクセスを許可するのは正直あまり好ましくない。というわけで、アクセスコントロールを設定することができるが、これは各自の環境と運用ポリシーに合わせて設定を行う。

具体的な記述に関しては、その他のセキュリティ対策と一緒に別エントリで。

Apache再起動

設定を書き終わったら、Apacheを再起動して起動に問題がないかを確認する。

(ヽ´ω`) < 長い…

ここまでで、ようやくファイルの配置と周辺環境の設定が完了。

いよいよMailman自身の設定を行っていくことになるが、長くなったので一旦ここで区切り。次のエントリでMailmanの設定について説明していく。

(ヽ'ω`) < DMARCでメーリングリストがやばい

(ヽ'ω`) < メーリングリストからメールが届かんのよ…

という声がそのうち届きそうな予感。未だ実際に、DMARCの副作用による報告は受けていない。

(ヽ'ω`) < いきなり何いってんの?

メール関連技術に関する最近の動向を色々しらべていたら、DMARCというメール送信元偽装による、なりすまし対策の技術が出てきてるらしい。

(ヽ'ω`) < どんな技術か?

現在のメールシステムでは、ヘッダFromの欄はユーザが任意の値を設定できるので、送信者メールアドレスのドメイン名はいくらでも偽装可能な状態。

こういった偽装メールへの対策としてSPFやDKIM等の技術が既に存在し、それなりに普及が進んでいる。DMARCはそれらの技術で「送信元が偽装されている」と疑われたメールに対して、その送信元のドメインの所有者が、そのメールをどのように処理して欲しいかを通達するための技術となる。

このあたりの解説は多分他の図とかを使った解説ページのほうがわかりやすいと思うので、以下を参照。

DMARC - Overview

(ヽ'ω`) < んで、その設定方法は?

DMARCの設定場所としては、ISPのメールサーバとドメイン所有者のDNSサーバの2つ。

ドメイン所有者側での設定作業は

  1. 自分のドメインに偽装して送信されたメールをどういうふうに処理して欲しいかポリシーを決める。ポリシーの選択肢としては
    • 受け取ってほしい
    • 隔離して欲しい
    • 拒否して欲しい
  2. 自分のドメインのDNSに_dmarc.<mydomain>というホストエントリを追加する
  3. 上記で作成したエントリのTXTレコードに、下記のページを参考にしてポリシー設定を流し込む DMARC レコードを作成する - Google Apps ヘルプ

次に、ISPのメールサーバ側での設定…とつなげたいところだが、2014/11/11現在でPostfixでDMARCに対応するためには色々とややこしい手順が必要な様子。うち程度の規模なら、もう少しこなれて来てからの対応でいいかなーという甘え。

[opendmarc-users] OpenDMARC useless with Postfix

で、話を元に戻すとこのDMARCでメーリングリストがやばい、という話題。

(ヽ'ω`) < 何がやばいの?

上述の通り、DMARCは送信元が偽装されたメールの取り扱いを、そのドメインの所有者がどうして欲しいのかを通知する仕組みなのだが、明確な副作用として挙げられているのがメーリングリストから配送されたメールは送信元偽装メールとしてマークされるという点。

通常、メーリングリストから配送されてくるメールの送信元アドレスは投稿者のメールアドレスとなる。しかし、実際にリストのメンバーにメールの送信を行うのはメーリングリストのシステムが動いているドメインのサーバとなり、これは必ずしも送信者のドメインと一致するとは限らない(というより、一致しないケースがほとんどだと思う)

そうなると、メーリングリストから配送されたメールは送信元偽装疑いのメールとして扱われ、DMARCに対応したISPがそのメールを受け取ると、ポリシーが拒否に設定されているドメインの場合はメールが破棄されてしまう。

実際に2014年4月、アメリカのYahooとAOL(@yahoo.com, @aol.com)がDMARCのポリシーを拒否にしたことで、大きな混乱が発生したとのこと。(某冊子ソース)

日本では未だそれほど大きな問題にはなっていないが、DMARCのコントリビュータ一覧を見てみると、いつポリシーの変更による影響を受けてもおかしくはない。

DMARC.org - Domain-based Message Authentication, Reporting and Conformance

(ヽ'ω`) < ん?どうして欲しいかポリシーを公開するだけでなんで破棄確定なん?

ここがちょっとややこしいんだけど、

例えばyahoo.comがDMARCのポリシーとしてrejectを設定しているという事は、yahoo.comのMTAはDMARC対応していれば、当然そのポリシーに従いますよね、と。

DMARCのコントリビュータで、ポリシーも明記しているyahoo.comのMTAがDMARCに対応していないとは考えにくい。

現時点でDMARCポリシーを公開しているドメインは、おおよそMTAがDMARCに対応していると考えられる。結果的に、そのドメインへの正規のメール以外は破棄される可能性が(現状では)非常に高い。

ただ、DMARCの設定のうちDNS側の作業に比べて、MTA側の作業は複雑なので、普及期では「とりあえずDNS側の設定だけをしておいた」というところも出てくるかもしれない。

(ヽ'ω`) < おい、対策方法

まずは問い合わせがあったドメイン名がDMARCのポリシーを拒否にしていないかを確認する。確認方法は、上記の通り、DNSで_dmarcのTXTレコードの値を確認すれば良い。Windowsであればコマンドプロンプトから

C:\> nslookup
> set type=txt
> _dmarc.yahoo.com
サーバー:  *****.*******.***
Address:  ***.***.***.***

権限のない回答:
_dmarc.yahoo.com        text =

        "v=DMARC1; p=reject; sp=none; pct=100; rua=mailto:dmarc-yahoo-rua@yahoo-
inc.com, mailto:dmarc_y_rua@yahoo.com;"

(以下省略)

p=rejectとあればアウト。p=の取りうる値は

  • none - 何もしない(=受け取って欲しい)
  • quarantine - 迷惑メールのマークを付与
  • reject - メール配送を拒否

某冊子の記事の通り、_dmarc.yahoo.com_dmarc.aol.comではp=rejectとなっていた。

_dmarc.gmail.comではp=noneだったが、これがrejectになる日が来るかは不明。あまり想像したくない。

(ヽ'ω`) < 事前に取れる対策はなんかないの?

mailmanではver2.1.16からfrom_is_listというオプションで、投稿されたメールのヘッダFromをメーリングリストに書き換える機能を用意しており、ver2.1.18からはデフォルトでOnとなっている。書き換えられると同時に、Reply-toにオリジナルのFromが付与されるとのこと。

http://wiki.list.org/plugins/viewsource/viewpagesrc.action?pageId=17891477

FMLでは、流石、筑波大学が上記のmailman対策方法と並んで案内をしている。

http://ml.cc.tsukuba.ac.jp/pdf/dmarc-with-mlservice-from.pdf (PDFファイル)

(ヽ'ω`) < Majordomoさん…

That said, perhaps it's time to switch users to Mailman.

Majordomo, DMARC and Yahoo