fml 8 tutorial
Dr . Ken'ichi Fukamachi
FML.ORG
< fukachan@fml.org >
Copyright © 2001-2018 Ken'ichi Fukamachi
All rights reserved. This program is free software; you can redistribute it and
/or modify it under the same terms as Perl itself.
The current status of fml8 is PRE ALPHA. The version is 7.98.x. We plan to
assign version 7.99.x to fml 8 ALPHA through fml 8 RC (release candidate).
The current TODO is seen at http://www.fml.org/software/fml-devel/fml/doc/ja/
todo/STATUS.html (Japanese only now, sorry). See Chapter 8 on the changes
between fml 4 and fml8.
It is verified that fml8 works on the following environemnt now.
perl 5.8.5 on NetBSD 2.0
perl 5.8.5 on NetBSD 1.6
perl 5.6.1 on NetBSD 1.5.x (1.5 stable)
perl 5.6.1 on NetBSD 1.6
perl 5.6.1 on FreeBSD 5.2.1
perl 5.00503 on FreeBSD 4.3 STABLE
perl ? on FreeBSD 4.6 RELEASE
perl 5.00503 on FreeBSD 4.7 RELEASE-p3
perl 5.00503 on FreeBSD 4.6.2 RELEASE
perl 5.6.1 on Turbolinux Server 8 (qmail)
perl 5.6.1 on Redhat Linux 7.2 (postfix)
perl 5.00503 on Redhat Linux 6.2 (sendmail8.11.6)
postfix + perl 5.6.1 on Solaris 7
postfix 2.0.3 + perl 5.6.1 on Solaris 9
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Table of Contents
Preface
fml8 Status
The Road To The Next Generation Of Fml
Relation Between fml4 And fml8 Development Branch.
Mailing List
Please Let Me Know Your Opinion ...
On This Tutorial
Technical terms in this tutorial
I. Fml Fundamental Usage
1. What Is Mailing List ?
Email
Mailing List (Ml)
2. fml8 Overview
fml8 Features
Installation Overview
Create An ML
Add A New User To ML
Remove The User
Customize
Recipes
II. How To Set Up ML
3. Download fml8 Source Code.
Download Via FTP.
Access To GitHUB.
4. fml8 Installation On Unix
Preparation Of Installation
Run Configure
Appendix: Directory Roles
Fml Installation: make install
Edit main.cf
Edit site_default_config.cf (optional)
Filter
Virtual Domain
MTA Configuration (postfix)
MTA configuration (qmail)
recipes
5. Create ML On Unix
Run "makefml newml" To Create An ML (In The Case Of Default Domain)
Run "makefml newml" To Create An ML (In The Case Of Virtual Domain)
MTA Configuration (postfix)
MTA Configuration (qmail)
Customize config.cf
Recipes
6. fml8 installation on Microsft 2000/NT
7. Convert fml4 Style ML To fml8 Style ML
Overview: fml4 To fml8 (1)
Overview: Convert fml4 To fml8 (2)
Overview: Difference Between fml4 and fml8
Discussion
8. Difference Between fml4 And fml8
Difference Between fml4 And fml8: License.
Difference Between fml4 And fml8: Command Mail And Error Messages.
Difference Between fml4 And fml8: CUI
Difference Between fml4 And fml8: GUI (CGI)
File Naming Convention
9. Upgrade And Downgrade Of fml8
Upgrade
downgrade.
10. Configure CGI
"makefml newml" Creates CGI Script Always
Edit .htaccess
Example: Master Cgi
CGI Example: Create ML
CGI Example: subscribe
CGI Skin Selection
11. Apache Configuration
Use Suexec Of Apache
12. Test
Before Test
Test Of MTA
Send A Mail To ML
Test Of fml8 Itself.
Reset After Test.
III. How To Customise
13. What A User Can
Get ML Guide
Subscribe
Posting Article
Help: When You Want To know The Usage
Get Past Articles
Unsubscribe
Command Mail (Control fml By Sending Mail)
14. What Can You Do On The Mailing List Server
On The Host
Policy Of Command Creation
Common Command Line Options
Create A New ML
Remove An ML
Subscribe and Unsubscribe
Change the registered address
Stop Realtime Delivery
Start Realtime Delivery
See Log
See The Member List
Modify Configuration
Add or Remove A Remote Administrator.
Add or Remove A Modrator
"fml" And "makefml" Command
Show Addresses (Users + Aliases)
Show Alias
Show Configuration
Show Perl Module Document
Convert Articles To HTML Form
Recipes
15. Modify Configuration Files
Change Default For All ML's On Thie Host
16. [Caution] File Names
Filename Structure
Case Study: Address List
Case Study: List Of Remote Administrators
Case Study: List Of Moderators
Case Study: Remote Administrator Password Files
17. Case Studies Of Customization
Case Study: Auto File Responder
Case Study: Anyonen Can Use Command Mail.
Case Study: Disable Command Mail
Case Study: Mail Magazine (1)
Case Study: Mail Magazine (2)
Case Study: Anyone Can Post.
Case Study: Article Posting Allowd If It Is A Reply To The Former One.
Case Study: PGP/PGP Based Authentication In Posting
Case Study: Authenticate command mail by PGP/GPG
case study: hierarchical ML
I Want To Use ML By My Account.
Case Study: Office (1)
Case Study: Office (2)
18. Header Rewriting
Recipe's
19. Extend Command
Case Study: Create Your Own Help Command.
Recipes
20. Filtering
21. Extend Message
Case Study: Customize Message
22. Be ML Articles public via WWW
Recipes
IV. Operations
23. Logging
See Log
Show Computer Oriented Log
Recipes
24. Back Up Of Configurations
Back Up fml8 Configurations
Back Up All Files Except For Some Large Directories.
V. Troubleshoot
25. Troubleshoot
When The File System Error Ocuurs
VI. fml8 Design
26. [LOG] Original Idea Of fml8 Project
The Original Idea Of fml8 (fml-devel) Project
Details Of Idea
Refactoring
Architecture image
release engineering
27. Programming Style
Variable Naming Convension
A Few Topics On Design And Coding Style
Programming Style Original Idea
VII. fml8 Internals
28. fml8 Boot Loader To Resolve Version Dependence Dynamically
Case: Distribution
FML::Process:: Class Structure
Modules In Process Execution
Discussion: Where Function Should Resolve $ml_name And $ml_domain.
29. Configuration File: config.cf
ML Specific Configuration File: config.cf
config.cf Format
Extension To Postfix Style
Overload Variables In config.cf
Modifying/Adding Variables After All Configuration Files Have Been
Loaded.
Variable List (Alphabetical Order)
Variable List (Class Based)
Recipes
30. Create A New Program
Create A Program (CUI)
Create A Program (CGI)
31. fml8 Mail Delivery System
The Difference Between fml4 And fml8
Mail::Message Object
Incoming Queuing
fml Sends Back A Mail Message
Mail Queue And Delivery System
Mail Queue Directory
Queue Management System
Discussion: FML::Mailer Is Apropriate ?
Delivery TIPS
32. Digest Delivery
Files Used For Digest Delivery Control
Idea: Digest Related Commands
recipes
33. Language Preference In Processing
Problems Of Language Preference
Japanese Preferred ML
English preferred ML
34. Manipulate Message (Mail Message)
Mail::Message Class
Mail::Message::Parse Class
Mail::Message::Compose Class
Message Internationalization: The Usage Of reply_message_nl()
Discussion: How To Send Back Language Dependent Error Mesages
35. Filter
Overview Of Filter System
Configuration Variables
Size Limit
Limit For Command Mail
Mime Component Filter Rules
Discussion: Mime Component Filter Needs What Functions ?
36. Subscribe / Unsubscribe
Which Map Subscribe/Unsubscribe Is Operated To ?
37. Command (Command Mail, CUI And GUI)
Modules for commands
Data Flow Of Command Request Processing
Command Extension: Command Mail
CUI Command Extension: makefml/fml
GUI Command Extension: CGI
How Differ Coding Style Among fml4 And fml8
38. Internal Of CGI Process
Method
Screen Of CGI And The Method
Screen And Trampolin Mechanism
MISC: Hard Coding Is Mandatory ?
CGI Implementation: Inheritance Among CGI Classes
CGI Implementation: config.cgi
39. Directory
Q: How Recursively Sub Directory Can Be Created ?
Recipes
40. Restrict Input Data
Overview: Checks Of Input Data
FML::Restriction Class
How CGI Restricts The Input
Discussion: FML::Restriction Is Too Restrictive ?
41. User Authentication
Discussion: FML::Credential Implementation
42. Hook
Overview
Hook Naming Convension
Recipes
43. Virtual Domain
Overview: virtual domain handling in fml8
Case study: movement ?
44. Errormail Analyzer (libexec/error)
Overview
Algorithm Of Error Detection
Cache Of Error Messages Data
Forward Error Messages
45. IO Interface And Operations
Fundamentals Of IO::Adapter
Methods / Operation Vector
Discussion
46. Lock
Overview: Lock
TODO
47. Database Related Modules
Overview
Persistent Data Use
Tie::JournaledFile Class
FML::Cache::Ring Class
48. Database Management System
Overview
49. Convert Another ML System To fml8
Implementation: fml4 To fml8
VIII. Modules
50. IO Abstraction Layer (IO::Adapter Class)
IO::Adapter Overview
IO::Adapter Methods
Argument Type Of Methods
File Map
Unixgroup Map
Nis Map
MySQL Map
51. Mail::Message Module
Mail::Message Overview
Mail::Message Module: Analyze
Mail::Message Module: Create A New Object
Mail::Message Module: Header Manipulations
Mail::Message Module: Manipulate Messabe Body
Mail::Message Module: Search
Mail::Message Module: Print
Mail::Message Module: Utility Functions
References
52. Language Dependent Functions
Something::Language:: Class
53. Mail::Message::Encode Class
Mail::Message::Encode Specification
run_in_chcode()
54. Execise: Create A New Program
Case Study: Create A fmlsch
Case Study: fmlsch.cgi
IX. Apendixes
Glossary (function and variable names convention)
A. Struct curproc (Object In Fact)
curproc Object
PCB Category List
List of Tables
4-1. directory structure
8-1. Difference between fml4 and fml8: CUI
26-1. refactoring TODO
26-2. release interval
29-1. table description
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Preface
fml8 Status
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│fml8 has already implemented fundamental functions. Several people uses fml8 │
│as hobby and office mailing list system under normal operations. │
│ │
│When you configure fml8, you need to edit configuration files since │
│configuration helper tool has basic functions now. Except it, you can use │
│fml8 as same as fml4. │
│ │
│See http://www.fml.org/software/fml-devel/fml/doc/ja/todo/STATUS.html for the│
│current status of fml8. │
│ │
│See Chapter 8 on the difference between fml4 and fml8. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
The Road To The Next Generation Of Fml
fml8 is fully rewritten mailing list driver from scratch to re-implement fml4.
The main purpose of this project is re-implementation of fml mailing list
driver system with reflecting our 10 years experience on mailing list driver
developement.
Roughly speaking, the relation between fml4 and fml8 is similar to one between
sendmail and Postfix.
fml8 re-implements almost all features of fml4 functions. We re-design fml and
clean up the function and variable naming convenstion. Also, We reinforce guide
line to the coding style for clean source codes.
For example, when you use fml4, you'll find that fml assumes the list of
members is a text file on the host. fml4 inherits the assumption from version
1.0 through 4.0. It affetcts the core part of the design. Hence, it is
difficult to extend fml IO for the use of RDBMS, redundency et.al. In fact,
fml4 supports RDBMS but the code is ugly. We should need to fully rewrite fml
core parts.
Also, I want a lot of new features. fml8 should provide tiny bug tracking
system maintatined automatically. It is better to co-relate fml with cvs log.
These features help the support by mail and developer mailing list. I need it,
of course.
Firstly, we need to discuss what we should inherit from fml4 design and
features, and discard what in fml4.
• What we should inherit into fml8 from fml4 ?
• easily customizable ?
• what obsolete features we should remove ?
Anyway, we should write codes for the further discussion! You can find it at
the following URL.
http://www.fml.org/software/fml8/
ftp://ftp.fml.org/pub/fml8/
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Relation Between fml4 And fml8 Development Branch.
We implement new features at fml8 branch. fml4 imports it if needed. We only
have to bug-fix at fml4 branch.
(further translation omited).
fml-devel
-----------------------------> 8.0
A |
| | (interaction)
| V
1.2 -> 4.0 ------------------------------> 4.0-current
| |
4.0.1 4.0.2 .... (release / 4.0-stable release)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mailing List
fml-users@ffs.fml.org is prepared. Use it for English discussion.
To subscribe it, send the mail with "subscribe YOUR NAME" in the body to
fml-users-ctl@ffs.fml.org. You will receive the reply for confirmation. Please
reply the confirmation and send back it to fml-users-ctl@ffs.fml.org again. For
example, a subscribe mail is as follows:
From: your-account@your-domain
To: fml-users-ctl@ffs.fml.org
subscribe Kinomoto Sakura
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Please Let Me Know Your Opinion ...
Please send me the idea on fml8 to the mail address: fml-request@fml.org or
myself fukachan@fml.org directly.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
On This Tutorial
For the fml4 user, the order of chapters and sections are almost same as the
book "fml bible" publishded by O'reilly Japan (rewritten in Japanese).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Technical terms in this tutorial
See Glossary (function and variable names convention) also.
%
user prompt on the shell
#
root user prompt on the shell
~
user's home directory
CUI
command line tool such as makefml or fml.
fml
fml software in general use.
fml (command)
fml command included in fml8 software. fml is same as makefml command
except for the argument order.
user fml
a user called as fml. a user account for fml8 software.
fml4
fml4 series.
fml8
fml8 series.
GUI
CGI interface.
makefml (command)
configuration helper tool included in fml4 and fml8. You can use them when
you login the mailing list server.
I. Fml Fundamental Usage
This part describes a brief guide for beginners.
See http://www.fml.org/software/fml/ and other sites for more details on
mechanism of the mailing list.
Table of Contents
1. What Is Mailing List ?
2. fml8 Overview
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 1. What Is Mailing List ?
Email
Email is an electirc version of mail.
One email has the following structure which consists of two parts. The former
is header, the latter is body. The separator between them is one null line
(empty line).
[Example]
From: rudo@nuinui.net
To: kenken@nuinui.net
Subject: asobo.
Hi, Kenken. I am Rudo.
// rudo
See RFC822 and RFC2822 for more details of definitions.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mailing List (Ml)
Mailing list (ML) is forwarding mechanism of email. The program for it is
called as ML driver. ML driver receives the email injected via MTA over the
network, copy and redistributes it to members subscribed to the ML.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Model Of An ML.
[ml]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 2. fml8 Overview
See Chapter 8 on the detail of difference between fml4 and fml8.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
fml8 Features
• fml8 configuration file format is changed to new Postfix style format
configuration files (.cf files).
• usage of CUI is almost same as fml4 (it is same as could as possible). You
can use CUI (makefml and fml command)
to create/remove an ML,
to add/remove/change an addresse of ML members,
to add/remove/change an address of remote administrators,
to see log and member list,
et.al.
Makefml and fml are same programs except for argument order.
See the Section called Difference Between fml4 And fml8: CUI in Chapter 8
on the CUI usage difference between fml4 and fml8.
• GUI (CGI) interface. The functions are a subset of CUI ones.
to create/remove an ML,
to add/remove/change an address of ML members,
to add/remove/change an address of remote administrators,
to see log and member list,
et.al.
The configuration file editing is incomplete yet.
• article delivery, header rewriting and several filters ( corresponding with
fml4's envelope filter and content filter ).
• command mail for users.
to add/remove/change the address,
get article summary,
get old articles,
et.al.
• command mail (admin command mail) for remote administratoin by mail.
to add/remove/change an addresse of ML members,
to add/remove/change an address of remote administrators,
to see log and member list,
et.al.
• automatic analyzer of error messages.
• IPv6 ready.
• tiny thread track system.
• built-in module for HTML converter of articles. support automatic
conversion by default.
fmlhtmlify and makefml supports html conversion functions.
• main programs (fml/libexec): distribute command error
• utilities: fmladdr fmlailas fmlconf fmldoc makefml fml
• fml4 emulation: if you replace fml.pl of fml4 and fml.pl of fml8, fml8 runs
as fml4.
• After 2004 summer, the queueing system is implemanted. Currently the
delivery system is queuing based. So, fml8 is a MTA in fact.
• Abstracted IO layer to get member list in unified way from a file, /etc/
group, NIS, SQL.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Installation Overview
Important: Run GNU autoconf firstly, and "make install". It is defact
standard in the world of open sources. This procedure is different from
fml4 installation steps. It may confuse you if you are customered with fml4
But fml8 is more friendly for package systems of free unix like systems.
The main differece between fml4 and fml8 in installation is "run programs
as root", "use of configure", and editing of configuration files.
Suppose we create a new ML named elena ML (elena@fml.org). The brief flow of
installation is as follows:
1. Download fml8 source and extract it on the disk.
2. Install it by user root. Firstly, change user to "root" and create the user
"fml" and the group "fml". Secondly, run configure and "make install".
% su root
# groupadd fml
# useradd -m -g fml fml
# ./configure
# make install
By default, 4.4 BSD style sub-directories are created. The path is
configurable at configure options.
For example, main programs called from MTA such as distribute, command,
et.al. are installed into under /usr/local/libexec/fml/. Instead, utility
programs are installed to /usr/local/bin. These are wrappers to call real
programs at /usr/local/libexec/fml/.
Perl modules are installed into /usr/local/lib/fml/$fml_version/ and
message templates et.al. are installed into /usr/local/share/fml/
$fml_version/.
3. Change user to "fml" and create elena ML for test.
% su fml
% makefml newml elena
You can use "fml" instead of makefml. Both are same except for the argument
order.
% su fml
% fml elena newml
4. Set up MTA which runs fml8 programs.
5. Test.
6. Customize your ML.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│Please install by user root. It is different from fml4. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Create An ML
Create an ML by CUI (makefml). To create elena@fml.org ML (fml.org is the
default domain), run
% su fml
% makefml newml elena
. See the section Chapter 5 for more details.
In the virtual domain case, specify the whole address as an argument. For
example, to create an ML elena@nuinui.net, run the following command:
(At the first time)
% su root
% makefml newdomain nuinui.net /some/where/nuinui.net
% su fml
% makefml newml elena@nuinui.net
(After the 2nd time)
% su fml
% makefml newml elena@nuinui.net
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│See Chapter 43 for the virtual domain case detail. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Add A New User To ML
In the case of the default domain (fml.org)
% su fml
% makefml subscribe elena rudo@nuinui.net
in the case of virtual domain (nuinui.net), specify the whole adress of ML
name.
% su fml
% makefml subscribe elena@nuinui.net fukachan@sapporo.iij.ad.jp
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Remove The User
In the case of the default domain (fml.org),
% su fml
% makefml unsubscribe elena rudo@nuinui.net
in the case of virtual domain (nuinui.net), specify the whole adress of ML
name.
% su fml
% makefml unsubscribe elena@nuinui.net fukachan@sapporo.iij.ad.jp
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Customize
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│"makefml config" is a CUI to customize ML by menu form. BUT YET INCOMPLETE. │
│ │
│Edit configuration files anyway now. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Common Configurations On This Host
/usr/local/etc/fml/site_default_config.cf affects all ML on this host
irrespective of the default domain or virtual domains. [1]
The format of site_default_config.cf is same as config.cf described below.
See list of all variables for the configurable variation.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
elena ML's Configuration
To customize elena ML, edit /var/spool/ml/elena/config.cf file. The format is a
little modified postfix style. It is different from both fml4's config.ph and
cf. Add hooks after =cut line if needed.
Add or modify the least variables. If unspecified, the default value is used.
The default value depends fml version and is defined at
/usr/local/etc/fml/defaults/${fml_version}/default_config.cf
The library path depends fml version. This technique ensures the easy upgrade/
downgrade procedure. This is a feature of fml8.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipes
1. Why fml8 is the next official release of fml4 series ?
2. What difference between fml4 and fml8 ?
3. Which of current, stable and release should we download ?
1. Why fml8 is the next official release of fml4 series ?
1 bit shift of version with greate internal change is traditional :-)
fml8 is build from scratch by discarding fml4 source codes. fml8 is not a
upgraded fml4 software. So we use 1 bit shifted version number for fml8.
2. What difference between fml4 and fml8 ?
See Chapter 8 fore more details.
3. Which of current, stable and release should we download ?
fml8 does not provide such release line today. Please download the latest one
by comparing file name which has date in int.
See Chapter 3 on download.
II. How To Set Up ML
Topics driven in this part.
Table of Contents
3. Download fml8 Source Code.
4. fml8 Installation On Unix
5. Create ML On Unix
6. fml8 installation on Microsft 2000/NT
7. Convert fml4 Style ML To fml8 Style ML
8. Difference Between fml4 And fml8
9. Upgrade And Downgrade Of fml8
10. Configure CGI
11. Apache Configuration
12. Test
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 3. Download fml8 Source Code.
Download Via FTP.
You can find fml8 source at ftp://ftp.fml.org/pub/fml8/ . You can get it by
ftp.
We build snapshot as a tarball in some interval. The file name contains date
such as YYYYMMDD form. Please get the latest one.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Access To GitHUB.
https://github.com/fmlorg/
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 4. fml8 Installation On Unix
Preparation Of Installation
Create the user "fml" and the group "fml" before running configure.
% su root
# groupadd fml
# useradd -g fml -m fml
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Run Configure
Run configure (GNU autoconf) and make.
% su root
# groupadd fml
# useradd -g fml -m fml
# ./configure
# make install
where configure replaces variables in scripts and .cf files.
After runnig configure, run "make install". The fml installer (perl scripts)
reads ./etc/fml/install.cf configure created and install fml8 to e.g. /usr/
local/.
You can specify the user name and fundamental directory names by configure
arguments. Customizable variables are follows: configure --help shows them.
variables default value example
--------------------------------------------------------
prefix /usr/local /usr/local
exec_prefix /usr/local
bindir ${exec_prefix}/bin /usr/local/bin
sbindir ${exec_prefix}/sbin /usr/local/sbin
libexecdir ${exec_prefix}/libexec /usr/local/libexec/fml
datadir ${prefix}/share /usr/local/share/fml
sysconfdir ${prefix}/etc /usr/local/etc/fml
sharedstatedir ${prefix}/com
localstatedir ${prefix}/var
libdir ${exec_prefix}/lib /usr/local/lib/fml
includedir ${prefix}/include
oldincludedir /usr/include
infodir ${prefix}/info
mandir ${prefix}/man
You can overwrite the following variables by configure arguments.
fmlconfdir $sysconfidr/fml /usr/local/etc/fml
mlspooldir /var/spool/ml /var/spool/ml
fml_owner fml fml
fml_group fml fml
default_domain (spaculated by configure) (spaculated by configure)
These options are shown by runnig
configure --help
.
--without-warning run perl as perl without -w
--with-fmlconfdir=DIR use DIR instead of SYSCONFDIR/fml
--with-mlspooldir=DIR use DIR instead of /var/spool/ml
--with-fml-owner=USER use USER instead of fml
--with-fml-group=GROUP use GROUP instead of fml
--with-default-domain=DOMAIN use DOMAIN as the ML domain
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Example: Running Configure
Example: On NetBSD, you should install 3rd party programs into /usr/pkg.
% ./configure --prefix=/usr/pkg
Example: On FreeBSD, use /usr/local.
% ./configure
If you use /etc/fml as configuration directory on e.g. Debian,
# ./configure --with-fmlconfdir=/etc/fml
loading cache ./config.cache
checking for perl... (cached) perl
checking for perl... (cached) /usr/local/bin/perl
checking whether optional useful commands are available or not
checking for cksum... (cached) /usr/bin/cksum
checking for md5... (cached) /usr/bin/md5
checking for ls... (cached) /bin/ls
checking for tar... (cached) /usr/bin/tar
checking for gzip... (cached) /usr/bin/gzip
checking for zcat... (cached) /usr/bin/zcat
checking for gunzip... (cached) /usr/bin/gunzip
checking for lha... (cached) /usr/pkg/bin/lha
checking for ish... no
checking for bzip2... (cached) /usr/bin/bzip2
checking for bunzip2... (cached) /usr/bin/bunzip2
checking for uuencode... (cached) /usr/bin/uuencode
checking for compress... (cached) /usr/bin/compress
checking for sendmail... (cached) /usr/sbin/sendmail
checking for newaliases... (cached) /usr/bin/newaliases
checking for postfix... (cached) /usr/sbin/postfix
checking for postalias... (cached) /usr/sbin/postalias
checking for postconf... (cached) /usr/sbin/postconf
checking for postmap... (cached) /usr/sbin/postmap
checking for nkf... (cached) /usr/pkg/bin/nkf
checking for kakasi... no
checking for namazu... no
checking for pgp... (cached) /usr/pkg/bin/pgp
checking for pgp5... no
checking for pgpe... no
checking for pgpk... no
checking for pgps... no
checking for pgpv... no
checking for gpg... no
checking for less... (cached) /usr/bin/less
checking for more... (cached) /usr/bin/more
checking for w3m... (cached) /usr/pkg/bin/w3m
updating cache ./config.cache
creating ./config.status
creating config.sh
creating fml/etc/main.cf
creating fml/etc/default_config.cf.ja
creating fml/etc/site_default_config.cf
creating fml/libexec/loader
creating fml/bin/fmlalias
creating fml/bin/fmlconf
creating fml/bin/fmldoc
creating fml/bin/fmlhtmlify
creating fml/bin/fmlsch
creating fml/bin/fmlthread
creating fml/bin/fmlspool
creating fml/bin/makefml
enabled perl -w
fml has been configure with the following options:
prefix: /usr/local
exec_prefix: ${prefix}
bindir: ${exec_prefix}/bin
sbindir: ${exec_prefix}/sbin
lib_dir: ${exec_prefix}/lib
libexec_dir: ${exec_prefix}/libexec
mandir: ${prefix}/man
datadir: ${prefix}/share
fml process owner: fml
fml process group: fml
fmlconfdir: /etc/fml
mlspooldir: /var/spool/ml
default domain: home.fml.org
Now you must run "make install".
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Appendix: Directory Roles
fml8 installs files under /usr/local by default.
Table 4-1. directory structure
┌─────────┬───────────────────────────────────────────────────────────────────┐
│directory│ description │
├─────────┼───────────────────────────────────────────────────────────────────┤
│/usr/ │Configuration files. It corresponds with fml4's /usr/local/fml/.fml│
│local/etc│and default_config.ph. /usr/local/etc/fml/main.cf has fml version │
│/fml │and library paths et.al. │
├─────────┼───────────────────────────────────────────────────────────────────┤
│/usr/ │ │
│local/ │Executables (corresponding with fml4's /usr/local/fml ) │
│libexec/ │ │
│fml │ │
├─────────┼───────────────────────────────────────────────────────────────────┤
│/usr/ │ │
│local/lib│Perl module location ( fml4's /usr/local/fml ) │
│/fml │ │
├─────────┼───────────────────────────────────────────────────────────────────┤
│/usr/ │Message templates ( fml4's /usr/local/fml/messages/). Template │
│local/ │files are language dependendent. │
│share/fml│ │
├─────────┼───────────────────────────────────────────────────────────────────┤
│ │The top directory for mailing lists of the default domain. same as │
│ │fml4. caution: the owner of /var/spool/ml can be specified by │
│/var/ │configure arguments. Prepare different directory for each domain. │
│spool/ml │For example, /var/spool/ml for fml.org (default domain), whereas / │
│ │var/spool/nuinui.net for nuinui.net domain (virtual domain). See │
│ │ml_home_prefix_maps for the relation between domain and directory. │
│ │Also see Chapter 43 for the virtual domain detail. │
└─────────┴───────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Fml Installation: make install
change user to "root" and run "make install" after configure runs.
% su root
# make install
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│You need not to run configure by the user root. But, you need to run "make │
│install" by root. So, it may be better to run both by root. │
│ │
│% su root │
│# ./configure │
│# make install │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Edit main.cf
Please edit /usr/local/etc/fml/main.cf if needed, though already configure
rewrites main.cf to fit your environment.
The file main.cf contains the most fundamental configuration variables to
control fml8 basic features: fml version control, library path, virtual domain
et.al.
Instead, the detail of each ML configuration depends on config.cf file of each
ML such as /var/spool/ml/elena/config.cf for elena ML. "config.cf" can override
all configuration variables: header customizations, filter rules, member file
locations et.al.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Example: /usr/local/etc/fml/main.cf
/usr/local/etc/fml/main.cf is not ML specific. This is meta file to define
fundamental variables e.g. fml version, directory path et.al. fml8 loader reads
them.
The format of main.cf is same as other .cf files: [2]
variable = value
style.
#
# $FML: main.cf.sgml,v 1.1 2005/07/27 12:21:36 fukachan Exp $
#
# fml version
# This is important
# Example: fml 8.0
# fml-current YYYYMMDD
# fml-devel YYYYMMDD
fml_version = current-20020701
fml_owner = fml
fml_group = fml
###
### DIRECTORIES
###
# Example: /usr/local
prefix = /usr/local
exec_prefix = ${prefix}
# $config_dir holds the global main configuration and
# several version-dependent default configurations
# Example: /usr/local/etc/fml
config_dir = /usr/local/etc/fml
# Example: /usr/local/etc/fml/defaults/$fml_version
default_config_dir = $config_dir/defaults/$fml_version
# defined for convenience, for example, we need this variable
# at include, include-ctl, which needs expansion of ../libexec/fml/fml.pl
# Example: /usr/local/libexec/fml
executable_prefix = ${exec_prefix}/libexec/fml
# Example: /usr/local/libexec/fml/$fml_version
libexec_dir = ${exec_prefix}/libexec/fml/$fml_version
# Example: /usr/local/lib/fml/$fml_version
lib_dir = ${exec_prefix}/lib/fml/$fml_version
# Example: /usr/local/share/fml/$fml_version
share_dir = ${prefix}/share/fml/$fml_version
# site local library location
# which is prepared but not used by fml itself
local_lib_dir = ${exec_prefix}/lib/fml/site_local
# ml's home directories
# $ml_home_dir (e.g. /var/spool/ml/elena ) is taken from loader's @ARGV.
# This is compatible with fml 4.0.
# Example: /var/spool/ml
default_ml_home_prefix = /var/spool/ml
###
### CONFIGURATION FILES AND DEFAULT PARAMETERS
###
# default domain
default_domain = fml.org
# version dependent default_config.cf location
# whic holds
# Example: /usr/local/etc/fml/defaults/8.0/default_config.cf
default_config_cf = $default_config_dir/default_config.cf
# domain specific configurations
# Example: /usr/local/etc/fml/domains/fml.org/default_config.cf
domain_default_config = $config_dir/domains/$default_domain/config.cf
# virtual format: domain directory
# for example,
# fml.org /var/spool/ml/fml.org
# nuinui.net /var/spool/ml/nuinui.net
virtual_maps = $config_dir/virtual
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Edit site_default_config.cf (optional)
/usr/local/etc/fml/site_default_config.cf is the configuration file common over
all mailing list on this host (site). [3]
site_default_config.cf overrides default_config.cf file. Each ML configuration
file (/var/spool/ml/elena/config.cf for elena ML) overrides
site_default_config.cf.
By default, some example configurations are added to this file.
#
# site default_config.cf EXAMPLE
#
# fml-devel loads .cf files in this order for elena ML.
# 1. ${prefix}/etc/fml/defaults/$VERSION/default_config.cf
# 2. ${prefix}/etc/fml/site_default_config.cf
# 3. ${prefix}/etc/fml/domains/$DOMAIN/default_config.cf
# 4. /tmp/dir/elena/config.cf
#
# This file overrides the default "default_config.cf" configurations
# in the following way.
#
# We want to disable the subject tag in articles by default.
article_header_rewrite_rules -= rewrite_article_subject_tag
# mime based comonent filter
use_mime_component_filter = yes
# [site specific options]
# Example:
# key = value
# key += value
# key -= value
=cut
#
# you can write hooks here after.
# Example:
# $distribute_run_start_hook = q{ ... };
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Filter
All filter are enabled by default.
"mime component filter" is important. By default mime component filter is
enabled, Only text/plain article can be passed through fml8.
To disable mime component filter on all ML's, set
use_mime_component_filter = no
at site_default_config.cf.
To customize mime component filter, set
use_mime_component_filter = yes
at site_default_config.cf, and edit rules in /usr/local/etc/fml/
mime_component_filter file.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Virtual Domain
You do not need edit /usr/local/etc/fml/main.cf but you need to edit
$ml_home_prefix_maps (/usr/local/etc/fml/ml_home_prefix file by default). You
can use "makefml newdomain" command to control $ml_home_prefix_maps. See "ML
creation" for newdomain command.
Suppose that fml.org is the default domain. In this case, /var/spool/ml/$ml is
used for $ml ML of fml.org. /var/spool/ml is used only for the domain fml.org.
If you want to set up elena@nuinui.net, you need to specify other directory.
Specify the relation between domain and directory, edit /usr/local/etc/fml/
ml_home_prefix and set the following:
nuinui.net /var/spool/nuinui.net
Please use "makefml newdomain" command to change /usr/local/etc/fml/
ml_home_prefix file. It is recommended that you do not edit this file directly.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│site_default_config.cf is applied to all domains. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MTA Configuration (postfix)
Please set up postfix properly before "makefml newml" can set up a ml.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Default Domain (Example: fml.org)
Set up /etc/postfix/main.cf like this:
[/etc/postfix/main.cf]
allow_mail_to_commands = alias,forward,include
alias_maps = hash:/etc/mail/aliases
hash:/var/spool/ml/etc/mail/aliases
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│Please check that $mydestination contains the default domain (may be │
│$mydomain). │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Virtual Domain (Example: nuinui.net)
You need to edit /etc/postfix/main.cf to set up $virtual_maps.
[/etc/postfix/main.cf]
allow_mail_to_commands = alias,forward,include
alias_maps = hash:/etc/mail/aliases
hash:/var/spool/ml/etc/mail/aliases
hash:/var/spool/nuinui.net/etc/mail/aliases
virtual_maps = hash:/var/spool/nuinui.net/etc/postfix/virtual
[/usr/local/etc/fml/ml_home_prefix]
nuinui.net /var/spool/nuinui.net
Both alias files and /var/spool/nuinui.net/etc/postfix/virtual are updated by
makefml automatically where we suppose ml_home_prefix_maps defines
nuinui.net /var/spool/nuinui.net
relation.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│Postfix variable $mydestination should contain the default domain (may be │
│$mydomain) but not virtual domain. Pay attention that we assume we use │
│postfix style virtual domain. Please see postfix document for more details. │
│ │
│When you begin to use a new virtual domain, you need to update both │
│$alias_maps and $virtual_maps in /etc/postfix/main.cf. Also, you have to │
│update /usr/local/etc/fml/ml_home_prefix by running "makefml newdomain". │
│ │
│Recent postfix has $virtual_alias_maps and $virtual_maps variables. But │
│$virtual_alias_maps = $virtual_maps by default. You can use either. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MTA configuration (qmail)
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│fml8 assumes that qmail configurations is always based on /var/qmail/control/│
│virtualdomains regardless of the default domain or not. │
└─────────────────────────────────────────────────────────────────────────────┘
The template of /var/qmail/control/virtualdomains is created at /var/spool/ml/
etc/qmail by makefml.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
The default domain (example: fml.org)
It is good to prepare "ml.fml.org" domain for ml specific. At
/var/qmail/control/virtualdomains
specify the following rule
ml.fml.org:fml-fml.org
. "makefml newml" can set up ~/.qmail-* automatically.
See the section on "makefml newml and qmail" on how "makefml newml" creates ~
/.qmail-* files.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
virtual domain (example: nuinui.net)
For "nuinui.net" virtual domain, not the default one, specify
nuinui.net:fml-nuinui.net
at /var/qmail/control/virtualdomains. It is same as in default domain case.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
recipes
1. Can we use other user as fml process ?
2. When should we change use to fml in installation ?
3. Can we install fml8 without document.
4. Can we specify per path in installation ?
5. Can we use jperl ?
6. Can we overwrite elena ML ?
7. Can we edit alias files under /var/spool/ml/etc ?
8. Can we use fml8 on Windows 2000/NT4 but MTA on Unix server ?
9. Can we initialize ML ?
1. Can we use other user as fml process ?
Run configure with --with-fml-owner option.
configure --with-fml-owner=$USER
Do not use your own account but use fml specific user for all fml processes.
Please use procmail et.al. if fml processes are kicked off by .forward not
aliases. See /var/spool/ml/etc/procmail/procmailrc for more details on procmail
usage.
2. When should we change use to fml in installation ?
In installation.
You can download source code and run configure by not user root (e.g. user
fml), but run "make install" by user root. It may be better to run by user too
always.
3. Can we install fml8 without document.
Yes by default. fml8 does not install document. If you need documentation,
please install ./SOURCE/Documentation/ into /usr/local/share/doc/fml8/
$FML_VERSION/.
4. Can we specify per path in installation ?
No directly. Run configure with proper environment variable PATH.
% env PATH=/some/where/:$PATH sh configure
5. Can we use jperl ?
Unknown.
6. Can we overwrite elena ML ?
Run "makefml newml" with --force option.
% makefml --force newml elena
7. Can we edit alias files under /var/spool/ml/etc ?
Yes but please control them by yourself. These files are controlled by makefml/
fml scripts. These scripts edit them. If the ML is removed, the corresponding
entries are removed and cannot be back.
8. Can we use fml8 on Windows 2000/NT4 but MTA on Unix server ?
Caution: not tested.
It can be. Run fetchfml on Windows 2000 or NT4 and run MTA on Unix.
9. Can we initialize ML ?
It is easy to run rmml once and newml again.
% makefml rmml elena
% makefml newml elena
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 5. Create ML On Unix
Run "makefml newml" To Create An ML (In The Case Of Default Domain)
┌─────────────────────────────────────────────────────────────────────────────┐
│ Caution │
├─────────────────────────────────────────────────────────────────────────────┤
│The usage of fml8 makefml is same as fml4 in the case of default domain. But │
│differs in the virtual domain case. See the Section called Run "makefml │
│newml" To Create An ML (In The Case Of Virtual Domain) for the virtual domain│
│case. │
└─────────────────────────────────────────────────────────────────────────────┘
To create an ML, use "makefml" command (CUI) in the same way as fml4.
% su fml
% makefml newml elena
... snip ...
In the case of non default domain (virtual domain), run "makefml newdomain"
command before running "makefml newml".
% su root
# makefml newdomain fml.org /var/spool/virtual/fml.org
# exit
% su fml
% makefml newml elena
... snip ...
"makefml newml" processes the following steps.
• Create files such as
config.cf
include
include-ctl
at /var/spool/ml/elena. The domain name et.al. in these files is replaced
to proper value.
• Add elena ML entry into /var/spool/ml/etc/mail/aliases. Run postalias to
rebuild /var/spool/ml/etc/mail/aliases.db.
• Create ~fml/.qmail-* files for qmail.
• Update procmailrc as a sample.
• Prepare the directory
~fml/public_html/fml/mlarchive/$domain/$ml/
for html archive. For example, for elena@fml.org
~fml/public_html/fml/mlarchive/fml.org/elena/
is creatd. HTML archive of ML articles is created by default.
• Prepare CGI (GUI). Set up
~fml/public_html/cgi-bin/fml/$domain/admin/config.cgi
for the master cgi, instead cgi to control one ML $ml@$domain is set up at
~fml/public_html/cgi-bin/fml/$domain/ml-admin/$ml/config.cgi
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Run "makefml newml" To Create An ML (In The Case Of Virtual Domain)
┌─────────────────────────────────────────────────────────────────────────────┐
│ Caution │
├─────────────────────────────────────────────────────────────────────────────┤
│The usage of makefml differs from fml4. In the case of fml8 firstly use │
│"makefml newdomain" command, in the next run "makefml newml" command. Also │
│ml_name differs. For virtual domain, use ml_name@ml_domain form. │
└─────────────────────────────────────────────────────────────────────────────┘
In using "makefml newml", the usage is same as fml4 except for the ml_name.
ml_name part is ml_name@ml_domain in the case of fml8
At the first time to use a virtual domain, run "makefml newdomain" before
"makefml newml".
% su root
# makefml newdomain nuinui.net /var/spool/virtual/nuinui.net
# exit
% su fml
% makefml newml elena@nuinui.net
After the second time, just use "makefml newml".
% su fml
% makefml newml elena@nuinui.net
In running "makefml newdomain", specify a pair of domain and directory in
ml_home_prefix_maps. This command edits /usr/local/etc/fml/ml_home_prefix file
to add the following line.
nuinui.net /var/spool/virtual/nuinui.net
To remove this line, use "makefml rmdomain".
The usage of "makefml newml" command is same as in the case of default domain.
"makefml newml" creates an example of virtual domain configurations for several
MTA's such as
/var/spool/ml/etc/sendmail/virtusertable
/var/spool/ml/etc/postfix/virtual
. No example for qmail (not needed). No example for procmail since .procmailrc
contains domain.
See the chapter of virtual domain for more details.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MTA Configuration (postfix)
Important: If $alias_maps of Postfix is properly set up, "makefml newml"
automatically prepares fml and postfix configuration for the new ML.
See the Section called MTA Configuration (postfix) in Chapter 4 for the
detail of postfix configuration.
"makefml" does not update system aliases (e.g. /etc/mail/aliases), but updates
only alias file $ml_home_prefix/etc/mail/aliases file, which is used only for
fml. "makefml" rebuilds $ml_home_prefix/etc/mail/aliases.db automatically, too.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
NOTE: Format Of /var/spool/ml/etc/mail/aliases
$ml_home_prefix/etc/mail/aliases has the following entry for elena@home.fml.org
ML.
### ###
# address for post
elena: :include:/var/spool/ml/elena/include
owner-elena: fukachan
# address for command
elena-ctl: :include:/var/spool/ml/elena/include-ctl
owner-elena-ctl: fukachan
# maintainer
elena-request: elena-admin
elena-admin: fukachan, elena-error
# error analyzer
elena-error: :include:/var/spool/ml/elena/include-error
owner-elena-error: fukachan
### ###
In the case of virtual domain, $ml_home_prefix varies with $virtual_maps.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MTA Configuration (qmail)
"makefml newml" creates the following files for qmail:
~fml/.qmail-fml:org-elena
~fml/.qmail-fml:org-elena-admin
~fml/.qmail-fml:org-elena-ctl
~fml/.qmail-fml:org-elena-default
~fml/.qmail-fml:org-elena-request
Hence, if /var/qmail/control/virtualdomains contains the following definition
fml.org:fml-fml.org
you have only to run "makefml newml" to create an ML in the case of qmail.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│This configuration assumuss ML's uses the whole one domain only for mailing │
│list. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Virtual Domain
The logic is same as above. So you need to edit /var/qmail/control/
virtualdomains to make an ML effective automatically when you runs "makefml
newml". This edit needs root priviledge. Please contact the administrator on
it.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Customize config.cf
In running "makefml newml", makefml sets up configuration files such as
config.cf, include files for sendmail and postfix and ~fml/.qmail-* files.
% su fml
% makefml newml elena
... snip ...
% ls /var/spool/ml/elena
config.cf include include-ctl include-error
... snip ...
To customize one ML configuraiton, edit config.cf.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│menu tool to edit config.cf is incomplete. │
└─────────────────────────────────────────────────────────────────────────────┘
config.cf contains little definition. For example, /var/spool/ml/elena/include
file follows:
"| /usr/local/libexec/fml/distribute elena@fml.org"
/var/spool/ml/elena/include-ctl file follows:
"| /usr/local/libexec/fml/commande elena@fml.org"
/usr/local/libexec/fml/PROGMAR resolves ml_name and ml_domain from the
arguments such as elena@fml.org. That is, elena@fml.org in this argument
determines values of $ml_domain and $ml_name. It is enough that ml_name and
ml_domain in config.cf is a comment.
The content of include, include-ctl and aliases are same as fml4 except for the
path.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipes
1. Specify administrator's mail address in alias file when "newml" command
runs.
2. Not create a configuration file for a specific MTA not used.
1. Specify administrator's mail address in alias file when "newml" command
runs.
CUI (makefml/fml) creats an alias in "newml".
${ml_name}-admin: ADDRESS
where ADDRESS is defined by $newml_command_ml_admin_default_address. By
default, $newml_command_ml_admin_default_address == $fml_owner defined in /usr/
local/etc/fml/main.cf file. To change the value, specify
$newml_command_ml_admin_default_address in site_default_config.cf.
$newml_command_ml_admin_default_address = YOUR_ADDRESS
You can use $ml_name here.
$newml_command_ml_admin_default_address = $ml_name-owner@$ml_domain
2. Not create a configuration file for a specific MTA not used.
$newml_command_mta_config_list defines list of MTA. "makefml newml" command
creates examples of the specified MTA's. Remove the specific MTA from the list
to disable example creation.
For example, you do not need "qmail" configuration example
newml_command_mta_config_list -= qmail
fml8 does not generate ~/.qmail-* files.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 6. fml8 installation on Microsft 2000/NT
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│not yet implemented. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 7. Convert fml4 Style ML To fml8 Style ML
2004/03: We have implemented a converter which converts ML HOME DIRECTORY
($DIR) such as /var/spool/ml/elena ($ml_home_dir in fml8) from fml4 style to
fml8 style. It is incomplete but is being developed.
2004/11: You can replace fml.pl of fml4 with fml.pl of fml8. now. It means that
fml8 directly emulates fml4. It enables easy upgrade from fml4 to fml8.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Overview: fml4 To fml8 (1)
It is a little wrong that fml8 works if fml8 overwrites fml4 programs.
Currently fml8 can work but it needs automatic conversion in the background.
Hence, fml8 modifies fml4 to emulate fml4.
Firstly there is a problem. You want to upgrade all ML's at the same time from
fml4 to fml8? It is better to upgrade from one to one ? When something fails,
you want to downgrade your system if could.
We want to support both types. So it is available that some ML's are fml8,
other ML's are fml4 in one domain simultaneously. Downgrading if needed are
supported.
One example of upgrade operation follows:
1. install fml8
2. (in the case of Postfix) add fml8 aliases to postfix's alias_maps.
Example:
alias_maps = hash:/etc/mail/aliases
hash:/var/spool/ml/etc/aliases (fml4)
hash:/var/spool/ml/etc/mail/aliases (fml8)
3. convert fml4 ML to fml8 one.
fml $ml mergeml fml4's$DIR
for example,
fml elena mergeml /var/spool/ml/elena
Apply 3. for ML's which would be converted to fml8.
You can use "makefml mergeml" command to convert aliases, include files, fml4
configuration files and member lists from fml4 to fml8.
It is not easy to convert difficult fml4's config.ph file. Now we can convert
simple config.ph to fml8 config.cf style file automatically. We suppose this
simple config.ph is generated by fml4's "makefml config" command.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Overview: Convert fml4 To fml8 (2)
2004/11: you can replace fml4's fml.pl with fml8's fml.pl.
Configure like this.
[1. Install fml8]
% su fml
% sh configure
% su root
# make install
[2. Emulate fml4]
# mv /usr/local/fml/fml.pl /usr/local/fml/fml.pl.orig
# ln -s /usr/local/libexec/fml/fml.pl /usr/local/fml/fml.pl
# ln -s /usr/local/libexec/fml/msend.pl /usr/local/fml/msend.pl
# ln -s /usr/local/libexec/fml/mead.pl /usr/local/fml/libexec/mead.pl
Precisely fml8 can not read fml4 configuration file. If fml8's fml.pl cannot
find config.cf, it tries to convert config.ph in ML's home directory to fml8
config.cf, read it and starts to run.
The conversion is incomplete but fml8 can convert simple configurations
manipulated by fml4 CUI or GUI.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Overview: Difference Between fml4 and fml8
There are several fml8 variables and functions not related with fml4 since fml8
is re-designed and re-coded from scratch.
Also not one to one even if the relation found.
Let's see a few examples below.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Anyone Can Post
Users registered as members can post ML by default. This default behaviour is
common between fml4 and fml8. To set "anyone can post", in the case of fml4,
$PERMIT_POST_FROM = "anyone";
in the case of fml8,
article_post_restrictions = reject_system_special_accounts
permit_anyone
reject
.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Subject Tag
No subject tag defined by default. This is common between fml4 and fml8 To set
the tag such as '[ML_NAME:00100]', in the case of fml4,
$SUBJECT_TAG_TYPE = '[:]';
This corresponds to the following fml8 configuration:
article_header_rewrite_rules = rewrite_article_subject_tag
article_subject_tag = [$ml_name:%05d]
fml8 configuration concepts are more orthogonal.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Disable Specific Command In Command Mail
Commands such as "members" are prohibited in fml8 by default. fml4 needs the
following configurations to disable dangerous commands:
&DENY_PROCEDURE('member');
&DENY_PROCEDURE('active');
&DENY_PROCEDURE('members');
&DENY_PROCEDURE('actives');
&DENY_PROCEDURE('status');
&DENY_PROCEDURE('stat');
Old fml4 use no filter by default but fml8 uses filter by default.
fml8 applies confirmation for subscribe, chaddr, unsubscribe commands by
default. fml4 not. Currently fml8 always applies confirmation, which can not be
disabled by configuration.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Discussion
"makefml mergeml" command processes the following steps automatically.
To clarify details more, explain conversion of aliases and include files below.
Our purpose is to run fml8 anyway. If fml8 runs, converter of config.ph runs
too. So, we need MTA runs fml4 and fml4 runs fml8.
Explain more details. Consider ML driver internal section.
For example, when you use Postfix, Postfix reads aliases and recognizes it
needs to read include file. By reading include file, Postfix knows how to call
fml8 process. Finally, postfix runs /usr/local/libexec/fml/distribute command.
Executed distribute command reads config.cf and knows the location of member
lists and processes et.al.
That is, when fml8 process starts, the following two phases
aliases (MTA configuration)
include
ends.
It is mandatory that no duplication in aliases files. For example, if /etc/
postfix/main.cf contains the following configuration:
alias_maps = hash:/etc/mail/aliases
hash:/var/spool/ml/etc/aliases (fml4)
hash:/var/spool/ml/etc/mail/aliases (fml8)
aliases of fml4 and fml8 should not have duplication.
In othe words, in the case of fml4 process,
MTA -> fml4's aliases -> fml4's include -> fml4 (fml.pl) runs
in the case of fml8 process,
MTA -> fml8's aliases -> fml8's include -> fml8 runs
So we need the following condition:
remove the ml from fml4's aliases file.
add the ml to fml8's aliases file.
If no duplication in aliases, both fml4 and fml8 runs on the same host.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 8. Difference Between fml4 And fml8
In this chapter, we describe the difference beetween fml4 and fml8
Intuitively fml4 vs fml8 is equal to sendmail vs Postfix. It is good image.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Difference Between fml4 And fml8: License.
Roughly speaking, fml8 license is composed of Artistic, BSD or GPL. A part of
fml8 is either of them.
In the case of fml4, almost all codes are written by fml project. The license
of such codes is GPL. jcode.pl and some perl modules are exceptions.
In the case of fml8, the source tree has sub tree which is divided according to
the license. For example, the license of fml/ sub tree is Artictic, cpan/ is
Artistic or GPL, gnu/ is GPL and img/ is BSD. See the license files under them
on the detail.
It is easy to remove some licensed files since the sub-tree is license based.
fml8 installs all modules of the tree into the proper path, so installed
modules are hybrid of licenses. You need to clarify the license before
installation.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Difference Between fml4 And fml8: Command Mail And Error Messages.
fml8 selects language of the return mail for command mail and error messages by
Accept-Language of the incoming message and other information. See Chapter 33
for more details.
In sending back files or messages, fml8 uses MIME/Multipart. tar.gz and zip
formats are not supported..
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Difference Between fml4 And fml8: CUI
There are two CUI: makefml and fml. The syntax of the two is different.
makefml COMMAND ML OPTIONS
fml ML COMMAND OPTIONS
The only difference is the order of command argument.
fml4 command shows processing information as could as possible. Instead fml8
command runs as could as silently since it is proper for automatic process. [4]
This behaviour is UNIX style.
Table 8-1. Difference between fml4 and fml8: CUI
┌──────────────┬──────────────────────────┬───────────────────────────────────┐
│ Content │ fml4 │ fml8 │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│ │"makefml help ML". │ │
│ │"makefml info ML" is same │ │
│show help │as "makefml help ML". If │not implemented. │
│ │the environment variable │ │
│ │PAGER, use it as pager. │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│ │run "make install" at the │run "configure" and "make install" │
│installation │source top directory. In │at the source top directory. In │
│of fml │fact "make install" │fact "make install" executes │
│ │executes "makefml │install.pl script. │
│ │install". │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│ │interactive by default. │not interactive. You can use │
│Behaviour of │You can use interactive │configure for most important │
│install script│menu for most important │options. │
│ │options. │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│create ML │"makefml newml ML" or │makefml newml ML │
│ │"makefml new ML" │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│templates of │ │ │
│alias files │only for sendmail (also │all for postfix, sendmail, qmail, │
│"makefml │used as postfix for │procmail MTA's. │
│newml" │compatibility). │ │
│generates. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│alias file │ │ │
│path "makefml │/var/spool/ml/etc/aliases │/var/spool/ml/etc/mail/aliases │
│newml" │ │ │
│generates. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│how to │ │ │
│generate qmail│makefml qmail-setup ML │"makefml newml" generates it. │
│configuration │ │ │
│files. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│re-generate │makefml recollect-aliases │not implemented. │
│aliaes. │ML │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│remove ML │makefml destructml ML │makefml rmml ML │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│how to set up │run "makefml mead ML" and │ │
│error │set up aliases properly. │enabled by default. │
│analyzer. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│test of fml │makefml test ML │not implemented │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│set up │makefml fmlserv ML │ │
│LISTSERV style│listserv majordomo is same│not implemented │
│server. │as. │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│ │ │"makefml subscribe ML ADDRESS". │
│ │"makefml add ML ADDRESS". │Other 4 commands (add subscribe │
│subscribe (add│"makefml adduser ML │adduser useradd) are same as │
│addess to │ADDRESS" is same. the │subscribe. No message is shown │
│member and │changes is shown after the│unless error occurs. This operation│
│recipient │operation. This operation │is applied to │
│list) │is applied to both actives│$primary_recipient_map and │
│ │and members files. │$primary_member_map (recipients and│
│ │ │members files actually). │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│ │ │"makefml unsubscribe ML ADDRESS". │
│ │"makefml bye ML ADDRESS". │Other 7 commands ( bye unsubscribe │
│remove address│byeuser is same. the │deluser remove resign signoff │
│from recipient│changes is shown after the│userdel ) are same as unsubscribe. │
│and member │operation. This operation │No message is shown unless error │
│list. │is applied to both actives│occurs. This operation is applied │
│ │and members files. │to $primary_recipient_map and │
│ │ │$primary_member_map (recipients and│
│ │ │members files actually). │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│ │"makefml chaddr ML │"makefml chaddr ML OLD_ADDRESS │
│change address│OLD_ADDRESS NEW_ADDRESS". │NEW_ADDRESS". No message is shown │
│(in recipient │the changes is shown after│unless error occurs. This operation│
│and member │the operation. This │is applied to │
│list) │operation is applied to │$primary_recipient_map and │
│ │both actives and members │$primary_member_map (recipients and│
│ │files. │members files actually). │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│ │"makefml addactives ML │ │
│ │ADDRESS". Commands │"makefml addactives ML ADDRESS ". │
│add address to│(addactive add2active │No message is shown unless error │
│only recipient│add2actives) are same. the│occurs. This operation is applied │
│list │changes is shown after the│to $primary_recipient_map │
│ │operation. This operation │(recipients file actually). │
│ │is applied to actives │ │
│ │file. │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│ │"makefml addmembers ML │ │
│ │ADDRESS". Commands │"makefml addmembers ML ADDRESS". No│
│add address to│(addmember add2member │message is shown unless error │
│only member │add2members) are same. the│occurs. This operation is applied │
│list. │changes is shown after the│to $primary_member_map (members │
│ │operation. This operation │file actually). │
│ │is applied to members │ │
│ │file. │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│ │"makefml off ML ADDRESS". │"makefml off ML ADDRESS". No │
│ │skip is same as off. the │message is shown unless error │
│disable real │changes is shown after the│occurs. This operation is applied │
│time delivery │operation. This operation │to $primary_recipient_map │
│ │is applied to actives │(recipients file actually). │
│ │file. │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│ │"makefml on ML ADDRESS". │"makefml digestoff ML ADDRESS" or │
│ │the changes is shown after│"makefml digest ML ADDRESS off". No│
│enable real │the operation. This │message is shown unless error │
│time delivery.│operation is applied to │occurs. This operation is applied │
│ │actives file. │to $primary_recipient_map │
│ │ │(recipients file actually). │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│ │"makefml matome ML │"makefml digeston ML ADDRESS" or │
│change real │ADDRESS". digest is same. │"makefml digest ML ADDRESS on". No │
│time to digest│the changes is shown after│message is shown unless error │
│delivery. │the operation. This │occurs. This operation is applied │
│ │operation is applied to │to $primary_recipient_map │
│ │actives file. │(recipients file actually). │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│ │"makefml addadmin ML │"makefml addadmin ML ADDRESS". No │
│add a remote │ADDRESS". the changes is │message is shown unless error │
│administrator │shown after the operation.│occurs. This operation is applied │
│address. │This operation is applied │to recipients-admin and │
│ │to members-admin file. │members-admin. │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│remove a │"makefml byeadmin ML │"makefml byeadmin ML ADDRESS". No │
│remote │ADDRESS". the changes is │message is shown unless error │
│administrator │shown after the operation.│occurs. This operation is applied │
│address. │This operation is applied │to recipients-admin and │
│ │to members-admin file. │members-admin. │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│set up │ │ │
│password of │"makefml passwd ML". │ │
│remote │interactive. │"makefml passwd ML" (incomplete ?) │
│administrator │ │ │
│(1). │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│set up │ │ │
│password of │"makefml passwd ML │"makefml passwd ML ADDRESS". │
│remote │ADDRESS" interactive. │interactive. │
│administrator │ │ │
│(2). │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│set up │"makefml passwd ML ADDRESS│"makefml passwd ML ADDRESS │
│password of │PASSWORD". the changes is │PASSWORD". No message is shown │
│remote │shown after the operation.│unless error occurs. This operation│
│administrator │This operation is applied │is applied to etc/passwd-admin │
│(3). │to etc/passwd file. │file. │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│menu style │ │ │
│configuration │makefml config ML │incomplete. │
│tool. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│edit │"makefml edit ML". Ask the│"makefml edit ML". Not ask the │
│configuration │editor to use before │editor to use before running. use │
│file. │running. "vi" by default. │environment variable EDITOR if │
│ │ │specified. "vi" by default. │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│fml4 specific │"makefml update-config │ │
│configuration │ML". Commands (update │ │
│file │config-update │no corresponding idea (one │
│conversion │update-config.ph) are │configuration file). │
│(generate cf │same. the operations is │ │
│to config.ph) │shown. │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│edit cf │ │ │
│template by │makefml config-template ML│not implemented │
│menu. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│edit template │makefml edit-template FILE│ │
│files "makefml│list up available file │not implemented │
│newml" uses │list unless FILE │ │
│ │specified. │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│re-generate │ │ │
│files e.g. │makefml │ │
│help at the ml│create-doc-template ML │no corresponding idea. │
│home │ │ │
│directory. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│convert SRC │ │ │
│file to DST │ │ │
│file with │makefml conv ML SRC DST │not implemented │
│variable │ │ │
│conversion. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│see log (the │"makefml log ML [OPTION]".│"makefml log ML". options are not │
│last 100 lines│"makefml tail ML" is same.│implemented. │
│shown). │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│set up │ │ │
│admin.cgi │ │ │
│(scripts and │"makefml admin.cgi ML". │incomplete. │
│apache │interactive. │ │
│configuration │ │ │
│helper). │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│set up │ │ │
│ml-admin.cgi │"makefml ml-admin.cgi ML".│ │
│(scripts and │"makefml mladmin.cgi ML" │incomplete. │
│apache │is same. interactive. │ │
│configuration │ │ │
│helper). │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│set up │makefml │ │
│.htpasswd for │html_cgiadmin_passwd ML │not implemented │
│admin.cgi. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│html_config │ │ │
│(makefml │makefml html_config ML │not implemented │
│internal use │html_config_set is same. │ │
│command) │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│set up │ │ │
│.htpasswd for │ │ │
│ml-admin.cgi │ │ │
│and the │makefml html_passwd ML │not implemented │
│password of │ │ │
│admin command │ │ │
│mail. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│set up │ │ │
│.htpasswd for │makefml htpasswd ML │not implemented │
│ml-admin.cgi. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│pgp command │makefml pgp ML │fmlpgp │
│wrapper │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│pgp2 command │makefml pgp2 ML │fmppgp2 │
│wrapper │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│pgpe command │makefml pgpe ML │fmlpgpe │
│wrapper │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│pgpk command │makefml pgpk ML │fmlpgk │
│wrapper │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│pgps command │makefml pgps ML │fmlpgps │
│wrapper │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│pgpv command │makefml pgpv ML │fmlpgpv │
│wrapper │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│gpg command │makefml gpg ML │fmlgpg │
│wrapper │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│admin-auth │ │ │
│(PGP, GPG KEY │makefml admin-auth ML │fmlpgp* command │
│RING │ │--admin-command-mail-auth │
│operation) │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│admin-encrypt │ │ │
│(PGP, GPG KEY │makefml admin-encrypt ML │not implemented │
│RING │ │ │
│operation) │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│dist-auth │ │ │
│(PGP, GPG KEY │makefml dist-auth ML │fmlpgp* command --article-post-auth│
│RING │ │ │
│operation) │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│dist-encrypt │ │ │
│(PGP, GPG KEY │makefml dist-encrypt ML │fmlpgp* command │
│RING │ │--article-post-encrypt │
│operation) │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│set up popfml │ │ │
│(emulate MTA │makefml popfml │fetchfml │
│and ML via │ │ │
│POP). │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│set up │ │write password in configuration │
│password for │makefml pop_passwd │file config.cf. │
│POP. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│lock ML. │makefml lock ML │not implemented (no corresponding │
│ │ │idea, no giant lock). │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│create a │makefml │ │
│template of │bug-report-template ML │not implemented │
│bug report. │send-pr is same. │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│execute │makefml command ML │not implemented │
│command. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│set up │makefml delivery_mode ML │not implemented │
│delivery mode.│ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│change │ │ │
│configuration │ │ │
│variable in │makefml setq ML │-o options. │
│running │ │ │
│makefml. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│show │ │ │
│environment │makefml showconfig ML │not implemented / no plan │
│summary where │showconf is same. │ │
│fml runs. │ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│show OS │ │ │
│information by│"makefml show". │not implemented / no plan │
│"show COMMAND"│ │ │
│style command.│ │ │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│send a file. │makefml resend ML │not implemented / no plan │
├──────────────┼──────────────────────────┼───────────────────────────────────┤
│upgrade │ │ │
│command: │ │ │
│convert fml │makefml upgrade ML │not needed │
│2.0 to fml │ │ │
│3.0. │ │ │
└──────────────┴──────────────────────────┴───────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Difference Between fml4 And fml8: GUI (CGI)
In the case of fml4, you need to set up .cgi scripts and apache configurations
after installation.
In the case of fml8, "makefml newml" generates GUI scripts except for the
apache configurations.
Interface differs a lot. The interface of fml4 GUI is classical. That of fml8
is table based by default.
It is a TODO to select GUI skin dynamically.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
File Naming Convention
See Chapter 16 for the file naming convention. You need not to know the
detail, since the conversion tools convert files from fml4 style to fml8 one.
But it is useful to know it to see files.
The policy to handle member list and recipient list separately is same. But the
file name differs.
The file name is "filename-role" style. The role is abbreviated if the role is
default.
"actives" is renamed to "recipients". The meaning is clear. Instead "members"
is "members".
"members-admin" is same. "recipients-admin" exists virtually but is is not
used.
"etc/passwd" is renamed to "etc/passwd-admin". The format differs a little.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 9. Upgrade And Downgrade Of fml8
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│This chapter describes upgrade and downgrade of fml8. │
│ │
│See Chapter 7 on the upgrade from fml4 to fml8. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Upgrade
Install again.
After fml8 installation, rewrite fml_version line in /usr/local/etc/fml/main.cf
to switch fml to the version installed now. Just when the file is saved, fml is
changed to the new version.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
downgrade.
No need to install. Edit /usr/local/etc/fml/main.cf to back the fml_version to
the previous one.
Just when the file is saved, fml is changed to the new version.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 10. Configure CGI
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│See the section the Section called Method in Chapter 38 for CGI Internal │
│details. │
│ │
│We assumes you use suexec under apache. │
│ │
│Now fml8 provides both the master cgi to control all ML's in one domain and a│
│cgi for each ML. You can add and remove a user, or view member list et.al. by│
│this interface. Editing of configuration on this cgi is incomplete. │
│ │
│If you use postfix and qmail, you do not need to modify MTA configuration for│
│cgi specific reason. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
"makefml newml" Creates CGI Script Always
"makefml newml" sets up CGI scripts such as config.cgi under ~fml/public_html
/... directory. There are two types of cgi scripts. One is for the whole
domain, one for each ML.
In creating elena@fml.org ML, makefml creates the following cgi
http://lists.fml.org/~fml/cgi-bin/fml/$domain/admin/config.cgi
[Example]
http://lists.fml.org/~fml/cgi-bin/fml/fml.org/admin/config.cgi
for all ML's of fml.org.
To control only elena ML, please use
http://lists.fml.org/~fml/cgi-bin/fml/$domain/ml-admin/${ml_name}/config.cgi
[Example]
http://lists.fml.org/~fml/cgi-bin/fml/fml.org/ml-admin/elena/config.cgi
[cgi]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Edit .htaccess
.htaccess is created but it is configured to deny all.
http://lists.fml.org/~fml/cgi-bin/fml/$domain/.htaccess
[Example]
http://lists.fml.org/~fml/cgi-bin/fml/fml.org/.htaccess
The default .htaccess is a dummy like this:
AuthName ByPassword
AuthType Basic
require valid-user
Please edit .htaccess properly.
Apache does not support ~user style access by default. Please set up apache to
enable it.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Example: Master Cgi
The role of this cgi is same as limited makefml (CUI). Though this cgi permits
ML creation and destruction, all functions makefml has are not supported. The
function is limited.
Eample: TOP MENU
@home.fml.org CGI for configuration
fml admin menu fml CGI interface for @home.fml.org ML's
mailing list:
[elena]
command: .. help message ...
[subscribe ]
[submit][reset]
subscribe
unsubscribe
addadmin
byeadmin
options Language: list
[Japanese] [change] log
newml
rmml
[cgi]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CGI Example: Create ML
Select newml and push "submit". No need to select ML name in this stage.
You find another menu at the center. Specify the ML name you create and push
"submit" at the center.
[cgi]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CGI Example: subscribe
Specify the ML name and select "subscribe", push "submit".
You find another menu at the center. Specify the address to subscribe and push
"submit" at the center.
[cgi]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CGI Skin Selection
config.cgi is TABLE and SELECT based. If you use old style menu, use menu.cgi.
for a whole domain
~fml/public_html/fml/DOMAIN/admin/menu.cgi
for a ml
~fml/public_html/fml/DOMAIN/ml-admin/menu.cgi
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 11. Apache Configuration
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│See the Section called Method in Chapter 38 for the fml8 CGI internals. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Use Suexec Of Apache
Build apache enabled with suexec. Run configure by
(apache 1.x)
configure --enable-suexec --suexec-caller=www
In this case, the user "www" can call suexec. Please prepare a user specific
for suexec-ed environment.
After apache installation, change httpd.conf to allow ~user/cgi-bin/ form.
Example:
AllowOverride FileInfo AuthConfig Limit
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec ExecCGI
Order allow,deny
Allow from SPECIFIC_HOST
... snip ...
AddHandler cgi-script .cgi
... snip ...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 12. Test
Before Test
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│Set up MTA properly before test of fml. │
└─────────────────────────────────────────────────────────────────────────────┘
In this chapter, fml8 and MTA works on ahodori.fml.org, which is called as the
mail server.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Test Of MTA
Firstly, check MTA without fml on ahodori.fml.org.
Prepare one personal user address such as rudo@fml.org. Usually, just create a
user named as "rudo".
# useradd rudo
Check you can send a mail to rudo@fml.org on ahodori.fml.org and rudo receives
the mail.
% echo test |Mail rudo@fml.org
If it not works, check MTA configuration. See /var/log/maillog et.al to track
errors.
Secondary, verify mail delivery over network. Send a mail to rudo@fml.org from
other host (not ahodori.fml.org). If rudo receives the mail, MTA is o.k.
If both work well, MTA configuration must be ok.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Send A Mail To ML
Create elena ML (elena@fml.org) and subscribe rudo@fml.org to elena ML.
% su fml
% makefml newml elena
% makefml add elena rudo@fml.org
Send a test mail to elena@fml.org from on the host and from other host (not
ahodori.fml.org). Verify the header of this test mail should be "From:
rudo@fml.org" since fml8 checks the From: header field.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Checkpoints
If something not work well, check the following points:
check the mail server log (e.g. /var/log/maillog)
check the fml log (e.g. /var/spool/m/elena/log)
fml can pass the message to MTA ? (e.g. /var/spool/m/elena/log)
MTA succeeds to deliver it? (e.g. /var/log/maillog)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Test Of fml8 Itself.
*** not yet implemented ***.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Reset After Test.
It is easy to re-create this mailing list (e.g. test ML).
% su fml
% makefml rmml test
% makefml newml test
The removed ML home is left as /var/spool/ml/@test.$DATE.$SEQUENCE. Please
remove it since this is a test to avoid the duplication in the future.
% rm -fr /var/spool/ml/@test.$DATE.*
III. How To Customise
Topics driven in this part.
Table of Contents
13. What A User Can
14. What Can You Do On The Mailing List Server
15. Modify Configuration Files
16. [Caution] File Names
17. Case Studies Of Customization
18. Header Rewriting
19. Extend Command
20. Filtering
21. Extend Message
22. Be ML Articles public via WWW
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 13. What A User Can
Get ML Guide
Send the mail with
guide
to elena-ctl@fml.org address. fml8 sends back the guide message to the sender.
If a file named "guide" is found at $ml_home_dir, it is used as a message
template.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Subscribe
Suppose elena@fml.org ML. Firstly, send the mail with
subscribe YOUR-NAME
to elena-ctl@fml.org address.
fml8 sends back the confirmation to both addresses. Please send back the reply
for the confirmation to elena-ctl@fml.org again. When your reply to the
confirmation is confirmed to be valid, fml8 add the address as a new ML member.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Posting Article
Send a mail to elena@fml.org. MTA running on the mailing list server host (on
e.g. ahodori.fml.org) receives the mail and finally kicks off /usr/local/
libexec/fml/distribute command.
"distribute" command recieves the message from STDIN, rewrites the header, save
it in the spool directory and pass it back to MTA for delivery.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Distribution Process
1) fml8 adds a tag to the subject, update the article sequence number.
Example:
Subject: [elena:00100] teddy bear is cute.
(no tag by default).
2) save article (as a text file).
3) create a HTML version of the article under ~fml/public_html/ directory.
4) update database (udb) on thread.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Variables
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│*** sorry, not yet written *** │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Example: Boot Sequence Of Distribute Process
fml boot loader boots off in the following way.
/usr/local/libexec/fml/distribute command is symlink-ed to /usr/local/libexec/
fml/loader. These files are same.
/usr/local/libexec/fml/loader reads /usr/local/etc/fml/main.cf firstly.
$fml_vesrion such as "current-20010501" is defined in the main.cf. fml8
resolves $fml_version from it and determines the library path as /usr/local/lib
/fml/current-20010501/. fml8 loads perl modules under it.
fml8 sets up @INC properly. fml loader loads FML::Process::Switch module and
check $0 (process name). fml knows the process role from $0. In this case of
distribute, fml loads FML::Process::Distribute module (defined as /usr/local/
etc/fml/$fml_version/modules), switch itself to it and processes distribution.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Help: When You Want To know The Usage
Send the mail with
help
to elena-ctl@fml.org address. It sends back the help message to the sender.
If a file named "help" is found at $ml_home_dir, it is used as a message
template.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Get Past Articles
Send the mail with
get NUMBER
to elena-ctl@fml.org address where NUMBER is the article number. fml8 sends
back articles by mime/multipart form to the sender.
You can use MH style arguments as NUMBER.
[Example]
get 100
get 1-100
get first:3
get last:3
get 1-100,first:3,last:3
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Unsubscribe
In the case of elena@fml.org ML, send the mail with
unsubscribe YOUR-NAME
to elena-ctl@fml.org (control address).
fml8 sends back the confirmation to the sender. Please send back the reply for
the confirmation to elena-ctl@fml.org again. When your reply to the
confirmation is confirmed to be valid, fml8 removes the address.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Command Mail (Control fml By Sending Mail)
fml8 accepts control commands which is sent as a mail. It is called "command
mail".
Important: The use of CUI (makefml/fml) is basic in fml world. It is
expected you should use CUI if you can login the mailing list server.
The role of command mail is to delegate fml control priviledge to users who
cannot login the mailing list server.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Flow
Consider elena ML. Send the command mail to elena-ctl@fml.org which is the
address for command mail. MTA receives the mail and finally kicks off /usr/
local/libexec/fml/command program. This program receives the mail (command
mail) from STDIN , processes the requests and sends back the result to the
sender. The mail to send back is passed to MTA for delivery via SMTP.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│The result is aggreagated to one msssage as MIME/Multipart. This is different│
│from fml4 behaviour. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Perl Modules For Command Mail
All modules which CUI, GUI and command mail uses are implented as
FML::Command:: class.
In fact, a sub set of FML::Command:: class is allowed as command mail.
$user_command_mail_allowed_commands, $anonymous_command_mail_allowed_commands
and $admin_command_mail_allowed_commands variables defines it.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 14. What Can You Do On The Mailing List Server
On the host which serves ML driver, you can use CUI (makefml and fml) and edit
all configuration files as you like. It implies you are the greatest
administrator :)
"makefml" command of fml8 is same as fml4 as could as possible to preserve
compatibility.
See the Section called Difference Between fml4 And fml8: CUI in Chapter 8 on
the detail of the difference.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
On The Host
You need no confirmation in using makefml.
Person who can login the host of mailing list server has priviledge for all
ML's on the host. So, He/She can edit all configuration files.
But He/She may do wrong operations.
To avoid careless wrong operations, in usual cases you should use CUI (makefml
or fml) to configure fml. Of course you can edit files directly if you can
understand fml structures. By default we recommend you should use CUI always on
the host.
"fml" command is same as "makefml" command except for the argument order.
makefml COMMAND ML OPTIONS
fml ML COMMAND OPTIONS
Please either as you like.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Policy Of Command Creation
fml8 provides a different command for each function. Its policy makes the
number of commands infinite. So, except for some special cases, we should unify
all functions into makefml/fml command since such commands can be shared among
CUI, GUI and commmnd mail.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Operation May Modify The Specific ML (Read + Write)
We should implement sub-command of makefml/fml when some operation may modify
the specific ML.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Operation For Read Only Data Of The Specific ML (Read Only)
We should implement it as a makefml/fml command since it is related to the
specific ML.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Show The General Data (Read Only)
If the data is not related to the specific ML, for example, see the module
manual, aliases on the host, we implement specific commands other than makefml/
fml. This command name begins with "fml" prefix.
fmladdr [-n]
fmlalias [-n]
fmldoc MODULE
fmlconf [-n] ML
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ML Specific But A Command Wrapper
PGP / GPG related command (e.g. fmlpgp) is very command speicific. So, it looks
difficult to incorporate them into "makefml" and "fml" framework. So we
implement it as another command such as fmlpgp, fmlgpg, ...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Misc
We implement specific commands other than makefml/fml. This command name begins
with fml prefix.
For example, "fmlhtmlify" is a conveter from text to html form. This command is
used to convert both fml spool and MH folders.
fmlhtmlify [-I DIR] $src_dir $dst_dir
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Common Command Line Options
Programs under libexec/ and bin/ supports the following common command line
options.
--debug
--help
-c file
-o key=value
Use -c to specify non default main.cf path. -o overwrites configuration
variables. Plural -o are acceptable.
-o key1=value1 -o key2=value2
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Create A New ML
% su fml
% makefml newml ML
If ML without @domain part is specified, the domain of the ML is treated as the
default domain. Both ML and ML@DOMAIN form is o.k. for the default domain.
Example: In the case of default domain:
% makefml newml elena
% makefml newml elena@fml.org
In the case of virtual domain, you should specify the address with the domain
such as user@domain form as ML string.
See the section Chapter 5 for more details.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Remove An ML
Example:
% su fml
% makefml rmml ML
fml accepts ML string without @domain as the default domain. Both user and
user@domain syntax is acceptable.
Example: in the case of default domain:
% makefml rmml elena
% makefml rmml elena@fml.org
Please use user@domain syntax for virtual domains.
It reverts the action newml did. It removes ML home directory, alias entries
and ~fml/.qmail-*.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Subscribe and Unsubscribe
Use "useradd" commadn to subscribe the user, "userdel" to unsubscribe the user.
Example:
% su fml
% makefml useradd ML ADDRESS
% makefml userdel ML ADDRESS
fml treats ML without @domain part as one of the default domain.
Examle:
% su fml
% makefml useradd elena rudo@nuinui.net
% makefml userdel elena rudo@nuinui.net
% makefml useradd elena@fml.org rudo@nuinui.net
% makefml userdel elena@fml.org rudo@nuinui.net
For convenience, useradd is an acronym. The following commands,
useradd
adduser
subscribe
add
, are same as useradd. In the same way,
userdel
deluser
bye
remove
resign
signoff
unsubscribe
are same as userdel.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Change the registered address
Example:
% su fml
% makefml chaddr ML OLD-ADDRESS NEW-ADDRESS
fml treats ML without @domain part as one of the default domain. For example,
Example: in the case of a virtual domain
% su fml
% makefml chaddr elena rudo@nuinui.net teddy@nuinui.net
% makefml chaddr elena@fml.org rudo@nuinui.net teddy@nuinui.net
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Stop Realtime Delivery
% makefml off elena ADDRESS
Delivery to ADDRESS is switched to digest.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Start Realtime Delivery
% makefml on elena ADDRESS
Delivery to ADDRESS is switched from digest to real time.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
See Log
% makefml log elena
% makefml log elena@fml.org
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
See The Member List
% makefml list elena
It shows recipients of this ML. Also,
% makefml list elena recipient
lists up only recipients of this ML. Instead
% makefml list elena member
shows the list who can post this ML.
You can specify arbitrary MAP as an argument to show it.
% makefml list elena MAP
MAP can be an abbrebiation. For example, you can use "xxx" as MAP to imply
"primary_xxx_map" or "xxx_maps".
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Modify Configuration
Edit config.cf directly now.
Configuration helper tool is incompletely implemented.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Add or Remove A Remote Administrator.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│A remote administor is a person who cannot login to the mail server but │
│control an ML by sending a command mail (which is called "admin command"). │
│ │
│Please use CUI to control remote administrators. If you use CUI, you can have│
│priviledge to do since the use of CUI needs login to this host. │
└─────────────────────────────────────────────────────────────────────────────┘
[Example]
% su fml
% makefml addadmin ML ADDRESS
% makefml deladmin ML ADDRESS
fml treats ML without @domain part as one of the default domain.
[Example: in the case of a virtual domain]
% su fml
% makefml addadmin elena rudo@nuinui.net
% makefml deladmin elena rudo@nuinui.net
% makefml addadmin elena@fml.org rudo@nuinui.net
% makefml deladmin elena@fml.org rudo@nuinui.net
For convenience,
adminadd
addpriv
are same as addadmin.
byeadmin
byepriv
are same as deladmin.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Add or Remove A Modrator
[Example]
% su fml
% makefml addmoderator ML ADDRESS
% makefml delmoderator ML ADDRESS
fml treats ML without @domain part as one of the default domain.
[Example: in the case of a virtual domain]
% su fml
% makefml addmoderator elena rudo@nuinui.net
% makefml delmoderator elena rudo@nuinui.net
% makefml addmoderator elena@fml.org rudo@nuinui.net
% makefml delmoderator elena@fml.org rudo@nuinui.net
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
"fml" And "makefml" Command
"fml" (/usr/local/bin/fml) and "makefml" (/usr/local/bin/makefml) is same
except for argument order. Please use it as you like.
% fml ML COMMNAD [OPTIONS]
% makefml COMMAND ML [OPTIONS]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Show Addresses (Users + Aliases)
"fmladdr" (/usr/local/bin/fmladdr) lists up all users on this host. It shows
users defined in /etc/passwd and aliases defined in Postfix.
% fmladdr
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│The difference between "fmladdr" and "fmlalias" is whether it contains users │
│defined at /etc/passwd or not. "fmladdr" contains it but "fmlalias" not. │
│"fmlalias" lists up all users defined at aliases. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Show Alias
fmlalias (/usr/local/bin/fmlalias) shows all aliases. Precisely speaking, it
shows all aliases defined as valid aliases of Postfix.
% fmlalias
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│The difference between "fmladdr" and "fmlalias" is whether it contains users │
│defined at /etc/passwd or not. "fmladdr" contains it but "fmlalias" not. │
│"fmlalias" lists up all users defined at aliases. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Show Configuration
"fmlconf" (/usr/local/bin/fmlconf) takes ML name as an argument. It shows all
variables of the specified ML. If "-n" option specified, it shows variables
different from default ones.
To list up all variable list,
% fmlconf elena
To list up variables different from the default one,
% fmlconf -n elena
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Show Perl Module Document
The usage of fmldoc is same as perldoc. This is a wrapper for perldoc.
To see FML::Process::Kernel perl module document,
% fmldoc FML::Process::Kernel
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Convert Articles To HTML Form
By default, fml converts the article to HTML form. "fmlhtmlify" command is a
tool to convert all articles to initialize the html archive.
[Usage]
% fmlhtmlify SPOOL_DIRECTORY HTML_ARCHIVE_DIRECTORY
[Example]
% fmlhtmlify /var/spool/ml/elena/spool /some/where/mlarchive/elena
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipes
1. I've removed ML accidentally. Can I revive it ? (CUI,CGI,admin command)
2. Add an address who can post (CUI,CGI,admin command)
3. Add an address who receive articles but not post.
4. Change registered address.
1. I've removed ML accidentally. Can I revive it ? (CUI,CGI,admin command)
If you have removed ML by running "makefml rmml", please use
% makefml reviveml ML
Same as CGI.
When you use admin command (remote administration), you cannot use this
operation.
If you have removed ML by running "rm -fr /var/spool/ml/elena", you cannot
revive it. Please revive ML from back-up.
2. Add an address who can post (CUI,CGI,admin command)
Usually run
% makefml add ML ADDRESS
If you post from both office and home but want to receive article at office, it
is better to add an address who can post but not receive. It implies we should
add the address to only member_maps.
On the mailing list server host, use makefml.
% makefml addmember ML ADDRESS
The following 4 commands are same function: add2member add2members addmember
addmembers
When you use "admin command", as in same way.
To: elena-ctl@fml.org
Subject:
admin pass PASSWORD
admin addmember ML ADDRESS
CGI does not provide this function now.
3. Add an address who receive articles but not post.
The usage of address, who cannot post but can receive articles, is for such as
mail magazine case.
n the mailing list server host, use makefml.
% makefml addrecipient ML ADDRESS
This ADDRESS is added to only recipient_maps. The following 4 commands are same
function: add2recipient add2recipients addrecipient addrecipients
The usage is same in "admin command".
To: elena-ctl@fml.org
Subject:
admin pass PASSWORD
admin addrecipient ML ADDRESS
CGI does not provide this function.
4. Change registered address.
On the mailing list server host, use makefml.
% makefml chaddr ML OLD-ADDRESS NEW-ADDRESS
The usage is same in "admin command".
To: elena-ctl@fml.org
Subject:
admin pass PASSWORD
admin chaddr ML OLD-ADDRESS NEW-ADDRESS
"chaddr" command is available in using CGI.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 15. Modify Configuration Files
Change Default For All ML's On Thie Host
Edit /usr/local/etc/fml/site_default_config.cf file. The format is same as
config.cf.
This file corresponds to site_force.ph of fml4.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 16. [Caution] File Names
References: fml-devel 205
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Filename Structure
The fundamental syntax is
FILENAME-ROLE
. For example, fml uses the following syntax for address lists.
recipients-ROLE
members-ROLE
Other than address lists, fml uses similar manner for other type of files. For
example,
passwd-admin
passwd-moderator
passwd-cgiadmin
for several password files.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: Address List
primary_recipient_maps = recipients
# add actives for backward compatibility
recipient_maps = recipients
actives
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: List Of Remote Administrators
recipients-admin
members-admin
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: List Of Moderators
recipients-moderator
members-moderator
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: Remote Administrator Password Files
etc/passwd-admin
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│etc/passwd, lack of role name, was used in the case of fml4. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 17. Case Studies Of Customization
Case Study: Auto File Responder
Modify delivery process ( libexec/distribute ) to send back /some/where/help
file. For example, when a user can send anything to help@fml.org, fml sends
back the help file to the sender.
In this case, set the following at config.cf
article_post_restrictions = permit_anyone
and define the following hook after =cut line.
$distribute_run_start_hook = q{
$curproc->reply_message( {
type => "text/plain; charset=iso-2022-jp",
path => "/some/where/help",
filename => "help",
disposition => "help example",
});
$curproc->stop_this_process();
};
The last
$curproc->stop_this_process();
method of fml8 corresponds to the statement
$DO_NOTHING = 1;
of fml4. After this statement, the normal processing stops.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: Anyonen Can Use Command Mail.
$command_mail_restrictions defines who can use command mail. By default user
registerd as a poster can use command mail. To enable that anyone can use
command mail, set
command_mail_restrictions = permit_anyone
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipes
1. Anyone can use command mail.
2. Anyone except system accounts can use command mail.
3. nobody use command mail.
1. Anyone can use command mail.
command_mail_restrictions = permit_anyone
2. Anyone except system accounts can use command mail.
command_mail_restrictions = reject_system_accounts
permit_anyone
3. nobody use command mail.
command_mail_restrictions = reject
There are other methods to disable command mail. See the Section called Case
Study: Disable Command Mail for more details.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: Disable Command Mail
It is most safe to remove command mail entries from aliases.
Another 2nd best solution follows:
use_command_mail_function = no
In this case, /usr/local/libexec/fml/command runs once but does not work and
ends as soon as possible.
The following solution may be possible.
use_command_mail_function = yes
command_mail_restrictions = reject
When fml receives the incoming command mail, it inform the rejection to the
sender in all cases.
This configuration works but it evalutates each line. It is useless.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: Mail Magazine (1)
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│Please use PGP auth if could, though we describe header based auth here. Also│
│please set up MTA properly e.g. to disable smtp interfaces as could as │
│possible. │
│ │
│It is a problem that PGP auth requires user's skill at some level. │
└─────────────────────────────────────────────────────────────────────────────┘
In the case of header based auth, you can create a mail magazine by using the
asymmetirc member list. Consider asymmetric case of member list (list of
persons who can post) and recipient list below.
Firstly, remove $primary_member_map from $member_maps. Instead, define
$ml_home_dir/members-mailmag who can post to $member_maps.
member_maps = $ml_home_dir/members-mailmag
The use of "subscribe" command is same as default one since "subscribe" command
changes $primary_member_map not $member_maps. It is a little tricky but crafty
use of $primary_XXX_map and $XX_maps enhances fml8 configuration.
In this case, when a new user is subscribed, the user address is added to both
$ml_home_dir/members ($primary_member_map) and $ml_home_dir/recipinets
($primary_recipient_map). But $member_maps is defined as $ml_home_dir/
members-mailmag. $ml_home_dir/members is not used. Hence, only the list of
recipients is updated but the list of posters is NOT changed.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│Strictly speaking, this configuration is not enough safe. If somebody fakes │
│From: address, he/she can post since fml checks only From: address. │
│ │
│So, pgp auth is recommended. │
└─────────────────────────────────────────────────────────────────────────────┘
Another solution.
primary_member_map = $tmp_dir/members-dummy
and use $member_maps (member_maps = $ml_home_dir/members) for normal use. It
has only poster's addresses.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: Mail Magazine (2)
After 2004/06, fml8 supports the queuing system. So the outgoing mail fails
once, after the confirmation of content, you flush again to deliver if the
content is ok.
The queuing system support enables "queue once, dequeue after content
confirmation". It avoids delivery of wrong content.
The configuration is as follows.
Specify irrelevant port at config.cf.
smtp_servers = IRRELEVANT_PORT
[Example]
smtp_servers = 127.0.0.1:2025
This makes the delivery fail. The message is queued.
Check the content. If the content is correct and delivery is ready, runs the
following command by specifying the correct transport.
% fml -o smtp_servers=TRANSPORT ML_NAME flushq
[Example]
% fml -o smtp_servers=127.0.0.1:25 ML_NAME flushq
"flush" and "flushq" command are same.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: Anyone Can Post.
article_post_restrictions = permit_anyone
$article_post_restrictions parameter controls who can post to this ML. To set
this as "permit_anyone", anybody (including system special account e.g. root,
postmaster) can post.
By default, $article_post_restrictions is defined as follows for fml4
compatibility,
article_post_restrictions = reject_system_special_accounts
permit_member_maps
reject
"reject_system_special_accounts" denies post if From: looks like system
accounts e.g. root, postmaster.
This configuration means that system special accounts cannot post and only user
contained in $member_maps can post article.
Attention that reject_XXX and permit_XXX statement is first match.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
recipes
1. Any persons in a domain can post always.
1. Any persons in a domain can post always.
It is not easy to handle global variables in the case of fml4 .
By using the following restriction, you can ermit only sender of example.co.jp
domain and reject other domain.
[/var/spool/ml/elena/config.cf]
article_post_restrictions = reject_system_special_accounts
permit_member_maps
reject
member_maps = pcre:$ml_home_dir/sender.pcre
[$ml_home_dir/domains]
\S+\@example.co.jp
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: Article Posting Allowd If It Is A Reply To The Former One.
From time to time we can find that a posted article is denied due to posting
from not a member.
One reason is that the member who replied some article forgot to notify changes
of his/her mail address to the mailing list administrator. Another reason that
his/her mail address is changed from @DOMAIN to @SUB.DOMAIN vice versa. Yet
another reason is that he/she replied it from other location which recieved the
article via mail forwarding at some other host.
After 2004/10/28 fml8 current, fml8 supports "allow article post irrespective
of the From: address if some condition satisfied" at article_post_restrictions.
The current implementation suppors the condition that "if the reply refers a
known message-id within some time limit". Precisely speaking, "known
message-id" implies the id is found at the message-id database which holds
In-Reply-To: and References: of old articles within some time limit (e.g. one
week).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipes
1. Article Posting Allowd If It Is A Reply To The Former One.
1. Article Posting Allowd If It Is A Reply To The Former One.
"check_article_thread" is the keyword to enable this check.
article_post_restrictions = reject_system_special_accounts
check_article_thread
permit_member_maps
reject
Not used by default. To use it, specify it at article_post_restrictions.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Discussion
Hmm, this is similar to a cookie. There are some problems.
1) What is proper time scale ? $article_post_article_thread_lifetime controlls
it. One day by default.
article_post_article_thread_lifetime = 86400
Also, boundary of the time scale ? When starts the allowd window ? It starts
from the first article of the specific thread ? Or from the last article ?
2) More restricted condition support required ? If so, we should check the
corelation between subject: and the thread?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipes
1. Only A Few Persons Can Starts Article Thread.
1. Only A Few Persons Can Starts Article Thread.
member_maps = $tmp_dir/members-thread-init
article_post_restrictions = reject_system_special_accounts
check_article_thread
permit_member_maps
reject
Only persons registered at members-thread-init file can post article always.
Other persons can post the article if the article is a reply to some other
article.
Hmm, it looks a variation of moderator system ?
Better that they use PGP auth if could.
member_maps = $tmp_dir/members-thread-init
article_post_restrictions = reject_system_special_accounts
check_article_thread
check_pgp_signature
reject
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: PGP/PGP Based Authentication In Posting
┌─────────────────────────────────────────────────────────────────────────────┐
│ Caution │
├─────────────────────────────────────────────────────────────────────────────┤
│Please install Crypt::OpenPGP perl module firstly. It is better to use OS │
│dependent pacakge system since Crypt::OpenPGP depends a lot of other │
│packages. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipes
1. PGP/PGP Based Authentication In Posting
1. PGP/PGP Based Authentication In Posting
check_pgp_signature options enables PGP/GPG based auth. If the degital
signature is confirmed, the user can post articles.
article_post_restrictions = reject_system_special_accounts
check_pgp_signature
reject
This function is disabled by default. Change article_post_restrictions if use.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Key Operations
PGP KEY RING directories are separeted for each purpose. For example, the
keyring dir for article pgp auth is $ml_home_dir/etc/pgp-article-post-auth/
directory, the keyring dir for remote administration by command mail is
$ml_home_dir/etc/pgp-admin-command-mail-auth/ directory.
Use pgp2, pgp5 and gpg commands to edit keys under them It is useful to use the
following fmlpgp wrapper command. The wrapper sets up proper environment
variables.
[Example] operations for elena ML
fmlpgp elena --article-post-auth -kg
the command line options available:
--article-post-auth (auth for post article)
--command-mail-auth (auth for command mail)
--admin-command-mail-auth (auth for admin command mail)
--article-post-encrypt (article encryption)
Available wrappers follow:
pgp2: fmlpgp
pgp5: fmlpgp5 fmlpgpe fmlpgpk fmlpgps fmlpgpv
gpg: fmlgpg fmlgpgv
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: Authenticate command mail by PGP/GPG
1. Authenticate user mode command mail by PGP/GPG.
2. Authenticate admin command mail by PGP/GPG.
1. Authenticate user mode command mail by PGP/GPG.
command_mail_restrictions = check_pgp_signature
reject
Use CLI ( fmlgpg fmlgpgv fmlpgp fmlpgp5 fmlpgpe fmlpgpk fmlpgps fmlpgpv ) to
manipulate PGP/GPG keys.
Example: generate key for mailing list "ML_NAME".
% fmlpgp --command-mail-auth ML_NAME -kg
See the Section called Case Study: PGP/PGP Based Authentication In Posting for
more details.
2. Authenticate admin command mail by PGP/GPG.
admin_command_mail_restrictions = check_pgp_signature
reject
Use CLI ( fmlgpg fmlgpgv fmlpgp fmlpgp5 fmlpgpe fmlpgpk fmlpgps fmlpgpv ) to
manipulate PGP/GPG keys.
Example: generate key for mailing list "ML_NAME".
% fmlpgp --admin-command-mail-auth ML_NAME -kg
See the Section called Case Study: PGP/PGP Based Authentication In Posting for
more details.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
case study: hierarchical ML
Consider usual ML's which allows post from registered members. For example,
sales 1, 2 and 3 division.
Create sales-1, sales-2 and sales-3 ML. Each division manages each member list.
Also, create sales ML other than that to inform the whole sales members. If you
send a mail to sales ML, the mail is sent to all members of sales-1, sales-2
and sales-3 ML.
Define the following $recipient_maps in the config.cf of sales ML.
recipient_maps += $ml_home_dir/../sales-1/recipients
recipient_maps += $ml_home_dir/../sales-2/recipients
recipient_maps += $ml_home_dir/../sales-3/recipients
Define $member_maps in the same way to allow post from all sales members:
member_maps += $ml_home_dir/../sales-1/members
member_maps += $ml_home_dir/../sales-2/members
member_maps += $ml_home_dir/../sales-3/members
Instead of $member_maps change, it is simple that you allow post from anybody.
If so set
article_post_restrictions = permit_anyone
This example is simplest. It is easy to use this style.
If you need to use SQL e.g. MySQL, it is modern. It needs a lot of preparions
and operation know-how.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
I Want To Use ML By My Account.
When you set up an ML within your account, for example when you are using
virtual domain service of ISP, you need to use a mail processor such as
procmail.
To catch up messages to ML's, you need to filter messages according to To: or
Cc: in the mail header.
fml8 expects the user uses a filter tool such as procmail in such a situation.
fml8 distribution itself does not provide such a tool.
When running "makefml newml", "makefml" creates/updates ~/.procmailrc sample at
/var/spool/ml/etc/procmail/procmailrc. Please use it as a sample.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
~/.procmailrc Example
PATH=$HOME/bin:/usr/bin:/usr/ucb:/bin:/usr/local/bin:/usr/pkg/bin
MAILDIR=$HOME/Mail # You'd better make sure it exists
DEFAULT=$HOME/Mail/mbox
LOGFILE=$MAILDIR/procmail.log
LOCKFILE=$HOME/.lockmail
VERBOSE=on
:0
* To.*elena@fml.org
| /usr/local/libexec/fml/fml.pl /var/spool/ml/elena
:0
* To.*elena-ctl@fml.org
| /usr/local/libexec/fml/fml.pl /var/spool/ml/elena --ctladdr
# last resort, mail for me et. al.
:0
inbox/.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Virtual Domain Case
The procmail rules above contains ml_name and ml_domain within it. So it does
not need special handling for virtual domain. It is same for both default
domain and virtual domain.
MTA configuration is another issue. Please contact administrator on it.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: Office (1)
Edit /usr/local/etc/fml/site_default_config.cf to apply the effect to all ML's.
No tag of subject. [5]
article_header_rewrite_rules -= rewrite_article_subject_tag
This means header rewrite rules minus "adding subject tag" operation.
Prepend office# at X-ML-Name:. That is, mlname is changed to office#mlname.
# office#$mlname
outgoing_mail_header_x_ml_name = office#$ml_name
Anybody can post to this ML since customers send mails to this address.
article_post_restrictions = permit_anyone
In this case, anybody including system special accounts e.g. root, postmaster
can post.
Disable almost all filters since a lot of customer messages looks something
wrong.
use_article_filter = no
Change spool type as subdir since the number of articles may become over
million.
spool_type = subdir
Disable command mail.
use_command_mail_function = no
If someboby want to use command mail (e.g. by CGI), we use this variable. It is
recommended to remove proper alias entries if could to ensure the command mail
is prohibited.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: Office (2)
Edit /usr/local/etc/fml/site_default_config.cf to apply the effect to all ML's.
Add uppercase-ed ML name to the article subject tag.
article_subject_tag = (\U$ml_name\E %05d)
For example, an article of support@example.co.jp has the tag
Subject: (SUPPORT 10000)
.
Allow the use of command mail, which comes only from the specific domain (my
domain e.g. example.co.jp). This hook enables it.
$command_verify_request_end_hook = q{
my $cred = $curproc->credential();
my $from = $cred->sender();
unless ($from =~ /\@example\.co\.jp/i) {
$curproc->stop_this_process();
$curproc->logerror("deny command request from $from");
}
};
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 18. Header Rewriting
Header information is stored at FML::Header class object. FML::Header class
inherits Mail::Header. See Mail::Header for method details.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipe's
1. Uppercase the tag in article Subject:
2. Lowercase the tag in article Subject:
1. Uppercase the tag in article Subject:
article_subject_tag = [\U$ml_name\E:%05d]
(available after 2002/10/29 snapshot)
2. Lowercase the tag in article Subject:
article_subject_tag = [\L$ml_name\E:%05d]
(available after 2002/10/29 snapshot)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 19. Extend Command
Case Study: Create Your Own Help Command.
To extend help command of elena ML, create help.pm perl module at
/var/spool/ml/elena/local/lib/FML/Command/User/help.pm
In loading module, libraries under local/ path is preferred. So, this help
command is loaded for help command (FML::Command::User::help).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipes
1. initialize ML by admin command.
2. add or remove a log of user by admin command.
3. send welcome message when "admin add" runs.
4. restrict subscribers.
5. I forget how to use admin command ?
1. initialize ML by admin command.
now allowd. Please use CUI on the mail server host.
2. add or remove a log of user by admin command.
Specific command not yet supported. Use ordinary admin commands.
admin add ..
admin add ..
admin add ..
3. send welcome message when "admin add" runs.
not implemented.
4. restrict subscribers.
not implemented.
5. I forget how to use admin command ?
See fml8 document ;-)
http://www.fml.org/software/fml8/
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 20. Filtering
1. Where the mail is sent back to when filter system rejects ?
2. Reject SPAM messages by using spamassassin.
3. Add X-Spam-Status: Yes header field if spamassassin determines the message
as a spam.
4. How to write a hook to reject a message with danger attachment(s).
1. Where the mail is sent back to when filter system rejects ?
By default, It is defined as
use_article_filter_reject_notice = yes
article_filter_reject_notice_recipient = maintainer sender
When the filter system rejects the request, fml sends back it to both the ML
maintainer and the sender.
To change the recipient to the sender (From: address) only, set
article_filter_reject_notice_recipient = sender
To notify the rejection to both ML maintainer and the sender, set
article_filter_reject_notice_recipient = maintainer sender
To disable notification of rejection, set
use_article_filter_reject_notice = no
2. Reject SPAM messages by using spamassassin.
Case 1: use internal filter.
use_article_spam_filter = yes
article_spam_filter_drivers = spamassassin
Case 2: In this case, fml8 use not spamassassin internal filter but use a hook.
$distribute_verify_request_end_hook = q{
my $spamassassin = '/usr/pkg/bin/spamc -c';
use FileHandle;
my $wh = new FileHandle "| $spamassassin";
if (defined $wh) {
$wh->autoflush(1);
my $msg = $curproc->incoming_message();
$msg->print($wh);
$wh->close();
if ($?) {
$curproc->log("spam: (code = $?)");
$curproc->stop_this_process();
}
}
};
3. Add X-Spam-Status: Yes header field if spamassassin determines the message
as a spam.
$distribute_verify_request_end_hook = q{
my $spamassassin = '/usr/pkg/bin/spamc -c';
use FileHandle;
my $wh = new FileHandle "| $spamassassin";
if (defined $wh) {
$wh->autoflush(1);
my $msg = $curproc->incoming_message();
$msg->print($wh);
$wh->close();
if ($?) {
$curproc->log("spam: (code = $?)");
my $hdr = $curproc->incoming_message_header();
$hdr->add('X-Spam-Status', 'Yes');
}
}
};
This is a little tricky but it works well.
4. How to write a hook to reject a message with danger attachment(s).
fml8 analyzed the incoming message firstly and creates a chain of Mail::Message
objects on memory. It is easy for fml8 to analyze the chain to check the
message content.
The following examples uses hooks. In all cases, if matched, call
stop_this_process() to stop further processing. Pay attension that these
examples do not try to return error messsages.
If you need to return error messages, use reply_message(). It is better not to
return it since this message must be a virus or a spam.
Here is an example to check attachment keywords e.g. .exe in mesages. Before
fml8 2004/12/08 current, it follows:
$distribute_verify_request_start_hook = q{
my $msg = $curproc->incoming_message() || undef;
for (my $m = $msg; $m ; $m = $m->{ next } ) {
my $hs = $m->message_fields() || '';
if ($hs =~ /filename=.*\.(com|vbs|vbe|wsh|wse|js|exe|doc|rtf)/o) {
$curproc->log("attachment \.$1 found");
$curproc->stop_this_process();
}
}
};
After fml8 2004/12/08 current, it follows:
$distribute_verify_request_start_hook = q{
my $msg = $curproc->incoming_message() || undef;
my $list = $msg->message_chain_as_array_ref();
for my $m (@$list) {
my $hs = $m->message_fields() || '';
if ($hs =~ /filename=.*\.(com|vbs|vbe|wsh|wse|js|exe|doc|rtf)/o) {
$curproc->log("[new] attachment \.$1 found");
$curproc->stop_this_process();
}
}
};
Another solution is to trap
Content-Disposition: attachment;
to detect the existence of attachments. Before fml8 2004/12/08 current, it
follows:
$distribute_verify_request_start_hook = q{
my $msg = $curproc->incoming_message() || undef;
for (my $m = $msg; $m ; $m = $m->{ next } ) {
my $hs = $m->message_fields() || '';
if ($hs =~ /Content-Disposition:.*attachment;/o) {
$curproc->log("attachment \.$1 found");
$curproc->stop_this_process();
}
}
};
After fml8 2004/12/08 current, it follows:
$distribute_verify_request_start_hook = q{
my $msg = $curproc->incoming_message() || undef;
my $list = $msg->message_chain_as_array_ref();
for my $m (@$list) {
my $hs = $m->message_fields() || '';
if ($hs =~ /Content-Disposition:.*attachment;/o) {
$curproc->log("[new] attachment \.$1 found");
$curproc->stop_this_process();
}
}
};
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 21. Extend Message
Case Study: Customize Message
Create file at
/var/spool/ml/elena/local/share/message/$language/class
See /usr/local/share/fml/$version/message/$language/class as samples. Copy, cut
and paste one of them :)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 22. Be ML Articles public via WWW
Recipes
1. convert articles to html form after ML runs without html conversion.
2. convert articles to html form for resetting.
3. How to create html archive on a different machine?
1. convert articles to html form after ML runs without html conversion.
use fmlhtmlify command.
Example
% fmlhtmlify /var/spool/ml/elena/spool ~fml/public/fml/mlarchive/DOMAIN/ML
2. convert articles to html form for resetting.
use fmlhtmlify command.
Example
% fmlhtmlify /var/spool/ml/elena/spool ~fml/public/fml/mlarchive/DOMAIN/ML
3. How to create html archive on a different machine?
1. syncrhnize archive by e.g. rsync.
2. set up html converter such as mhonarch on the machine.
3. NFS but pay attension network structure in using NFS seen from Internet.
IV. Operations
This part describes operations.
Table of Contents
23. Logging
24. Back Up Of Configurations
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 23. Logging
See Log
% makefml log ML_NAME
% fml ML_NAME log
shows the latest 30 lines of log.
GUI uses log command.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Show Computer Oriented Log
When not fml program or CGI calls fml8 CUI and such program wants to analyze
the output, you can use use the following option.
% makefml --log-computer-output COMMAND ML_NAME
% fml --log-computer-output ML_NAME COMMAND
It shows the computer oriented log into STDERR channel.
For example
% fml --log-computer-output elena@fml.org list
rudo@nuinui.net
1070109341 info lock channel=recipient_map_modify
1070109342 info unlock channel=recipient_map_modify
This example shows "TIME LOG_LEVEL MESSAGE" style log. It is suitable for
computer proceessing.
The command line option --log-computer-output is same effect as
use_log_computer_output = yes
in config.cf file.
When "use_log_computer_output = yes" specified in config.cf, all programs are
affected. All programs shows the computer oriented log to STDERR. So use of
command line option is recommended.
We should use perl module which holds a set of functions. In this case, the
print out engine is the class called as FML::Log::Print::Simple. The output
style is contolled by $log_computer_output_engine in config.cf file.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipes
1. show fml error log of yesterday.
2. See old logs.
3. Centralize log messages.
4. extract specific log messages in monitoring.
5. extrace the specific log messages with coping it.
6. Expire old log files.
1. show fml error log of yesterday.
daily.pl of fml4 is not implemented yet.
Currently use grep to parse the log file.
2. See old logs.
fml8 appends log messages continuously into the log file at $ml_home_directory
by default. All log messages exist in it.
On the other hand, Unix log expires. So you cannot trace too lod messages.
Please tune parameters of expiration tools e.g. newsyslog which program differs
from unix variants to variants to save log messages in at least 3 months.
3. Centralize log messages.
Unix uses syslog mechanism. To redirect all messages to /var/log/messages, set
the following:
[/etc/syslog.conf]
*.* /var/log/messages
Also, fml8 can use syslog mechanism.
[/var/spool/ml/elena/config.cf]
log_type = syslog
To use these configuration, all messages are centralized to /var/log/messages
file.
4. extract specific log messages in monitoring.
% tail -F /var/spool/ml/elena/log | grep 'PATTERN'
5. extrace the specific log messages with coping it.
% tail -F /var/spool/ml/elena/log | grep 'PATTERN' | tee FILE
6. Expire old log files.
Newsyslog mechanism provided by fml4 is not implemented.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 24. Back Up Of Configurations
To preserve fml8 configurations, back up the following two directories:
/usr/local/etc/fml/
$ml_home_prefix (e.g. /var/spool/ml/, domain specific)
Attention: These directories holds all articles, log files and others et.al.
It is better to back up MTA configurations, too. For example, /etc/postfix in
the case of Postfix.
In summary, the following three (generally speaking 2 + number of domains fml8
operatates) are targets.
/etc/postfix/
/usr/local/etc/fml/
$ml_home_prefix (e.g. /var/spool/ml/)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Back Up fml8 Configurations
To back up fml8 configurations, it is enough to back up the following two
directories. But it is too large since they contains articles, log files and
all contents.
/usr/local/etc/fml/
$ml_home_prefix (e.g. /var/spool/ml/, domain specific)
The hard disk is cheap. So it is safe to preserve all contents as could as
possible.
If you preserve only configuratoins, it is enough to back up the following
files.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Configuration Files To Back Up
It is useful to make a list of targets based on the file naming convension.
In the case of fml8, a file with .cf extension is a configuration file. The
format of .cf file is
key = value
style. This style configuration files follow
/usr/local/etc/fml/main.cf
/usr/local/etc/fml/site_default_config.cf
/EACH_ML_HOME_DIRECTORY/config.cf
et.al.
Configuration files with other syntax are
/usr/local/etc/fml/mime_component_filter
/usr/local/etc/fml/ml_home_prefix
This type of files are space separeted.
/usr/local/etc/fml/ contains only configuration files. So back up all under
them.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Address List To Back Up
Lists of mail addresses are
/ML_HOME_DIRECTORY/members*
/ML_HOME_DIRECTORY/recipients*
Article delivery uses both recipients and members. For other roles, fml8 uses
members-$role and recipients-$role. So, back up all members* and recipients*
files.
Remote administration by command mail (admin command mail) uses the following
password files
/ML_HOME_DIRECTORY/etc/passwd-$role
. Back up /ML_HOME_DIRECTORY/etc/ too.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Back Up All Files Except For Some Large Directories.
It is easy to back up all files except for the following large directories.
They contains large data or temporary files.
spool articles
tmp temporary files
var useful data
If you use rsync, rsync --exclude is useful.
V. Troubleshoot
This part describes how to shoot troubles.
Table of Contents
25. Troubleshoot
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 25. Troubleshoot
1. I want to know fml version.
2. Check Postfix version.
3. Check Sendmail version.
4. List up pre-defined addresses on this host.
5. List up defined aliases on this host
6. List up all ML addresses containing the specific member address.
1. I want to know fml version.
[Example: in the case of "test" ML]
% fmlconf test fml_version
fml_version = fml-devel current-20021029
2. Check Postfix version.
% postconf mail_version
3. Check Sendmail version.
% echo '$v' | sendmail -bt
4. List up pre-defined addresses on this host.
"fmladdr" command lists up users defined at both /etc/passwd and aliases.
% fmladdr
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│The difference between "fmladdr" and "fmlalias" is whether it contains users │
│defined at /etc/passwd or not. "fmladdr" contains it but fmlalias not. │
│"fmlalias" lists up only users defined at aliases. │
└─────────────────────────────────────────────────────────────────────────────┘
5. List up defined aliases on this host
Run "fmlalias". It shows all addresses defined in aliases files.
% fmlalias
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│The difference between "fmladdr" and "fmlalias" is whether it contains users │
│defined at /etc/passwd or not. "fmladdr" contains it but fmlalias not. │
│"fmlalias" lists up only users defined at aliases. │
└─────────────────────────────────────────────────────────────────────────────┘
6. List up all ML addresses containing the specific member address.
For each ML, run the following command:
% fml ML list |grep ADDRESS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
When The File System Error Ocuurs
When the file system error occurs, fml8 exit abnormally to make MTA re-deliver
the message again to fml8 or fml8 re-delivers it by itself without saving the
article on the file system. So fml8 do not lost received messages whereas both
log or summary file lack something.
Describe below what happans when the file system error occurs in the delivery
process.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
When Passed From MTA MTA To fml8
fml8 reads a message and writes it into the disk once. If succeeded, it
processes more. If failed, fml8 exits abnormally as exit(EX_TEMPFAIL) for MTA
to re-deliver it. See the Section called Incoming Queuing in Chapter 31 for
more details.
In this case, incoming message queue may have a incomplete message. fml8 tries
to remove it in abnormal exit. Even if failed, the queue management system
removes it later.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
If Updating Of The Article Sequence Number Failed
In normal case, fml8 updates the article sequence number and re-reads it and
compares it again. If the check fails, fml8 exit(EX_TEMPFAIL) for MTA to
re-deliver it.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Caution │
├─────────────────────────────────────────────────────────────────────────────┤
│The article sequence number updated. After that, fml8 does not do exit │
│(EX_TEMPFAIL) to deliver the message on memory as could as possible. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
When Saving Of Article Failed
┌─────────────────────────────────────────────────────────────────────────────┐
│ Caution │
├─────────────────────────────────────────────────────────────────────────────┤
│In this stage, the article sequence has been updated. │
└─────────────────────────────────────────────────────────────────────────────┘
In this case, fml8 does not create a new article file but the original message
is already on the disk. The header of the article differs from the original one
but the body content is same. So fml8 tries to link(2) the original mail in the
incoming queue to the article file to save the content. [6]
fml8 tries to deliver the message on memory.
If the delivery process exits abnormally, distribution of article ends
incompletely since fml8 can not use outgoing queue due to file system error.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Delivery Process
fml8 saves the message into the outgoing queue, after succeeded, the delivery
process runs.
When fml8 fails to write the outgoing queue, fml8 exits incompletely.
See the Section called fml Sends Back A Mail Message in Chapter 31 for more
details.
VI. fml8 Design
This part describes the design policy of fml.
Table of Contents
26. [LOG] Original Idea Of fml8 Project
27. Programming Style
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 26. [LOG] Original Idea Of fml8 Project
The Original Idea Of fml8 (fml-devel) Project
fml8 project called as fml-devel also is refactoring of fml4 mailing list
driver.
See http://www.fml.org/software/fml8/ for more details on the furure plan,
design and implementation of fml-current.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Details Of Idea
• simple implementation of configuration files and menu.
• perl module (> perl 5.00504 )
• support more integrated CUI (makefml) and GUI.
• Separation
□ easy upgrade
□ use CPAN modules as could as possible.
□ 3rd party directory
• abstracted IO layer
□ file (implemented)
□ /etc/group (implemented)
□ NIS (implemented)
□ SQL (MySQL implemetned)
□ LDAP
• IPv4/IPv6 ready (implemented)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Refactoring
Table 26-1. refactoring TODO
┌─────────┬──────────────────────────────────────┬────────────────────────────┐
│ status │ entry │ detail │
├─────────┼──────────────────────────────────────┼────────────────────────────┤
│done. │license │perl conformance │
├─────────┼──────────────────────────────────────┼────────────────────────────┤
│ │ │fml4 to fml8 is similar to │
│underway.│image │sendmail to postfix. support│
│ │ │configuration converter. │
├─────────┼──────────────────────────────────────┼────────────────────────────┤
│done. │wrapper (separation layer). │separation layer for upgrade│
│ │ │/downgrade, debug. │
├─────────┼──────────────────────────────────────┼────────────────────────────┤
│ │ │use CPAN modules as could as│
│ │adapter │possible. prepare adapter │
│ │ │layer in using CPAM module. │
├─────────┼──────────────────────────────────────┼────────────────────────────┤
│ │new single configuration file format. │ │
├─────────┼──────────────────────────────────────┼────────────────────────────┤
│ │rule of variable naming convension │use_XXX, XXX_TYPet ... │
│ │ │prohibit NOT_USE style. │
├─────────┼──────────────────────────────────────┼────────────────────────────┤
│ │function name convension use X11 style│use Perl Cookbook style ? │
│ │for main:: space. use method style for│e.g. "MemberP() -> IsMember │
│ │method. not use Lisp like style (-p). │()" │
├─────────┼──────────────────────────────────────┼────────────────────────────┤
│done. │queue manager │re-delivery by itself │
├─────────┼──────────────────────────────────────┼────────────────────────────┤
│ │tools │not use BSD make. │
└─────────┴──────────────────────────────────────┴────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Architecture image
[architectu]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
release engineering
Not be an architect nor developer. Not too abstractive and not too object
oriented. Be between them. Feedback in one month to manage project and code
review.
Table 26-2. release interval
┌────────────────────┬────────────────────────────────────────────────────────┐
│ days in one month │ content │
├────────────────────┼────────────────────────────────────────────────────────┤
│the first 4 - 5 days│manage project. apply at least 20 % of the project to │
│ │this stage. │
├────────────────────┼────────────────────────────────────────────────────────┤
│2 - 3 weeks │coding. │
├────────────────────┼────────────────────────────────────────────────────────┤
│the last week │code review, document review │
├────────────────────┼────────────────────────────────────────────────────────┤
│at the last of the │release a snapshot. alpha-0, alpha-1, alpha-2, ... │
│month │ │
└────────────────────┴────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 27. Programming Style
This chapter describes a few topics on programming technique.
See FNF on FML.ORG programming style.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Variable Naming Convension
It is ambiguous where "default" word in the variable name is proper. The left
side of the naming string is expected to show large scale such as CLASS.
Let us consider article related variables. We expect $article_* variables for
them.
It seems better to use CLASS_default_XXX syntax not default_XXX.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Structure Of Variable Naming
It seems proper to use systematic naming convension. For it, we define base
class or inheritence of naming syntax.
Consider class names. For example, "mail" implies messsage/rfc822 format text.
The input into fml system is a mail, outgoing one is a mail. The variable are
sub class of "mail" object, so the name is unified as PREFIX_mail_ATTRIBUTE
style.
mail_XXX
mail_default_XXX
use_incoming_mail_XXX
incoming_mail_XXX
use_outgoing_mail_XXX
outgoing_mail_XXX
use_report_mail_XXX
report_mail_XXX
Other example (header):
header_XXX
header_default_XXX
article_header_XXX
use_article_header_XXX
command_mail_header_XXX
use_command_mail_header_XXX
We can describe structure of class as follows:
command {
SOMETHING_command
admin_command
}
directory {
XXX_directory
}
file {
template_file
}
mail {
incoming_mail
outgoing_mail
report_mail
}
message {
reply_message
}
article {
article_digest (not use digest to show digest of article)
article_spool (not use spool to show spool of article)
}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Example: Standard Pattern (e.g. log.cf lock.cf)
use_VARIABLE = yes or no
# append _dir for directory.
VARIABLE_dir = STRING
# append _file for file.
VARIABLE_file = STRING
VARIABLE_type = STRING
VARIABLE_format = STRING
VARIABLE_format_type = STRING
VARIABLE_limit = STRING (NUMBER but STRING)
VARIABLE_upper_limit = STRING (NUMBER but STRING)
VARIABLE_lower_limit = STRING (NUMBER but STRING)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Example 2: (e.g. acl.cf)
VARIABLE_restrictions = reject_ATTRIBUTE1
check_ATTRIBUTE2
permit_XXX
ATTRIBUTE1 = PATTERN1
PATTERN2
...
ATTRIBUTE2 = var1
var2
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Example 3: (program name prefix)
PROGRAM_VARIABLE_ATTRIBUTE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
A Few Topics On Design And Coding Style
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│See also FNF on style. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
A Few Cautions
Apply quotemeta() for search key.
Use access method for object not handle directly within objects. Example: To
access to main.cf object, not use
$curproc->{ ... }->{ main_cf }
instead use
$curproc->main_cf();
style.
It is better not to use @EXPORT and @EXPORT_OK.
How depth of classes is allowed ? two such as String::is_japanese_string() ? At
least 3, I think.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Programming Style Original Idea
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│Here is the original idea log. │
└─────────────────────────────────────────────────────────────────────────────┘
• We can use polymorphism in perl. Use it and object composition instaed of
multiple inheritence.
• Perl 5's OOP is not OOP. Do not depent on it. It just provides simple use
of variable since variable itself knows the home (object / package).
• Interface for re-use and abstraction should be OOP style.
• We want to use OOP style in using Perl 5 but take care for OOP-ism. Balance
is important.
• not use deep inheritence.
Programs in libexec/ describes the basic flow of processes. They may be allowd
to be structured not object oriented programming
Polymorphism and re-use is important especially in sub-classes.
VII. fml8 Internals
This part describles the fml internals for developers.
Table of Contents
28. fml8 Boot Loader To Resolve Version Dependence Dynamically
29. Configuration File: config.cf
30. Create A New Program
31. fml8 Mail Delivery System
32. Digest Delivery
33. Language Preference In Processing
34. Manipulate Message (Mail Message)
35. Filter
36. Subscribe / Unsubscribe
37. Command (Command Mail, CUI And GUI)
38. Internal Of CGI Process
39. Directory
40. Restrict Input Data
41. User Authentication
42. Hook
43. Virtual Domain
44. Errormail Analyzer (libexec/error)
45. IO Interface And Operations
46. Lock
47. Database Related Modules
48. Database Management System
49. Convert Another ML System To fml8
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 28. fml8 Boot Loader To Resolve Version Dependence Dynamically
fml8 provides a boot loader to resolve version dependence dynamically. For
example, the loader boot straps fml8 as follows:
fml (libexec/distribute) boots like this ...
functions class
----------------------------------------
main::Bootstrap() libexec/loader
|
V
main::Bootstrap2() FML::Process::Switch
|
V
ProcessSwitch() FML::Process::Switch
|
|
| switch to ($obj = FML::Process:Distribute)
|
V
ProcessStart($obj,$args) FML::Process::Flow
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case: Distribution
fml8 loader boot straps like this in the case of distribution.
/usr/local/libexec/fml/distributre (is same as /usr/local/libexec/fml/loader in
fact) reads /usr/local/etc/fml/main.cf and resolvers the version it should use
from $fml_version variable. Let $fml_version current-20010501. The loader uses
library perl modules under /usr/local/lib/fml/current-20010501/.
The loader resets @INC (perl include path). It loads FML::Process::Switch and
checks $0 (program name in process table). The loader resolves from the name
that the role is distribution. It loads FML::Process::Distribute and switches
to the class.
The relation between program name and class (perl module) is defined at /usr/
local/etc/fml/defaults/$fml_version/modules file.
FML::Process::Flow::ProcessStart() function drives these sequential steps.
ProcessStart() takes FML::Process::Distribute object as an argument and drives
the object.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FML::Process:: Class Structure
FML::Process::Distribute >-|
FML::Process::Command >-|-- FML::Process::Kernel
FML::Process::Mead >-| |
|-use-a FML::Parse
|-use-a FML::Config
|-use-a FML::Log
|-use-a ... SOMETHING ...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Modules In Process Execution
• libexec/loader (wrapper): executes Bootstrap() runction. libexec/distribute
et.al. is a symlink(2) to this loader. See under /usr/local/libexec/fml/
path.
•
□ reads /usr/local/etc/fml/main.cf and resolves $fml_version. reset @INC
by main.cf value. Since default_config.cf is version dependent, the
loader should evaluate the file before it reads ML specific
configuration files.
□ Evaluate @ARGV and resolves which ML specific configuration files we
need to load.
□ load FML::Process::Switch class which is also version dependent.
☆ The loader executes Bootstrap2() and ProcessSwitch() to switch the
context to each one such as distribution, command mail et.al. In
this time, the loader knows the role from $0 process name.
☆ Exapmle of Polymorphyism: dynamic binding of module and creation of
process object in starting the process. FML::Process::Flow
describes the flow of process like this:
$process = new FML::Process::SOMETHING;
$process->prepare($args);
$process->verify_request($args);
$process->run($args);
$process->finish($args);
Each process should probide proper methods under FML::Process::
class.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Discussion: Where Function Should Resolve $ml_name And $ml_domain.
Currently fml8 resolves them in prepare() under FML::Process:: classes.
Here is a part of background idea.
main::Bootstrap()
resoles $fml_version based on main.cf information.
pass hints to some processes e.g. CGI.
CGI only
it should ignore invalid input.
$ml_name $and ml_domain is hard-coded in cgi scripts.
main::Bootstrap2()
ProcessSwitch()
resolves the module, configuration files, library path and @INC.
pass hints to some processes e.g. CGI.
CGI only
ProcessStart($obj, $args)
main process starts
new
prepare
resoles $ml_name and $ml_domain.
parse input from CGI using hints.
determine ml specific configuration files.
parse incoming message.
parse command line arguments.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 29. Configuration File: config.cf
ML Specific Configuration File: config.cf
You can customize each ML differently. fml4 and fml8 are same in this point.
In the case of fml4, there is a config.ph in ML home directory, $DIR (e.g. /var
/spool/ml). This "config.ph" file is a perl script.
There is one configuration file (config.cf) in fml8, too. But the format is
different. The format is like this:
variable = value
. It is similar to postfix or .ini files.
It is similar to a perl module. You can write perl codes after =cut line.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Problems in fml4
The configuration file of fml4, config.ph, is a perl script. Perl script is
good for human editing but it is not suitable for configuration tools. It
implies it is difficult to prepare configuration tools for config.ph. So, in
fml4 two files, cf and config.ph are used. [7]
The use of cf is suitable for configuration tools but introduces another
difficulty such as inconsistency between cf and config.ph since human may edit
config.ph but forgets editing cf. So, fml8 introduces only one configuration
file. It is a new format which is similar to Postfix main.cf.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
config.cf Format
The format of "config.cf" is "variable = value syntax". If plural values are
required, space or "\n\s" is a separator.
variable = value
valiable = value1 value2 value3
variable = value1
value2
value3
The syntax of files with the suffix .cf e.g. /etc/fml/main.cf ,
default_config.cf, is same.
$variable at the right hand is expanded. For example,
a = value1
b = $a/value2
is expanded to
a = value1
b = value1/value2
.
The variable expansion is done at the last. So, the following definitions
a = value1
b = $a/value2/$c
c = value3
a = value4
are expaned to
b = valu4/value2/value3
since the last $a overwrites the previous one.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Extension To Postfix Style
variable += value
variable -= value
is used for adding or removing the specific value.
x = a b c d
x -= b
becoms
x = a c d
.
Another case,
x = a b c d
x += e
becomes
x = a b c d e
.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Overload Variables In config.cf
Overloading of .cf files is possible. It overwrites variables.
It enables separation of configuration files e.g. the default file, the host
specific file, the domain specific file, and ML specific file.
fml8 reads these files sequentially. At the last, fml8 expands variables when
variable reading is requested.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Modifying/Adding Variables After All Configuration Files Have Been Loaded.
The variable expansion is always done. If some value with $ is added to some
variable, the next reading operation [8] causes variable expansion.
For example, set
$config->{ key } = '$ml_home_dir/value';
here. The next read operation e.g.
$config->{ another_key }
(where the key is any) evaluates the variable expansion.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Internal Of Variable Expansion
%_fml_config hash holds pairs of key and value. The format is $dir/$file in
this hash, it is not expanded. get() returns the value of %_fml_config_result.
The value in this hash is after the variable expansion. The variable is
expanded in calling get() method.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Variable List (Alphabetical Order)
Table 29-1. table description
┌─────────────────────────────────────────────────┬───────────────────────┬─────────────────────────────────────┐
│ variable name │ descrition │ default value(s) │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │domain matching level │ │
│address_compare_function_domain_matching_level │in comparing mail │3 │
│ │addresses │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │case insensitive │ │
│address_compare_function_type │comparison of user part│user_part_case_insensitive │
│ │of mail address. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │base directory which │ │
│admin_cgi_base_dir │locates .cgi for this │$cgi_base_dir/admin │
│ │domain. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │gpg configurations for │ │
│admin_command_mail_auth_gpg_config_dir │admin commnad mail │$etc_dir/gpg-admin-command-mail-auth │
│ │authentication. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│admin_command_mail_auth_gpg_config_dir_alias │conventional naming │$etc_dir/gpg-admin │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │pgp configurations for │ │
│admin_command_mail_auth_pgp_config_dir │admin commnad mail │$etc_dir/pgp-admin-command-mail-auth │
│ │authentication. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│admin_command_mail_auth_pgp_config_dir_alias │conventional naming │$etc_dir/pgp-admin │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│admin_command_mail_restrictions │restrictions for admin │reject_system_special_accounts │
│ │command mail │check_admin_member_password reject │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│admin_member_maps │all remote │$primary_admin_member_map │
│ │administrator lists │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│admin_member_password_maps │all password files. │$primary_admin_member_password_map │
│ │ │file:$etc_dir/passwd │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│admin_recipient_maps │dummy │$primary_admin_recipient_map │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│anonymous_cgi_base_dir │top level directory for│$fml_owner_home_dir/public_html/ │
│ │anonymous cgi scripts. │cgi-bin/anonymous │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │expire limit of │ │
│anonymous_cgi_expire_limit │anonymous CGI session │15m │
│ │ID. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_delivery_transport │specify transport for │smtp │
│ │article delivery. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_expire_limit │how old article to be │90d │
│ │removed │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_filter_reject_notice_data_type │how fml refer the │string │
│ │rejeced message. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_filter_reject_notice_recipients │recipients to inform │maintainer sender │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_header_filter_rules │header filter rules. │check_message_id check_date permit │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_header_list_help │list-help of article │$mail_header_default_list_help │
│ │header. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_header_list_id │list-id of article │$mail_header_default_list_id │
│ │header. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_header_list_owner │list-owner of article │$mail_header_default_list_owner │
│ │header. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_header_list_post │list-post of article │$mail_header_default_list_post │
│ │header. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_header_list_software │default list-software │$mail_header_default_list_software │
│ │header field. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_header_list_subscribe │list-subscribe of │$mail_header_default_list_subscribe │
│ │article header. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_header_list_unsubscribe │list-unsubscribe of │$mail_header_default_list_unsubscribe│
│ │article header. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │ │delete_unsafe_header_fields │
│ │ │rewrite_article_subject_tag │
│ │ │rewrite_reply_to rewrite_errors_to │
│ │ │rewrite_stardate rewrite_precedence │
│article_header_rewrite_rules │header rewriting rules │rewrite_message_id add_software_info │
│ │ │add_fml_ml_name │
│ │ │add_fml_traditional_article_id │
│ │ │add_fml_article_id add_x_sequence │
│ │ │add_rfc2369 │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_message_id_cache_dir │article Message-ID │$db_dir/article_message_id │
│ │cache directory │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_mime_component_filter_rules │file of filter rules │$fml_config_dir/mime_component_filter│
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_non_mime_filter_rules │dummy │permit │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │permit post from anyone│ │
│article_post_article_thread_lifetime │if the posted message │86400 │
│ │follows │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_post_auth_gpg_config_dir │gpg configurations for │$etc_dir/gpg-article-post-auth │
│ │article authentication.│ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_post_auth_pgp_config_dir │pgp configurations for │$etc_dir/pgp-article-post-auth │
│ │article authentication.│ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_post_encrypt_gpg_config_dir │gpg configurations for │$etc_dir/gpg-article-post-encrypt │
│ │article encryption. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_post_encrypt_pgp_config_dir │pgp configurations for │$etc_dir/pgp-article-post-encrypt │
│ │article encryption. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_post_restrictions │restrictions for post │isolate_system_special_accounts │
│ │ │permit_member_maps isolate │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_post_restrictions_reject_notice_data_type│how to inform the │string │
│ │rejected message │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_sequence_file │file to store sequence │$sequence_file │
│ │number │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_size_filter_rules │size based filter │check_header_size check_body_size │
│ │rules. │permit │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_spam_filter_bogofilter_options │"-e" implies embedded │-e │
│ │mode. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_spam_filter_drivers │external spam checker. │bogofilter │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_spam_filter_functions │list up driver names │bogofilter │
│ │used as spam checker. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_spam_filter_rules │action if the message │header_rewrite │
│ │looks a spam. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │exit non-zero status │ │
│article_spam_filter_spamassassin_options │code when spam caught │-e │
│ │if "-e" specified. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_spam_filter_spamc_options │spamc optoins. "-c" │-c │
│ │means check only. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_subject_tag │Subject: tag. │[$ml_name:%05d] │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_summary_file │article summary file. │$ml_home_dir/summary │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │save the first N bytes │ │
│article_summary_file_format_address_length │of the address in │15 │
│ │summary. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_summary_file_format_style │format style. │fml4_compatible │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │ │reject_not_iso2022jp_japanese_string │
│ │ │reject_null_mail_body │
│ │filter rules of text/ │reject_one_line_message │
│article_text_plain_filter_rules │plain filter. │reject_old_fml_command_syntax │
│ │ │reject_invalid_fml_command_syntax │
│ │ │reject_japanese_command_syntax │
│ │ │reject_ms_guid permit │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_thread_outline_greeting_en │greeting prepended to │[outline of this thread] │
│ │thread outline │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_thread_outline_greeting_ja │ ɤγ Ϥޤ │[ ɤΤ 餹 ] │
│ │ˤĤ 밧 │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_thread_outline_rules │where should we add │add_outline_to_header │
│ │thread outline ? │append_outline_to_body │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_virus_filter_clamav_options │--mbox needed for mail │--quiet --mbox │
│ │files. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_virus_filter_drivers │external virus checker.│clamscan │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_virus_filter_functions │list up driver names │clamav │
│ │used as virus checker. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│article_virus_filter_rules │action if virus found. │reject │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │base directory which │$fml_owner_home_dir/public_html/ │
│cgi_base_dir │locates .cgi for this │cgi-bin/fml/$ml_domain │
│ │domain. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│cgi_charset_en │cgi charset in English │us-ascii │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│cgi_charset_ja │cgi charset in Japanese│euc-jp │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│cgi_default_charset │default charset │us-ascii │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│cgi_default_language │language mode of CGI (!│english │
│ │= charset) │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│cgi_language_select_list │available language mode│english japanese │
│ │in CGI │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│cgi_main_menu_color │default bgcolor │#FFFFFF │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │choise of address list │ │
│cgi_menu_address_map_select_list │types in CGI │member recipient admin_member │
│ │operations. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │default value of list │ │
│cgi_menu_default_address_map │types in CGI │recipient │
│ │operations. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│cgi_navigation_bar_color │default bgcolor in │#FFFFFF │
│ │navigation menu │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│chaddr_command_auth_type │use comnfirmation in │confirmation │
│ │chaddr command ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │operate action │ │
│chaddr_command_operation_mode │automatically or │automatic │
│ │manually by maintainer │ │
│ │? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │gpg configurations for │ │
│command_mail_auth_gpg_config_dir │(user) commnad mail │$etc_dir/gpg-command-mail-auth │
│ │authentication. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │pgp configurations for │ │
│command_mail_auth_pgp_config_dir │(user) commnad mail │$etc_dir/pgp-command-mail-auth │
│ │authentication. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│command_mail_filter_reject_notice_data_type │how fml refer the │string │
│ │rejeced message. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│command_mail_filter_reject_notice_recipients │recipients to inform │maintainer sender │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │the numfer of │ │
│command_mail_invalid_command_limit │ineffective commands in│100 │
│ │one command mail. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│command_mail_line_length_limit │maximum length of one │128 │
│ │command line. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│command_mail_reply_prompt │command prompt in │>>> │
│ │message reply │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │restrictions for │isolate_system_special_accounts │
│command_mail_restrictions │command mail │permit_anonymous_command │
│ │ │permit_user_command isolate │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │size based filter │check_header_size check_body_size │
│command_mail_size_filter_rules │rules. │check_command_limit │
│ │ │check_line_length_limit permit │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │the numfer of effective│ │
│command_mail_valid_command_limit │commands in one command│100 │
│ │mail. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│confirm_command_expire_limit │how long confirmation │14d │
│ │is effective ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│confirm_command_prefix │special command name │confirm │
│ │used as confirmation │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │restrict "who can │ │
│createonpost_newml_maps │create a new ML". PCRE │pcre:$ml_home_dir/newml.allow.pcre │
│ │is available. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │ │reject_system_special_accounts │
│ │ │reject_errormail │
│createonpost_newml_restrictions │Who can create a new │reject_fml8_managed_address │
│ │CREATE-ON-POST ML ? │reject_createonpost_domain │
│ │ │permit_createonpost_maintainer_maps │
│ │ │permit_ml_domain │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │restrict "who can │ │
│createonpost_sender_maps │post". PCRE is │pcre:$ml_home_dir/sender.allow.pcre │
│ │available. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │ │reject_system_special_accounts │
│ │ │reject_errormail │
│createonpost_sender_restrictions │who can post for │reject_list_header_field │
│ │CREATE-ON-POST ML ? │reject_fml8_managed_address │
│ │ │reject_createonpost_domain │
│ │ │permit_anyone │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │restrict "who can │pcre:$ml_home_dir/ │
│createonpost_subscribe_maps │subscribe". PCRE is │subscribe.allow.pcre │
│ │available. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │ │reject_system_special_accounts │
│ │ │reject_errormail │
│createonpost_subscribe_restrictions │who can subscribe ? │reject_fml8_managed_address │
│ │ │reject_createonpost_domain │
│ │ │permit_anyone │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│db_dir │directoy to hold │$var_dir/db │
│ │several data files │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│default_mail_body_size_limit │body size limit │10240000 │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│default_mail_header_size_limit │header size limit │102400 │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│deny_file │deny file │$ml_home_dir/deny │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│digest_header_rewrite_rules │digest article header │add_software_info add_rfc2369 │
│ │rewrite rules │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│digest_member_maps │dummy │$primary_member_maps │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│digest_recipient_maps │all maps of digest │$primary_digest_recipient_map │
│ │recipients. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│digest_sequence_file │file to store the last │$ml_home_dir/seq-digest │
│ │sequence to deliver │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│directory_default_mode │default mode in │0755 │
│ │creating directory. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│domain_config_base_dir │system data directory │$ml_home_prefix/etc │
│ │provided by fml │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│domain_exim_config_dir │directory to hold exim │$domain_config_base_dir/exim │
│ │specific config files. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│domain_local_dir │domian local directory.│$ml_home_prefix │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│domain_local_log_file │domin local log file. │$domain_local_dir/@log@ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│domain_local_tmp_dir │domian local temporary │$ml_home_prefix/@tmp@ │
│ │directory. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│domain_mail_config_dir │directory to hold │$domain_config_base_dir/mail │
│ │config files for MTA │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │directory to hold │ │
│domain_postfix_config_dir │postfix specific config│$domain_config_base_dir/postfix │
│ │files. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │directory to hold │ │
│domain_procmail_config_dir │procmail specific │$domain_config_base_dir/procmail │
│ │config files. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│domain_qmail_config_dir │directory to hold qmail│$domain_config_base_dir/qmail │
│ │specific config files. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │directory to hold │ │
│domain_sendmail_config_dir │sendmail specific │$domain_config_base_dir/sendmail │
│ │config files. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│error_mail_analyzer_cache_dir │directory to cache │$db_dir/error │
│ │error messages. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│error_mail_analyzer_cache_mode │mode of cache │temporal │
│ │expiration │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│error_mail_analyzer_cache_size │cache size. │14 │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│error_mail_analyzer_cache_type │module as cache engine │File::CacheDir │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │function in │ │
│error_mail_analyzer_function │FML::Error::Analyze to │histgram │
│ │analyze. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│error_mail_analyzer_function_select_list │functions defined in │simple_count histgram │
│ │FML::Error::Analyze │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │error limit in using │ │
│error_mail_analyzer_simple_count_limit │simple_count as anlyzer│5 │
│ │function. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│etc_dir │etc directory │$ml_home_dir/etc │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│event_queue_dir │event queue directory │$var_dir/event/queue │
│ │for scheduler │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │password to fetch │ │
│fetchfml_article_post_password │article messages for │******** │
│ │$ml_name ML │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │username to fetch │ │
│fetchfml_article_post_user │article messages for │$ml_name │
│ │$ml_name ML │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │password to fetch │ │
│fetchfml_command_mail_password │command messages for │******** │
│ │$ml_name ML │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │username to fetch │ │
│fetchfml_command_mail_user │command messages for │$ml_name-ctl │
│ │$ml_name ML │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │password to fetch error│ │
│fetchfml_error_mail_analyzer_password │messages for $ml_name │******** │
│ │ML │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │username to fetch error│ │
│fetchfml_error_mail_analyzer_user │messages for $ml_name │$ml_name-admin │
│ │ML │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│fetchfml_fetch_protocol │protocol to fetch │pop3 │
│ │messages. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│fetchfml_imap_servers │imap servers fetchfml │localhost │
│ │process uses. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│fetchfml_pop_servers │pop servers fetchfml │localhost │
│ │process uses. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │queue_dir fetchfml uses│ │
│fetchfml_queue_dir │as temporary incoming │$var_dir/mail/queue-fetchfml │
│ │queue │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│file_default_mode │default mode in │0600 │
│ │creating file │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │maximu number of │ │
│get_command_request_limit │request in get command │100 │
│ │(s) in one mail. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│guide_file │guide file │$ml_home_dir/guide │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│help_file │help file │$ml_home_dir/help │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│html_archive_dir │html archive directory │$fml_owner_home_dir/public_html/fml/ │
│ │of the specific ML. │mlarchive/$ml_domain/$ml_name │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│html_tmp_base_url │temporary url base for │/~$fml_owner/fml/tmp │
│ │CGI │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│html_tmp_dir │temporary directory for│$fml_owner_home_dir/public_html/fml/ │
│ │CGI │tmp │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │maximum size limit of │ │
│incoming_article_body_size_limit │article body passed │$default_mail_body_size_limit │
│ │from MTA. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │maximum size limit of │ │
│incoming_article_header_size_limit │article header passed │$default_mail_header_size_limit │
│ │from MTA. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │maximum size limit of │ │
│incoming_command_mail_body_size_limit │article body passed │$default_mail_body_size_limit │
│ │from MTA. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │maximum size limit of │ │
│incoming_command_mail_header_size_limit │article header passed │$default_mail_header_size_limit │
│ │from MTA. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│incoming_mail_body_checksum_cache_dir │Message-ID cache │$db_dir/body_checksum │
│ │directory │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│incoming_mail_body_loop_check_rules │body loop check rules │check_body_checksum │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│incoming_mail_cache_dir │incoming mail queue │$var_dir/mail/incoming │
│ │directory │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│incoming_mail_cache_size │the maximum number of │128 │
│ │cached incoming mails │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│incoming_mail_envelope_loop_check_rules │envelope based loop │check_envelope_sender │
│ │check rules │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│incoming_mail_header_loop_check_rules │loop check rules │check_message_id check_x_ml_info │
│ │ │check_list_post │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│isolated_queue_dir │top level directory to │$var_dir/mail/queue-isolated │
│ │hold isolated messages │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│isolated_queue_expire_limit │expire messages in the │14d │
│ │queue after this limit.│ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ldap_base_dn │base DN to contact in │dc=$ml_name, dc=fml, dc=org │
│ │modify, search et.al. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ldap_bind_dn │DN to bind. │dc=fml, dc=org │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ldap_query_add_as_ldif │attributes to add into │fmlrecipient:&address fmlmember:& │
│ │$ldap_base_dn entry. │address │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │attributes to remove │fmlrecipient:&address fmlmember:& │
│ldap_query_delete_as_ldif │from $ldap_base_dn │address │
│ │entry. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ldap_user │dummy │fml │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│list_addresses │addresses fml uses: │$maintainer $article_post_address │
│ │e.g. elena, elena-ctl │$command_mail_address │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│list_command_default_maps │default map to show by │$recipient_maps │
│ │list command. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│listinfo_base_dir │base directory for ML │$fml_owner_home_dir/public_html/fml/ │
│ │information │listinfo │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│listinfo_dir │directory for ML │$listinfo_base_dir/$ml_domain/ │
│ │information │$ml_name │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│listinfo_template_base_dir │listinfo template │$fml_share_dir/listinfo │
│ │template dir │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│listinfo_template_dir │listinfo template │$fml_share_dir/listinfo/ │
│ │ │$template_file_charset │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│lock_dir │directory where lock │$var_dir/lock │
│ │files are created. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│lock_file │giant lock file name │$lock_dir/giantlock │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│lock_type │lock algorithm type │flock │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │show the last N lines │ │
│log_command_tail_starting_location │of log file where N == │100 │
│ │100. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│log_computer_output_engine │specify perl module for│FML::Log::Print::Simple │
│ │output engine. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│log_dir │log dir │$var_dir/log │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│log_file │log file. │$ml_home_dir/log │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│log_format_type │log message format │process[pid] │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │number of archive files│ │
│log_rotate_archive_file_total │to be kept besides the │7 │
│ │log │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │The interval field │ │
│log_rotate_interval │specifies the time │86400 │
│ │separation │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│log_rotate_policy │log rotation policy. │size │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│log_rotate_size_limit │rotate log if the size │300000 │
│ │is over this size. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│log_syslog_facility │see syslog(3) │mail │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│log_syslog_ident │string prepended to │fml/$program_name │
│ │every message. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│log_syslog_options │see syslog(3) │pid │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│log_syslog_priority │see syslog(3) │info │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│log_type │logging type │file │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│mail_aliases_file │aliases │$domain_mail_config_dir/aliases │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│mail_header_default_errors_to │default Errors-To: │$maintainer │
│ │field. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│mail_header_default_list_help │default list-help │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│mail_header_default_list_id │default list-id header │$ml_name ML <$ml_name.$ml_domain> │
│ │field. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│mail_header_default_list_owner │default list-owner │ │
│ │header field. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│mail_header_default_list_post │default list-post │ │
│ │header field. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│mail_header_default_list_software │default list-software │$fml_version │
│ │header field. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│mail_header_default_list_subscribe │default list-subscribe │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │default │ │
│ │field. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│mail_header_default_precedence │default Precedence: │bulk │
│ │field. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│mail_header_default_x_ml_name │default X-ML-Name: │$ml_name │
│ │field. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│mail_queue_dir │mail queue directory │$var_dir/mail/queue │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│member_maps │all maps used to check │$primary_member_map │
│ │member list. │$admin_member_maps │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│member_total_limit │upper limit of posters.│3000 │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│message_id_cache_dir │Message-ID cache │$db_dir/message_id │
│ │directory │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│message_template_dir │directory to hold │$fml_share_dir/message │
│ │message template files │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │base directory which │ │
│ml_admin_cgi_base_dir │locates .cgi for this │$cgi_base_dir/ml-admin/$ml_name │
│ │ML. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ml_anonymous_cgi_allowed_commands │ │subscribe unsubscribe │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │ml specific directory │$anonymous_cgi_base_dir/$ml_domain/ │
│ml_anonymous_cgi_base_dir │for anonymous cgi │$ml_name │
│ │scripts. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │ml specific url base │/~$fml_owner/cgi-bin/anonymous/ │
│ml_anonymous_cgi_base_url │for anonymous cgi │$ml_domain/$ml_name │
│ │scripts. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ml_local_dir │ML local directory │$ml_home_dir/local │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ml_local_lib_dir │ML local library path │$ml_local_dir/lib │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │directory to hold ml │ │
│ml_local_message_template_dir │specific message │$ml_local_share_dir/message │
│ │template files │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ml_local_share_dir │ML local share/ │$ml_local_dir/share │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │queue_dir moderate uses│ │
│moderate_queue_dir │as temporary incoming │$var_dir/mail/queue-moderate │
│ │queue │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │expire submitted queue │ │
│moderate_queue_expire_limit │after │14d │
│ │$moderate_expire_limit.│ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│moderator_member_maps │all list of moderator │$primary_moderator_member_map │
│ │lists. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│moderator_recipient_maps │dummy │$primary_moderator_recipient_map │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│newml_command_ml_admin_default_address │fml_owner value used by│$fml_owner │
│ │newml command. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│newml_command_postfix_template_files │templates of include │include include-ctl include-error │
│ │files │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │templates files of ~fml│dot-qmail dot-qmail-ctl │
│newml_command_qmail_template_files │/.qmail-* │dot-qmail-admin dot-qmail-request │
│ │ │dot-qmail-default │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│newml_command_template_files │template files used in │config.cf │
│ │running "makefml newml"│ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│objective_file │objective file │$ml_home_dir/objective │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│outgoing_article_body_size_limit │maximum size limit of │$default_mail_body_size_limit │
│ │deliverd article body. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │maximum size limit of │ │
│outgoing_article_header_size_limit │deliverd article │$default_mail_header_size_limit │
│ │header. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│outgoing_command_mail_body_size_limit │maximum size limit of │$default_mail_body_size_limit │
│ │deliverd article body. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │maximum size limit of │ │
│outgoing_command_mail_header_size_limit │deliverd article │$default_mail_header_size_limit │
│ │header. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│outgoing_mail_cache_dir │outgoing mail cache │$var_dir/mail/outgoing │
│ │directory │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│outgoing_mail_cache_size │the maximum number of │128 │
│ │cached outgoing mails │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│outgoing_mail_header_errors_to │Errors-To: field │${mail_header_default_errors_to} │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│outgoing_mail_header_precedence │Precedence: field │${mail_header_default_precedence} │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │ml name in both │ │
│outgoing_mail_header_x_ml_name │X-ML-Name: and │${mail_header_default_x_ml_name} │
│ │X-Sequence header │ │
│ │fields. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│postfix_verp_delimiters │verps delimieters used │+= │
│ │in postfix │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│postfix_virtual_map_file │virtual map file │$domain_postfix_config_dir/virtual │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │list of remote │ │
│primary_admin_member_map │administrators who has │file:$ml_home_dir/members-admin │
│ │priviledge │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │primary password file │ │
│primary_admin_member_password_map │to authenticate remote │file:$etc_dir/passwd-admin │
│ │administrator │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│primary_admin_recipient_map │dummy │file:$ml_home_dir/recipients-admin │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│primary_digest_member_map │dummy │$primary_member_map │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│primary_digest_recipient_map │primary list of digest │file:$ml_home_dir/recipients-digest │
│ │recipients. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │member list == primary │ │
│primary_member_map │address list who can │file:$ml_home_dir/members │
│ │post. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│primary_moderator_member_map │primary list of │file:$ml_home_dir/members-moderator │
│ │moderators. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│primary_moderator_recipient_map │dummy │file:$ml_home_dir/ │
│ │ │recipients-moderator │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│primary_recipient_map │primary recipients │file:$ml_home_dir/recipients │
│ │list. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│primary_user_db_gecos_map │primary { address => │$user_db_dir/gecos │
│ │gecos_field } map. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │primary { address => │ │
│primary_user_db_subscribe_date_map │unix time when │$user_db_dir/subscribe_date │
│ │subscribed } map. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │special command name │ │
│privileged_command_prefix │used as admin command │admin │
│ │mail │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│procmail_aliases_file │sample of ~fml │$domain_procmail_config_dir/ │
│ │/.procmailrc │procmailrc │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│qmail_verp_delimiters │verps delimieters used │-= │
│ │in qmail │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│qmail_virtual_map_file │template of /var/qmail/│$domain_qmail_config_dir/ │
│ │control/virtualdomains │virtualdomains │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │virtual domain │ │
│qmail_virtualdomains_file │configurations for │/var/qmail/control/virtualdomains │
│ │qmail │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│recipient_maps │all maps used as │$primary_recipient_map │
│ │recipient list. │file:$ml_home_dir/actives │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│recipient_total_limit │upper limit of │3000 │
│ │recipients. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│sendmail_virtual_map_file │sample of /etc/mail/ │$domain_sendmail_config_dir/ │
│ │virtusertable │virtusertable │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│sequence_file │file to store article │$ml_home_dir/seq │
│ │sequence. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│shared_db_dir │database directory │$ml_home_prefix/@db@ │
│ │shared among ML's │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│smtp_recipient_limit │recipient limits over │1000 │
│ │one smtp transaction. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│smtp_sender │MAIL FROM: │$maintainer │
│ │<$smtp_sender> in SMTP │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│smtp_servers │smtp servers. │[::1]:25 127.0.0.1:25 │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│spammer_maps │list of spammers or │$primary_spammer_map │
│ │addresses to reject. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│spool_dir │spool directory │$ml_home_dir/spool │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│spool_type │use subdir in spool │plane │
│ │directory ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│subscribe_command_auth_type │use comnfirmation in │confirmation │
│ │subscribe command ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │operate action │ │
│subscribe_command_operation_mode │automatically or │automatic │
│ │manually by maintainer │ │
│ │? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│system_has_alarm │has alarm(2) ? │yes │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│system_has_fork │has fork(2) ? │yes │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│system_has_getpwgid │has getpwgid(2) ? │yes │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│system_has_getpwuid │has getpwuid(2) ? │yes │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│system_has_select │has select(2) ? │yes │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │ │root postmaster MAILER-DAEMON msgs │
│system_special_accounts │list of system │nobody news majordomo listserv │
│ │accounts. │listproc \S+\-help \S+\-subscribe \S+│
│ │ │\-unsubscribe │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│thread_cgi_base_url │CGI relative path │/cgi-bin/fmlthread.cgi │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│thread_cgi_bgcolor │CGI color │#E6E6FA │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│thread_cgi_title │CGI title │thread tracking system interface │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│thread_db_dir │directory to hold │$shared_db_dir/thread │
│ │ticket data │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│thread_id_syntax │ticket number │$ml_name/%d │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│thread_sequence_file │file to store ticket │$ml_home_dir/thread.seq │
│ │sequence │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│thread_subject_tag │syntax added to │[$thread_id_syntax] │
│ │Subject: │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│thread_subject_tag_location │location of insertion │appended │
│ │of tag │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│thread_subject_tag_name │ml name assigned to │$ml_name │
│ │ticket │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│tmp_dir │directory to hold │$ml_home_dir/tmp │
│ │temporary files │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│udb_base_dir │database directory │$ml_home_prefix/@udb@ │
│ │shared among ML's. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│unsafe_header_fields │remove unsafe header │Return-Receipt-To │
│ │fields │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│unsubscribe_command_auth_type │use comnfirmation in │confirmation │
│ │unsubscribe command ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │operate action │ │
│unsubscribe_command_operation_mode │automatically or │automatic │
│ │manually by maintainer │ │
│ │? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_address_compare_function │FML::Credential checks │yes │
│ │address comparison │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_admin_command_mail_function │use admin command mail │no │
│ │? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │allow a request e.g. │ │
│use_anonymous_cgi_function │subscribe and │yes │
│ │unsubscribe from www. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_delivery │user article delivery │yes │
│ │function ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_expire │expire too old article │no │
│ │or not ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_filter_reject_notice │infor the filter │yes │
│ │rejection ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_header_filter │use header based filter│yes │
│ │? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_header_rewrite │use article header │yes │
│ │rewrite function ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_mime_component_filter │MIME structure based │yes │
│ │filter │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_non_mime_filter │dummy │yes │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_post_function │use function of article│${use_distribute_program:-yes} │
│ │delivery │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_size_filter │use size based filter. │yes │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_spam_filter │use external spam │no │
│ │checker. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_spool │store article into │${ues_spool:-yes} │
│ │spool directory ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │remove content │ │
│use_article_summary_file_expire │correspoding with │no │
│ │article expiration. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │use text/plain filter, │ │
│use_article_text_plain_filter │which is a simple │yes │
│ │syntax checker. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_thread_outline │add thread outline │no │
│ │automatically ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_article_virus_filter │external virus checker.│no │
│ │disabled by default. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_command_mail_filter_reject_notice │inform filter rejection│yes │
│ │? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_command_mail_function │use commnd mail ? │${use_command_mail_program:-yes} │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │add self introduction │ │
│use_command_mail_reply_preamble │into the preamble of │yes │
│ │command mail reply. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │add processing summary │ │
│use_command_mail_reply_trailor │into the trailor of │yes │
│ │command mail reply. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_command_mail_size_filter │use size based filter │yes │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_createonpost_function │use CREATE-ON-POST or │yes │
│ │not ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_debug │debug on or off (off by│no │
│ │default). │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │use digest article │ │
│use_digest_header_rewrite │header rewrite function│yes │
│ │? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_error_mail_analyzer_function │use error message │${use_error_analyzer_program:-yes} │
│ │analyzer ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │use fetchfml │ │
│use_fetchfml_article_post_function │article_post function │yes │
│ │or not. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │use fetchfml │ │
│use_fetchfml_command_mail_function │command_mail function │yes │
│ │or not. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │use fetchfml │ │
│use_fetchfml_error_mail_analyzer_function │error_mail_analyzer │yes │
│ │function or not. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_fetchfml_function │use fetchfml function │no │
│ │or not. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_html_archive │use html converter │yes │
│ │function ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_incoming_mail_body_loop_check │use loop check based on│yes │
│ │body information │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_incoming_mail_cache │cache incoing mail ? │yes │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_incoming_mail_envelope_loop_check │enable envelope based │yes │
│ │loop check or not ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_incoming_mail_header_loop_check │use loop check based on│yes │
│ │header information ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_lock │use lock system ? │yes │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_log │user logging function │yes │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │if yes, makefml/fml │ │
│use_log_computer_output │outputs machine │no │
│ │friendly log. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_log_rotate │rotate log files or │no │
│ │not. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │upper limit of posters.│ │
│use_member_total_limit │no limitation by │no │
│ │default. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_moderate_function │use moderate function │yes │
│ │or not. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_outgoing_mail_cache │cache outgoing mail │yes │
│ │cache ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │upper limit of │ │
│use_recipient_total_limit │recipients. no │no │
│ │limitation by default. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_smtp_log │log smtp transaction ? │yes │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_spool │store article into │yes │
│ │spool directory ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_thread_subject_tag │use special subject tag│no │
│ │? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│use_thread_track │user thread tracking │yes │
│ │system ? │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│ │effective command in │help get mget get mget send subscribe│
│user_command_mail_allowed_commands │normal commnd mail (for│add unsubscribe bye on off digest │
│ │usual users) │remove resign signoff chaddr confirm │
│ │ │guide info admin objective summary │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│user_db_dir │user database │$db_dir/user_info │
│ │directory. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│user_db_gecos_maps │{ address => │$primary_user_db_gecos_map │
│ │gecos_field } maps. │ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│user_db_subscribe_date_maps │{ address => unix time │$primary_user_db_subscribe_date_map │
│ │when subscribed } maps.│ │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│var_dir │directory hoding │$ml_home_dir/var │
├─────────────────────────────────────────────────┼───────────────────────┼─────────────────────────────────────┤
│welcome_file │welcome file │$ml_home_dir/welcome │
└─────────────────────────────────────────────────┴───────────────────────┴─────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Variable List (Class Based)
__exceptional__ {
? $timezone
}
address {
address_compare {
? $address_compare_function_domain_matching_level
$address_compare_function_type
$use_address_compare_function
}
}
admin {
admin_command {
}
admin_command_mail {
? $admin_command_mail_allowed_commands
$admin_command_mail_auth_gpg_config_dir
? $admin_command_mail_auth_gpg_config_dir_alias
$admin_command_mail_auth_pgp_config_dir
? $admin_command_mail_auth_pgp_config_dir_alias
$admin_command_mail_restrictions
$use_admin_command_mail_function
}
admin_member {
$admin_member_maps
$primary_admin_member_map
}
admin_member_password {
$admin_member_password_maps
$primary_admin_member_password_map
}
admin_recipient {
$admin_recipient_maps
$primary_admin_recipient_map
}
admin_* {
? $admin_cgi_allowed_commands
$admin_cgi_base_dir
}
}
anonymous {
anonymous_cgi {
$anonymous_cgi_base_dir
$anonymous_cgi_expire_limit
? $ml_anonymous_cgi_allowed_commands
$ml_anonymous_cgi_base_dir
? $ml_anonymous_cgi_base_url
$use_anonymous_cgi_function
}
anonymous_command {
? $anonymous_command_mail_allowed_commands
}
}
article {
article_delivery {
? $article_delivery_transport
$use_article_delivery
}
article_digest {
$use_article_digest_function
}
article_expire {
$article_expire_limit
$use_article_expire
}
article_filter {
$article_filter_functions
$use_article_filter
}
article_filter_reject_notice {
$article_filter_reject_notice_data_type
? $article_filter_reject_notice_recipients
$use_article_filter_reject_notice
}
article_header_filter {
$article_header_filter_rules
$use_article_header_filter
}
article_header_rewrite {
$article_header_rewrite_rules
$use_article_header_rewrite
}
article_mime_component_filter {
$article_mime_component_filter_rules
$use_article_mime_component_filter
}
article_non_mime_filter {
$article_non_mime_filter_rules
$use_article_non_mime_filter
}
article_post {
? $article_post_address
? $article_post_article_thread_lifetime
$article_post_auth_gpg_config_dir
$article_post_auth_pgp_config_dir
$article_post_encrypt_gpg_config_dir
$article_post_encrypt_pgp_config_dir
$article_post_restrictions
$article_post_restrictions_reject_notice_data_type
$use_article_post_function
}
article_size_filter {
$article_size_filter_rules
$use_article_size_filter
}
article_spam_filter {
? $article_spam_filter_bogofilter_options
? $article_spam_filter_drivers
$article_spam_filter_functions
$article_spam_filter_rules
? $article_spam_filter_spamassassin_options
? $article_spam_filter_spamc_options
$use_article_spam_filter
}
article_spool {
$use_article_spool
}
article_summary_file_expire {
$use_article_summary_file_expire
}
article_text_plain_filter {
$article_text_plain_filter_rules
$use_article_text_plain_filter
}
article_thread_outline {
? $article_thread_outline_greeting_en
? $article_thread_outline_greeting_ja
$article_thread_outline_rules
$use_article_thread_outline
}
article_virus_filter {
? $article_virus_filter_clamav_options
? $article_virus_filter_drivers
$article_virus_filter_functions
$article_virus_filter_rules
$use_article_virus_filter
}
article_* {
? $article_header_list_help
? $article_header_list_id
? $article_header_list_owner
? $article_header_list_post
? $article_header_list_software
? $article_header_list_subscribe
? $article_header_list_unsubscribe
$article_message_id_cache_dir
$article_sequence_file
? $article_subject_tag
$article_summary_file
? $article_summary_file_format_address_length
? $article_summary_file_format_style
}
}
cgi {
cgi_* {
$cgi_base_dir
? $cgi_charset_en
? $cgi_charset_ja
? $cgi_default_charset
? $cgi_default_language
? $cgi_language_select_list
? $cgi_main_menu_color
? $cgi_menu_address_map_select_list
$cgi_menu_default_address_map
? $cgi_navigation_bar_color
}
}
command {
command_mail {
? $command_mail_address
$command_mail_auth_gpg_config_dir
$command_mail_auth_pgp_config_dir
$command_mail_line_length_limit
? $command_mail_reply_prompt
$command_mail_restrictions
$use_command_mail_function
}
command_mail_filter {
$command_mail_filter_functions
$use_command_mail_filter
}
command_mail_filter_reject_notice {
$command_mail_filter_reject_notice_data_type
? $command_mail_filter_reject_notice_recipients
$use_command_mail_filter_reject_notice
}
command_mail_invalid_command {
$command_mail_invalid_command_limit
}
command_mail_reply_preamble {
$use_command_mail_reply_preamble
}
command_mail_reply_trailor {
$use_command_mail_reply_trailor
}
command_mail_size_filter {
$command_mail_size_filter_rules
$use_command_mail_size_filter
}
command_mail_valid_command {
$command_mail_valid_command_limit
}
}
admin_command {
admin_command {
}
admin_command_mail {
}
}
anonymous_command {
anonymous_command {
}
}
chaddr_command {
chaddr_command {
$chaddr_command_auth_type
? $chaddr_command_operation_mode
}
}
confirm_command {
confirm_command {
$confirm_command_expire_limit
? $confirm_command_prefix
}
}
get_command {
get_command {
$get_command_request_limit
}
}
list_command {
list_command {
}
list_command_default {
$list_command_default_maps
}
}
log_command {
log_command {
? $log_command_tail_starting_location
}
}
newml_command {
newml_command {
? $newml_command_init_private_directories
? $newml_command_init_public_directories
? $newml_command_ml_admin_default_address
? $newml_command_mta_config_list
$newml_command_postfix_template_files
$newml_command_qmail_template_files
$newml_command_template_files
}
}
privileged_command {
privileged_command {
? $privileged_command_prefix
}
}
rmml_command {
rmml_command {
? $rmml_command_mta_config_list
}
}
subscribe_command {
subscribe_command {
$subscribe_command_auth_type
? $subscribe_command_operation_mode
}
}
unsubscribe_command {
unsubscribe_command {
$unsubscribe_command_auth_type
? $unsubscribe_command_operation_mode
}
}
user_command {
user_command {
? $user_command_mail_allowed_commands
}
}
createonpost {
createonpost {
$use_createonpost_function
}
createonpost_newml {
$createonpost_newml_maps
$createonpost_newml_restrictions
}
createonpost_sender {
$createonpost_sender_maps
$createonpost_sender_restrictions
}
createonpost_subscribe {
$createonpost_subscribe_maps
$createonpost_subscribe_restrictions
}
}
debug {
debug {
$use_debug
}
}
default {
default_* {
$default_mail_body_size_limit
$default_mail_header_size_limit
}
}
digest {
digest_header_rewrite {
$digest_header_rewrite_rules
$use_digest_header_rewrite
}
digest_member {
$digest_member_maps
$primary_digest_member_map
}
digest_recipient {
$digest_recipient_maps
$primary_digest_recipient_map
}
digest_* {
$digest_sequence_file
}
}
directory {
directory_* {
? $directory_default_mode
? $directory_private_mode
? $directory_public_mode
}
}
domain {
domain_* {
$domain_config_base_dir
$domain_exim_config_dir
$domain_local_dir
$domain_local_tmp_dir
$domain_mail_config_dir
$domain_postfix_config_dir
$domain_procmail_config_dir
$domain_qmail_config_dir
$domain_sendmail_config_dir
}
}
error {
error_mail_analyzer {
$error_mail_analyzer_cache_dir
? $error_mail_analyzer_cache_mode
? $error_mail_analyzer_cache_size
$error_mail_analyzer_cache_type
? $error_mail_analyzer_function
? $error_mail_analyzer_function_select_list
$error_mail_analyzer_simple_count_limit
$use_error_mail_analyzer_function
}
}
fetchfml {
fetchfml {
? $fetchfml_fetch_protocol
? $fetchfml_imap_servers
? $fetchfml_pop_servers
$fetchfml_queue_dir
$use_fetchfml_function
}
fetchfml_article_post {
? $fetchfml_article_post_password
? $fetchfml_article_post_user
$use_fetchfml_article_post_function
}
fetchfml_command_mail {
? $fetchfml_command_mail_password
? $fetchfml_command_mail_user
$use_fetchfml_command_mail_function
}
fetchfml_error_mail_analyzer {
? $fetchfml_error_mail_analyzer_password
? $fetchfml_error_mail_analyzer_user
$use_fetchfml_error_mail_analyzer_function
}
}
html {
html_archive {
? $html_archive_charset_en
? $html_archive_charset_ja
? $html_archive_default_charset
$html_archive_dir
$html_archive_index_order_type
$use_html_archive
}
html_archive_address_mask {
$html_archive_address_mask_type
$use_html_archive_address_mask
}
html_* {
? $html_tmp_base_url
$html_tmp_dir
}
}
incoming {
incoming_article {
$incoming_article_body_size_limit
$incoming_article_header_size_limit
}
incoming_command_mail {
$incoming_command_mail_body_size_limit
$incoming_command_mail_header_size_limit
}
incoming_mail_body_loop_check {
$incoming_mail_body_loop_check_rules
$use_incoming_mail_body_loop_check
}
incoming_mail_cache {
$incoming_mail_cache_dir
? $incoming_mail_cache_size
$use_incoming_mail_cache
}
incoming_mail_envelope_loop_check {
$incoming_mail_envelope_loop_check_rules
$use_incoming_mail_envelope_loop_check
}
incoming_mail_header_loop_check {
$incoming_mail_header_loop_check_rules
$use_incoming_mail_header_loop_check
}
incoming_* {
$incoming_mail_body_checksum_cache_dir
}
}
ldap {
ldap_* {
? $ldap_base_dn
? $ldap_bind_dn
? $ldap_password
? $ldap_query_add_as_ldif
? $ldap_query_delete_as_ldif
? $ldap_query_find_result_attribute
? $ldap_query_find_search_filter
? $ldap_query_get_next_key_result_attribute
? $ldap_query_get_next_key_search_filter
? $ldap_query_getline_result_attribute
? $ldap_query_getline_search_filter
? $ldap_servers
? $ldap_user
}
}
list {
list_command {
}
list_command_default {
}
list_* {
? $list_addresses
}
}
lock {
lock {
$lock_dir
$lock_file
$lock_type
$use_lock
}
}
log {
log {
$domain_local_log_file
$log_dir
$log_file
? $log_file_charset_en
? $log_file_charset_ja
? $log_file_default_charset
$log_format_type
? $log_syslog_facility
? $log_syslog_ident
? $log_syslog_options
? $log_syslog_priority
? $log_syslog_servers
$log_type
$use_log
}
log_command {
}
log_computer_output {
? $log_computer_output_engine
$use_log_computer_output
}
log_rotate {
? $log_rotate_archive_file_total
? $log_rotate_interval
? $log_rotate_policy
$log_rotate_size_limit
$use_log_rotate
}
}
mail {
mail_* {
$mail_aliases_file
? $mail_header_default_errors_to
? $mail_header_default_list_help
? $mail_header_default_list_id
? $mail_header_default_list_owner
? $mail_header_default_list_post
? $mail_header_default_list_software
? $mail_header_default_list_subscribe
? $mail_header_default_list_unsubscribe
? $mail_header_default_precedence
? $mail_header_default_x_ml_name
$mail_queue_dir
}
}
maintainer {
maintainer_recipient {
$maintainer_recipient_maps
}
maintainer_* {
? $maintainer
? $maintainer_signature
}
}
member {
member {
$member_maps
$primary_member_map
}
member_total_limit {
$member_total_limit
$use_member_total_limit
}
}
message {
message_* {
? $message_default_subject
$message_id_cache_dir
$message_template_dir
}
}
ml_local {
ml_local_* {
$ml_local_dir
$ml_local_lib_dir
$ml_local_message_template_dir
$ml_local_share_dir
}
}
moderate {
moderate {
$moderate_queue_dir
$moderate_queue_expire_limit
$use_moderate_function
}
}
moderator {
moderator_member {
$moderator_member_maps
$primary_moderator_member_map
}
moderator_recipient {
$moderator_recipient_maps
$primary_moderator_recipient_map
}
}
outgoing {
outgoing_article {
$outgoing_article_body_size_limit
$outgoing_article_header_size_limit
}
outgoing_command_mail {
$outgoing_command_mail_body_size_limit
$outgoing_command_mail_header_size_limit
}
outgoing_mail_cache {
$outgoing_mail_cache_dir
? $outgoing_mail_cache_size
$use_outgoing_mail_cache
}
outgoing_* {
? $outgoing_mail_header_errors_to
? $outgoing_mail_header_precedence
? $outgoing_mail_header_x_ml_name
}
}
path {
path_* {
$path_bogofilter
$path_bunzip2
$path_bzip2
$path_cksum
$path_clamscan
$path_compress
$path_emacs
$path_gpg
$path_gpgsplit
$path_gpgv
$path_gunzip
$path_gzcat
$path_gzip
$path_ish
$path_kakasi
$path_less
$path_lha
$path_ls
$path_makemap
$path_md5
$path_more
$path_mule
$path_namazu
$path_newaliases
$path_ng
$path_nkf
$path_perl
$path_pgp
$path_pgp5
$path_pgpe
$path_pgpk
$path_pgps
$path_pgpv
$path_postalias
$path_postconf
$path_postfix
$path_postmap
$path_sendmail
$path_spamassassin
$path_spamc
$path_spamd
$path_sum
$path_tar
$path_uuencode
$path_vi
$path_w3m
$path_xemacs
$path_zcat
}
}
post {
}
postfix {
postfix_* {
? $postfix_verp_delimiters
$postfix_virtual_map_file
}
}
procmail {
procmail_* {
$procmail_aliases_file
}
}
qmail {
qmail_* {
? $qmail_verp_delimiters
$qmail_virtual_map_file
$qmail_virtualdomains_file
}
}
recipient {
recipient {
$primary_recipient_map
$recipient_maps
$smtp_recipient_limit
}
recipient_total_limit {
$recipient_total_limit
$use_recipient_total_limit
}
}
reply_message {
}
report_mail {
report_mail_* {
? $report_mail_charset_en
? $report_mail_charset_ja
? $report_mail_default_charset
? $report_mail_subject
}
}
sendmail {
sendmail_* {
$sendmail_virtual_map_file
}
}
smtp {
smtp_log {
$use_smtp_log
}
smtp_* {
? $smtp_sender
? $smtp_servers
}
}
spammer {
spammer {
$primary_spammer_map
$spammer_maps
}
}
spool {
spool {
$spool_dir
? $spool_subdir_unit
$spool_type
$use_spool
}
}
sql {
sql_* {
? $sql_database
? $sql_password
? $sql_query_add
? $sql_query_delete
? $sql_query_find
? $sql_query_get_next_key
? $sql_query_getline
? $sql_servers
? $sql_table
? $sql_user
}
}
system {
system_* {
? $system_default_umask
? $system_has_alarm
? $system_has_fork
? $system_has_getpwgid
? $system_has_getpwuid
? $system_has_select
? $system_special_accounts
? $system_timezone
}
}
template_file {
template_file_* {
? $template_file_charset_en
? $template_file_charset_ja
? $template_file_charset_select_list
? $template_file_default_charset
}
}
thread {
thread_subject_tag {
? $thread_subject_tag
? $thread_subject_tag_location
? $thread_subject_tag_name
$use_thread_subject_tag
}
thread_track {
$use_thread_track
}
thread_* {
? $thread_cgi_base_url
? $thread_cgi_bgcolor
? $thread_cgi_title
$thread_db_dir
? $thread_id_syntax
$thread_sequence_file
}
}
user {
user_command {
}
user_db_gecos {
$primary_user_db_gecos_map
$user_db_gecos_maps
}
user_db_subscribe_date {
$primary_user_db_subscribe_date_map
$user_db_subscribe_date_maps
}
user_* {
$user_db_dir
}
}
x {
}
_file$ {
$compat_old_fml_default_config_ph_file
$deny_file
$guide_file
$help_file
$objective_file
$sequence_file
$welcome_file
}
_dir$ {
$compat_config_base_dir
$compat_old_fml_config_dir
$db_dir
$etc_dir
$event_queue_dir
$isolated_queue_dir
$listinfo_base_dir
$listinfo_dir
$listinfo_template_base_dir
$listinfo_template_dir
$ml_admin_cgi_base_dir
$shared_db_dir
$tmp_dir
$udb_base_dir
$var_dir
}
*** unclassified ***
? $file_default_mode
$isolated_queue_expire_limit
? $language_preference_order
? $ml_admin_cgi_allowed_commands
? $unsafe_header_fields
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipes
1. What functions are proper used in config.cf file ?
1. What functions are proper used in config.cf file ?
Use methods of $curproc (in hooks).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 30. Create A New Program
Create A Program (CUI)
Firstly, prepare a new module in FML::Process class. See FML::Process::Calendar
as the least functional model and see FML::Process::Distribute for the most
complicated class.
See FML::Process::Flow::ProcessStart() for mandatory methods to implement.
FML::Process::Flow::ProcessStart() kicks off several methods sequentially. At
2002/07, these methods are mandatory.
new()
prepare()
verify_request()
run()
finish()
FML::Process::Kernel
| uses-a FML::Process::{Flow,Utils} FML::Parse ...
|
A
FML::Process::MODULE
uses-a FML::Something
uses-a CPAN module
uses-a ...
If you have prepared FML::Process::MODULE, define relation between the program
name and the module at fml/etc/modules. Also, define available command line
options at fml/etc/command_line_options if needed.
After it is prepared, symlink the loader and the new program name. For example,
% ls -l /usr/local/libexec/fml
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 command@ -> loader
drwxr-xr-x 2 root wheel 512 Apr 14 18:25 current-20030414/
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 digest@ -> loader
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 distribute@ -> loader
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 error@ -> loader
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 fml@ -> loader
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 fml.pl@ -> loader
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 fmladdr@ -> loader
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 fmlalias@ -> loader
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 fmlconf@ -> loader
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 fmldoc@ -> loader
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 fmlhtmlify@ -> loader
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 fmlsch@ -> loader
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 fmlserv@ -> loader
-rwxr-xr-x 1 root wheel 6863 Apr 14 18:24 loader*
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 makefml@ -> loader
lrwxr-xr-x 1 root wheel 6 Apr 14 18:25 mead@ -> loader
As a test, you symlink it explicitly. For the canonical programs, fml installer
symlinks them according to fml/etc/install.cf. You need to define the program
as $bin_programs or $exec_programs in install.cf.in (configure generates
install.cf).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Create A Program (CGI)
The main part of CGI program is implemented as an FML::CGI::XXX class. These
modules have the following relation.
FML::Process::Kernel
|
A
FML::Process::CGI::Kernel uses-a CGI
|
A
FML::Process::CGI
|
A
FML::CGI::XXX
How to write CGI programs is same as one of CUI. GUI modules locate under
FML::CGI to clarify the difference between CUI and GUI.
In the case of CGI, prepare the following methods for screen control in
FML::CGI::MODULE.
html_start()
html_end()
and
run_cgi_main()
run_cgi_title()
run_cgi_navigator()
run_cgi_menu()
run_cgi_command_help()
run_cgi_options()
These methods are called from verify_request() and run() in FML::Process::CGI.
CGI process is driven by FML::Process::CGI. run() method calls
$curproc->html_start($args);
call a set of run_cgi_xxx() methods
$curproc->html_end($args);
to control screen.
At 2001/11, FML::Process::CGI::Kernel consists of the following methods: [9]
new()
prepare()
verify_request()
run()
finish()
You do not need edit these files. FML::CGI:: is called at run() method.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 31. fml8 Mail Delivery System
The Difference Between fml4 And fml8
One of purposes of fml8 is unification and abstraction of member list
operations. Mail distribution is based on the following module Mail::Delivery.
Mail::Delivery class provides SMTP, ESMTP and LMTP delivery library interface.
Mail::Delivery is an adapter layer for Mail::Delivery subclass ( SMTP ESMTP
LMTP ).
For example,
use Mail::Delivery::SMTP;
my $service = new Mail::Delivery::SMTP;
if ($service->error) { Log($service->error); return;}
$service->deliver(
{
mta => '127.0.0.1:25',
smtp_sender => 'rudo@nuinui.net',
recipient_maps => $recipient_maps,
recipient_limit => 1000,
mesage => $message
});
where $message is a Mail::Message object.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message Object
This object provies message analyzer. It analyzes a message and build the
following object chains on memory.
header -> body
header -> preamble -> part1 -> part2 -> trailor (multipart)
Mail::Message class provides such data structure described above.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Incoming Queuing
MTA kicks off a fml process. It reads a message from STDIN.
The fml process reads a message once and write it onto the hard disk (write it
into the incoming queue). After the queuing succeeded, the process starts to
analyze a message. For this logic, the original mail is saved before main
processing starts.
If the queuing fails, fml calls exit(EX_TEMPFAIL). In almost cases, exit(75).
If MTA receives this exit code, MTA tries to deliver again later.
Mail::Delivery::Queue class processes the incoming queue. The queus is removed
when the process ends.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
fml Sends Back A Mail Message
Mail::Delivery::Queue class inserts a message to send back into the mail queue.
Later FML::Process::QueueManager handles the real delivery process.
Article delivery processing is a little diffferent but based on queueing by
Mail::Delivery::Queue. If someting error occurs in delivery, another fml
process tries to deliver it later.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Coding In fml8 Sources.
Code is like this to send back a message:
$curproc->reply_message( "you are not a ML member." );
If no recipient specified, the recipient is the sender of the message (From:
address).
To send a file, like this:
$curproc->reply_message( {
type => "text/plain; charset=iso-2022-jp",
path => "/etc/fml/main.cf",
filename => "main.cf",
disposition => "main.cf example",
});
$curproc->reply_message( {
type => "image/gif",
path => "/some/where/logo001.gif",
filename => "logo.gif",
disposition => "attachment",
});
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail Queue And Delivery System
FML::Process::QueueManager picks up one queue from the queue directory.
Mail::Message parses it. Mail::Delivery processes the real delivery via
FML::Mailer.
Mail::Delivery::Queue
|
| ---> queue directory
V
FML::Process::QueueManager
|
| <--- queue directory
V
FML::Mailer
|
V
Mail::Delivery
In manipulating queue, we should lock the target queue by flock(2).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail Queue Directory
The queue directory consists of the following plural directories:
new/
active/
incoming/
deferred/
info/sender/
info/recipients/
info/transport/
info/ stores envelope information. incoming/ holds incoming queue, others hold
outgoing information.
In creating a new outgoing queue file, make a temporary file in new/ once. When
the delivery preparation is ended, move the queue from new/ to active/. Hence
files under active/ is delivery ready.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Lock The Queue
When we need to handle the specific queue file, use lock()/unlock() method for
each $queue_id object. The lock algorithm is based on flock(2) for the file.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Queue Management System
Since 2004 summer, delivery system of fml8 is under queue management system
like MTA. Now fml8 can deliver again messages by itself.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Discussion: FML::Mailer Is Apropriate ?
Only FML::Process::QueueManager uses FML::Mailer. So, independent FML::Mailer
class is needed ?
In usual codes, reply_message() handles all message operations. FML::Mailer is
always behind it. But modules other than reply_message() is created in the
future ? Hmm, ...
FML::Mailer should be merged into FML::Process::QueueManager class?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Delivery TIPS
1. Wwitch forwarding address regarding the mail content.
1. Wwitch forwarding address regarding the mail content.
It is simple if you can prepare different files as necessary. For example,
prepare
recipients.A
recipients.B
recipients.C
for the corresponding conditions A B C. Set up the following hook:
if (condition A matched) {
$config->set('recipient_maps', "recipients.A");
}
elsif (condition B matched) {
$config->set('recipient_maps', "recipients.B");
}
elsif (condition C matched) {
$config->set('recipient_maps', "recipients.C");
}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 32. Digest Delivery
Run
/usr/local/libexec/fml/digest $ml_name
periodically for digest delivery. It aggregates articles into one MIME/
multipart message and send it to members defined by $digest_recipient_maps.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│Digest delivery program is a simple version yet now. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Files Used For Digest Delivery Control
This program uses the following files under $ml_home_dir.
seq-digest
members-digest
recipients-digest
seq-digest holds the last sequence delivered as digest.
members-digest is dummy. recipients-digest is a recipient list.
$digest_recipient_maps is this recipients-digest file only by default.
The argument of $digest_recipient_maps is IO::Adapter, so you can use mysql
here.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Idea: Digest Related Commands
Idea on digest commands (references: fml-devel:313).
Hmm, how about the further extension?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
makefml command
makefml digest $ml $address on
makefml digeston $ml $address
makefml digest $ml $address off
makefml digestoff $ml $address
(These commands are implemented already).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
admin command mail
admin digest $address on
admin digest $address off
(These commands are implemented already).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
user level command mail ?
digest on
digest off
The confirmation is needed ? Yes, we should need it to unify the fml
fundamental design. We should restrict address manipulation functions as could
as possible.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CGI
digeston
digestoff
ok?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
recipes
1. When digest program should run ?
2. Can we change default compression style in digest delivery ?
3. Can we specify parameters in running "makefml add" ?
4. Can we log digest log mesages in the file other than the default log file ?
1. When digest program should run ?
Anytime OK. Please edit crontab.
2. Can we change default compression style in digest delivery ?
No since fml8 supports only MIME/Multipart now.
3. Can we specify parameters in running "makefml add" ?
No since fml8 supports only MIME/Multipart now.
4. Can we log digest log mesages in the file other than the default log file ?
Not configurable. But you can if you us HOOK.
[Example]
$article_digest_prepare_start_hook = q{
$config->{ log_file } = "/some/where/log.digest";
};
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 33. Language Preference In Processing
Problems Of Language Preference
The simplest model is that we suppose we should return the japanese message
when the ML is configured as for Japanese. This model needs that the language
of a ML is fixed. This ML always returns the error message in Japanese.
However, it is not proper to ignore Accept-Language: header field since some
Japanese people cannot read Japanese on the screen. There may be invalid
Accept-Language: field. There are several problems.
For example, if "Accept-Language: ja" is given, we can recognize the language
is "ja". However, how about the case Japanese send a mail with the body content
"help" (English) ? In that case we cannot determine we should return the reply
in us-ascii or iso-2022-jp. For example, how about the following example ?
[Example]
From: rudo@example.co.jp
Subject: help
mime-version: 1.0
content-type: text/plain; charset=us-ascii
help
We should return the English reply message based on charset information since
this message contains English only, so charset is us-ascii. But in this case we
should return Japanese message since the sender is a Japanese. So we should
return the help message in both English and Japanese if the ML is configured as
Japanese preferrable. If English is preferrable, the reply is English only.
If Accept-Lanaguage: is specified, we prefer it. Even if the ML is English
preferrable (config: language_preference_order = en) and the message with
"Accept-Lanaguage: ja" is given, the ML returns the Japanese help message. fml8
behaves like it.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Japanese Preferred ML
language_preference_order variable controls the behaviour. By default, an ML
for Japanese is configured as
language_preference_order = ja en
fml8 uses this hint.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Accept-Language: ja, en
fml8 returns the message only in Japanese.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Accept-Language: en
fml8 returns the message only in English.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
no Accept-Language:, Content-Type: charset=iso-2022-jp
fml8 returns the message only in Japanese.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
no Accept-Language:, Content-Type: charset=us-ascii
We cannot determine the language. We should return the message in both English
and Japanese.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
no Accept-Language:, no Content-Type:
We cannot determine the language. We should return the message in both English
and Japanese.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
English preferred ML
By default, a ML for English people is configured as
language_preference_order = en
fml8 uses this hints.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Accept-Language: ja, en
fml8 returns the message only in Japanese.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Accept-Language: en
fml8 returns the message only in English.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
no Accept-Language:, Content-Type: charset=iso-2022-jp
fml8 returns the message only in Japanese.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
no Accept-Language:, Content-Type: charset=us-ascii
fml8 returns the message only in English.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
no Accept-Language:, no Content-Type:
fml8 returns the message only in English.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 34. Manipulate Message (Mail Message)
See Mail::Message class for the mail message object handling. Mail::Message
class provides fundamental methods. Several message handling modules e.g.
Mail::Bounce, Mail::Delivery depend on this class.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message Class
A mail consists of one header and one body. A multipart mail body consists of
several parts.
The mail delivery module needs not to know the detail of a message. But the
filter system needs to know the structure of the message.
These modules depend Mail::Message class to know the message structure. For
example, Mail::Bounce, Mail::Delivery et.al. use this class.
The usage is as follows:
my $fh = new FileHandle $file;
my $msg = Mail::Message->parse( { fd => $fh } );
use FML::Mailer;
my $obj = new FML::Mailer;
$obj->send( {
sender => $sender,
recipient => $rcpt,
message => $msg,
});
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message::Parse Class
dummy.
The real functions are within Mail::Message class.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message::Compose Class
dummy. This is an adapter for MIME::Lite class. All requests are forwarded to
MIME::Lite class.
See MIME::Lite class for the usage details.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Message Internationalization: The Usage Of reply_message_nl()
For the message internationalization, use reply_message_nl() [10] like this:
$curproc->reply_message_nl('error.already_member',
'already member',
{ _arg_address => $address });
This function uses the message template at /usr/local/share/fml/$fml_version/
message/$language/error/already_member .
$_arg_VARNAME in the message template such as
$_args_address
is expanded by using the value specified as the argument of reply_mesage_nl().
Usual $VARIABLE is also expaned by replacing it with value of config name
space. For example, $ml_name is expanded to ML name defined in config.cf. In
fact $_arg_ prefix is used for lexical scope variables to avoid conflicts
against variables in config.cf.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Discussion: How To Send Back Language Dependent Error Mesages
fml needs to send back language dependent error messages. How we should
implement it ?
(Below, just a discussion not implemation in fact.)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
fml4 Case
In the case of fml4, fml4 calls language dependent message converter like this:
Mesg(*e, KEYWORD, DEFAULT MESSAGE, ARGUMENT);
Mesg() searches the specified keyword in files under /usr/local/fml/messages/
Japanese/ directory. Each file contains messages with keywords to be
substituted properly.
For example, the keyword not_found matches not_found entry in /usr/local/fml/
messages/Japanese/kern file.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
What fml8 Should Do ?
"One file has one keyword" and "one file for one category, so one file contains
plural entries". Hmm, which is better? I don't determine it.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
X/Open Portability Guide Issue 4 Version 2 (``XPG4.2'')
If you use XPG (X/Open standard),
catgets(catd, set_id, msg_id, char *s);
function converts the message specified by LOCALE_XXX. [11] For example, the
usage is as follows:
printf(catgets(catd, 30, 4, "%s: Internal match error.\n"), progname);
This function uses set 30 and entry 4 in the local definition file such as /usr
/pkg/share/nls/ja_JP.EUC/PROGNAME.cat.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
fml8: Design (Temporary ?)
One problem is whether we should use locale or not ? In considering CUI e.g.
makefml, it is better to use locale. For example, prepare
/usr/local/lib/fml/$fml_version/messages/ja_JP.EUC/kern
1: %s not found
2: %s (error number = %d)
.
Instead, one file for one message may be useful. Especially it is easy we can
customize only one message.
To try the latter case, we can prepare a lot of classes such as
FML::Message::ja::KEYWORD
For example, there are 200 or 300 files such as
FML::Message::ja::not_found
.
This methods has the following problems:
• separete files but in contrast more customizable.
• locale friendly? may be no.
Consider an example. In the latter case, the message module will be like this?
sub not_found
{
my .. = @_;
return <<"_EOF_"
$sender is ... something ...
_EOF_
}
Hmm, is it good ???
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 35. Filter
┌─────────────────────────────────────────────────────────────────────────────┐
│ Caution │
├─────────────────────────────────────────────────────────────────────────────┤
│Filter described here is filter system for articles posted to ML. This filter│
│is implemented as FML::Filter class. │
│ │
│Other than article filter, there may be command mail filter. FML::Filter does│
│not provide such function. Instead, FML::Command::Filter class provides │
│command mail specific filter e.g. line length limit of one line. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Overview Of Filter System
There are three types of filter system for content check such as for header,
body and mime structure based. Other than the tree cases, we should consider
text/plain and non mime text (text/?) filter. So there may be four types of
filter.
header
body
non-mime
permit / reject (!MIME of 4.0's content filter)
mime component filter
4.0's content filter
text/plain filter
ja, en, ... (language dependent)
language independent (e.g. M$ GUID scanner)
check of the first text/plain part
syntax check
external filter (call external virus/spam checker)
clamav
spamassassin
bogofilter
Other than these filters, content_filter using SMTP/LMTP can be needed but not
implemented. If you need content_filter, please use the function of Postfix.
Traffic based filter is also needed but not implemented yet.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Configuration Variables
Each sub filter system is enabled/disabled independently.
use_SERVICE_filter = yes
SERVICE_filter_functions = function_A function_B
use_function_A = yes
function_A_rules = rule_01 urle_02
# Descriptions: how to inform the rejected message
# when the filter system rejects.
# We prefer string not mime/multipart to avoid parsing by MUA.
# History: string in 4.0.
# Value: SELECT ( multipart string )
# Examples: string
article_post_restrictions_reject_notice_data_type = string
=head2 filter
# Descriptions:
# History: fml8 rearragena fml4 filter functions and integrates them
# into one.
# Roughly speaking, fml8 filter is composed of the following
# $USE_DISTRIBUTE_FILTER
# $INCOMING_MAIL_SIZE_LIMIT
# ADD_CONTENT_HANDLER()
# functions.
# Value: YES_OR_NO
# Examples: yes
use_article_filter = yes
# Descriptions:
# History:
# Value: MIX (
# article_size_filter
# article_header_filter
# article_non_mime_filter
# article_mime_component_filter
# article_text_plain_filter
# article_spam_filter
# article_virus_filter
# )
# Examples:
article_filter_functions = article_size_filter
article_header_filter
article_non_mime_filter
article_mime_component_filter
article_text_plain_filter
article_spam_filter
article_virus_filter
=head2 size based filter
# Descriptions: use size based filter.
# History: no
# Value: YES_OR_NO
# Examples:
use_article_size_filter = yes
# Descriptions: size based filter rules.
# first match.
# permit post if no rule matched.
# History:
# Value: MIX ( check_header_size
# check_body_size
# permit
# )
# Examples:
article_size_filter_rules = check_header_size
check_body_size
permit
=head2 header base filter
# Descriptions: use header based filter ?
# History: disabled by default.
# "yes" always if $USE_DISTRIBUTE_FILTER is yes.
# Value: YES_OR_NO
# Examples:
use_article_header_filter = yes
# Descriptions: header filter rules.
# first match.
# permit post if no rule matched.
# History: fml4 has no check_date rule.
# Value: MIX (
# check_message_id
# check_date
# permit
# )
# Examples:
article_header_filter_rules = check_message_id
check_date
permit
=head2 filter for non MIME structure
# Descriptions: dummy
# History: disabled by default.
# !MIME of 4.0 content filter.
# Value: YES_OR_NO
# Examples:
use_article_non_mime_filter = yes
# Descriptions: dummy
# History:
# Value: MIX ( permit reject_empty_content_type )
# Examples: permit
article_non_mime_filter_rules = permit
# Descriptions: MIME structure based filter
# History: 4.0 content filter. disabled by default.
# Value: YES_OR_NO
# Examples:
use_article_mime_component_filter = yes
# Descriptions: file of filter rules
# History: @CONTENT_HANDLER
# Value: FILE
# Examples:
article_mime_component_filter_rules = $fml_config_dir/mime_component_filter
=head2 filter for text/plain
# Descriptions: use text/plain filter, which is a simple syntax checker.
# History: 4.0's EnvelopeFilter.
# half of the following rules applied when
# $USE_DISTRIBUTE_FILTER is enabled.
# Value: YES_OR_NO
# Examples:
use_article_text_plain_filter = yes
# Descriptions: filter rules of text/plain filter.
# first match.
# permit post if no rule matched.
# History: See kern/libenvf.pl for more detail.
# [DISABLED BY DEFAULT]
#
# reject_not_iso2022jp_japanese_string
# <=> FILTER_ATTR_REJECT_INVALID_JAPANESE
# reject_old_fml_command_syntax
# <=> FILTER_ATTR_REJECT_COMMAND
# reject_japanese_command_syntax
# <=> FILTER_ATTR_REJECT_2BYTES_COMMAND
#
# [ENABLED BY DEFAULT]
#
# reject_null_mail_body
# <=> FILTER_ATTR_REJECT_NULL_BODY
# reject_invalid_fml_command_syntax
# <=> FILTER_ATTR_REJECT_INVALID_COMMAND
# reject_one_line_message
# <=> FILTER_ATTR_REJECT_ONE_LINE_BODY
# reject_ms_guid
# <=> FILTER_ATTR_REJECT_MS_GUID
#
# Note: permit by default
# Value: MIX (
# reject_not_iso2022jp_japanese_string
# reject_null_mail_body
# reject_one_line_message
# reject_old_fml_command_syntax
# reject_invalid_fml_command_syntax
# reject_japanese_command_syntax
# reject_ms_guid
# permit
# )
# Examples:
article_text_plain_filter_rules = reject_not_iso2022jp_japanese_string
reject_null_mail_body
reject_one_line_message
reject_old_fml_command_syntax
reject_invalid_fml_command_syntax
reject_japanese_command_syntax
reject_ms_guid
permit
=head2 external SPAM filter
# Descriptions: use external spam checker.
# disabled by default.
# add flag to header and go through if the message looks a spam.
# History: none
# Value: YES_OR_NO
# Examples: no
use_article_spam_filter = no
# Descriptions: action if the message looks a spam.
# History: none
# Value: MIX ( reject ignore header_rewrite )
# Examples: header_rewrite
article_spam_filter_rules = header_rewrite
# Descriptions: external spam checker.
# if plural drivers specified, try them sequentially.
# History: none
# Value: MIX ( spamassasin spamc bogofilter )
# Examples: bogofilter
article_spam_filter_drivers = bogofilter
# Descriptions: external virus checker. disabled by default.
# History: none
# Value: YES_OR_NO
# Examples: no
use_article_virus_filter = no
# Descriptions: action if virus found.
# History: none
# Value: MIX ( reject ignore header_rewrite )
# Examples: reject
article_virus_filter_rules = reject
# Descriptions: external virus checker.
# if plural drivers specified, try them sequentially.
# History: none
# Value: MIX ( clamscan )
# Examples: clamscan
article_virus_filter_drivers = clamscan
=head2 inform the filter rejection
# Descriptions: infor the filter rejection ?
# History: halfly hard-coded in fml 4.0.
# notice is always sent to maintainer,
# but not to sender by default.
# $FILTER_NOTIFY_REJECTION controlls notice to sender.
# Value: YES_OR_NO
# Examples: yes
use_article_filter_reject_notice = yes
# Descriptions: recipients to inform
# History: halfly hard-coded in fml 4.0.
# notice is always sent to maintainer,
# but not to sender by default.
# $FILTER_NOTIFY_REJECTION controlls notice to sender.
# Value: MIX ( maintainer sender )
# Examples: maintainer sender
article_filter_reject_notice_recipients = maintainer
sender
# Descriptions: how fml refer the rejeced message.
# We prefer string not multipart to avoid parsing of MUA.
# History: string in fml 4.0.
# Value: SELECT ( multipart string )
# Examples: string
article_filter_reject_notice_data_type = string
# Descriptions:
# History:
# Value: YES_OR_NO
# Examples:
use_article_spam_filter = no
# Descriptions: list up driver names used as spam checker.
# History: none
# Value: MIX ( spamassassin spamc bogofilter )
# Examples: bogofilter
article_spam_filter_functions = bogofilter
# Descriptions: exit non-zero status code when spam caught if "-e" specified.
# History: none
# Value: COMMAND_LINE_OPTIONS
# Examples: -e
article_spam_filter_spamassassin_options = -e
# Descriptions: spamc optoins. "-c" means check only.
# History: none
# Value: COMMAND_LINE_OPTIONS
# Examples: -c
article_spam_filter_spamc_options = -c
# Descriptions: "-e" implies embedded mode.
# History: none
# Value: COMMAND_LINE_OPTIONS
# Examples: -e
article_spam_filter_bogofilter_options = -e
# Descriptions:
# History:
# Value: YES_OR_NO
# Examples:
use_article_virus_filter = no
# Descriptions: list up driver names used as virus checker.
# History: none
# Value: MIX ( virusassassin virusc bogofilter )
# Examples: bogofilter
article_virus_filter_functions = clamav
# Descriptions: --mbox needed for mail files.
# History: none
# Value: COMMAND_LINE_OPTIONS
# Examples: --quiet --mbox
article_virus_filter_clamav_options = --quiet --mbox
=head2 filter
# Descriptions:
# History:
# Value: YES_OR_NO
# Examples:
use_command_mail_filter = yes
# Descriptions:
# History:
# Value: MIX ( command_mail_size_filter )
# Examples:
command_mail_filter_functions = command_mail_size_filter
=head2 size based filter
# Descriptions: use size based filter
# History:
# Value: YES_OR_NO
# Examples:
use_command_mail_size_filter = yes
# Descriptions: size based filter rules.
# first match.
# permit if no rule matched.
# History:
# Value: MIX (
# check_header_size
# check_body_size
# check_command_limit
# check_line_length_limit
# permit
# )
# Examples:
command_mail_size_filter_rules = check_header_size
check_body_size
check_command_limit
check_line_length_limit
permit
=head2 inform filter rejection
# Descriptions: inform filter rejection ?
# History: hard-coded.
# Value: YES_OR_NO
# Examples: yes
use_command_mail_filter_reject_notice = yes
# Descriptions: recipients to inform
# History: hard-coded.
# Value: MIX ( maintainer sender )
# Examples: maintainer sender
command_mail_filter_reject_notice_recipients = maintainer
sender
# Descriptions: how fml refer the rejeced message.
# We prefer string not multipart to avoid parsing of MUA.
# History: string in fml 4.0.
# Value: SELECT ( multipart string )
# Examples: string
command_mail_filter_reject_notice_data_type = string
# Descriptions:
# History:
# Value: FILE
# Examples:
path_bogofilter = @BOGOFILTER@
# $article_digest_finish_end_hook = q{ 1;};
# $article_digest_finish_start_hook = q{ 1;};
# $article_digest_prepare_end_hook = q{ 1;};
# $article_digest_prepare_start_hook = q{ 1;};
# $article_digest_run_end_hook = q{ 1;};
# $article_digest_run_start_hook = q{ 1;};
# $article_digest_verify_request_end_hook = q{ 1;};
# $article_digest_verify_request_start_hook = q{ 1;};
# $article_filter_end_hook = q{ 1;};
# $article_filter_start_hook = q{ 1;};
# $article_header_rewrite_end_hook = q{ 1;};
# $article_header_rewrite_start_hook = q{ 1;};
# $article_post_finish_end_hook = q{ 1;};
# $article_post_finish_start_hook = q{ 1;};
# $article_post_prepare_end_hook = q{ 1;};
# $article_post_prepare_start_hook = q{ 1;};
# $article_post_run_end_hook = q{ 1;};
# $article_post_run_start_hook = q{ 1;};
# $article_post_verify_request_end_hook = q{ 1;};
# $article_post_verify_request_start_hook = q{ 1;};
# $command_mail_filter_end_hook = q{ 1;};
# $command_mail_filter_start_hook = q{ 1;};
# $command_mail_finish_end_hook = q{ 1;};
# $command_mail_finish_start_hook = q{ 1;};
# $command_mail_prepare_end_hook = q{ 1;};
# $command_mail_prepare_start_hook = q{ 1;};
# $command_mail_run_end_hook = q{ 1;};
# $command_mail_run_start_hook = q{ 1;};
# $command_mail_verify_request_end_hook = q{ 1;};
# $command_mail_verify_request_start_hook = q{ 1;};
# $createonpost_finish_end_hook = q{ 1;};
# $createonpost_finish_start_hook = q{ 1;};
# $createonpost_prepare_end_hook = q{ 1;};
# $createonpost_prepare_start_hook = q{ 1;};
# $createonpost_run_end_hook = q{ 1;};
# $createonpost_run_start_hook = q{ 1;};
# $createonpost_verify_request_end_hook = q{ 1;};
# $createonpost_verify_request_start_hook = q{ 1;};
# $distribute_finish_end_hook = q{ 1;};
# $distribute_finish_start_hook = q{ 1;};
# $distribute_prepare_end_hook = q{ 1;};
# $distribute_prepare_start_hook = q{ 1;};
# $distribute_run_end_hook = q{ 1;};
# $distribute_run_start_hook = q{ 1;};
# $distribute_verify_request_end_hook = q{ 1;};
# $distribute_verify_request_start_hook = q{ 1;};
# $error_mail_analyzer_finish_end_hook = q{ 1;};
# $error_mail_analyzer_finish_start_hook = q{ 1;};
# $error_mail_analyzer_prepare_end_hook = q{ 1;};
# $error_mail_analyzer_prepare_start_hook = q{ 1;};
# $error_mail_analyzer_run_end_hook = q{ 1;};
# $error_mail_analyzer_run_start_hook = q{ 1;};
# $error_mail_analyzer_verify_request_end_hook = q{ 1;};
# $error_mail_analyzer_verify_request_start_hook = q{ 1;};
# $faker_finish_end_hook = q{ 1;};
# $faker_finish_start_hook = q{ 1;};
# $faker_prepare_end_hook = q{ 1;};
# $faker_prepare_start_hook = q{ 1;};
# $faker_run_end_hook = q{ 1;};
# $faker_run_start_hook = q{ 1;};
# $faker_verify_request_end_hook = q{ 1;};
# $faker_verify_request_start_hook = q{ 1;};
# $fetchfml_finish_end_hook = q{ 1;};
# $fetchfml_finish_start_hook = q{ 1;};
# $fetchfml_prepare_end_hook = q{ 1;};
# $fetchfml_prepare_start_hook = q{ 1;};
# $fetchfml_run_end_hook = q{ 1;};
# $fetchfml_run_start_hook = q{ 1;};
# $fetchfml_verify_request_end_hook = q{ 1;};
# $fetchfml_verify_request_start_hook = q{ 1;};
# $fmladdr_finish_end_hook = q{ 1;};
# $fmladdr_finish_start_hook = q{ 1;};
# $fmladdr_prepare_end_hook = q{ 1;};
# $fmladdr_prepare_start_hook = q{ 1;};
# $fmladdr_run_end_hook = q{ 1;};
# $fmladdr_run_start_hook = q{ 1;};
# $fmladdr_verify_request_end_hook = q{ 1;};
# $fmladdr_verify_request_start_hook = q{ 1;};
# $fmlalias_finish_end_hook = q{ 1;};
# $fmlalias_finish_start_hook = q{ 1;};
# $fmlalias_prepare_end_hook = q{ 1;};
# $fmlalias_prepare_start_hook = q{ 1;};
# $fmlalias_run_end_hook = q{ 1;};
# $fmlalias_run_start_hook = q{ 1;};
# $fmlalias_verify_request_end_hook = q{ 1;};
# $fmlalias_verify_request_start_hook = q{ 1;};
# $fmlconf_finish_end_hook = q{ 1;};
# $fmlconf_finish_start_hook = q{ 1;};
# $fmlconf_prepare_end_hook = q{ 1;};
# $fmlconf_prepare_start_hook = q{ 1;};
# $fmlconf_run_end_hook = q{ 1;};
# $fmlconf_run_start_hook = q{ 1;};
# $fmlconf_verify_request_end_hook = q{ 1;};
# $fmlconf_verify_request_start_hook = q{ 1;};
# $fmldoc_finish_end_hook = q{ 1;};
# $fmldoc_finish_start_hook = q{ 1;};
# $fmldoc_prepare_end_hook = q{ 1;};
# $fmldoc_prepare_start_hook = q{ 1;};
# $fmldoc_run_end_hook = q{ 1;};
# $fmldoc_run_start_hook = q{ 1;};
# $fmldoc_verify_request_end_hook = q{ 1;};
# $fmldoc_verify_request_start_hook = q{ 1;};
# $fmlhtmlify_finish_end_hook = q{ 1;};
# $fmlhtmlify_finish_start_hook = q{ 1;};
# $fmlhtmlify_prepare_end_hook = q{ 1;};
# $fmlhtmlify_prepare_start_hook = q{ 1;};
# $fmlhtmlify_run_end_hook = q{ 1;};
# $fmlhtmlify_run_start_hook = q{ 1;};
# $fmlhtmlify_verify_request_end_hook = q{ 1;};
# $fmlhtmlify_verify_request_start_hook = q{ 1;};
# $fmlpgp_finish_end_hook = q{ 1;};
# $fmlpgp_finish_start_hook = q{ 1;};
# $fmlpgp_prepare_end_hook = q{ 1;};
# $fmlpgp_prepare_start_hook = q{ 1;};
# $fmlpgp_run_end_hook = q{ 1;};
# $fmlpgp_run_start_hook = q{ 1;};
# $fmlpgp_verify_request_end_hook = q{ 1;};
# $fmlpgp_verify_request_start_hook = q{ 1;};
# $makefml_finish_end_hook = q{ 1;};
# $makefml_finish_start_hook = q{ 1;};
# $makefml_prepare_end_hook = q{ 1;};
# $makefml_prepare_start_hook = q{ 1;};
# $makefml_run_end_hook = q{ 1;};
# $makefml_run_start_hook = q{ 1;};
# $makefml_verify_request_end_hook = q{ 1;};
# $makefml_verify_request_start_hook = q{ 1;};
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Size Limit
fml8 provides size limit for header and body. Also you can use different size
limit of article or command mail.
Implementation of this filter is easy since the input message is analyzed
already.
=head1 size limit
=head2 default size limit
# Descriptions: header size limit
# History:
# Value: NUM
# Examples: 102400
default_mail_header_size_limit = 102400
# Descriptions: body size limit
# History:
# Value: NUM
# Examples: 10240000
default_mail_body_size_limit = 10240000
# Descriptions: the maximum number of cached incoming mails
# History: $NUM_LOG_MAIL
# Value: NUM
# Examples: 128
incoming_mail_cache_size = 128
# Descriptions: the maximum number of cached outgoing mails
# History: $NUM_LOG_MAIL
# Value: NUM
# Examples: 128
outgoing_mail_cache_size = 128
# Descriptions: log rotation policy.
# History: none
# Value: SELECT ( size interval )
# Examples: size
log_rotate_policy = size
# Descriptions: rotate log if the size is over this size.
# History: $LOGFILE_NEWSYSLOG_LIMIT value.
# Value: NUM
# Examples: 300000 (300K bytes)
log_rotate_size_limit = 300000
=head2 size limit
# Descriptions: maximum size limit of article header passed from MTA.
# History:
# Value: NUM
# Examples: 102400
incoming_article_header_size_limit = $default_mail_header_size_limit
# Descriptions: maximum size limit of article body passed from MTA.
# History:
# Value: NUM
# Examples: 10240000
incoming_article_body_size_limit = $default_mail_body_size_limit
# Descriptions: maximum size limit of deliverd article header.
# (not yet implemented ;-)
# History:
# Value: NUM
# Examples: 102400
outgoing_article_header_size_limit = $default_mail_header_size_limit
# Descriptions: maximum size limit of deliverd article body.
# (not yet implemented ;-)
# Value: NUM
# Examples: 10240000
outgoing_article_body_size_limit = $default_mail_body_size_limit
# Descriptions:
# History:
# Value: MIX (
# article_size_filter
# article_header_filter
# article_non_mime_filter
# article_mime_component_filter
# article_text_plain_filter
# article_spam_filter
# article_virus_filter
# )
# Examples:
article_filter_functions = article_size_filter
article_header_filter
article_non_mime_filter
article_mime_component_filter
article_text_plain_filter
article_spam_filter
article_virus_filter
=head2 size based filter
# Descriptions: use size based filter.
# History: no
# Value: YES_OR_NO
# Examples:
use_article_size_filter = yes
# Descriptions: size based filter rules.
# first match.
# permit post if no rule matched.
# History:
# Value: MIX ( check_header_size
# check_body_size
# permit
# )
# Examples:
article_size_filter_rules = check_header_size
check_body_size
permit
=head2 size limit
# Descriptions: maximum size limit of article header passed from MTA.
# History:
# Value: NUM
# Examples: 102400
incoming_command_mail_header_size_limit = $default_mail_header_size_limit
# Descriptions: maximum size limit of article body passed from MTA.
# History:
# Value: NUM
# Examples: 10240000
incoming_command_mail_body_size_limit = $default_mail_body_size_limit
# Descriptions: maximum size limit of deliverd article header.
# (not yet implemented ;-)
# History:
# Value: NUM
# Examples: 102400
outgoing_command_mail_header_size_limit = $default_mail_header_size_limit
# Descriptions: maximum size limit of deliverd article body.
# (not yet implemented ;-)
# History:
# Value: NUM
# Examples: 10240000
outgoing_command_mail_body_size_limit = $default_mail_body_size_limit
# Descriptions:
# History:
# Value: MIX ( command_mail_size_filter )
# Examples:
command_mail_filter_functions = command_mail_size_filter
=head2 size based filter
# Descriptions: use size based filter
# History:
# Value: YES_OR_NO
# Examples:
use_command_mail_size_filter = yes
# Descriptions: size based filter rules.
# first match.
# permit if no rule matched.
# History:
# Value: MIX (
# check_header_size
# check_body_size
# check_command_limit
# check_line_length_limit
# permit
# )
# Examples:
command_mail_size_filter_rules = check_header_size
check_body_size
check_command_limit
check_line_length_limit
permit
# Descriptions: cache size.
# it implies days if the cache mode is temporal.
# History: none
# Value: NUM
# Examples:
error_mail_analyzer_cache_size = 14
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Limit For Command Mail
fml8 provides restrictions such as "the number of commands in one command mail
message", "the number of articles in one command mail message", et.al.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mime Component Filter Rules
The format of fml8 mime component filter is space separeted. It is not fml4's
content filter rules.
text/plain permit
text/html reject
* permit
This filter supporse MIME, not including non mime operations. To identify the
whole type (e.g. text/plain) and the part type (e.g. text/plain in multipart/
mixed), we use the following format.
Whole message type part type action
----------------------------------------------
text/plain * permit
multipart/mixed text/plain permit
multipart/mixed text/html reject
multipart/mixed image/* cutoff
* * permit
the following operations are not implemented but needed ?
text/plain :uuencoded: cutoff
text/plain :size>500k cutoff
But there are several problems of rule construction.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
First Match Vs Last Match ?
This is a filter but not a router filter. Router filter is first match in
almost cases. But both first match and last match are not suitable for mime
component filter when we consider the meaning of "cutoff" operation.
( NOT TRANSLATED AFTER THIS )
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Discussion: Mime Component Filter Needs What Functions ?
( NOT TRANSLATED AFTER THIS )
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 36. Subscribe / Unsubscribe
Which Map Subscribe/Unsubscribe Is Operated To ?
Subscribe/unsubscribe is operated to $primary_*_map.
For example, subscription of remote administrators is operated into both
$primary_admin_member_map and $primary_admin_recipient_map. Unsubscription of
remote administrators is operated into both $primary_admin_member_map and
$primary_admin_recipient_map.
Why use primary_*_map ? If we use admin_member_maps and admin_recipient_maps,
it causes a problem.
Subscription should be operated into one map. So we should operate it into
primary_*_map.
Unsubscription must be same since xxx_maps is composed of different privileged
maps.
For example, $member_maps is as follows. It contais a list of member and a list
of remote administrators.
member_maps = $primary_member_map
$admin_member_maps
So unsubscription operated for $member_maps may cause unsubscription of remote
administrators. It is wrong logic.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 37. Command (Command Mail, CUI And GUI)
Modules for commands
In fml8, all command modules are shared among command mail, CUI (makefml, fml)
and GUI (CGI). Commands are caregorized into user and administrative ones by
the priviledge.
FML::Command class consists of the following classes:
FML::Command entrance into FML::Command. command dispatcher.
FML::Command::User command for general ML users.
FML::Command::Admin command for remote administrators.
For example, a user command in a command mail kicks off FML::Command firstly,
after some steps, calls FML::Command::User::$command where $command is the
specified command name.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
User Command In Command Mail
FML::Process::Command call FML::Command::User::$command for $command via
FML::Command.
FYI: some module calls FML::Command::Admin::$command for real work even if it
is a user command. For example, FML::Command::Admin::subscribe works for
subscription. In this case, FML::Command::User::subscribe module is a wrapper/
entrance for confirmation before the real subscription process runs.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Admin Command (Administrative Command In Command Mail)
It calles FML::Command::Admin::$command for $command via FML::Command via
FML::Process::Command.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CUI (makefml/fml)
FML::Process::Configure calls FML::Command::Admin::$command via FML::Command.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GUI (CGI)
FML::Process::CGI calls FML::Command::Admin::$command via FML::Command.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Data Flow Of Command Request Processing
All command processing calls FML::Command::MODE::COMMAND class via FML::Command
class. GUI, CUI and command mail has different pre processing stage.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Command Mail Procssing
┌─────────────────────────────────────────────────────────────────────────────┐
│ Caution │
├─────────────────────────────────────────────────────────────────────────────┤
│We adopt new frame work after 2004/03/05. │
└─────────────────────────────────────────────────────────────────────────────┘
Firstly, parse and analyze each line in one message.
An empty line is ignored. The buffer is clean up. After them, check if the
command line is allowed in our context.
For example,
1) if this command matches anonymous command such as "guide" or "subscribe",
call command processor. Allowd list of commands are defined in
$anonymous_command_mail_allowed_commands.
2) if this command matches a normal command which are allowd for a member,
check other conditions based on rules of $command_mail_restrictions. Allowd
list of commands are defined in $user_command_mail_allowed_commands.
Command dispatcher checks the return path dependent on the command and the
syntax, finally executes the command via FML::Command class. This process runs
as normal user priviledge.
"admin" command needs administrator priviledge. So an exception. If "admin"
command is given, process user priviledged "admin" command and execute
FML::Command::User::admin class. [12] In this user command class, checks the
context by $admin_command_mail_restrictions to see that the current context has
remote administrator priveledge. If enough priviledge is satisfied, execute
FML::Command::Admin::COMMAND class via FML::Command again.
FML::Command::Admin::COMMAND needs admin priviledge.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CUI (makefml/fml)
If you use this program, you can have priveledge to login the mailing list
server host and switch user to the user "fml". So please use CUI as you like.
In this case, CUI calls FML::Command::Admin::COMMAND directly.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Command Extension: Command Mail
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│To make a new local command usable for all ML's on this host, you need to put│
│the module you wrote at │
│ │
│/usr/local/lib/fml/site_local/ │
│ │
│. If the command is allowed only for the specifiec ML (e.g. elena ML), put it│
│at the ML local library path │
│ │
│/var/spool/ml/elena/local/lib/ │
│ │
│where $ml_home_dir = /var/spool/ml/elena. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Create A New User Command
Consider to make a new local user command "uja". Pick up a command at
FML::Command::User, cut and paste it. Please put it at
/usr/local/lib/fml/site_local/FML/Command/User/uja.pm
To permit the use of it for all ML's, edit site_default_config.cf to add it
into $commands_for_user to permit the user of "uja" command.
user_command_mail_allowed_commands += uja
It you allow the command only for the specific elena ML, edit /var/spool/ml/
elena/config.cf in the same way.
user_command_mail_allowed_commands += uja
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Create A New Admin Command Such As "admin uja"
In the same way described above, hack the module!:) but the module path
differs. Put it at the FML::Command::Admin:: class. For example
/usr/local/lib/fml/site_local/FML/Command/Admin/uja.pm
Edit site_default_config.cf to add it into $user_command_mail_allowed_commands
to permit the use of "admin uja" command.
admin_command_mail_allowed_commands += uja
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CUI Command Extension: makefml/fml
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│To make a new local command usable for all ML's on this host, put the module │
│you wrote at │
│ │
│/usr/local/lib/fml/site_local/ │
│ │
│If you permit the command is used only for the specifiec ML (e.g. elena ML), │
│put it at the ML local library path │
│ │
│/var/spool/ml/elena/local/lib/ │
│ │
│. │
│ │
│In this section, we consider the former case. In both cases, the module codes│
│are same. │
└─────────────────────────────────────────────────────────────────────────────┘
Create a module "uja" and put it at
/usr/local/lib/fml/site_local/FML/Command/Admin/uja.pm
You do not need to edit .cf files. The existence of module file enables the
command automatically in the CUI case since the usability of CUI implies
administrator use.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GUI Command Extension: CGI
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│You need another work to create a menu screen. │
│ │
│To make a new local command usable for all ML's on this host, put the module │
│you wrote at │
│ │
│/usr/local/lib/fml/site_local/ │
│ │
│If you permit the command is used only for the specifiec ML (e.g. elena ML), │
│put it at the ML local library path │
│ │
│/var/spool/ml/elena/local/lib/ │
│ │
│. │
│ │
│In this section, we consider the former case. In both cases, the module codes│
│are same. │
└─────────────────────────────────────────────────────────────────────────────┘
Craete a module "uja" and put it at
/usr/local/lib/fml/site_local/FML/Command/Admin/uja.pm
Edit site_default_config.cf to add it into $admin_cgi_allowed_commands to
permit the use of "uja" command.
admin_cgi_allowed_commands += uja
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
How Differ Coding Style Among fml4 And fml8
Consider localization of "help" command as an example of an fml command, which
sends back help message to the sender.
In the case of fml4, prepare myProcHelpFileSendBack() function and register it
at %LocalProcedure hash to enable it.
%LocalProcedure = (
'help', 'myProcHelpFileSendBack',
);
myProcHelpFileSendBack as follows:
sub myProcHelpFileSendBack
{
local($proc, *Fld, *e, *misc) = @_;
my $UJA_FILE = "/some/where/help";
&SendFile($Envelope{'Addr2Reply:'}, "UJA $ML_FN", $UJA_FILE);
}
In the case of fml8, the main code of help command locates at
FML::Command::User::help class. This class is called by FML::Process::Command
via AUTOLOAD of FML::Command.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│All fml8 commands are implemented at either of FML::Command::User or │
│FML::Command::Admin classes. Both CUI (makefml, fml) and GUI (CGI) uses │
│FML::Command::Admin class. Instead command mail users both classes according │
│to the context. │
└─────────────────────────────────────────────────────────────────────────────┘
The real content of help command is process() method in
FML::Command::User::help class.
sub process
{
my ($self, $curproc, $optargs) = @_;
my $config = $curproc->{ config };
my $charset = $config->{ report_mail_charset_ja };
my $help_file = $config->{ help_file };
# template substitution: kanji code, $varname expansion et. al.
my $params = {
src => $help_file,
charset_out => $charset,
};
my $help_template = $curproc->reply_message_prepare_template( $params );
if (-f $help_template) {
$curproc->reply_message( {
type => "text/plain; charset=$charset",
path => $help_template,
filename => "help",
disposition => "help",
});
}
else {
croak("no help file ($help_template)\n");
}
}
where $curproc is an object, which type is hash reference. It corresponds to
%Envelope of fml4. It contains several references to objects for this process.
For exmple, variable $config is an object holding configuration variables.
All variables of fml4 are global. Instead variables of fml8 locates within
configuration space accessed via $config object.
reply_message_prepare_template() converts the message language and expands the
arguments in the message templates.
$curproc->reply_message() inserts the specified mesage string into the message
queue of this process on memory.
The error/log messages queued in on memory are aggergated to one message at the
last of the current process. Mail::Delivery class handles the aggregation and
send it. If needed, the aggregator handles text strings or multipart properly
to build one message.
This mechanism is same as Notify() of fml4 but the last aggregator which
handles all at the last is different.
FYI: commands such as "get" for the file manipulation uses the same message
queuing mechanism. fml4's Notify() sends back immediately. Instead fml8's
mechanism is queuing based always. This fml8 mechanism is different from fml4's
Notify() fundamentally.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 38. Internal Of CGI Process
Method
FML::CGI class should implement the following methods:
html_start()
run_cgi_main()
run_cgi_title()
run_cgi_navigator()
run_cgi_menu()
run_cgi_command_help()
run_cgi_options()
html_end()
where html_start() prints out the header of HTML such as DOCTYPE ... BODY,
html_end() prints /BODY and /HTML. run_XXX methons prints the main content.
run() of $curproc method drives
html_start()
run_cgi_XXX()
html_end()
sequentially. That is, the flow of CGI process is as follows:
new()
prepare()
verify_request()
run()
html_start()
run_cgi_XXX()
html_end()
finish()
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Screen Of CGI And The Method
fml8 CGI script creates the screen:
header
space menu space
bar 1 main bar 2
space menu space
footer
The bar 1 and 2 are called as navigation bar.
html_start() generates header part(DOCTYPE ... BODY of HTML, NOT HTTP HEADER).
html_end() generates footer part.
Instead, BODY content generates 3 x 3 tables by using methods drived by run_cgi
().
9 sub methods called by run_cgi() generetes the following 9 pieces on the
screen.
nw north ne
west center east
sw south se
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Screen Of The Current CGI
CGI screen generates 3 x 3 table structure. The following methods generates the
corresponding part of the screen.
run_cgi_main
run_cgi_title
run_cgi_navigator run_cgi_menu run_cgi_command_help
run_cgi_options
These methods use TABLE to create 3 x 3 matrix. These methods are defined in
hash table. run_cgi() executes them sequentially.
run_cgi_main() print nothing if nothing to do. In almost cases, print just "OK
..." message. If needed, it shows error messages. run_cgi_main() runs before
all other methonds to print out the latest information.
run_cgi_main() is adapter layer defined at FML::CGI::Menu::Admin. Each command
is executed via this layer.
In a few cases such as showing log, listing up addresses, run_cgi_menu() print
out the data.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Screen And Trampolin Mechanism
CGI print engine is moved to FML::Command:: class. However FML::Command:: does
not contains all content of print engine. By object composition, some modules
use methods FML::CGI:: provides. For example, subscribe command internal is as
follows.
FML::CGI::Admin::Main ->
FML::Command::Admin::subscribe ->
FML::CGI::Admin::User ->
SCREEN
The flow goes and back again like trampolin mechanism.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MISC: Hard Coding Is Mandatory ?
FML::CGI::Admin::User contains the relation between $comname and maps. It is
hard-coded. But it cannnot be avoided.
If we move the relation to configuration space, we need a lot of variables in
it. It is better to use configuration variables for cusotomization, but ...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CGI Implementation: Inheritance Among CGI Classes
@ISA of config.cgi follows:
FML::CGI::Menu FML::Process::CGI::Kernel FML::Process::CGI::Param
In the case of thread.cgi, @ISA is
FML::CGI::Thread FML::Process::CGI::Kernel FML::Process::CGI::Param
.cgi specific codes locate at FML::CGI:: class layer.
FML::Process::CGI::Kernel provides the main part of CGI process and CGI
specific function run_cgi_XXX(). If needed, FML::CGI:: class overloads this
layer. Currently, the following methods in FML::Process::CGI::Kernel are not
used.
run_cgi_log
run_cgi_dummy
run_cgi_date
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CGI Implementation: config.cgi
@ISA of config.cgi is as follows:
FML::CGI::Menu FML::Process::CGI::Kernel FML::Process::CGI::Param
Let see processing of config.cgi below.
config.cgi process object $curproc is a FML::Process::CGI::Kernel class.
new()
prepare()
verify_request()
run()
finish()
is sequentially called from FML::Process::CGI::Kernel class.
run() is important. run() executes the following methods sequentially.
$curproc->html_start(); (FML::CGI::Menu)
$curproc->_drive_cgi_by_table(); (FML::Process::CGI::Kernel)
$curproc->html_end(); (FML::CGI::Menu)
_drive_cgi_by_table() prepares the screen. This function calls the main part of
CGI.
$curproc->_drive_cgi_by_table() calles the following run_XXX() methods.
run_cgi_main (FML::CGI::Menu)
calls cgi_execute_command (FML::Process::CGI::Kernel) to execute
FML::Command::Admin::$COMMAND via FML::Command class. This is the main part of
command execution via CGI but the screen creation is a role of another part.
For example, consider subscribe an address via CGI. run_cgi_main() executes the
real process of subscription. Instead run_cgi_menu() creates input menu. Former
calls FML::Command::Admin::subscribe::process() method, latter calls
FML::Command::Admin::subscribe::cgi_menu() method.
There are several other run_cgi_XXX() methods. They are optional for screen
creation.
The following run_cgi_XXX() uses the default method.
run_cgi_title FML::Process::CGI::Kernel (show title)
run_cgi_options FML::Process::CGI::Kernel (show language selection)
.cgi specific methods are as follows:
run_cgi_navigator FML::CGI::Menu
run_cgi_help FML::CGI::Menu
run_cgi_command_help FML::CGI::Menu
run_cgi_menu FML::CGI::Menu
run_cgi_menu() executes FML::Command::Admin::COMMAND::cgi_menu() via
cgi_execute_cgi_menu() method.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 39. Directory
Q: How Recursively Sub Directory Can Be Created ?
The structore holding the html-ized article is as follows:
200201/msg\d+.html
One sub-directory by default.
Consider directory listing. "ls" returns 1000 files soon, but 10000 files a
little slowly.
To accelerate listing, we should use sub-directory structure. For example, each
sub-directory holds 1000 files. The structure such as "spool/sub/file" holds 10
^6 ( million ) files and listing of it is fast.
It must be enough to assume that 1 million articles for one ML.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipes
1. Where directory names are defined ?
1. Where directory names are defined ?
There are default definitiions at /usr/local/etc/fml/defaults/$VERSION/
default_config.cf file. Each config.cf of each ML overloads them. Use fmlconf
command to show the current value.
% fmlconf $ml_name | grep _dir
You can extract values from config object in a hook.
$_xxx_hook = q{
my $config = $curproc->config();
my $xxxdir = $config->{ some_where_dir };
... snip ...
}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 40. Restrict Input Data
fml8 checks the input by regular expression FML::Restriction class provides.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Overview: Checks Of Input Data
Restriction For Article Posting
Restrictions for article are ambiguous or too restrictive. In fact
FML::Restriction class does not provide restriction rules for article posting.
Instead FML::Filter filter system checks each line of content.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Restrictions For Command Mail
FML::Process::Command class parses each line of the command mail and checks the
input by regular expressions FML::Restriction::Command provides. If the check
is passed, fml8 calls FML::Command::{User,Admin}::COMMAND at the next step.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CGI
CGI programs can receive the input from HTTP via only safe_param_XXX() method.
It is expected that safe_param_*() and try_cgi_*() returns the safe value.
These safe_param_XXX() functions checks the input by regular expressions
FML::Restriction::CGI provides (FML::Restriction::CGI inherits
FML::Restriction::Base).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
makefml / fml
CUI runs on the shell. It means he/she who runs CUI has priviledge to log in
the mailing list server. So it does not check the input.
Each module checks the input independetly in that case though no checks by
FML::Restriction at the entrance. For example, "adduser" module checks whether
the input address is valid or not even in the case of CUI. These restrictions
are dependent command specific modules. These are applied even in the case of
CUI.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FML::Restriction Class
ACLs for the input data and commands are found at FML::Restriction class.
For example, CGI modules use FML::Restriction::CGI class to check if the input
data matches the proper regular expression.
Though FML::Restriction inherits FML::Restriction::Base class, fundamentally
each module should use FML::Restriction as object composition. For example, use
in the following way:
use FML::Restriction::CGI;
$safe = new FML::Restriction::CGI;
my $allowed_regexp = $safe->param_regexp();
if ($value =~ /^$allowed_regexp{$key}$) { ... ok, do something ... ;}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
How CGI Restricts The Input
CGI checks the input data by using FML::Restriction::CGI class.
The input should be restricted by FML::Restriction class. We should not use
param() method provided by perl's CGI class. Instead use safe_param_xxx()
method always to get value.
The following use may be allowed
for my $dirty_buf (param()) {
... check ...
}
but we should not use raw param() call.
param($dirtty_buf)
Instead, use safe_param_key().
for my $key (param()) {
... check ...
if (key eq $key) {
value = safe_param_key()
}
}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Discussion: FML::Restriction Is Too Restrictive ?
FML::Restriction class allows a subset of RFC defined expression.
RRC definition is too large. It is too difficult to implement it ;-) We
restrict the expression a little.
FML::Restriction::Command may be more granular but more granular version is not
implemented.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 41. User Authentication
User authentication is provided by methods of FML::Credential class.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Discussion: FML::Credential Implementation
Case Sensitive / Case Insensitive
For the user@domain address, we handle user part as case sensitively and domain
as case insensitively. Is it better to prepare the option that handling of user
part is insensitive? (Yes, I think so.)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 42. Hook
Overview
Hooks are required to resolve complicated problems or for compilcated
customization. But there are several problems in implemantation.
One problem is naming convension. $START_HOOK of fml4 is ambiguous. It means
the location in process but not clarify where in which process. So, fml8 hook
naming convension has role and function in it.
$ROLE_FUNCTION_start_hook
$ROLE_FUNCTION_end_hook
There is no common hook among processes. Each process has each hook. In other
words, there is no common hook. You need to define plural hooks for different
processes even if the hook is same content.
$distribute_XXX_start_hook = q{ ... };
$YYY_XXX_start_hook = $distribute_XXX_start_hook;
Coding style of hooks are expected not too restrictive since perl beginners may
code it. fml8 modules have
use strict;
definition but not effective in evalauating hooks. In evaluating a hook, fml8
evaluate it as
no strict;
HOOK CONTENT
to disable the strict check.
Function scope differs among fml4 and fml8. In fml4 all functions are global.
Instead in fml8 functions are methods, which is not called anytime anywhere. We
should provide hooks when we can see $curproc.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Hook Naming Convension
Hook standard form is
ROLE_METHOD_start_hook
ROLE_METHOD_end_hook
The role is "ROLE" part of $use_ROLE_function (e.g. $use_article_post_function)
in configuration variables. This hook directory corresponds to some variables
in configuration. More granular hooks do not match this rule.
For example, the main part of fmlconf command, run() method, provide the
following hooks:
fmlconf_run_start_hook
fmlconf_run_end_hook
The actual code calling hooks as follows:
sub run
{
my ($curproc, $args) = @_;
my $config = $curproc->{ config };
my $eval = $config->get_hook( 'fmlconf_run_start_hook' );
if ($eval) {
eval qq{ $eval; };
print STDERR $@ if $@;
}
$curproc->_fmlconf($args);
$eval = $config->get_hook( 'fmlconf_run_end_hook' );
if ($eval) {
eval qq{ $eval; };
print STDERR $@ if $@;
}
}
This case is fundamental. More granular hooks must be needed. The naming
convension may differ from this convension.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Recipes
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 43. Virtual Domain
2003/10: We enhanced fml8 to handle virtual domains as same way as default
domain.
It is difficult to handle virtual domains and the default domain in the same
way.
One proper enhancement is using "user@domain" form for the ML name as an
argument of commands. For example, for a virtual domain, use makefml like this
% makefml newml mlname@virtualdomain
The following two syntaxes are acceptable for the default domain.
% makefml newml mlname@defaultdomain
% makefml newml mlname
Fml treats these properly as could as possible. But fml needs some hints such
as ml home directory information for each domain. You need to prepare /usr/
local/etc/fml/ml_home_prefix file for a hint on mappping between domain and
directory.
This file name is defined as $ml_home_prefix_maps (formerly $virtual_maps) in
main.cf. $virtual_maps is obsolete but effective now for compatibility.
To handle $ml_home_prefix_maps, you can use "makefml newdomain" and "makefml
rmdomain".
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Overview: virtual domain handling in fml8
It is easy in use. For the first time to use a virtual domain, run "newdomain"
command to add {domain => directory} relation to ml_home_prefix_maps (precisely
primary_ml_home_prefix_map).
After that, you can use "user@domain" form in makefml arguments in handling
virtual domains.
makefml newml ML@virtualdomain
makefml add ML@virtualdomain address
makefml bye ML@virtualdomain address
Instead, for the default domain, definitions in ml_home_prefix_maps is not
needed and either of user and user@domain is accpetable.
When you use CGI, you need not to use user@domain syntax since config.cgi knows
the domain name the cgi handles.
http://lists/~fml/cgi-bin/fml/$domain/admin/config.cgi
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│The domain name is hard-coded within config.cgi since makefml injects the │
│domain name in creating config.cgi when "makefml newml" runs. That is, │
│"config.cgi" does not resolve its domain by the URL. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case study: movement ?
*** SORRY, NOT YET WRITTEN ***.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 44. Errormail Analyzer (libexec/error)
fml8 error (/usr/local/libexec/fml/error) program corresponds to mead (/usr/
local/fml/libexec/mead) of fml4
Set "$use_error_mail_analyzer_function = yes" to enable error mail analyzer
function. By default, $use_error_mail_analyzer_function is "yes". That is, fml8
error analyzer is enabled by default but fml4 not. This default behaviour
differs from fml4.
In fact, typical functions of fml8 are enabled by default.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Overview
In creating a ML, fml8 sets up that $ml-admin address (address error messages
returned to) calls /usr/local/libexec/fml/error.
/usr/local/libexec/fml/error reads a message, analyzes it and creates a chain
of Mail::Message objects on memory. Mail::Bounce class analyzes the detail of
error based on the objects.
Mail::Bounce analylzes which MTA generates the error, which address generates
the error, and the error reason.
The result is cached at $error_mail_analyzer_cache_dir directory.
After some time interval, $error_mail_analyzer_function analyzes the cache data
to determine if an address is effective or not. If some address is determined
to be removed, fml8 removes it from member/recipient list.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Algorithm Of Error Detection
Functions of $error_mail_analyzer_function_select_list are available to
determine error or not. Currently "simple_count histgram" and "histgram"
algorithm are supported. "histgram" is used by default.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Algorithm: simple_count
Count up the number of error messages from an address and determine whether the
address is effective or not.
This logic depends on just the total number of errors. If the traffic of ML is
high, even a little configuration error of recipients caueses removal of the
address soon. This is the main problem of this logic.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Algorithm: histgram
Count up the number of continuous days that error messages returned. If the
number oversomes the threshold, fml8 removes the corresponding address. The
threshold is 14 days by default. That implies continuous errors in 14 days.
This logic assumes that the traffic of an ML is at least one message per day.
In other words, this logic requires the continuous error. So, little
configuration error in the side of recipient has no effect.
fml8 uses this algorithm by default.
Caution: If the traffic of the ML is too little under at least one message per
day, this algorithm does not work.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Cache Of Error Messages Data
Error messages data is cached at $error_mail_analyzer_cache_dir directory.
IO to cache uses Tie::JournaledDir class via FML::Error::Cache.
FML::Error::Cache is a front end (adapter layer) for Tie::JournaledDir class.
All IO should be done via methods provided by FML::Error::Cache.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Forward Error Messages
You can specify the location the error message is forwarded to as
$maintainer_recipient_maps variable.
Undefined by default. Error messages are logged at a log file but not
forwarded.
If enabled, this function forwards the error messages. Just forward it as mime/
multipart which contains one messages/rfc822 part.
FUTURE PLAN: we forward error messages with the analyzed data.
REFERENCE: fml-devel ML 451 around
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 45. IO Interface And Operations
We need IO abstraction layer for porting and extension. See Vnode/VFS interface
(vnode(9)) on IO abstraction.
struct vnode {
...
voff_t v_size; /* size of file */
int v_numoutput; /* num pending writes */
long v_writecount; /* ref count of writers */
...
int (**v_op)(void *); /* vnode ops vector */
...
void *v_data; /* private data for fs */
};
vop_open(), vop_read(), vop_getattr(), ... are defined over v_op.
**v_op (vnode operation vector) corresponds to a method of object oriented
programming. fml8 provides IO::Adapter class as IO abstraction layer.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Fundamentals Of IO::Adapter
IO::Adapter is most fundamental in fml8 architecture. It is well considered and
implemented. It provides enough primitive methods.
IO::Adapter class abstracts
KEY => VALUE
or
KEY => [ VALUE, VALUE2, VALUE3 ]
type data structure. It is similar to RDBMS theory like this.
KEY1 VALUE1-1 "" ""
KEY2 VALUE2-1 VALUE2-2 VALUE2-3
KEY3 VALUE3-1 VALUE3-2 VALUE3-3
KEY4 VALUE4-1 VALUE4-2 VALUE4-3
To maintain address list, least fundamental methods of IO::Adapter are
open()
close()
and IO operations to the object
add(KEY, ARGV) (ARGV is class dependent)
delete(KEY)
find(KEY or REGEXP)
get_next_key()
methods. At least, enough to write user management codes.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Methods / Operation Vector
Mentioned above, the fundamental methods of IO::Adapter are as follows:
open()
close()
add(KEY, ARGV) (ARGV = class dependent)
delete(KEY)
find(KEY or REGEXP)
get_next_key()
Other than these methods, new() as a constructor and destructor() are needed.
The constructor is new() methond. For example, use like this;
$obj = new IO::Adapter MAP;
The argument is a map which calls map dependent constructor.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
open()
For a file, call open(2), for RDBMS, connect to the specified SQL server.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
close()
Reverse of open().
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
add(KEY, ARGV)
add KEY (primary key) or KEY and the associated VALUE into the object. ARGV is
class dependent.
We assume an object is composed of a form. It is similar to RDBMS.
The primary key is a mail address. This assumption is correct in the case of
mailing list driver. This is basic data structure.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
delete(KEY)
Delete KEY and the associated VALUE.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
find(KEY) / find(REGEXP)
Search data corresponding with the primary key within an object.
The target is specified as regular expression. Regular expression search is
useful.
The return value is STR of ARRAY_REF (KEY => [ VALUE, VALUE2, VALUE3 ]).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
get_next_key()
Return the list of primary keys like this:
while ($obj->get_next_key()) { ... }
This operation corresponds to FIRST_KEY() and NEXT_KEY() of perl hash.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Discussion
What ARRAY_REF return ?
What expected in using ARRAY_REF as the return value ? A list of PRIMARY KEY ?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
How To Get All Primary Keys ?
We need to call get_next_keys() again and again to retrieve all keys. It may be
useful to implement special method to return a list of keys but it is not
implemented.
get_primary_keys() ? find('*', { all => 1 }) is used for this purpose. It is of
no use to implement specific method for this.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
HASH_REF As Return Value ?
What expected ?
RETURN VALUE = {
KEY_1 => VALUE_1,
KEY_2 => VALUE_2,
}
If a mail address has several attributes, this method is useful. For example,
consider digest delivery:
ADDRESS => {
internal => 3 hours,
compression => no,
format => mime/multipart,
};
Abstracted Cache IO layer is this type such as:
FML::Error -> FML::Error::Cache -> Tie::JournaledDir
But ... dependent on Tie::* hmm ..
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 46. Lock
Synchronization among processes uses lock. fml8 provides flock(2) or lockf(2)
based lock mechanism.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Overview: Lock
After 2003/03, fml8 provides more granular not giant lock.
Each resource defines each lock channel name.
For example, Mail::Delivery related class accesses the member list. It needs
several locks.
Mail::Delivery::SMTP needs lock of member list. FML::Send and
FML::Process::Delivery locks member list access in callling
Mail::Delivery::SMTP.
Instead Mail::Delivery::Queue just sees the mail queue. The function can access
the queue concurrently, also. So this module does not need lock.
Generally speaking, modules using maps require lock. For example, FML/Command/
UserControl.pm and FML/Command/Auth.pm needs write lock, but FML/Credential.pm
needs only read lock.
It is useful if fml8 provides reader writer lock. But it is not implemented.
Currently we attension we use short critical region.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
TODO
Mutex lock in calling *_maps.
READER WRITER LOCK in calling IO::Adapter.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 47. Database Related Modules
Overview
ML driver needs to hold some data on mail. Some data exixsts persistently but
some data with expiration (data is discarded after some interval).
An example of permisistent data is thread database. The latter case, an exapmle
of non persistent data, is message-id cache. The thread database also has
message-id cache in it, which is a sub-set of all message-id set of incoming
messages. We handle these two data separately.
We should handle these data in integrated way.
module A ---| A |--- persistent database
module B ---| da |
module C ---| pt |
modlue D ---| er |--- cache with expiration
An example of this persistent DB, thread DB, is Mail::Message::DB class.
Examples of cache database are Tie::JournaledDir and FML::Cache::Ring classes.
It is better to use RDBMS for important persistent data such as address list.
This chapter describes persistent data handling only for fml8 internal use.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Persistent Data Use
Handling of persistent data is important. We should consider use of DBMS [13]
for important data.
This chapter describes only fml8 internal use.
fml8 provides two type of cache databases. The type is time saving or space
saving.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Tie::JournaledFile Class
This class appends data into a file. Tie::JournaledFile class provides this
function.
This class is append only. It is similar to LFS (Log Structured File System).
Operation to extract a value is to get the latest (last appended) value. That
is, the last match.
In other words, data cache logs all data to enable back track.
We cannot restrict the maximum size of this cache. This class holds data within
some period without size limitation. We control cache expiration by time.
To get the following structure as a result, you can use
get_all_values_as_hash_ref() method.
key => [
log1 (line A of file 1),
log2 (line B of file 2),
log2 (line C of file 3),
]
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│Search algorithm is either of first match or last match. The last match by │
│default since the last appended data is latest. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FML::Cache::Ring Class
FML::Cache::Ring holds data with size limit but without time limitation.
It is suitable for debug since the debug data is expected not to eat disk.
This class holds data in files in a directory such as $ml_home_dir/var/db/. For
example, files named as db/1 .. db/100 are created. These files are used
repeatedly.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Warning │
├─────────────────────────────────────────────────────────────────────────────┤
│RingBuffer class is integrated into FML::Cache::Ring class. FML::Cache::Ring │
│is derived from File::CacheDir class. │
└─────────────────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 48. Database Management System
This chapter describes how to handle persistent data. You should use DBMS
(DataBase Management System) for that data. See Chapter 47 on the internal use
database.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Overview
Communication with DBMS (database management system) via IO::Adapter class.
This class provides fundamental functions such as insersion and deletion of
data. If more complex operation is needed, the preprocessing module calling
IO::Adapter should handle it.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 49. Convert Another ML System To fml8
Implementation: fml4 To fml8
Case 1: /var/spool/ml/elena/ From fml4 To fml8
This conversion does the following steps in fact.
1) install fml8 firstly. In this case, add /var/spool/ml/etc/mail/aliases into
$alias_maps of postfix main.cf. /var/spool/ml/etc/mail/aliases may be empty.
2) run "makefml --force newml elena" to create several files fml8 needs.
3) convert address lists in /var/spool/ml/elena to fml8 style.
3-1) IO::Adapter ignores a line beginning with '^#' as a comment. We should
handle carefully it since "actives" file contains ^# lines as "off" address.
3-2) s=skip (off) options is ignored. It handles as "on".
3-3) m=... (digest) options is ignored. Also, "# address" is "off" in the case
of fml4 but ignored in the case of fml8. We should warn it ?
4) remove the corresponding entry of alias file (/var/spool/ml/etc/fml/aliases)
of fml4 and rebuild .db.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case 2: Convert The Whole /var/spool/ml/ From fml4 To fml8
Apply case 1 for all ML's.
If we can stop all ML's, it is easy to remove /var/spool/ml/etc/fml/aliases of
fml4 firstly and apply case 1 steps. Please stop MTA in migration.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Discussion: Use Half And Half Of fml4 And fml8 Softwares.
(X-Sequence: fml-devel 389)
How in half and half case.
For example, site_init.ph or config.ph of fml4 follows
[fml4]
push(@ACTIVE_LIST,"$DIR/recipients") if( -f "$DIR/recipients" ) ;
instead in the case of fml8 site_default_config.cf or config.cf follows:
[fml8]
html_archive_dir = $ml_home_dir/htdocs
VIII. Modules
This part descripbes how to use most important modules.
Table of Contents
50. IO Abstraction Layer (IO::Adapter Class)
51. Mail::Message Module
52. Language Dependent Functions
53. Mail::Message::Encode Class
54. Execise: Create A New Program
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 50. IO Abstraction Layer (IO::Adapter Class)
IO::Adapter Overview
All IO of fml8 should use IO::Adapter class like vfs/vnode framework. For
example, read/write member list, add/remove a user. The usage is like this:
use IO::Adapter;
$obj = new IO::Adapter $map, $map_params;
$obj->open || croak("cannot open $map");
while ($x = $obj->get_next_key()) { ... }
$obj->close;
$map is map:identifier. file: can be omitted. Currently available maps follow:
file:/var/spool/ml/elena/recipients
unix.group:root
nis.group:root
mysql:id
postgresql:id
ldap:id
"file:" map is a normal file (text file). "unix.group:root" map is to read root
entry in /etc/group file. "nis.group:root" map is to read root entry in NIS
(YP). "mysql:id" map implies the use of MySQL. Parameters for MySQL access is
defined in "mysql:id" entry. These paraemeters should be specified before
calling "new IO::Adapter".
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
IO::Adapter Methods
Official methods IO::Adapter provides currently follow:
new()
open()
close()
get_next_key()
add(KEY)
delete(KEY)
getpos()
setpos(NUM)
eof()
touch()
find(REGEXP, $args)
KEY is a primary key to handle database access. In almost cases, the primary
key is a mail address. REGEXP is a regular expression (regexp), this is usually
also a mail address.
Unification of all types of IO needs that we should implement least methods.
The currently implemented methods are selected by test and our operations. If
could, we refer SQL IO more than file IO as an abstraction base model of
IO::Adapter. It introduces difference between fml4 and fml8 but it is mandatory
for further abstraction.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Argument Type Of Methods
The argument needs nothing, STR or ARRAY_REF as the argument and the return
value is STR. get_next_key() is typical as the no argument case. This method is
used to list up the content of files or retrieve the specific address in the
file.
In other case, the return value may be a pair of strings.
KEY_STR => [
VALUE_STR_1
VALUE_STR_2
VALUE_STR_3
]
This is used as the return value to represent ARRAY_REF. For example, "actives"
file of fml4 consists of lines which have plural space separeted entries. So it
can be representated as a type of array.
rudo@nuinui.net s=skip m=xxx.yyy.z # commnet
rudo@nuinui.net => [
s=skip
m=xxx.yyy.z
# comment
]
If retrieval value could be represented as ARRAY_REF, argument of store
operations alsot needs ARRAY_REF.
It is summarized as follows. The argument is one of "nothing", "STR" or
ARRAY_REF. The return value is either of STR of ARRAY_REF (array reference).
argument return value
---------------------------------------
none => STR
STR => STR
none => [STR, STR, ... ]
STR => [STR, STR, ... ]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
File Map
"file:/some/where/file/name" or file name "/some/where/file/name" map is
abstraction of IO to/from a text file. The format of text file is space
separated.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Unixgroup Map
Abstraction of /etc/group. IO is read only.
For example, the access to
wheel:*:0:root,rudo,kenken
in /etc/group is "unixgroup:wheel" map in IO::Adapter.
$obj = new IO::Adapter "unixgroup:wheel";
If you call get_next_key() method for this object, you will get the member of
wheel group sequentially. In other words the wheel group is regarded as the
following file by IO::Adapter.
root
rudo
kenken
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Nis Map
It is same as one of /etc/group but the data is retrieved from NIS/YP.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MySQL Map
For easy maintenance, it is better to write all mysql configurations in one
file. For example, it is good that we have only to write SQL configurations in
config.cf.
But we identify plural mysql conditions. So, we use the tag [mysql:members] to
declare one region between a tag to the next tag or =cut. It is similar to .ini
file format used on Microsoft OS. We use the tags like this:
config.cf example
member_maps = mysql:members
recipient_maps = mysql:recipients
[mysql:members]
sql_server = localhost
sql_user = fml
sql_password = uja
sql_database = fml
sql_table = ml
sql_find = select * from ...
...
In calling IO::Adapter, use
new IO::Adapter "mysql:members", $config;
where $config is a hash reference holding some paremeters like this:
$config => {
[mysql:members] => {
sql_sever => localhost
...
}
}
FML::Config prepares this $config by reading .cf files. Hence, we usually use
FML::Config object as an argument of IO::Adapter::new() method.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Discussion: How To Write SQL Statements In config.cf ? (fml-devel 204)
How about lexical scope ? The .cf files cannot contain all variables since
lexical scope variables exist. We use &varname syntax for such lexical scope
variables.
For example, use different member and recipient maps. In SQL statements, the
difference is a flag (fml_recipient) in a table. For example, consider the case
that "where" statement has different value but it is determined lexically in
calling MySQL.
member_maps = mysql:members
recipient_maps = mysql:recipients
[mysql:members]
sql_server = localhost
sql_user = fml
sql_password = uja
sql_database = fml
sql_table = ml
sql_get_next_key = select fml_address from $sql_table
where fml_ml = '$ml_name'
and
fml_domain = '$ml_domain'
sql_getline = select * from $sql_table
where fml_ml = '$ml_name'
and
fml_domain = '$ml_domain'
sql_add = insert into $sql_table
values ('$ml_name', '$ml_domain', '&address', 1, 1)
sql_delete = delete from $sql_table
where fml_ml = '$ml_name'
and
fml_domain = '$ml_domain'
and
fml_address = '&address'
sql_find = select * from $sql_table
where fml_ml = '$ml_name'
and
fml_domain = '$ml_domain'
and
fml_address like '®exp'
[mysql:recipients]
sql_server = localhost
sql_user = fml
sql_password = uja
sql_database = fml
sql_table = ml
sql_get_next_key = select fml_address from $sql_table
where fml_ml = '$ml_name'
and
fml_domain = '$ml_domain'
and
fml_recipient = '1'
sql_getline = select * from $sql_table
where fml_ml = '$ml_name'
and
fml_domain = '$ml_domain'
and
fml_recipient = '1'
sql_add = update ml
set recipient = 1
where fml_ml = '$ml_name'
and
fml_domain = '$ml_domain'
and
fml_address = '&address'
sql_delete = update ml
set recipient = 0
where fml_ml = '$ml_name'
and
fml_domain = '$ml_domain'
and
fml_address = '&address'
sql_find = select * from $sql_table
where fml_ml = '$ml_name'
and
fml_domain = '$ml_domain'
and
fml_recipient = '1'
and
fml_address like '®exp'
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 51. Mail::Message Module
Mail::Message Overview
Mail::Message object provides several methods to analyze a message and
manipulate messages or parts of a message.
Precisely speaking, this module analyzes the specified mail message and build a
chain of Mail::Message objects.
If not multipart
header -> body
else if multipart
header -> preamble -> part1 -> part2 -> ... -> trailor
The link between objects is double link list. Mail::Message class provides
several methods to manipulate these structures.
Each part of this chain is a Mail::Message object. In other words, one mail
message consits of a chain of plural Mail::Message objects in fml8 internal.
For example, "header" is a Mail::Message, which type is text/rfc822-headers and
the data is stored as Mail::Header object. Instead "part1" is a Mail::Message
object, which type is text/plain and the data is reference to the message
string.
References: Mail::Message module manual.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message Module: Analyze
parse() analyzes the file. The argument is the file name or the file handle for
the file which should be specified at the argument.
data_type_list() returns information of the chain. The return value is array
reference. For example, MIME/multipart consists of the following objects.
type[ 1]: text/rfc822-headers | multipart/mixed
type[ 2]: multipart/mixed | multipart/mixed
type[ 3]: multipart.preamble | multipart/mixed
type[ 4]: multipart.delimiter | multipart/mixed
type[ 5]: text/plain | multipart/mixed
type[ 6]: multipart.delimiter | multipart/mixed
type[ 7]: image/gif | multipart/mixed
type[ 8]: multipart.close-delimiter | multipart/mixed
type[ 9]: text/plain | multipart/mixed
The center row is the object type, the right one is the mime type of the whole
message (content-type in the mail header).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message Module: Create A New Object
new() method is used to create a new object chain.
The following MIME/multipart specific methdos exist.
build_mime_multipart_chain($args)
parse_and_build_mime_multipart_chain($args)
build_mime_header($args)
These methods are used internally now. So these will become private methods in
the furure. Please do not use these methods.
To create a new MIME/mulitpart message, use Mail::Message::Compose. It is
MIME::Lite class in fact :-)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message Module: Header Manipulations
dup_header() method duplicates only header part of a chain and left the body
part as it is. The new chain has different head (header object) but others
begining from the second part is same as the original chain.
|<--------------- mail body ------------->
header0 ----> part1 -> part2 -> ...
A
|
dup_header0 ---
whole_message_header() returns the header object of the chain. The return value
is a Mail::Message object not string.
header_data_type() returns the type of the whole message as string. It tells
whether this message is text or multipart.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message Module: Manipulate Messabe Body
Consider the following object chain.
If not multipart
header -> body
else if multipart
header -> preamble -> part1 -> part2 -> ... -> trailor
header_data_type() return the type of the whole type. It is known from
Content-Type: in the whole message header.
whole_message_body() returns body or part1 if multipart.
whole_message_body_head() is same.
find_first_plaintext_message($args) return the first text/plain type object in
the chain. This is useful in filter codes since filter system checks the first
text field in a lot of cases.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message Module: Search
find() searches the specified type of Mail::Message in the object chain and
returns the first matched object.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message Module: Print
print() method is usual print() function. Usually specify the file descriptor
as an argument.
print() has the concept "mode" to specify CRLF or LF. use set_print_mode(mode)
and reset_print_mode() to set the mode. By default, mode is raw. Specify smtp
mode in using print() within SMTP codes.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message Module: Utility Functions
Size
size() returns the size of the object not the whole message size.
is_empty() tells the object data is empty or not.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
General Information
envelope_sender() returns the envelope sender as string.
data_type() returns the type of the object (a part of an object chain) not the
whole message type (Content-Type: in the whole message header).
encoding_mechanism() returns the encoding mechanism of the object (a part of an
object chain) as string. This is not of the whole message encoding mechanism.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message Internals
num_paragraph() returns the number of paragraphs in the data of the object.
nth_paragraph(N) returns N-th paragrah as the string. Caution that N starts
from 1 not 0.
header() returns the header part of a multipart block (header part of an
object). data() returns the data part (data part of an object). Respectively,
alias of message_fields($size) and message_text($size).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
References
Mail::Message manual
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 52. Language Dependent Functions
fml8 needs language dependent functions internally. Especially, JIS to/from
EUC-JP Janapese code conversion is used anywhere since Japanese mail messages
are written in JIS code but programs are easy to use strings in EUC-JP.
See message internationalization for the language dependence handling in
messages.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Something::Language:: Class
Language dependent module locates at Something::Language.
For example, there are
FML::Language::Japanese::String
Mail::Bounce::Language::Japanese
, The former provides Japanese dependent string functions. The latter provides
Japanese dependent error mail analyzer functions.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 53. Mail::Message::Encode Class
[References] fml-help ML's Count: 02012, 02013, 02016.
[Usage]
use Mail::Message::Encode;
my $encode = new Mail::Message::Encode;
my $str_euc = $encode->convert( $s, 'euc-jp' );
my $str_euc = $encode->convert( $s, 'euc-jp', 'iso-2022-jp' );
my $encode = new Mail::Message::Encode;
my $status = $encode->convert_str_ref( \$s, 'euc-jp' );
my $status = $encode->convert_str_ref( \$s, 'euc-jp', 'jis' );
my $fp = sub { ... };
$encode->run_in_chcode( $fp, $oout, $in );
* If you want to use 4.0 compatible functions,
ues Mail::Message::Encode qw(STR2EUC);
my $euc_s = STR2EUC( $s );
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Mail::Message::Encode Specification
The main code is within _convert_str_ref() method.
sub convert # if the argument is STR.
{
my ($self, $str, $out_code, $in_code) = @_;
_convert_str_ref(\$str, $out, $in);
return $str;
}
sub convert_str_ref # if the argument is STR_REF.
{
my ($self, $str, $out, $in) = @_;
_convert_str_ref($str, $out, $in);
}
sub _convert_str_ref # if the argument is STR_REF.
{
my ($str, $out, $in) = @_;
# 1. speculate charset
if $in unspecified -> speculat -> fail -> return 0
# 2. try conversion
if ($in resolved or or $in specified in @_) {
converted to $out charset
(use jcode, Jcode, use Encode if perl version > 5.8).
conversion
return 1 ; # success
}
else { # principle of least surprise ?
nothing todo ;
return $str;
}
return 0 ; # failed
}
sub base64 {}
sub quoted_printable {}
is implemented for convenience.
$x = $encode->base64($s);
For backward compatibility, STR2XXX() functoins are prepared, too.
STR2EUC( $str, [$icode] )
STR2JIS( $str, [$icode] )
STR2SJIS( $str, [$icode] )
These wraps convert_str_ref().
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
run_in_chcode()
In language dependent processes, convert the charset to machine friendly one,
process something and back it to the original chaset each time. This step is
widely used. So it is convenient to prepare a function to pack these steps into
one function.
run_in_chcode example:
sub run_in_chcode
{
my ($self, $proc, $s, $out_code, $in_code) = @_;
my $conv_status = convert_str_ref($s, $EUC_JP, $in_code);
my $proc_status = &$proc($s, @_);
convert_str_ref($s, $out_code, $EUC_JP) if $conv_status && $out_code;
return wantarray ? ($conv_status, $proc_status): $conv_status;
}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Chapter 54. Execise: Create A New Program
Consider creation of a simple scheduler listing tool in the fml8 framework.
Here the program name is "fmlsch" and the cgi is "fmlsch.cgi".
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: Create A fmlsch
Step 1: Add fmlsch Into Installer Configuration
Prepare fml/bin/fmlsch.in, add fmlsch into $bin_programs in fml/etc/
install.cf.in. Run configure to re-create fml/etc/install.cf.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Step 2: Build A Module
Write fml/lib/FML/Demo/Calendar.pm as the main library of fmlsch.
Import other libraries if needed. For fmlsch we import
HTML-CalendarMonthSimple-1.02.tar.gz from CPAN. See cpan/ directory.
Also, install Date-Calc if your system has not it.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Step 3: Modify FML::Process:: Class
FML::Demo::Calendar works mainly. We need to prepare FML::Process class for
fml8 bootloader to call FML::Demo::Calendar.
Firstly, write mandatory methods for fmlsch process in fml/lib/FML/Process/
Calender.pm. You need to create this file.
Secondly, set up boot loader configuration. In the case of fmlsch, the
bootloader loads FML::Process::Calender. Define it in fml/etc/modules. Set up
fml/etc/command_line_options properly. This "command_line_options" file has a
map between a command and the command line options parsed by Getopt::Long().
Create FML::Process::Calender module by copy-and-pasting other FML::Process::
modules :-) Though fmlsch has only to contain least functions, you need to
write FML::Process::Calender::run() method. For undefined methods, fml loads
FML::Process::Kernel functions (inheritence).
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Case Study: fmlsch.cgi
The way of hacking is similar to fmlsch. The differnce is the target to modify,
which is FML::CGI:: class. FML::CGI::Calender is a sub-class of
FML::Process::CGI.
If undefined method is called, fml loads it from FML::Process::CGI or
FML::Process::Kernel. FML::Process::CGI uses CGI.pm to create a http header
et.al. If FML::Process::CGI functions are not enough, FML::CGI class module
should support the lack.
IX. Apendixes
Table of Contents
Glossary (function and variable names convention)
A. Struct curproc (Object In Fact)
Glossary (function and variable names convention)
fml4
fml4 series
fml8
fml8 series
fml-devel
current development version on the way to fml8 in the future.
same as fml8 now.
curproc
abbrebiation of "current process".
Typical abbrebiation form used in UNIX kernel.
PCB
Process Control Block.
Typical abbrebiation form used in UNIX kernel.
config
configuration.
conf
configuration.
arg / args
argument / arguments.
fh
file handle.
dh
directory handle.
fp
function pointer == code reference of perl 5.
_foobar
keyword begining with _ is used for internal function or variable.
private in other words.
rfoobar
The first "r" implies "reference". This called hangalian form but we use it
very little in fml8.
STR
string.
Japanese character set name
JIS, SJIS, EUC ...
2
the same pronounciation as "to".
STR2EUC (== STRing to EUC)
use String qw(STR2EUC);
$euc_string = STR2EUC($string);
4
the same pronounciation as "for".
command mail
a mail which message body includes commands for fml.
By sending the command mail to some address, a user can make fml8 action
something, such as subscribe, file retrieve, unsubscribe et.al, The address
is typically $ml-ctl@$domain for $ml@$domain ML.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Appendix A. Struct curproc (Object In Fact)
curproc Object
Example of FML::Process::Distribute object.
__parent_args => HASH {
ARGV => ARRAY
___shared_memory___ => HASH
argv => ARRAY
cf_list => ARRAY
curproc => FML::Process::Distribute
fml_version
main_cf => HASH
module_info => HASH
myname
need_ml_name
options => HASH
program_fullname
program_name
}
__print_style => SCALAR
__start_time => SCALAR
article => HASH {
body => Mail::Message
header => FML::Header
message => Mail::Message
}
config => FML::Config
credential => FML::Credential
incoming_message => HASH {
body => Mail::Message
header => FML::Header
message => Mail::Message
}
log_message_queue => FML::Log::Print::Simple
main_cf => HASH {
_hints => HASH
config_dir
debug
default_command_line_option_config
default_config_cf
default_config_dir
default_cui_menu
default_domain
default_gui_menu
default_ml_home_prefix
default_module_config
default_paths_cf
domain_default_config
domain_default_config_cf
exec_prefix
executable_prefix
fml_group
fml_owner
fml_version
group_writable_config_dir
lib_dir
libexec_dir
local_lib_dir
ml_home_prefix_maps
prefix
prefix_dir
primary_ml_home_prefix_map
share_dir
site_default_config_cf
virtual_maps
}
pcb => FML::PCB
scheduler => FML::Process::Scheduler
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PCB Category List
PCB category list, which contains module and function relation.
module function category
<-- (get value)
--> (set value)
--------------------------------------------------------------------------------
State command_context_get_ml_name <-- process_command
State command_context_get_admin_auth <-- process_command
State command_context_get_normal_stop <-- process_command
State command_context_get_need_confirm <-- process_command
State command_context_get_stop_process <-- process_command
State command_context_get_admin_password <-- process_command
State command_context_get_try_admin_auth_request <-- process_command
State command_context_set_ml_name --> process_command
State command_context_set_admin_auth --> process_command
State command_context_set_normal_stop --> process_command
State command_context_set_need_confirm --> process_command
State command_context_set_stop_process --> process_command
State command_context_set_admin_password --> process_command
State command_context_set_try_admin_auth_request --> process_command
State command_context_reset_try_admin_auth_request --> process_command
State article_get_id <-- article_message
State article_set_id --> article_message
Utils incoming_message_get_cache_file_path <-- incoming_message
Utils incoming_message_set_cache_file_path --> incoming_message
State filter_state_get_error <-- filter_state
State filter_state_get_tempfail_request <-- filter_state
State filter_state_spam_checker_get_error <-- filter_state
State filter_state_virus_checker_get_error <-- filter_state
State filter_state_set_error --> filter_state
State filter_state_set_tempfail_request --> filter_state
State filter_state_spam_checker_set_error --> filter_state
State filter_state_virus_checker_set_error --> filter_state
State smtp_server_state_get_error <-- smtp_transaction
State smtp_server_state_set_error --> smtp_transaction
Utils incoming_message_get_current_queue <-- incoming_smtp_transaction
Utils incoming_message_set_current_queue --> incoming_smtp_transaction
Fake _get_emul_domain <-- faker
Fake _get_emul_ml_list <-- faker
Fake _get_emul_user_list <-- faker
Fake _set_emul_domain --> faker
Fake _set_emul_ml_list --> faker
Fake _set_emul_user_list --> faker
Error finish <-- error
Error run --> error
Kernel sysflow_finalize_stderr_channel <-- stderr
Kernel sysflow_finalize_stderr_channel <-- stderr
Kernel sysflow_reopen_stderr_channel --> stderr
Kernel sysflow_reopen_stderr_channel --> stderr
Kernel sysflow_finalize_stderr_channel --> stderr
State restriction_state_get_deny_reason <-- check_restrictions
State restriction_state_set_deny_reason --> check_restrictions
State current_process_get_ml_name <-- current_process
State current_process_set_ml_name <-- current_process
Utils langinfo_get_charset <-- charset
Utils langinfo_get_charset <-- charset
Utils langinfo_set_charset --> charset
Utils langinfo_get_language_hint <-- language_hint
Utils langinfo_set_language_hint --> language_hint
State error_message_get_count <-- reply_message_count
State error_message_set_count <-- reply_message_count
State error_message_set_count --> reply_message_count
Notes
[1] This corresponds to site_force.ph of fml4.
[2] file extension corresponds to the format.
[3] This file corresponds to fml4's site_force.ph.
[4] This silent behaviour is proper for automatic work. If needed, makefml/fml
shows log output for computer processing.
[5] This is default in fml8 (default site_default_config.cf includes this
configuration).
[6] If it could be, it is useful to implement another command which fixes the
article header later. It is not implemented.
[7] It is similar to the conversion from .mc to .cf in sendmail.
[8] tie() operation of perl
[9] Almost cases, FML::Process::Kernel method is overloaded by other modules.
So, not called directly.
[10] See FML::Process::Kernel module.
[11] "s" is the default message.
[12] admin command is defined in $user_command_mail_allowed_commands as a
normal user command.
[13] DBMS = DataBase Management System