####
####   PPML ver.0.753 --- "Pigeon Post" Mail-list System
####   Copyright (c) 1999-2003 by Kazunori ANDO all rights reserved.
####
####   http://www.kk.iij4u.or.jp/~ando/ppml/README
#### 
#### This program is free software; you can redistribute it and/or
#### modify it under the terms of the GNU General Public License
#### as published by the Free Software Foundation; either version 2
#### of the License, or (at your option) any later version.
#### 
#### This program is distributed in the hope that it will be useful,
#### but WITHOUT ANY WARRANTY; without even the implied warranty of
#### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#### GNU General Public License for more details.
#### 
#### You should have received a copy of the GNU General Public License
#### along with this program; if not, write to the Free Software
#### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#### 02111-1307, USA.
####

目次


ChangeLog

2003.04.25 0.753
Bugfix/UnlockDone removed from sitedef.ph(suggested by tajima)
2003.04.12 0.752
Add/ppmilter.pl
2002.09.02 0.751
Add/Variable to save Received header(requested by pigeon-ml)
Add/Config to save Return-Path header(requested by pigeon-ml)
2002.08.30 0.750
Improve/exit code(suggested by moton)
Improve/logic around flock(suggested by minmin)
2002.04.11 0.740
Add/ppml-db patch(Config/Members are handled by DBI/PostgreSQL(contributed by koyama)
Add/PPML_VERSION and PPSERV_VERSION variables are set.(suggested by minmin)
Add/approve chirm command to show ppml version(requested by naoto)
2002.04.05 0.736
Add/NOTICE_TO_POSTER to control NOT MEMBER notice to poster(suggested by minmin)
2002.03.14 0.735
Bug fix/Pick-up for boundary of MIME-multipart(suggested by marushin)
2002.03.11 0.734
Bug fix/Pick-up for boundary of MIME-multipart(suggested by marushin)
2002.02.04 0.733
Bug fix/Pick-up for boundary of MIME-multipart
2002.01.29 0.732
Bug fix/Calling point of CheckVirus
2002.01.14 0.731
Change message handling in CheckCache(to avoid reject-loop)
遵法SPAM無視ルール追加
2001.12.30 0.730
Change message handling in CheckVirus(suggested by minmin)
2001.11.29 0.724
2001.11.29 0.723
2001.11.26 0.722
Against W32.Badtrans.B@mm
2001.08.11 0.721
DeletePartのバグフィックス
2001.07.31 0.720
flockまわりの書き直し
MIME multipart解析を第2層まで実施するように変更
※注意※ 設定ファイル中のDeletePartの引数が変わります
2001.07.14 0.711
0.710用IPv6用パッチを追加(contributed by yugawa)
2001.07.11 0.710
SMTP接続あたりの受信者数上限設定の追加(defaultは100)
2001.05.25 0.702
アドレスのlocalpart部分の大文字小文字を認識できるよう変更
一応小文字でも認証は通りますがlogにはoldと出ます(suggested by marushin)
2001.02.11 0.701
SMTPまわりの小変更
2001.02.09 0.70
OPTIMIZED_DELIVERLIST用CGI群を追加(contributed by yuh)
2001.01.31 0.606
sitedef.phの貼付ファイル拡張子判定部分の修正(suggested by mat)
multipart/alternativeへの対応(suggested by mat)
DeletePartのバグフィックス(suggested by nakatomi,yokonami)
2001.01.15 0.605
OPTIMIZED_SKIP機能追加
DELIVERLISTのハンドリングのバグフィックス(suggested by amaike)
2001.01.09 0.604
OPTIMIZED_DELIVERLIST用アンチエイリアス機能追加
投稿認証部分の修正
2001.01.04 0.603
OPTIMIZED_DELIVERLIST機能を追加
既存のmembers.phから共用DELIVERLISTを生成するスクリプト(by yuh)
2000.12.27 0.602
USERCOMMPERMの上書きバグフィックス(suggested by okada)
2000.10.27 0.601
異常終了時にunlock処理を追加(suggested by isihara)
2000.10.09 0.60
USERCOMMPERMのハンドリングのバグフィックス(suggested by hotta)
generateコマンドのパスワード入力部のバグフィックス(suggested by itsu)
2000.09.30 0.599
配送部のSMTP周りをちょこっとだけ変更
2000.09.16 0.598
License が GPL2 になりました
2000.09.11 0.597
さらにLockfileが消えない問題の修正(contributed by isihara)
2000.09.08 0.596
USERCOMMPERMの内部ハンドリングのバグフィックス(suggested by isihara)
Lockfileが消えない問題の解決(suggested by isihara)
2000.09.06 0.595
USERCOMMPERMの内部ハンドリングを変更(suggested by isihara)
2000.09.03 0.594
endコマンドを実装(requested by isihara)
2000.08.26 0.593
ヘルプファイルの選択肢の追加(suggested by isihara)
2000.08.23 0.592
アドレス分割処理を変更(suggested by isihara)
2000.08.18 0.591
USERCOMMPERMのタイプミス修正(suggested by onoue)
2000.08.10 0.59
approve getコマンドを追加
sitedef.phにユーザ用コマンドの抑止設定を追加
make update時にsitedef.ph等の設定ファイルを保存するようにした
(requested by isihara)
2000.07.31 0.582
get,deleteコマンドの不具合の解消(suggested by adachi)
onコマンドの完了通知のSubjectの訂正(suggested by isihara)
2000.07.25 0.581
approve welcomeコマンドの追加(requested by minmin)
2000.07.25 0.580
サイズ制限の通知形式(MIMEだけどmultipartでない場合)のバグフィックス
2000.07.22 0.579
Microsoft OutlookへのDateヘッダによるbuffer overflowアタックの阻止設定の追加
2000.07.20 0.578
サイズ制限の通知形式切替えのバグフィックス(suggested by yoshino)
2000.07.15 0.577
各OS調査の上、cd優先に変更(suggested by minmin)
アーカイブOFFの追加(requested by adachi)
配送アドレス0件でもexit 2しないようにした(requested by adachi)
2000.07.09 0.576
RedHatで/bin/sh(bash)にchdirがない問題に対応(suggested by aso)
2000.07.06 0.575
ppvirus.phがインストールされない問題を解決(suggested by minmin)
2000.05.23 0.574
ILOVEYOU virus対策(その4)
過去にウイルスとして使われたすべての拡張子を持つpartを削除する 設定例をsitedef.phに追加(contributed by hama)
2000.05.08 0.573
ILOVEYOU virus対策(その3)
.vbe/.wsh等のファイル名を持つpartも削除する設定例をsitedef.phに追加
2000.05.06 0.572
ILOVEYOU virus対策(その2)
digital signatureをppvirus.phに追加
.vbsなファイル名を持つpartを削除する設定例をsitedef.phに追加
2000.05.05 0.571
ILOVEYOU virus対策
2000.04.03 0.57
passwdコマンドのbug fix
patchesディレクトリにIPv6対応patchを追加(contributed by yugawa)
2000.01.14 0.56
MIMEの仕様に基因するSubjectの過剰空白の整理をdefaultに追加(suggested by minmin)
2000.01.03 0.55 (Y2KCC/JP memorial version)
コマンドの継続行を可能にした(suggested by akiko in Y2KCC/JP)
アドレス形式チェックを追加(suggested by minmin in Y2KCC/JP)
1999.12.26 0.54
Makefileで最初のインストールに失敗する問題を解決
MIMEマルチパート解析を強化
各パートのdigital-signatureをとりバイナリ貼付型ウイルス対策
マルチパートメールのdigital-signatureをとるツール(sigcheck.pl)追加
手始めに「troj_icqgreeting」のキーをppvirus.phに搭載
1999.12.10 0.53
DSN/MDN storm対策でヘッダ削除ルールをdefaultに追加
$AUTOGENERATEが1になっていない時にgenerateコマンドを受けた場合に
$AUTOGENERATEを1に指定するように応答するようにした
1999.11.30 0.52
Subscribe時に既にメンバーにいないかチェック
1999.11.28 0.51
ErrorMail Handler(ppeh.pl)試作版を追加
1999.11.21 0.50
MakefileでDigest::SHA1が既にあるかどうか確認
wait parameterの見直し
1999.11.18 0.49
ppml.plのIsAuthPosterの仕様変更。$e{'poster'}をset。
1999.11.16 0.48
1行コマンド排除設定を追加
&DecrSeqNum()追加
1999.11.11 0.47
BubbleBoyウイルス対策を追加
1999.11.07 0.46
generateコマンドのコーディング(特にエラーハンドリング)を強化
英語版helpファイルを追加
1999.11.03 0.45
IsAuthPosterでメンバー以外の場合の不測のエラーを回避 (suggested by minmin)
ライセンス表示を一部変更
1999.11.01 0.44
generateコマンドを実装 (thanks to seirios)
1999.10.19 0.43
メンバー認証ルーチン(IsAuthPoster)仕様変更 (suggested by sat,minmin)
1999.10.17 0.421
Makefileのドメイン書き換え部分の不具合修正 (suggested by sat)
1999.10.17 0.42
一般helpと管理者helpを分割 (suggested by moton)
コマンドメール空行でIllegal Commandが返らないように変更 (suggested by moton)
mailbox name "list-admin" changed to "list-request" for RFC2142 complience.(suggested by minmin)
1999.10.13 0.41
メンバ認証ルーチンの分割(suggested by moton,minmin,sat)
1999.09.18 0.40
ヘッダの内部形式を統一(suggested by minmin)
1999.09.16 0.39
getでアーカイブされたメールをas-isで送るように変更(suggested by minmin)
1999.09.07 0.386
ppml.html,ppml-e.htmlの構文チェック(thanks to minmin)
1999.09.07 0.385
tagに余分な空白が入るのを防止する措置(thanks to minmin)
1999.09.06 0.384
$ML_SERVER_ADMIN設定の追加
1999.09.03 0.383
英語版README追加
1999.08.30 0.382
ユーザコマンドの返信が返らないバグを修正。approve subscribeのバグを修正。 (suggested by minmin)
1999.08.28 0.381
lock方式を2つに整理(config.phをflock or .lockfileをlink)
1999.08.28 0.38
fctrl的flockに対応したlock方式を追加。flockを使わない方法、fctrl的flock対応のlock、flockでlockの3種類に。
1999.08.27 0.37
lockfileとリンクでlockするように改良(thanks to minmin)
1999.08.26 0.36
flock()がうまく動作しない場合にlockfileを作って問題を回避するしくみを追加
1999.08.24 0.35
複数コマンド実行時のファイル読込みの無駄を少し解消。Command Reportの末尾のsignature部分に空白を1つ追加。
1999.08.18 0.34
同一コマンドメール中のコマンドの優先実行順を規定。複数コマンド実行時のバグ修正。ppml.htmlを追加(converted by minmin:)。
1999.08.16 0.33
メンバーリストのアドレスを小文字で扱うよう統一し、 メンバー認証のループを解消(thanks to minmin)
1999.07.30 0.325
ppml.plとppserv.plの投稿者認証パターンを同一に
1999.07.25 0.324
sitedef.phのSubject加工部の不具合修正
1999.07.25 0.323
Makefileの不具合修正
1999.07.22 0.322
変数名間違い修正
1999.07.21 0.321
sitedef.ph中のX-Sequenceのタイポ修正
1999.07.20 0.32
コマンドラインsendmail使用時に多人数でtransactionが 分割されるとヘッダが消えるバグを修正。 (thanks to not@iri.co.jp)
Confirm完了通知の文面改良。
&DefaultMakeHeaderをsitedef.phに移動。
1999.07.20 0.31
へッダ加工がdefaultで良い場合にconfig.phに
sub MakeHeader { &DefaultMakeHeader(@_); }
とだけ書けば良いようにデフォルト設定をppml.plに搭載
1999.07.20 0.30
Subjectが空白な場合も考慮(skel/config.ph)
1999.07.19 0.291
ログ機能強化バージョン
1999.07.19 0.29
漢字GECOSトラブル対策さらに強化
1999.07.19 0.28
GECOSに「']が含まれる場合のトラブル回避
1999.07.18 0.27
SendInfoの小バグフィックス(thanks to not@iri.co.jp)
$MAXPARTSIZEがdefineされていない場合にMIME multipart解析 をOFFにするように変更(thanks to minmin@wide.ad.jp)
1999.07.18 0.26
変数間違いの小バグで置き直し(thanks to sat@tokyonet.gr.jp)
1999.07.17 0.26
本文配布サイズ制限と1パートあたりの配布サイズ制限機能を 追加. 制限を越えると本文/そのパートの代りに「必要なら get コマンドで取ってね」というメッセージを入れて送付する。
sub DeletePart を装備。
1999.07.16 0.25
loopcheck部分の小バグフィックスで置き直し
1999.07.16 0.25
漢字GECOS対応強化
READMEのインストールの項にtrusted addressの設定を追加
1999.07.16 0.24
アドレス抽出の正規表現のバグ取り(thanks to not@iri.co.jp)
sendmailが配送できずにエラーした場合にログに残るように改良
SHA1,MD5のdigestの表現形式をbase64に変更
1999.07.15 0.23
checksumにSHA1とMD5のdigestを利用できるよう変更
CPANのDigest-MD5-2.07 moduleを利用
1999.07.11 0.22
skelのconfig.phに設定例を追加
checksumの文字列の形式をbodysize-checksumに変更
1999.07.11 0.21
Makefileを追加
1999.07.09 0.20
アドレス小文字化処理の位置を変更
メンバーリスト送付をサブルーチン1つにして軽量化
On/Off処理をサブルーチン1つにして軽量化
ppserv.plのAuthMemberのバグ修正
1999.07.08 0.19
@MEMBERLIST未定義で投稿者認証しないモードを追加
ppserv.plではメンバー認証は@ADMINLISTと@DELIVERLISTで 行ない、@MEMBERLISTは配送認証に特化。
認証、登録、削除、on、off時にアドレスを小文字で扱う ことで統一(既に大文字で登録してるアドレスあったら 小文字に直しといて下さい)
1999.07.06 0.17
approve passwdコマンド追加
1999.07.06 0.16
TYPO修正(config.phの@DELIBERLISTを@DELIVERLISTに直すべし)
1999.07.05 0.15
自動subscribe機能の追加
1999.07.05 0.14
Not memberの通知をエラーからNoticeMailに。
1999.07.05 0.13
コマンドライン渡しの配送を追加
1999.07.05 0.12
approve newinfoコマンドの動作改善
1999.07.05 0.11
sitedef.phが見つからない問題の解決、インストール方法の改善
1999.07.04 0.1
test release

はじめに

Contributors in alpha period

民田さん@松井証券、さとる氏@とんきんぐらでゅえーとほか、選りすぐり の数名の方たちありがとう :)

