fml 8 tutorial

Dr . Ken'ichi Fukamachi

FML.ORG

    < fukachan@fml.org >
        

Copyright (C) 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/localConfiguration files. It corresponds with fml4's /usr/local/fml
/etc/fml  /.fml and default_config.ph. /usr/local/etc/fml/main.cf has   
          fml version and library paths et.al.                          

/usr/local                                                              
/libexec/ Executables (corresponding with fml4's /usr/local/fml )       
fml                                                                     

/usr/localPerl module location ( fml4's /usr/local/fml )                
/lib/fml                                                                

/usr/localMessage templates ( fml4's /usr/local/fml/messages/). Template
/share/fmlfiles are language dependendent.                              

          The top directory for mailing lists of the default domain.    
          same as fml4. caution: the owner of /var/spool/ml can be      
          specified by configure arguments. Prepare different directory 
/var/spoolfor each domain. For example, /var/spool/ml for fml.org       
/ml       (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.

### <ALIASES 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

### </ALIASES elena@home.fml.org ML> ###

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                                    
show help     same as "makefml help   not implemented.                
              ML". If the environment                                 
              variable PAGER, use it                                  
              as pager.                                               

              run "make install" at   run "configure" and "make       
installation  the source top          install" at the source top      
of fml        directory. In fact "makedirectory. In fact "make        
              install" executes       install" executes install.pl    
              "makefml install".      script.                         

              interactive by default. not interactive. You can use    
Behaviour of  You can use interactive configure for most important    
install scriptmenu 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,      
"makefml      used as postfix for     qmail, procmail MTA's.          
newml"        compatibility).                                         
generates.                                                            

alias file                                                            
path "makefml /var/spool/ml/etc/      /var/spool/ml/etc/mail/aliases  
newml"        aliases                                                 
generates.                                                            

how to                                                                
generate qmailmakefml qmail-setup ML  "makefml newml" generates it.   
configuration                                                         
files.                                                                

re-generate   makefml                 not implemented.                
aliaes.       recollect-aliases ML                                    

remove ML     makefml destructml ML   makefml rmml ML                 

how to set up run "makefml mead ML"                                   
error         and set up aliases      enabled by default.             
analyzer.     properly.                                               

test of fml   makefml test ML         not implemented                 

set up        makefml fmlserv ML                                      
LISTSERV stylelistserv majordomo is   not implemented                 
server.       same as.                                                

              "makefml add ML         "makefml subscribe ML ADDRESS". 
              ADDRESS". "makefml      Other 4 commands (add subscribe 
subscribe (addadduser ML ADDRESS" is  adduser useradd) are same as    
addess to     same. the changes is    subscribe. No message is shown  
member and    shown after the         unless error occurs. This       
recipient     operation. This         operation is applied to         
list)         operation is applied to $primary_recipient_map and      
              both actives and members$primary_member_map (recipients 
              files.                  and members files actually).    

                                      "makefml unsubscribe ML         
              "makefml bye ML         ADDRESS". Other 7 commands ( bye
              ADDRESS". byeuser is    unsubscribe deluser remove      
remove addresssame. the changes is    resign signoff userdel ) are    
from recipientshown after the         same as unsubscribe. No message 
and member    operation. This         is shown unless error occurs.   
list.         operation is applied to This operation is applied to    
              both actives and members$primary_recipient_map and      
              files.                  $primary_member_map (recipients 
                                      and members files actually).    

              "makefml chaddr ML      "makefml chaddr ML OLD_ADDRESS  
              OLD_ADDRESS             NEW_ADDRESS". No message is     
change addressNEW_ADDRESS". the       shown unless error occurs. This 
(in recipient changes is shown after  operation is applied to         
and member    the operation. This     $primary_recipient_map and      
list)         operation is applied to $primary_member_map (recipients 
              both actives and membersand members files actually).    
              files.                                                  

              "makefml addactives ML                                  
              ADDRESS". Commands      "makefml addactives ML ADDRESS  
add address to(addactive add2active   ". No message is shown unless   
only recipientadd2actives) are same.  error occurs. This operation is 
list          the changes is shown    applied to                      
              after the operation.    $primary_recipient_map          
              This operation is       (recipients file actually).     
              applied to actives file.                                

              "makefml addmembers ML                                  
              ADDRESS". Commands      "makefml addmembers ML ADDRESS".
add address to(addmember add2member   No message is shown unless error
only member   add2members) are same.  occurs. This operation is       
list.         the changes is shown    applied to $primary_member_map  
              after the operation.    (members file actually).        
              This operation is                                       
              applied to members file.                                

              "makefml off ML         "makefml off ML ADDRESS". No    
              ADDRESS". skip is same  message is shown unless error   
disable real  as off. the changes is  occurs. This operation is       
time delivery shown after the         applied to                      
              operation. This         $primary_recipient_map          
              operation is applied to (recipients file actually).     
              actives file.                                           

                                      "makefml digestoff ML ADDRESS"  
              "makefml on ML ADDRESS".or "makefml digest ML ADDRESS   
enable real   the changes is shown    off". No message is shown unless
time delivery.after the operation.    error occurs. This operation is 
              This operation is       applied to                      
              applied to actives file.$primary_recipient_map          
                                      (recipients file actually).     

              "makefml matome ML      "makefml digeston ML ADDRESS" or
              ADDRESS". digest is     "makefml digest ML ADDRESS on". 
change real   same. the changes is    No message is shown unless error
time to digestshown after the         occurs. This operation is       
delivery.     operation. This         applied to                      
              operation is applied to $primary_recipient_map          
              actives file.           (recipients file actually).     

              "makefml addadmin ML    "makefml addadmin ML ADDRESS".  
add a remote  ADDRESS". the changes isNo message is shown unless error
administrator shown after the         occurs. This operation is       
address.      operation. This         applied to recipients-admin and 
              operation is applied to members-admin.                  
              members-admin file.                                     

              "makefml byeadmin ML    "makefml byeadmin ML ADDRESS".  
remove a      ADDRESS". the changes isNo message is shown unless error
remote        shown after the         occurs. This operation is       
administrator operation. This         applied to recipients-admin and 
address.      operation is applied to members-admin.                  
              members-admin file.                                     

set up                                                                
password of   "makefml passwd ML".    "makefml passwd ML" (incomplete 
remote        interactive.            ?)                              
administrator                                                         
(1).                                                                  

set up                                                                
password of   "makefml passwd ML      "makefml passwd ML ADDRESS".    
remote        ADDRESS" interactive.   interactive.                    
administrator                                                         
(2).                                                                  

set up        "makefml passwd ML      "makefml passwd ML ADDRESS      
password of   ADDRESS PASSWORD". the  PASSWORD". No message is shown  
remote        changes is shown after  unless error occurs. This       
administrator the operation. This     operation is applied to etc/    
(3).          operation is applied to passwd-admin file.              
              etc/passwd file.                                        

menu style                                                            
configuration makefml config ML       incomplete.                     
tool.                                                                 

edit          "makefml edit ML". Ask  "makefml edit ML". Not ask the  
configuration the editor to use beforeeditor to use before running.   
file.         running. "vi" by        use environment variable EDITOR 
              default.                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       makefml config-template                                 
template by   ML                      not implemented                 
menu.                                                                 

edit template makefml edit-template                                   
files "makefmlFILE list up available  not implemented                 
newml" uses   file list unless FILE                                   
              specified.                                              

re-generate                                                           
files e.g.    makefml                                                 
help at the mlcreate-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   
last 100 lines". "makefml tail ML" is not implemented.                
shown).       same.                                                   

set up                                                                
admin.cgi                                                             
(scripts and  "makefml admin.cgi ML". incomplete.                     
apache        interactive.                                            
configuration                                                         
helper).                                                              

set up                                                                
ml-admin.cgi  "makefml ml-admin.cgi                                   
(scripts and  ML". "makefml           incomplete.                     
apache        mladmin.cgi ML" is same.                                
configuration interactive.                                            
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 MLnot implemented                 
RING                                                                  
operation)                                                            

dist-auth                                                             
(PGP, GPG KEY makefml dist-auth ML    fmlpgp* command                 
RING                                  --article-post-auth             
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.                                                                  

                                      not implemented (no             
lock ML.      makefml lock ML         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 MLnot 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:

<Directory /home/*/*/public_html>
    AllowOverride FileInfo AuthConfig Limit
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec ExecCGI
    <Limit GET POST OPTIONS PROPFIND>
        Order allow,deny
        Allow from SPECIFIC_HOST
    </Limit>
</Directory>

<IfModule mod_mime.c>
        ... snip ...

   AddHandler cgi-script .cgi

        ... snip ...
</IfModule>



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 
          adapter                           as possible. prepare      
                                            adapter layer in using    
                                            CPAM module.              

          new single configuration file                               
          format.                                                     

          rule of variable naming convensionuse_XXX, XXX_TYPet ...    
                                            prohibit NOT_USE style.   

          function name convension use X11  use Perl Cookbook style ? 
          style for main:: space. use methode.g. "MemberP() ->        
          style for method. not use Lisp    IsMember()"               
          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 daysmanage 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)           

address_compare_function_domain_matching_level    domain matching level in3                                     
                                                  comparing mail 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 administrator$primary_admin_member_map             
                                                  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 cache$db_dir/article_message_id            
                                                  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 rules.check_header_size check_body_size     
                                                                          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 if-e                                    
                                                  "-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                               

cgi_menu_address_map_select_list                  choise of address list  member recipient admin_member         
                                                  types in CGI operations.                                      

cgi_menu_default_address_map                      default value of list   recipient                             
                                                  types in CGI 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 commandisolate_system_special_accounts       
command_mail_restrictions                         mail                    permit_anonymous_command              
                                                                          permit_user_command isolate           

                                                                          check_header_size check_body_size     
command_mail_size_filter_rules                    size based filter 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 is14d                                   
                                                  effective ?                                                   

confirm_command_prefix                            special command name    confirm                               
                                                  used as confirmation                                          

                                                  restrict "who can create                                      
createonpost_newml_maps                           a new ML". PCRE is      pcre:$ml_home_dir/newml.allow.pcre    
                                                  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                      

createonpost_sender_maps                          restrict "who can post".pcre:$ml_home_dir/sender.allow.pcre   
                                                  PCRE is 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                                             
createonpost_subscribe_maps                       subscribe". PCRE is     pcre:$ml_home_dir/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 several$var_dir/db                           
                                                  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 creating0755                                  
                                                  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 config$domain_config_base_dir/mail          
                                                  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 config$domain_config_base_dir/procmail      
                                                  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 config$domain_config_base_dir/sendmail      
                                                  files.                                                        

error_mail_analyzer_cache_dir                     directory to cache error$db_dir/error                         
                                                  messages.                                                     

error_mail_analyzer_cache_mode                    mode of cache expirationtemporal                              

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                                                   

fetchfml_error_mail_analyzer_password             password to fetch error ********                              
                                                  messages for $ml_name ML                                      

fetchfml_error_mail_analyzer_user                 username to fetch error $ml_name-admin                        
                                                  messages for $ml_name 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 creating0600                                  
                                                  file                                                          

                                                  maximu number of request                                      
get_command_request_limit                         in get command(s) in one100                                   
                                                  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 from$default_mail_body_size_limit         
                                                  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 from$default_mail_body_size_limit         
                                                  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: e.g.$maintainer $article_post_address     
                                                  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/$ml_name
                                                  information                                                   

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                                 

log_command_tail_starting_location                show the last N lines of100                                   
                                                  log file where N == 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 header<mailto:${command_mail_address}?body= 
                                                  field.                  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      <mailto:${maintainer}>                
                                                  header field.                                                 

mail_header_default_list_post                     default list-post header<mailto:${article_post_address}>      
                                                  field.                                                        

mail_header_default_list_software                 default list-software   $fml_version                          
                                                  header field.                                                 

mail_header_default_list_subscribe                default list-subscribe  <mailto:${command_mail_address}?body= 
                                                  header field.           subscribe>                            

mail_header_default_list_unsubscribe              default list-unsubscribe<mailto:${command_mail_address}?body= 
                                                  header field.           unsubscribe>                          

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 $admin_member_maps
                                                  member list.                                                  

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_anonymous_cgi_base_url                         ml specific url base for/~$fml_owner/cgi-bin/anonymous/       
                                                  anonymous cgi scripts.  $ml_domain/$ml_name                   

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.                                        

outgoing_article_header_size_limit                maximum size limit of   $default_mail_header_size_limit       
                                                  deliverd article header.                                      

outgoing_command_mail_body_size_limit             maximum size limit of   $default_mail_body_size_limit         
                                                  deliverd article body.                                        

outgoing_command_mail_header_size_limit           maximum size limit of   $default_mail_header_size_limit       
                                                  deliverd article 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 to                                      
primary_admin_member_password_map                 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 list.file:$ml_home_dir/recipients          

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                        

qmail_virtualdomains_file                         virtual domain          /var/qmail/control/virtualdomains     
                                                  configurations for 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:<$smtp_sender>$maintainer                           
                                                  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 accounts.nobody news majordomo listserv        
                                                                          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 ticket$shared_db_dir/thread                 
                                                  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 Subject:[$thread_id_syntax]                   

thread_subject_tag_location                       location of insertion ofappended                              
                                                  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 spool${ues_spool:-yes}                     
                                                  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 syntaxyes                                   
                                                  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 oryes                                   
                                                  not.                                                          

                                                  use fetchfml                                                  
use_fetchfml_command_mail_function                command_mail function oryes                                   
                                                  not.                                                          

                                                  use fetchfml                                                  
use_fetchfml_error_mail_analyzer_function         error_mail_analyzer     yes                                   
                                                  function or not.                                              

use_fetchfml_function                             use fetchfml function orno                                    
                                                  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 friendlyno                                    
                                                  log.                                                          

use_log_rotate                                    rotate log files or not.no                                    

                                                  upper limit of posters.                                       
use_member_total_limit                            no limitation by        no                                    
                                                  default.                                                      

use_moderate_function                             use moderate function oryes                                   
                                                  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 spoolyes                                   
                                                  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 directory.$db_dir/user_info                     

user_db_gecos_maps                                { address => gecos_field$primary_user_db_gecos_map            
                                                  } 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 '&regexp'



[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 '&regexp'



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

