知识管理

Maillist Howto

修订历史
修订 0.2 2003/06/07 jiangxin
补充 Mail Archive
修订 0.1 2003/2/22 jiangxin
majordomo howto

摘要

(编译自版本: 408fb68,最后更新时间: 2007-06-19)


目录

1. 为什么使用邮件列表?
2. 用 majordomo 构建邮件列表
2.1. majordomo 的安装
2.2. 邮件列表的配置
2.3. Moderated Majordomo List
2.4. 邮件列表的使用
2.5. Majordomo 的Web界面 Majorcool
2.6. 新闻组和 Majordomo 邮件列表互转
2.7. 用 MHonarc 实现邮件归档
3. Mailman Howto

1. 为什么使用邮件列表?

在开放源码的世界里,Maillist 是除了 CVS 外的最重要的工具。那么 Maillist 有何特殊之处呢?

  • 配置简单

    作为沟通工具,邮件列表的配置要比论坛、新闻组简单的多,而且也易于使用,只要用户能收发邮件即可。

  • 实现内容的推

    我曾经在公司内部倡导使用新闻组进行小组沟通,新闻组或者论坛固然很好,但是必须经常提醒大家上去看,要是能实现内容的退该多好?而邮件列表就是以推的形式工作的。

  • 安全性高

    从安全性考虑,邮件列表借助电子邮件,而不像新闻组作为单独的一项服务要开放新的服务端口,增加了网络安全隐患。

    有些信息需要限制在一定的范围内,禁止非授权用户订阅。新闻组的权限配置非常麻烦,而邮件列表则简单的多,只要控制订阅邮件列表的用户名单,限制订阅的用户即可。

2. 用 majordomo 构建邮件列表

何为邮件列表?其实就是将一个邮件别名映射到一系列用户。majordomo 是用 perl 语言写的工具,能够更有效的管理别名文件,实现用户可以自由订阅和反订阅邮件列表(即将用户加入别名文件和从别名文件中删除)。邮件 moderate,即发送之前,必须先经过管理员对邮件进行审核。