ライセンス(1999.11.03)

著作権は安藤一憲(ando@kk.iij4u.or.jp)が保持しています。 本ソフトウェアのライセンスはGNU Public License(version 2)に準拠します。 詳しくはCOPYINGファイルをごらん下さい。 本ソフトのパッケージにはmime_plsとDigest-MD5-2.07の全パッケージ が含まれています。

命名の由来

このシステムの"Pigeon Post"(伝書鳩通信)の名前はシンプルで軽いという イメージからIRCの某チャンネルで民田さん(minmin@wide.ad.jp)によって 名付けられました。


プログラムについて

開発コンセプト

「読めないMLドライバはもういらない」のコンセプトのもと、余分なぜい 肉はそぎ落して、安全性に配慮して基本機能にこだわりつつ見通しの良い プログラムを目指しました。もちろんすべての部分をスクラッチから書い ています。コマンドインターフェースはmajordomo風味ですが完全に同じで はありません。若干のperlの知識があればかなりの自由度で各MLを設定で きます。わけのわからない変数で設定するよりはパーサの仕様を公開して ダイレクトにヘッダ等をいじるほうが中身が見える分安心でしょう。 従来のMLドライバと比較すると、ppmlはRFC822的メッセージ(メール)を perlでハンドリングするための基礎インターフェースと言った方が近い かもしれませんが、もちろんMLドライバとしても高性能です。

MLドライバの特徴

他の多くのMLドライバと決定的に違うことに、メンバーリストと管理者リス トが.phファイルになっており、リストはその中でhashとして定義されてい ます。これは、投稿者認証等の線形サーチ等による無駄と処理プログラムの 複雑化を防ぎ、同じアドレスの重複登録が構造的に発生しないという大きな 特徴を持っています。hashのdataの部分は、管理者リストではパスワード、 メンバーリストではGECOSの収納場所として使われており、whoコマンドに よるアドレスの一括漏洩の阻止に一役買っています。

ループ/bombing対策として、Message-Idとメールの本文部分のchecksumの ダブルチェックを行なっています。従って本文部分が全く同一のメールは pp.cacheがクリアされない限り2度と投稿できません(短いメールの多いML では1日1回くらいcronでクリアしたほうが良いかも)。また、log機能が 充実しておりSMTPで発信したメールの宛先アドレス数と終了ステータスは 全てlogに残ります。

バイナリ貼付型ウイルスへの対策としてdigital-signatureによる ウイルスチェックルーチンを搭載しました。手軽にマルチパートメール の各部分のdigital-signatureが取れるようにsigcheck.plコマンドも追加 してあります。ウイルスと判明した場合は次のようにして出力結果を お知らせ下さい。ppvirus.phに追加してリリースさせて頂きます。 (ただし、現状のところマクロウイルスには効果がありません)