2.1. majordomo 的安装

  1. 创建用户 majordom,属于用户组 daemon

    $ useradd -g daemon majordom
    

    You can create and use a group other id than "daemon" if you want, but if you do, that UID needs to be a "trusted" user as far as Sendmail is concerned (i.e., the user name needs to appear on a "T" line in your sendmail.cf file).

  2. 创建安装目录

    $ mkdir /usr/local/majordomo
    
  3. 创建安装目录

    $ mkdir /usr/local/majordomo
    
  4. 修改 Makefile

    Edit the Makefile, defining where Perl and the C compiler are, the Majordomo home directory (chosen in step 2), the location of the manual pages, the user and group that Majordomo will run under, and the permissions for the various files and directories. If running on a non-POSIX system, comment out the POSIX SECTION in the Makefile. Under POSIX, wrapper must be setuid "root", even if the programs will be running as something other than "root" (i.e., "daemon"), or it won't work. The symptom of this is that Perl starts complaining about security violations and "unsafe usages".

  5. 修改配置文件 majordomo.cf

    If this is a new install, copy sample.cf to majordomo.cf first.

    This .cf file is "require"ed into majordomo, so it needs to be valid Perl. Here are the important variables to set:

        $whereami		What machine am I on?
        $whoami		Who do users send requests to me as?
        $whoami_owner	Who is the owner of the above, for problems?
        $homedir		Where can I find my extra .pl files?
        $listdir		Where are the mailing lists?
        $log		Where do I write my log?
        $sendmail_command   Where the sendmail program resides.
        $mailer		What program and args do I use to send mail to the
                              lists?
        $bounce_mailer      What program and args do I use to send administrative
                              messages?
    
  6. make

    $ make wrapper
    $ make install
    $ make install-wrapper
    
  7. 增加单独的别名文件,由 majordomo 管理

    修改 sendmail.mc 配置文件,如下:

    define(`ALIAS_FILE',`/etc/aliases,/path/to/majordomo/majordomo.aliases')
    
  8. 增加 majordomo 管理别名

    修改别名文件:/path/to/majordomo/majordomo.aliases

    majordomo: "|/usr/local/majordomo/wrapper majordomo"
    owner-majordomo: root,
    majordomo-owner: root
    majordom: root
    

    之后执行如下命令:

    $ touch /usr/local/majordomo/majordomo.aliases.db
    $ chmod 644 /usr/local/majordomo/majordomo.aliases.db
    $ newaliases
    
  9. 测试配置文件

    
    $ su - <another_user>    # 以其它用户身份登录,非 root,majordom 用户。
    $ cd /path/to/majordomo
    $ ./wrapper config-test
    
    
  10. 测试邮件列表功能

    $ touch /usr/local/majordomo/lists/test
    $ echo 'lists' | mail majordomo
    

    如果配置正确,就会收到 Majordomo,而非 Mailer-Daemon 发送的邮件,提示现在已有的邮件列表。目前只有一个邮件列表,就是我们创建的 test。

  11. 可能遇到的问题有:

    由于 sendmail 使用了 smrsh 作为 shell,导致 wrapper 程序不在 smrsh 允许之列,拒绝执行。 参见:Email Howto

    由于 lists 目录、别名文件、或者 majordomo 其它配置文件的权限设置太为宽松,导致 sendmail 拒绝执行。 参见:Email Howto

    邮件列表的名称必须是小写,且按照模式:"[a-z0-9_-]+" 组成。

2.2. 邮件列表的配置

配置邮件列表别名文件:

  • 基本的邮件列表功能

    在别名文件 majordomo.aliases 中,进行如下配置:

    test:           :include:/usr/local/majordomo/lists/test            1
    owner-test:     root
    test-owner:     root
    test-request:   "|/usr/local/majordomo/wrapper request-answer test" 2
    test-approval:  root
    
    1

    需要创建文件 /usr/local/majordomo/lists/test,因为邮件别名 test 包含(:include:)了该文件。

    2

    使用 perl 脚本 request-answer 处理发向 test-request 别名的邮件。

    该邮件列表 test,只能完成邮件到邮件列表的原样拷贝。如果需要改动邮件内容,如加头加尾,需要用 perl 程序 resend 处理到 test 的邮件,如下例。

  • 使用 resend 处理邮件列表

    在别名文件 majordomo.aliases 中,进行如下配置:

    test:           "|/usr/local/majordomo/wrapper resend -l test test-list" 1
    test-list:      :include:/usr/local/majordomo/lists/test                 2
    owner-test:     root
    test-owner:     root
    test-request:   "|/usr/local/majordomo/wrapper request-answer test"
    test-approval:  root
    
    1

    即用perl程序 resend 处理发送到 test 邮件列表(-l test)的邮件,处理完毕,发送到 test-list 别名中。

    2

    test-list别名包含 test 别名文件。注意一定是名字 test,否则用户发送 lists 给 majordomo 时,得到错误的mail-list清单。

    resend 通过配置文件——lists目录下的<list-name>.config,对邮件进行处理。配置文件的具体配置,参见 resend 的 man 手册。

  • 对 mail-list 用另外的邮件地址管理订阅和退订

    在别名文件 majordomo.aliases 中,修改相应的 test-request 别名:

    test-request: 	"|/usr/local/majordomo/wrapper majordomo -l test"
    
  • 更多示例:

    
    #
    # Sample mailing list
    #
    # Adding "nobody" prevents expansion to "long" under sendmail v8:
    owner-sample: long, nobody
    sample-owner: long, nobody
    #sample: "|/usr/local/majordomo/wrapper resend -p bulk -M 10000 -R -l sample -f sample-owner -h girl.ee.ntu.edu.tw -s sample-outgoing"
    sample: "|/usr/local/majordomo/wrapper resend -l sample -h girl.ee.ntu.edu.tw sample-outgoing"
    sample-approval: owner-sample
    sample-outgoing: :include:/usr/local/majordomo/lists/sample, sample-archive,
    "|/usr/local/majordomo/wrapper digest -r -C -l sample-digest sample-digest-outgoing"
    #
    # For digest version list
    #
    sample-digest: sample
    sample-digest-outgoing: "|/usr/local/majordomo/wrapper request-answer sample-digest"
    owner-sample-digest: owner-sample
    owner-sample-digest-outgoing: owner-sample
    owner-sample-digest-request: owner-sample
    sample-digest-approval: sample-approval
    #
    # End of the digest version list
    #
    owner-sample-outgoing: owner-sample
    sample-archive: "|/usr/local/majordomo/wrapper archive -f /usr/local/majordomo/archives/sample/sample -m -a"
    owner-sample-archive: owner-sample
    #
    # For someone who may use listname-request to ask questions
    #sample-request: "|/usr/local/majordomo/wrapper request-answer sample"
    sample-request: "|/usr/local/majordomo/wrapper majordomo -l sample"
    owner-sample-request: owner-sample
    #
    # End of listname-request version 
    
    
        test:"|/tools/majordomo/wrapper resend -l test -h cs.umb.edu test-outgoing"
        test-digest:test
    
        # I put the digest and archive programs on the outgoing list so that
        # messages bounced by resend don't end up in the digest or archive
        # unless I send them through resend explicitly. 
        test-outgoing::include:/usr/local/Lists/test,
         "| /tools/majordomo/wrapper digest -r -C -l test-digest test-digest-outgoing",
         "| /tools/majordomo/wrapper archive2.pl -a  -m
    	-f /usr/local/mail/archive/test/test.archive"
        # archive produces a monthly archive with the -m flag.
    
        test-digest-outgoing::include:/usr/local/Lists/test-digest
    
        owner-test:rouilj
        owner-test-outgoing:owner-test
        # note that the "-digest" and "-digest-outgoing" suffixes
        # are required to allow the majordomo mkdigest command, and the
        # config code to work properly.
        owner-test-digest:owner-test
        owner-test-digest-outgoing:owner-test
    
        test-request: "|/tools/majordomo/wrapper request-answer test"
        test-digest-request: "|/tools/majordomo/wrapper request-answer test-digest"
    
        test-approval:rouilj
        test-digest-approval:test-approval
    
    
    

关于邮件列表的配置文件

  • 一个复杂的 footer [1]

    
    'message_fronter',      '#! local($TEMP) = $list;
    	if ( $list =~ /-digest$/ ) 
    	{
    		$TEMP =~ s/-digest$//;
    		"In this issue:\n\n\t_SUBJECTS_\n\nSee the end of the digest
    		 for information on subscribing to the $TEMP\nor $TEMP-digest mailing lists.\n";
    	} 
    	else 
    	{
    	    "";
    	}',
    'message_footer',      '#! local($TEMP) = $list;
    	if ( $list =~ /-digest$/ ) 
    	{
    		$TEMP =~ s/-digest$//;
    		"To subscribe to $TEMP-digest, send the command:\n\n\t
    		subscribe $TEMP-digest\n\nin the body of a message to \"Majordomo@
    		Majordomo.cso.uiuc.edu\".  If you want\nto subscribe something
    		other than the account the mail is coming from,\nsuch as a local
    		redistribution list, then append that address to the\n\"subscribe\"
    		command; for example, to subscribe \"local-$TEMP\":\n\n\tsubscribe
    		$TEMP-digest local-$TEMP@your.domain.net\n\nA non-digest
    		(direct mail) version of this list is also available;
    		to\nsubscribe to that instead, replace all instances of
    		\"$TEMP-digest\"\nin the commands above with \"$TEMP\".";
    	}
    	else
    	{
    		"";
    	}',
    
    
    

    以上设置比较复杂,如果没有设置相应的摘要邮件列表,或者不介意在摘要中每个文章都加上冗长的结尾的化,只要写一个字符串即可。如:

    
    message_footer      <<  END
    -
    ----------------------------------------------------------------------
    内部的 mail-list 使用指南:
    -  1. 将你机器的 DNS 服务器设置为内部 DNS;
    -  2. 只有在邮件服务器中将 SMTP 服务器设置为 内部邮件服务器,
    -     方可向 $LIST 发送邮件;
    -  3. 取消邮件列表:
    -     向 majordomo 发送邮件:
    -     内容为: unsubscribe $LIST <your_email_address>,标题为空;
    -  4. 寻求更多帮助,请发送邮件到 majordomo,
    -     内容为: help
    -
    -
    END
    
    
  • 邮件订阅受控,即订阅之前,先要由管理员审核用户

    参见:FAQ

2.3. Moderated Majordomo List

Moderated Majordomo List 就是受控的邮件列表,任何人向邮件列表发言前,先要经过审核。只需要在邮件列表的控制文件中如下修改:

moderate            =   yes
moderator           =

确省的邮件组审核小组别名为:<list>-approval

问: How do I approve a message on a moderated Majordomo list? [2]
问: How can I have more than one moderator/owner for a list? [1]
问: What steps are required to set up a list where: [1]
问: What steps are required to set up a list where:
问:

How do I approve a message on a moderated Majordomo list? [2]

I'm the list owner and I received a message that a post has bounced due to the list being moderated. What do I do to get it posted to the list?

答:

You'll need to add two lines to the top of the message and resend it to your list address. The two lines are:

Approved: your-list-password

followed by a blank line. It is important that the Approved: line is the first line in your new message, and that you have a blank line following the Approved line.

You can forward the message, or resend it (if your email client has that option) You'll want to change the subject of the forwarded message to something other than Bounced....etc. If you resend the message it will appear to come from you, so you may want to include the actual author's email address in the message.

问:

How can I have more than one moderator/owner for a list? [1]

答:

Again majordomo is your friend. Create a mailing list called "<listname>-owner". Again create it nonadvertised and closed. Set up the appropriate aliases for the list:

	owner-listname::include:/usr/local/Lists/<listname>-owner
	listname-owner:owner-listname
	owner-owner-listname: owner-majordomo

and you are done.

问:

What steps are required to set up a list where: [1]

* only the owners can subscribe new folks

* only the owners can send messages to the list

答:

Create listname.closed in the list directory. Alias incoming list submissions to go through "resend" with the -A and -a options.

Rather than use listname.closed, set

subscribe_policy = closed

The -A flag is handed by setting:

moderate = yes

and the -a <password> flag is handled using the

approve_passwd = <some password>

问:

What steps are required to set up a list where:

* only the owners can subscribe new folks

* any subscribers can send to the list

答:

Same as above, except leave of the -A and -a options.

Simply set moderate = no

The approval password can still be used to approve message bounced due to length restrictions or administrivia checks.

2.4. 邮件列表的使用

  • 寻求帮助

    向地址 Majordomo@YourDomain.Com 发送邮件,主题为空,内容为 help 。

  • 显示当前提供的邮件列表服务清单

    向地址 Majordomo@YourDomain.Com 发送邮件,主题为空,内容为 lists 。

  • 订阅邮件列表(假设邮件列表名为 test)

    向地址 Majordomo@YourDomain.Com 发送邮件,主题为空,内容为 subscribe test 。

    邮件服务器会发来一封确认信,按照确认信内容操作。

  • 退订邮件列表(假设邮件列表名为 test)

    向地址 Majordomo@YourDomain.Com 发送邮件,主题为空,内容为 unsubscribe test 。

    邮件服务器会发来一封确认信,按照确认信内容操作。

2.5. Majordomo 的Web界面 Majorcool

Majorcool 是用 Perl 写的 cgi 脚本,提供了 Majordomo 的易用接口。

网络资源:

我在 Linux 上安装 Majorcool,基本上没有费多大周折。按照前面的 Howto 一步步执行即可。在后面的运行维护阶段,曾经遇到过“Majorcool 不能更新列表的问题”:

Majordomo 创建的新的邮件列表,Majorcool 不能显示出来。即 Majorcool 不能更新列表。我的第一个反应是查看 Majorcool 的源代码,看看它是如何获取当前已有的邮件列表。

首先定位到函数 get_lists:


#-----------------------------------------------
# Find all lists matching a certain criteria.
#-----------------------------------------------
sub get_lists {
	local($address,$pattern,$criteria,$list_match) = @_;
	local(@lists);
	#
	# all lists
	if ($criteria eq "available") {
		@lists = sort(keys(%cached_descr));
	}
	#

发现邮件列表初始化自哈希表 %cached_descr,查找 %cached_descr 初始化的代码,自然定位到函数 load_cache:


#-----------------------------------------------
# Create a table of cached keys for each list.
#-----------------------------------------------
sub load_cache {
	&send_error("Cannot Open File <$cache> -- $!")
		unless open(CACHE, "$cache");
	while (<CACHE>) {
		chop;					# remove the trailing \n
		next if /^\s*$/;			# remove blank lines
		local($list,$owner,$spolicy,$upolicy,$descr,$adv,$noadv)
			 = split(/\007/);
		# only add good lists to the cache
		if (&valid_list($listdir,$list)) {
			$cached_owner{$list} = $owner;
			$cached_spolicy{$list} = $spolicy;
			$cached_upolicy{$list} = $upolicy;
			$cached_descr{$list} = &html_encode($descr);
			$cached_adv{$list} = $adv; 
			$cached_noadv{$list} = $noadv;
		}
	}
	close(CACHE);
}

原来是从文件 $cache 初始化的邮件列表。查找 $cache 的定义,找到在文件 majorcool_default.cf 中:


$cache  		= "/usr/local/majordomo/.majordomo_keys";

剩下的事情就简单多了,打开并编辑文件 /usr/local/majordomo/.majordomo_keys,发现 Majorcool 的邮件列表清单有了变化。

再到 Google 上搜一搜,找到了.majordomo_keys 文件初始化的命令。即在安装 Majorcool 过程中,使用了如下命令初始化该文件:

/usr/local/majordomo/wrapper mj_key_cache -v -K /usr/local/majordomo/.majordomo_keys -C /usr/local/majordomo/majordomo.cf

打开文件 /usr/local/majordomo/mj_key_cache,看到文件头中的注释,告诉应该将该命令设置为在 crontab 中自动执行。于是...

2.6. 新闻组和 Majordomo 邮件列表互转

参见:Newsgroup Howto

2.7. 用 MHonarc 实现邮件归档

邮件如何归档?MHonarc,一个强大的邮件归档工具,将邮件转换为 html,是一个不错的选择。 参见:搜索引擎 Howto 之 Web存档

3. Mailman Howto

Mailman 作为 GNU 的 maillist, 在功能上、管理上、界面上更胜一筹。

文档整理中,参见: http://jiangxin.worldhello.net/wiki/M/Mailman.htm...