% sigcheck.pl < 22 ^^ ウイルス入りと判明したファイル

0.57で湯川さん作のIPv6対応パッチを収録しています。パッチ適用のしかたは ppmlのソースディレクトリにて、

% patch -pl < patches/ppml-0.562-patch-yugawa-ipv6.txt
です。

0.603でOPTIMIZED_DELIVERLIST機能を追加しました。これは、 『複数ML宛にポストされたメールが各メンバーに重複して配送されるのを防ぐ』 という目的で設計されています。メンバーが重複しがちなMLでメンバーリストを 共用することでこの機能を実現しています。この機能を利用するには重複配送を 阻止したい各MLのconfig.phで、

### Optimized $OPTIMIZED_DELIVERLIST = 1; @MEMBERLIST = ('../opt-members.ph','admins.ph'); @DELIVERLIST = ('../opt-members.ph');

のように指定します。この例では各MLで共用する opt-members.ph は MLの設定ディレクトリの外($ML_SETTING_ROOT直下)に置いています。 メンバーファイルの中身は、

%members = (
    'user1@ppml.tv' => ['Kazunori ANDO','info','# staff','support',],
    'user2@hitokai.com' => ['Kazunori ANDO','info','support',],
    'user3@kk.iij4u.or.jp' => ['Kazunori ANDO','support','staff',],
);
1;

のようになっており、To及びCcヘッダに含まれるアドレスのうち、 メンバーリストで最も先(すなわち左)に書いてあるMLにだけメールが 配送されます。同じメールが何通も来る環境でお悩みの場合にお試し 下さい。コマンドメールもほぼそのまま使用できますが、この機能を 実現する上で、登録・削除・on・off等のコマンドが@DELIVERLISTの 先頭にあるリストにしか作用しなくなっているので注意しましょう。 ML名が他のaliasで指定される場合には別名の登録ができます。

0.605ではML以外のアドレスがTo及びCcヘッダに含まれている場合に MLでそのアドレスへの配送が発生してもSKIPするOPTIMIZED_SKIP機構が 追加されました。

0.70でOPTIMIZED_DELIVERLIST用CGI群をパッケージに追加しました。 詳しくはcontrib/READMEを御覧下さい。

0.740で小山さん作のperlのDBIを用いて設定ファイルのいくつかを PostgreSQL等のDB上に乗せてしまうことのできるppmldb patchをパッ ケージに追加しました。内容に関してはREADME-dbaccessを御覧下さい。 パッチの適用のしかたは、

% zcat patches/ppml-0.740-patch-koyama-ppmldb.gz | patch -pl
です。

0.752でppmilter.plをパッケージに追加しました。 Sendmail::Milterモジュールをインストールして御利用下さい。

perlのSendmail::Milterモジュールをインストールする。
sendmail-8.12.x/devtools/Site/site.config.m4に以下の一行を書く
APPENDDEF(`conf_sendmail_ENVDEF', `-DMILTER')
sendmail-8.12.x/cf/cf/config.mc等に以下の記述を追加
INPUT_MAIL_FILTER(`ppmilter', `S=local:/var/run/perl.sock')dnl

動作環境

perl5.005_05とsendmail-8.12.9でテストしながら作成しています。 あと、どこかにSMTPでメールを受けられる(relayしてくれる)ホスト (localhostでかまわない)あるいはコマンドラインで動くsendmail等が 必要になります。sendmail-8.12.9の設定については、

http://www.kk.iij4u.or.jp/~ando/config.txt

に簡単な文書を準備するつもりです(^^;

内部でのデータの扱い

メインルーチンの流れ

##### main #####
&ReadSiteConfig;     # sitedef.phを読む
&ChdirByArg;         # includeで指定したppml.plの引数のディレクトリにchdir
&PPLockWait;         # 排他的Lock
&ReadConfig;         # config.phを読む
&ParseInput(*e);     # メールを読んで%eに値を入れる
&CheckCache(*e);     # checksumとMessage-Idのcacheをチェック(ループ対策)
&AuthPoster(*e);     # 投稿者認証
&IncrSeqNum(*e);     # シーケンスナンバの生成
&MIMEdecode(*e);     # ヘッダのMIME decode
&MakeHeader(*e);     # ヘッダ加工(config.phで定義)
#&DebugPrint(*e);
&MIMEencode(*e);     # ヘッダのMIME encode
&SaveAsFile(*e) unless ($NOARCHIVE);
                         # 送信されるメールを$Savedirにアーカイブ
&Distribute(*e);     # SMTPでメールを配る
&Unlock;             # 排他的lockの解除
&Done;
################

パーサ(&ParseInput(*e))の処理

メール → $e{'Body'}   → $e{'checksum:body'},
                          $e{'size:body'},
                          $e{'line:body'},
                          ※ 以下はMIME multipartなメッセージの場合
                          $e{'mp:00'},          # パート数
                          $e{'mp:00:boundary'}  # バウンダリ
                          $e{'mp:00.01'},       # 1つめのパート
                          $e{'mhead:mp:00.01'}  # 1つめのパートのMIMEヘッダ
                          $e{'mbody:mp:00.01'}  # 1つめのパートの本文
                          $e{'size:mp:00.01'}   # 1つめのパートのサイズ
                          $e{'checksum:mp:00.01'} # 1つめのdigital-signature
                          $e{'mtype:mp:00.01'}  # 1つめのパートのMIME-type
                          $e{'mchar:mp:00.01'}  # 1つめのパートのcharset
                          $e{'mcode:mp:00.01'}  # 1つめのパートのencoding
                          $e{'mname:mp:00.01'}  # 1つめのパートのfile名
                          $e{'mp:00.02'},       # 2つめのパート
                          $e{'mhead:mp:00.02'}  # 2つめのパートのMIMEヘッダ
                          $e{'mbody:mp:00.02'}  # 2つめのパートの本文
                          $e{'size:mp:00.02'},  # 2つめのパートのサイズ
                          $e{'checksum:mp:00.02'}# 2つめのdigital-signature
                          $e{'mtype:mp:00.02'}  # 2つめのパートのMIME-type
                          $e{'mchar:mp:00.02'}  # 2つめのパートのcharset
                          $e{'mcode:mp:00.02'}  # 2つめのパートのencoding
                          $e{'mname:mp:00.02'}  # 2つめのパートのfile名
                          …
                         (以下は2つめのパートがmultipartだった場合の解析)
                          $e{'mp:02'}           # パート数
                          $e{'mp:02:boundary'}  # バウンダリ
                          $e{'mp:02.01'},       # 1つめのパート
                          $e{'mhead:mp:02.01'}  # 1つめのパートのMIMEヘッダ
                          $e{'mbody:mp:02.01'}  # 1つめのパートの本文
                          $e{'size:mp:02.01'},  # 1つめのパートのサイズ
                          $e{'checksum:mp:02.01'}# 1つめのdigital-signature
                          $e{'mtype:mp:02.01'}  # 1つめのパートのMIME-type
                          $e{'mchar:mp:02.01'}  # 1つめのパートのcharset
                          $e{'mcode:mp:02.01'}  # 1つめのパートのencoding
                          $e{'mname:mp:02.01'}  # 1つめのパートのfile名
                          …

          $e{'Header'} → $e{'size:header'}
                          $e{'OH:From'},       # ヘッダの左辺(field-name)
                          $e{'H:From'},        # ヘッダの右辺
                          $e{'OH:Subject'},    # ヘッダの左辺(field-name)
                          $e{'H:Subject'},     # ヘッダの右辺
                          $e{'OH:Message-Id'}, # ヘッダの左辺(field-name)
                          $e{'H:Message-Id'},  # ヘッダの右辺
                          … 

      $e{'H:Received'} → $e{'received:0'},    # ヘッダの右辺のみ(差出し元)
                          $e{'received:1'},    # ヘッダの右辺のみ(リレー1)
                          $e{'received:2'},    # ヘッダの右辺のみ(リレー2)
                          …

          ※ %e 中でkeyは「field-nameの先頭、'-'の後を大文字にしたもの」を使用
          ※ %e 中でヘッダはkeyの頭の'H:'で識別

インストール

1. ppmlを動作させるユーザを用意する

rootになってppmlを動作させるユーザを決めるor作成し、sendmail.cfの trusted userに加える(user:group = ppml:ppmlとする)

● /etc/sendmail.cf

# this is equivalent to setting class "t"
T root daemon uucp ppml

2. Makefileでppmlのインストール先等を編集し make install

##################### SET VARIABLES HERE ####################
UID                     = ppml
GID                     = ppml
DOMAIN                  = ppml.tv
FQDN                    = ns0.ppml.tv
PERL                    = /usr/local/bin/perl
PPMLDIR                 = /usr/local/ppml
ML_SETTING_ROOT         = /usr/local/lib/ppml
####
CHDIR                   = cd
#### for non-POSIX shells
# CHDIR                 = chdir                  
#############################################################

Digest-MD5-2.07のmoduleとppmlパッケージと設定例(skel)がインストールされる

2.1 make README でppml.htmlからテキストのREADMEを生成します

この機能はlynxとnkfに依存しているので、あらかじめREADMEをパッケージに入れてあります:)。

3. MLドライバの設定を確認する

● /usr/local/ppml/sitedef.ph

$Logfile = "pp.log";
$Savedir = "archive";
$Seqfile = "pp.seq";
$Cache = "pp.cache";
$PPEHLOG = "ppeh.log";
$ERRORLOG = "pp.err"; # エラーメール解析記録ファイル
# $USE_LOCKFILE = 1; # 設定の選択肢は以下の通り。
# 指定なし:flock(config.ph)  1:linkを使ったlock(lockfile)
# lockfileを使う方式の場合は、/etc/rc などに、
#         rm -f $ML_SETTING_ROOT/*/archive/.lockfile
# と入れておくと不意にOSが落ちたようなケースでも安心です。
$CHKSUMTYPE = 'SHA1'; # SHA1(160bit)とMD5(128bit)と指定なし(32bit)が選択可
# $ALIASES = "/etc/mail/aliases";
# $AUTOGENERATE = 1;
# この2つを設定するとgenerateコマンドが使えるようになります。
# /etc/aliases に設定を書いて、generate   
# するだけで新規MLの設定ができます。
$ML_SETTING_ROOT = "/usr/local/lib/ppml";  # ML設定ディレクトリのroot
$ML_CONTROL = 'ppserv@ppml.tv';          # コマンド受付アドレス
$ML_SERVER_ADMIN = 'ppserv-request@ppml.tv'; # サーバ管理者アドレス
$PPML_HOST = 'ns0.ppml.tv';             # PPML設置マシンFQDN
$SMTP_HOST = 'localhost:25';               # メール発信先(必要)
$SESSIONMAXRCPTS = 100;                    # SMTP1接続あたりの上限受信者数
$MIMEANALYZE = 1;                          # MIMEマルチパート解析オプション
$MAXBODYSIZE = 500000;                     # 配布本文上限サイズ
$MAXPARTSIZE = 200000;                     # 配布1パート上限サイズ
# $SENDMAILを設定してあると配送にコマンドラインのsendmailを利用
# $SENDMAIL = '/usr/sbin/sendmail';        
# IgnoreDotがsendmail.cfでTrueに設定されていない場合は以下のように指定
# $SENDMAIL = '/usr/sbin/sendmail -i';  
# ユーザコマンドの抑止設定(0にするとそのコマンド使用不可)
%USERCOMMPERM = (
		'index',       '1',
		'get',         '1',
		'on',          '1',
		'off',         '1',
		'unsubscribe', '1',
		'who',         '1',
		'subscribe',   '1',
		'confirm',     '1',
		'info',        '1',
		'help',        '1',
		);


# ヘッダ加工のデフォルト定義。
sub DefaultMakeHeader{
    $0 = "MakeHeader";
    local(*e) = @_;
    ### if you don't allow a field-name like "suBJeCt",
    # foreach $kk (keys(%e)){
    #     if ($kk =~ /^OH\:/){
    #         delete $e{$kk};
    #     }
    # }
    ### delete text/html part(sample:)
    # for ($b = 0 ; $b <= $e{'mp:00'} ; $b++){
    #   $mcb = sprintf("mp:%02d",$b);
    #   for ($i = 1 ; $i <= $e{$mcb} ; $i++){
    #     $mcs = sprintf("mp:%02d.%02d",$b,$i);
    #     if ($e{"mtype:$mcs"} =~ /text\/html/i){
    #         &DeletePart(*e,$b,$i);
    #     }
    #   }
    # }
    ### delete files based on extentions from attachment part(sample:)
    # for ($b = 0 ; $b <= $e{'mp:00'} ; $b++){
    #   $mcb = sprintf("mp:%02d",$b);
    #   for ($i = 1 ; $i <= $e{$mcb} ; $i++){
    #     $mcs = sprintf("mp:%02d.%02d",$b,$i);
    #     if (($e{"mname:$mcs"} =~ /(\.ade|\.adp|\.bas|\.bat|\.chm|\.cmd)/i)||
    #        ($e{"mname:$mcs"} =~ /(\.com|\.cpl|\.crt|\.css|\.exe|\.hlp)/i)||
    #        ($e{"mname:$mcs"} =~ /(\.hta|\.inf|\.ins|\.isp|\.js|\.jse)/i)||
    #        ($e{"mname:$mcs"} =~ /(\.lnk|\.mdb|\.mde|\.msc|\.msi|\.msp)/i)||
    #        ($e{"mname:$mcs"} =~ /(\.mst|\.pcd|\.pif|\.reg|\.scr|\.sct)/i)||
    #        ($e{"mname:$mcs"} =~ /(\.shs|\.url|\.vb|\.vbe|\.vbs|\.wsc)/i)||
    #        ($e{"mname:$mcs"} =~ /(\.wsf|\.wsh|\.csp|\.cab|\.pnf|\.ida)/i)){
    #        &DeletePart(*e,$b,$i);
    #     }
    #   }
    # }
    ### against BubbleBoy virus
    if (($e{'H:Subject'} =~ /BubbleBoy is back\!/i ) &&
        ($e{'Body'} =~ /http\:\/\/www\.towns\.com\/dorms\/tom\/bblboy\.htm/i )){
        &Log("$0:VIRUS: BubbleBoy detected");
        &NoticeMail($ML_ADMIN,"BubbleBoy detected($BRACKET)",$e{'Header'}.$e{'Body'},*r);
        &NoticeMail($ML_SERVER_ADMIN,"BubbleBoy detected($BRACKET)",$e{'Header'}.$e{'Body'},*r);
	exit;
    }
    ### against 1-line Command posting
    if (defined($e{'seq'}) && ($e{'line:body'} <= 2)){
        if ($e{'Body'} =~ /^\s*(info|on|off|who|help|subscribe|unsubscribe)\s*\S*/i){
            &Log("$0:COMM: Command from $e{'poster'} rejected");
            &NoticeMail($e{'poster'},"Command rejected($BRACKET)",$e{'Header'}.$e{'Body'},*r);
            &DecrSeqNum(*e);
            exit;
        }
    }
    ### delete header
    delete $e{'H:Received'};
    delete $e{'H:Return-Path'};
    delete $e{'H:X-Authentication-Warning'};
    delete $e{'H:Return-Receipt-To'};           # to avoid DSN storm
    delete $e{'H:Disposition-Notification-To'}; # to avoid MDN storm
    ### change header
    $e{'H:Subject'} =~ s/\n//;
    $e{'H:Subject'} =~ s/\[$BRACKET\s+\d+\]//;
    1 while $e{'H:Subject'} =~ s/\s*Re\:\s*Re\:\s*/Re\: /i ;
    $e{'H:Subject'} = "[$BRACKET $e{'seq'}] ".$e{'H:Subject'}."\n";
    $e{'H:Subject'} =~ s/(\s)+/$1/g;
    $e{'H:Reply-To'} = $e{'H:Reply-To'} || "$ML_ADDR\n";
    ### overwrite header
    $e{'H:Sender'} = "$ML_ADMIN\n";
    $e{'H:Precedence'} = "bulk\n";
    $e{'H:X-Sequense'} = "$BRACKET $e{'seq'}\n";
    $e{'OH:X-Ml-System'} = "X-ML-System";
    $e{'H:X-Ml-System'} = "Pigeon Post ver.0.753\n";

    return 1;
}
1;

● /usr/local/ppml/include

 "|/usr/local/ppml/ppserv.pl "

● /etc/aliases

# PPML Command Interface
ppserv: :include:/usr/local/ppml/include
ppserv-request: ando@ppml.tv
# ML Setting
skel: :include:/usr/local/lib/ppml/skel/include
skel-request: ando@ppml.tv
# newaliases を忘れずに

4. MLの設定ディレクトリの設定確認

● /usr/local/lib/ppml/skel/include

"|/usr/local/ppml/ppml.pl /usr/local/lib/ppml/skel "

※ ppml.plの引数にそのMLの設定ディレクトリを指定

● /usr/local/lib/ppml/skel/admins.ph

# 管理者アドレスと管理パスワードを設定
%members = (
         'ando@ppml.tv','PASSWORD',
         'ando@kk.iij4u.or.jp','PASSWORD',
);
1;

● /usr/local/lib/ppml/skel/config.ph

#
#  ppml configuration file -- config.ph
#
@ADMINLIST = ('admins.ph');                # 管理者ファイル
# @MEMBERLIST設定をコメントアウトすると誰でも投稿できるモード
### ノーマルな配送
# $OPTIMIZED_DELIVERLIST = 0;
# @MEMBERLIST = ('admins.ph','members.ph'); # 投稿認証用ファイル
# @DELIVERLIST = ('members.ph');            # メール配布先ファイル
### リスト共用で最適化配送
$OPTIMIZED_DELIVERLIST = 1;
$OPTIMIZED_SKIP = 1;
@MEMBERLIST = ('../opt-members.ph','admins.ph');
@DELIVERLIST = ('../opt-members.ph');
@H_ATOM = ('Subject','From','To','Cc','Date','Reply-To','Sender');
$BRACKET = 'PP-GENUINE';                   # [PP-GENUINE 119]
$ML_ADMIN = 'skel-request@ppml.tv';      # 管理者アドレス
$ML_ADDR = 'skel@ppml.tv';               # MLのアドレス
%MLALIAS = (
   'alias-of-skel' => 'skel',              # MLの別名登録
);
# $AUTOSUBSCRIBE = 1;                      # 設定すると自動登録
# $NOARCHIVE = 1;                          # 設定するとアーカイブなし

# ヘッダ加工自由自在 :p
sub MakeHeader{
    $0 = "MakeHeader";
    local(*e) = @_;
    &DefaultMakeHeader(*e);
    ### delete text/html part(sample:)
    # for ($i = 1 ; $i <= $e{'mp'} ; $i++){
    #    if ($e{"mp:$i"} =~ /Content-Type:\s*text\/html/){
    #        &DeletePart(*e,$i);
    #    }
    # }
    ### change Reply-To with AuthPoster
    ### これ使う時は sitedef.ph の関係行は削除のこと
    # if ($e{'auth'}){
    #     $e{'H:Reply-To'} = $e{'H:Reply-To'} || "$ML_ADDR\n";
    # }else{
    #     $e{'H:Reply-To'} = "$ML_ADDR\n";
    # }
    ### add footer(sample:)
    # $e{'Body'} .= "\n\n-- This is footer. Thanks!\n";
    return 1;
}
1;

5. newaliasesしてあとはコマンドでメンバー登録。


新しいMLを作るには?

1. aliasesに設定を書く

● /etc/aliases

# ML Setting
newml: :include:/usr/local/lib/ppml/newml/include
newml-request: ando@ppml.tv
# newaliases を忘れずに

2. generateコマンドを発行する

コマンド受け付けアドレス(ppserv)宛に

generate newml initpasswd

とコマンドを送ってMLを生成します。


PPMLのコマンド体系

管理者のコマンド

approve PASSWORD subscribe MLNAME GECOS-ADDRESS
  ex. approve Der.S subscribe ppmltest あんどー@謎 <ando@kk.iij4u.or.jp>
  ex. approve Des.S subscribe ppmltest ando@kk.iij4u.or.jp (Kazunori ANDO)
  ex. approve Dem.S subscribe ppmltest ando@kk.iij4u.or.jp
  ※ GECOSはメンバーリスト(members.ph)に反映されます。
approve PASSWORD unsubscribe MLNAME ADDRESS
approve PASSWORD off MLNAME ADDRESS
approve PASSWORD on MLNAME ADDRESS
approve PASSWORD passwd MLNAME NEWPASSWORD
  ※ パスワードはadmin1人1人で違うものに設定できます。
approve PASSWORD newinfo MLNAME
  ※ approve newinfoコマンド行の後の行にinfoの本文を書いて下さい。
approve PASSWORD welcome MLNAME
  ※ approve welcomeコマンド行の後の行にwelcomeの本文を書いて下さい。
  ※ welcomeファイルを設置するとアドレスを登録した時にwelcomeメール
     が発信されるようになります。
approve PASSWORD who MLNAME
  ※ アドレス一覧の出るwhoはこちらです。
approve PASSWORD help MLNAME
  ※ 認証にはMLNAMEが必要なんです
approve PASSWORD delete MLNAME 番号
  ex. approve Den.S delete ppmltest 1-3,5,8,9
  ex. approve Die.S delete ppmltest 1-4 6 10
approve PASSWORD get MLNAME 番号
  ex. approve Der.S get ppmltest 1-3,5,8,9
  ex. approve Der.S get ppmltest 1-4 6 10

メンバーのコマンド

get MLNAME 番号
  ex. get ppmltest 1-3,6,7,8
  ex. get ppmltest 2-6 9 10
index MLNAME
who MLNAME
  ※ GECOSの一覧だけでメールアドレスは表示されません。
unsubscribe MLNAME
off MLNAME
on MLNAME

それ以外のコマンド

info MLNAME
subscribe MLNAME
confirm AUTH-NUMBER MLNAME
  ex. confirm 931067337-00000001893 ppmltest
  ※ AUTH-NUMBERはsubscribeするとサーバから返信されてきます。
generate MLNAME PASSWORD
  ※ /etc/mail/aliasesの設定を読んでskelをもとにMLの設定ディレクトリを生成します。
  ※ 管理者の初期パスワードを指定します。
help