基础邮件服务器

概述

  • MUA(Mail User Agent)邮件用户代理:接收邮件所使用的邮件客户端程序,使用IMAP或POP3协议与服务器通信,它提供了阅读、发送和接收电子邮件的用户接口。常见的客户端:outlook、foxmail等

  • MTA(Mail Transfer Agent)邮件传送代理:通过SMTP协议负责邮件的存储、发送和转发。监视MUA的请求,根据电子邮件的目标地址找出对应的邮件服务器,将信件在服务器之间传输并将接受到的邮件进行缓冲。在linux环境中常见的MTA有:sendmail、qmail等

  • MDA(Mail Deliver Agent)邮件投递代理:将MTA接收到的邮件保存到磁盘或指定地方,通常会进行垃圾邮件及病毒扫描。常用的MDA:procmail、dropmail等

  • MRA(Mail Retrieval Agent)邮件取回代理:负责实现IMAP与POP3协议,与MUA进行交互。常用的MRA:dovecot

  • MSA(Mail Submission Agent)邮件提交代理:检查邮件安全性与垃圾等,处理额外的工作

开源邮件系统

  • Sendmail:资格最老,运行稳定,但安全性欠佳
  • Qmail:更好的执行效率,配置管理也很方便,但兼容性不高
  • Postfix:兼容Sendmail,采用模块化设计,在投递效率、稳定性、服务性能及安全方面都很优秀

一封邮件的流程

  • 发件人:MUA => 发送 => MTA => 若干个MTA… => MTA => MDA <= 收取 <= MUA:收件人
  • MUA并非直接将邮件发送至收件人手中,而是通过MTA代为传递,Sendmail和Postfix就是扮演MTA的角色
  • 一封邮件从MUA发出后,可能通过一个或多个MTA传递,最终到达MDA。然后存放在某个文件或特殊的数据库里,我们将这个长期保存邮件的地方称之为邮箱
  • 一旦邮件到达邮箱,就原地不动了,等用户再通过MUA将其取走,就是用Outlook,Foxmail等软件收信的过程
  • MUA到MTA,以及MTA到MTA之间使用的协议就是SMTP协议,而收邮件时,MUA到MDA之间使用的协议最常用的是POP3或IMAP。

邮件应用协议

  • 简单邮件传输协议(SMTP),用来发送或中转发出的电子邮件,占用tcp 25端口。
  • 第三版邮局协议(POP3),用于将服务器上把邮件存储到本地主机,占用tcp 110端口。
  • 第四版互联网信息访问协议(IMAP4),用于在本地主机上访问邮件,占用tcp 143端口。

注意事项:如果想搭建企业级的电子邮件系统,请考虑以下几点:

  • 反垃圾与反病毒模块:阻止垃圾邮件或病毒邮件对企业邮箱的干扰。
  • 邮件加密:保证邮件内容不被嗅探、篡改。
  • 邮件监控审核:监控全体职员邮件中有无敏感词,透露企业资料等。
  • 稳定性:有较好的防DDOS攻击的能力,保证系统在线率等。

搭建邮件服务器

准备工作

邮件服务依赖于 DNS 服务,事先确保 DNS 服务已经为邮件应用配置完成。为了方便,此处将邮件服务器和DNS服务器配置为一台:192.168.247.108。主机名为 mail.test.com ,区域为 test.com ,邮件服务器为 mail.test.com

修改主机名

1
2
3
name="mail.test.com"
sed -ri 's#(HOSTNAME=).*#\1'"${name}"'#' /etc/sysconfig/network
hostname ${name}

DNS配置

1
2
3
4
5
6
7
8
9
10
11
zone "test.com" IN {
type master;
file "test.com.zone";
allow-update { none; };
};
# 邮件服务器需要用到反向解析,否则会在互联网被视为垃圾邮件服务器
zone "247.168.192.in-addr.arpa" IN {
type master;
file "192.168.247.zone";
allow-update { none; };
};

正向区域文件/var/named/test.com.zone

1
2
3
4
5
6
7
8
9
10
11
$TTL 1D
@ IN SOA ns1.test.com. admin.test.com. (
20160217 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
IN NS ns1
IN MX 10 mail
ns1 IN A 192.168.247.108
mail IN A 192.168.247.108

反向区域文件/var/named/192.168.247.zone

1
2
3
4
5
6
7
8
9
10
$TTL 1D
@ IN SOA ns1.test.com. admin.test.com. (
20160217 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
IN NS ns1.test.com.
108 IN PTR ns1.test.com.
108 IN PTR mail.test.com.

权限修改

1
2
3
4
5
6
cd /var/named/
chown named.named test.com.zone 192.168.247.zone
chmod 640 test.com.zone 192.168.247.zone
# 语法检查
named-checkzone "test.com" test.com.zone
named-checkzone "247.168.192.in-addr.arpa" 192.168.247.zone

软件包、服务、用户环境配置

依赖包安装

1
2
3
yum -y groupinstall "Development Libraries" "Development Tools"
yum -y install db*-devel
yum -y install cyrus-sasl*

如果系统有sendmail,需要把sendmail关掉

1
2
service sendmail stop
chkconfig sendmail off

为了更好的支持sasl,因此编译安装postfix;如果有rpm的postfix,要删除掉并且把postfix用户等信息也删除掉。

1
2
3
4
5
rpm -e postfix --nodeps
userdel -r postfix
userdel -r postdrop
groupdel postfix
groupdel postdrop

安装 postfix

Postfix是一款由IBM出资研发的免费开源的邮局服务程序,兼容于Sendmail服务程序,即Sendmail用户可以很方便的迁移到Postfix程序,且收发件性能远超过Sendmail,能够自动增加减少进程的数量,保证邮局系统的高性能与稳定性,另外Postfix是由诸多的小模块组成,每个小模块完成特定的功能,使得管理员可以灵活的组合这些模块。

单独使用Postfix服务程序并不能让用户完成收发邮件的操作,因为一个基础的电子邮局系统至少需要有SMTP服务器、POP3/IMAP服务器,为了能够部署一个基础的电子邮件系统,我们需要使用到下面的软件:

  • Postfix:提供邮件发送服务,即SMTP。
  • Dovecot:提供邮件收取服务,即POP3。
  • OutLook Express:客户端收发邮件的工具。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 创建用户组,ID号最好大于1000
groupadd -g 2828 postfix
useradd -g postfix -u 2828 -s /sbin/nologin -M postfix
groupadd -g 2829 postdrop
useradd -g postdrop -u 2829 -s /sbin/nologin -M postdrop
# 编译安装
tar xf postfix-3.2.0.tar.gz
cd postfix-3.2.0
make tidy
make makefiles 'CCARGS=-DUSE_SASL_AUTH -DUSE_CYRUS_SASL -I/usr/include/sasl' 'AUXLIBS=-L/usr/lib64/sasl2 -lsasl2'
make && make install

# 创建邮件别名库
newaliases
ll /etc/aliases*

配置 postfix

Postfix 邮局服务程序的配置文件:

文件 作用
/usr/sbin/postfix 主服务程序
/etc/postfix/master.cf master主程序的配置文件。
/etc/postfix/main.cf postfix服务的配置文件。
/var/log/maillog 记录邮件传递过程的日志。
/usr/libexec/postfix 服务程序目录
/var/spool/postfix 邮件队列目录

Postfix 服务程序主配置文件:

参数 作用
myhostname 邮件系统的主机名。
mydomain 邮件系统的域名。
myorigin 从本机寄出邮件的域名名称。
inet_interfaces 监听的网卡接口。
mydestination 可接收邮件的主机名或域名。
mynetworks 设置可转发那些主机的邮件。
relay_domains 设置可转发那些网域的邮件

编辑 Postfix 主配置文件,直接执行辅助配置工具 postconf,可列出 postfix 服务所支持的所有配置。结合 -n 选项可排除默认配置,只列出非默认的配置。结合 -d 选项可查看默认配置。

1
2
3
4
5
# 备份main.cf文件,创建新的main.cf文件
postconf -n > tmp.file
mv /etc/postfix/main.cf{,.bak}
mv tmp.file /etc/postfix/main.cf
vim /etc/postfix/main.cf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
command_directory = /usr/sbin
compatibility_level = 2
daemon_directory = /usr/libexec/postfix
data_directory = /var/lib/postfix
debug_peer_level = 2
debugger_command = PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin ddd $daemon_directory/$process_name $process_id & sleep 5
html_directory = no
inet_protocols = ipv4
mail_owner = postfix
mailq_path = /usr/bin/mailq
manpage_directory = /usr/local/man
meta_directory = /etc/postfix
newaliases_path = /usr/bin/newaliases
queue_directory = /var/spool/postfix
readme_directory = no
sample_directory = /etc/postfix
sendmail_path = /usr/sbin/sendmail
setgid_group = postdrop
shlib_directory = no
unknown_local_recipient_reject_code = 550

myhostname = mail.test.com
# 邮件服务器自己的主机名,应改和邮件服务器上hostname命令结果保持一致
mydomain = test.com
# 邮件域
myorigin = $mydomain
# 发件域:发件人所在的域名,即做发件地址伪装(a@mail.test.com=>a@test.com)
mydestination = $myhostname, localhost.$mydomain, localhost,$mydomain
# 投递域
#home_mailbox =

inet_interfaces = 192.168.247.108,127.0.0.1
# 指定postfix系统监听的网络接口

注意:

  • postfix服务器支持两种邮件存储方式:Mailbox和Maildir。当指定存储位置最后一位为“/”时,自动使用Maildir方式存储。Mailbox存储方式将同一用户的所有邮件内容存储在同一个文件中,通常对应为目录“/var/spool/mail”中以用户名命名的文件。Maildir存储方式使用目录结构来储存用户的邮件内容,每一个用户对应有一个文件夹,每一封邮件作为为一个独立的文件保存,通常位于用户的主目录下。
  • 为了不修改原有的邮件存放地址,这个地方需要把home_mailbox注释掉。
  • 在postfix的配置文件中,参数行和注释行是不能处在同一行中的;
  • 任何一个参数的值都不需要加引号,否则,引号将会被当作参数值的一部分来使用;
  • 每修改参数及其值后执行 postfix reload 即可令其生效;但若修改了inet_interfaces,则需重新启动postfix;
  • 如果一个参数的值有多个,可以将它们放在不同的行中,只需要在其后的每个行前多置一个空格即可;postfix会把第一个字符为空格或tab的文本行视为上一行的延续

postfix服务

创建 sysv 服务脚本:/etc/rc.d/init.d/postfix

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/bin/bash
#
# postfix Postfix Mail Transfer Agent
#
# chkconfig: 2345 80 30
# description: Postfix is a Mail Transport Agent, which is the program \
# that moves mail from one machine to another.
# processname: master
# pidfile: /var/spool/postfix/pid/master.pid
# config: /etc/postfix/main.cf
# config: /etc/postfix/master.cf

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ $NETWORKING = "no" ] && exit 3

[ -x /usr/sbin/postfix ] || exit 4
[ -d /etc/postfix ] || exit 5
[ -d /var/spool/postfix ] || exit 6

RETVAL=0
prog="postfix"

start() {
# Start daemons.
echo -n $"Starting postfix: "
/usr/bin/newaliases >/dev/null 2>&1
/usr/sbin/postfix start 2>/dev/null 1>&2 && success || failure $"$prog start"
RETVAL=$?
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/postfix
echo
return $RETVAL
}

stop() {
# Stop daemons.
echo -n $"Shutting down postfix: "
/usr/sbin/postfix stop 2>/dev/null 1>&2 && success || failure $"$prog stop"
RETVAL=$?
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/postfix
echo
return $RETVAL
}

reload() {
echo -n $"Reloading postfix: "
/usr/sbin/postfix reload 2>/dev/null 1>&2 && success || failure $"$prog reload"
RETVAL=$?
echo
return $RETVAL
}

abort() {
/usr/sbin/postfix abort 2>/dev/null 1>&2 && success || failure $"$prog abort"
return $?
}

flush() {
/usr/sbin/postfix flush 2>/dev/null 1>&2 && success || failure $"$prog flush"
return $?
}

check() {
/usr/sbin/postfix check 2>/dev/null 1>&2 && success || failure $"$prog check"
return $?
}

restart() {
stop
start
}

# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
reload)
reload
;;
abort)
abort
;;
flush)
flush
;;
check)
check
;;
status)
status master
;;
condrestart)
[ -f /var/lock/subsys/postfix ] && restart || :
;;
*)
echo $"Usage: $0 {start|stop|restart|reload|abort|flush|check|status|condrestart}"
exit 1
esac

exit $?

启动postfix服务

1
2
3
4
chmod +x /etc/rc.d/init.d/postfix 
postfix check
chkconfig postfix on
service postfix start

部署 Dovecot

Dovecot 是一个开源的 IMAP 和 POP3 邮件服务器,支持 Linux/Unix 系统。

1
2
3
yum -y install openssl-devel pam-devel dovecot
chkconfig --add dovecot
chkconfig --level 2345 dovecot on

修改主配置文件

1
vim /etc/dovecot/dovecot.conf
1
2
3
4
5
6
7
8
# 修改第24行的支持邮局协议。
protocols = imap pop3 lmtp

# 修改第26行监听选项,如果不支持IPv6使用*
listen = *

# 允许登陆网段地址,全部允许即为(0.0.0.0/0)
#login_trusted_networks = 192.168.247.0/24

允许明文认证 /etc/dovecot/conf.d/10-auth.conf

1
disable_plaintext_auth = no

配置邮件的格式与存储路径 /etc/dovecot/conf.d/10-mail.conf

1
2
mail_location = mbox:~/mail:INBOX=/var/mail/%u
# 这里的路径一定要和postfix的保持一致(postconf | grep mail_spool_directory)

启动Dovecot服务程序

1
2
chkconfig dovecot on
service dovecot restart

部署Cyrus SASL

在Postfix邮件系统中,可以使用Cyrus SASL(Cyrus Simple Authentication and Security Layer,Cyrus简单认证安全层)软件来实现基本的SMTP认证。Postfix通过连接Cyrus SASL的函数库,调用认证服务saslauthd来核对系统账号和密码

1
2
3
4
5
yum -y install cyrus-sasl*

# 设置cyrus SASL 函数库
echo -e 'pwcheck_method:saslauthd\nmech_list: PLAIN LOGIN' >> /usr/lib64/sasl2/smtpd.conf
cp /usr/lib64/sasl2/smtpd.conf /etc/sasl2/

配置

1
vim /etc/sysconfig/saslauthd
1
2
3
MECH=shadow
# 认证方式改为帐号密码认证。
# saslauthd -v 可显示当前主机saslauthd服务支持的认证方式
1
2
service saslauthd start
chkconfig --level 2345 saslauthd on

修改postfix配置文件,加入配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#####################---CYRUS-SASL---#####################
broken_sasl_auth_clients = yes
# 是否通过sasl来验证client

smtpd_recipient_restrictions=permit_mynetworks,permit_sasl_authenticated,reject_invalid_hostname,reject_non_fqdn_hostname,reject_unknown_sender_domain,reject_non_fqdn_sender,reject_non_fqdn_recipient,reject_unknown_recipient_domain,reject_unauth_pipelining,reject_unauth_destination
# 收件人限定
# permit_mynetworks 允许本地网络
# permit_sasl_authenticated 允许sasl验证通过的用户
# reject_invalid_hostname 拒绝主机名不合法的主机来收发邮件
# reject_non_fqdn_hostname 拒绝非fqdn格式的主机来收发邮件
# reject_unknown_sender_domain 拒绝无法识别的发件人
# reject_non_fqdn_sender 拒绝非fqdn格式的发件人
# reject_non_fqdn_sender 拒绝非fqdn格式的收件人
# reject_unknown_recipient_domain 拒绝无法识别的收件人域
# reject_unauth_pipelining 拒绝无法验证的管道
# reject_unauth_destination 拒绝未认证的目标,此项必须放到最后

smtpd_sasl_auth_enable = yes
# 启用sasl认证功能

smtpd_sasl_local_domain = $myhostname
# 基于sasl认证的时候,我们本地的域

smtpd_sasl_security_options = noanonymous
# 禁止匿名发信

smtpd_sasl_path = smtpd
# 指定要使用ssl功能的服务器程序

mynetworks = 127.0.0.0/8
# 只允许给本地中继(注意:上面的smtpd_recipient_restrictions明确规定了permit_sasl_authenticated,允许给通过sasl认证的用户做邮件中继)
# 设置内网和本地IP指定你所在的网络的网络地址
# postfix根据其值来区别用户是远程的还是本地的,如果是本地网络用户则允许其访问

帐号的添加和测试

  • 邮箱账号采用的是系统账号,属组应该为邮件组mail,所以邮箱开通的时候,实际上是创建了一个系统账号。

命令要求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
userdel -r test1
userdel -r test2
useradd -u 1300 -g mail -s /usr/bin/passwd test1
echo test1 | passwd --stdin test1
useradd -u 1301 -g mail -s /usr/bin/passwd test2
echo test2 | passwd --stdin test2

# -c 添加新账号说明,一般是账号名称,但是每个字的首字母大写。
# -u uid编号,我们添加的时候,要先查看/etc/passwd的内容,看当前最后一个账号的uid,然后确定这里填写的数字。
# -g gid编号,这个必须是mail组,否则会导致权限不足
# -s 的设置也是固定的,不可更改,邮箱用户将不应直接登录邮件服务器。
# test1 账号名称。

testsaslauthd -u test1 -p test1
# 帐号认证测试

使用outlook进行两个用户之间邮件的发送接收测试

常见问题

映射表问题

1
2
3
4
5
# /var/log/mail/log中显示
Recipient address rejected: User unknown in local recipient table

# 修改postfix主配置
local_recipient_maps =

权限问题

1
2
3
4
5
# /var/log/mail/log中显示
Mar 25 02:19:34 mail dovecot: pop3(test1): Couldn't open INBOX top=0/0, retr=0/0, del=0/0, size=0
Mar 25 02:19:34 mail dovecot: pop3-login: Login: user=<test2>, method=PLAIN, rip=192.168.247.1, lip=192.168.247.108, mpid=51169
Mar 25 02:19:34 mail dovecot: pop3(test2): Error: chown(/home/test2/mail/.imap/INBOX, -1, 12(mail)) failed: Operation not permitted (egid=2831(test2), group based on /var/mail/test2)
# 权限不足,添加邮件帐号时指定属组为mail即可

日志 /var/log/mail/log 被勿删

1
2
3
4
5
6
7
# maillog日志是在syslog.conf文件中定义的,内容如下:

# Log all the mail messages in one place.
mail.* -/var/log/maillog

# 重启log服务即可:
service rsyslog restart

邮件服务器收发正常但OE无法收信

  • 核对postfix中的邮箱路径 postconf -d | grep mail_spool_directory 与dovecot中的邮箱路径 mail_location = mbox:~/mail:INBOX=/var/mail/%u 是否一致
  • 客户端和服务器端时间是否正确及是否同步(执行/usr/sbin/ntpdate time.nist.gov进行时间同步)

为 postfix 开启基于hash的别名文件支持

main.cf 中添加如下配置

1
2
alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases

/etc/aliases 文件中定义新的别名项,其格式通常为以冒号隔开的两个字段,前一个字段为初始目标邮件地址,后一个字段为实际发往的地址,如:

1
2
net_operation :	zhangsan,lisi,wangwu
# 发送给net_operation@test.com的邮件将发送给张三、李四、王五

/etc/aliases 转换为 hash 格式:

1
2
postalias  /etc/aliases
service postfix reload

postfix基于客户端的访问控制

postfix内置了多种反垃圾邮件的机制,其中就包括“客户端”发送邮件限制。

客户端判别机制可以设定一系列客户信息的判别条件:

1
2
3
4
5
6
smtpd_client_restrictions:当客户端发起连接请求时,判别此客户端IP的访问权限
smtpd_helo_restrictions : 限定哪些客户端可以发送helo指令
smtpd_sender_restrictions :限定哪些客户端可以发送mail from指令
smtpd_recipient_restrictions:限定哪些用户可以发送rctp to指令
smtpd_data_restrictions:限定哪些用户可以发送data指令
以上每一项参数分别用于检查SMTP会话过程中的特定阶段,即客户端提供相应信息的阶段。

如果DATA命令之前的所有内容都被接受,客户端接着就可以开始传送邮件内容了。邮件内容通常由两部分组成,前半部分是标题(header),其可以由header_check过滤,后半部分是邮件正文(body),其可以由check_body过滤。这两项实现的是邮件“内容检查”。

postfix的默认配置如下:

1
2
3
4
5
6
7
8
9
10
smtpd_client_restrictions =
smtpd_data_restrictions =
smtpd_end_of_data_restrictions =
smtpd_etrn_restrictions =
smtpd_helo_restrictions =
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination
smtpd_sender_restrictions =

# 这限制了只有mynetworks参数中定义的本地网络中的客户端才能通过postfix转发邮件,
# 其它客户端则不被允许,从而关闭了开放式中继(open relay)的功能。

Postfix有多个内置的限制条件,如上面的 permit_mynetworksreject_unauth_destination,但管理员也可以使用访问表(access map)来自定义限制条件。自定义访问表的条件通常使用 check_client_accesscheck_helo_accesscheck_sender_accesscheck_recipient_access进行,它们后面通常跟上 type:mapname 格式的访问表类型和名称。其中,check_sender_accesscheck_recipient_access 用来检查客户端提供的邮件地址,因此其访问表中可以使用完整的邮件地址,如 `admin@test.com;也可以只使用域名,test.com;还可以只有用户名的部分,如marion@`。

实现示例1

这里以禁止 172.16.100.200 这台主机通过工作在 172.16.100.1上 的 postfix 服务发送邮件为例演示说明其实现过程。访问表使用 hash 的格式。

1
2
3
4
5
6
7
8
9
10
11
# 首先,编辑/etc/postfix/access文件,以之作为客户端检查的控制文件,在里面定义如下一行:
172.16.100.200 REJECT

# 其次,将此文件转换为hash格式
postmap /etc/postfix/access

# 然后,配置postfix使用此文件对客户端进行检查
# 编辑/etc/postfix/main.cf文件,添加如下参数:
smtpd_client_restrictions = check_client_access hash:/etc/postfix/access

# 最后,让postfix重新载入配置文件即可进行发信控制的效果测试了。

实现示例2

这里以禁止通过本服务器向 microsoft.com 域发送邮件为例演示其实现过程。访问表使用 hash 的格式。

1
2
3
4
5
6
7
8
9
10
11
# 首先,建立/etc/postfix/denydstdomains文件(文件名任取),在里面定义如下一行:
microsoft.com REJECT

# 其次,将此文件转换为hash格式
postmap /etc/postfix/denydstdomains

# 然后,配置postfix使用此文件对客户端进行检查
# 编辑/etc/postfix/main.cf文件,添加如下参数:
smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/denydstdomains, permit_mynetworks, reject_unauth_destination

# 最后,让postfix重新载入配置文件即可进行发信控制的效果测试了。

检查表格式的说明

hash类的检查表都使用类似如下的格式:

1
2
3
pattern   action
# 检查表文件中,空白行、仅包含空白字符的行和以#开头的行都会被忽略。
# 以空白字符开头后跟其它非空白字符的行会被认为是前一行的延续,是一行的组成部分。

关于pattern

其 pattern 通常有两类地址:邮件地址和主机名称/地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
邮件地址的pattern格式如下:
user@domain 用于匹配指定邮件地址;
domain.tld 用于匹配以此域名作为邮件地址中的域名部分的所有邮件地址;
user@ 用于匹配以此作为邮件地址中的用户名部分的所有邮件地址;

主机名称/地址的pattern格式如下:
domain.tld 用于匹配指定域及其子域内的所有主机;
.domain.tld 用于匹配指定域的子域内的所有主机;
net.work.addr.ess
net.work.addr
net.work
net 用于匹配特定的IP地址或网络内的所有主机;
network/mask CIDR格式,匹配指定网络内的所有主机;

关于 action

1
2
3
4
5
6
7
8
9
10
11
接受类的动作:
OK 接受其pattern匹配的邮件地址或主机名称/地址;
全部由数字组成的action 隐式表示OK;

拒绝类的动作(部分):
4NN text
5NN text
# 其中4NN类表示过一会儿重试;5NN类表示严重错误,将停止重试邮件发送;
# 421和521对于postfix来说有特殊意义,尽量不要自定义这两个代码;
REJECT optional text... 拒绝;text为可选信息;
DEFER optional text... 拒绝;text为可选信息;

常见需求的配置

特定人员发送特定邮件

公司需求只有公司高层才可以向全体员工发送邮件,除此之外均无权向全体员工发送邮件

公司高层邮箱

1
2
3
4
5
wanglujing@test.com
renlina@test.com
caiyanyan@test.com
qinwen@test.com
shiwanting@test.com

全体员工邮箱

1
allemp@test.com

用到的参数

主配置文件中需要用到的参数(具体的请参考《postfix权威指南》,在第十一章 反垃圾邮件)

  • smtmpd_restriction_classes
    自定义规范等级的名称,列出管理员自定义的所有规范等级,每一组规范等级,都是由一系列UBE(挡信)限制条件组成。
  • check_client_access 客户端
  • check_sender_access 发件人
  • check_recipient_access 收件人
  • check_recipient_access maptype:mapname
  • check_recipient_access
    指向一个含有邮件地址、网域名称、人名的访问表,用于对比客户端在RCPT TO命令中提供的收件地址,如果发现相符的索引键,则postfix执行相对应的值所提定的动作。
  • check_sender_access maptype:mapname
    check_sender_access 指向一个含有邮件地址,网域名称,人名的访问表,用于对比客户端在MAIL FROM命令中提供的寄件人邮件地址,如果发现相符的索引键,则postfix执行相对应的值所指定的动作。

涉及的处理动作

  • OK 通过当前过滤规则的检查,postfix继续检查下一组过滤规则。
  • REJECT 拒绝邮件,后面可以加上一段简短信息,说明拒绝的理由,这段信息会连同拒绝码一起返回给客户端,并且被记录在postfix日志文件中。

实现方法

定义规范等级,分别为 local_sender_allallow_to_all

1
2
3
4
# 在postfix主配置文件中,末尾添加下列语句
smtpd_restriction_classes = local_sender_all,allow_to_all
local_sender_all = check_sender_access hash:/etc/postfix/plugin/local_sender_all,reject
allow_to_all = check_recipient_access hash:/etc/postfix/plugin/allow_to_all,reject

创建限定的收件人文件

1
2
install -cdv /etc/postfix/plugin
vim /etc/postfix/plugin/allow_to_all
1
allemp@test.com      allow_to_all

创建限定的发件人文件

1
vim /etc/postfix/plugin/local_sender_all
1
2
3
4
5
wanglujing@test.com OK 
renlina@test.com OK
caiyanyan@test.com OK
qinwen@test.com OK
shiwanting@test.com OK

使用 postmap 生成数据库文件

1
2
postmap /etc/postfix/plugin/allow_to_all 
postmap /etc/postfix/plugin/local_sender_all

邮件发送控制

  • 对于外域到本域的邮件,必须接收,否则,收不到任何来自外部的邮件
  • 对于本域到外域的邮件,只允许从本机发出,否则其他人通过伪造本域地址就可以向外域发信
  • 对于外域到外域的邮件,直接拒绝,否则我们的邮件服务器就是Open Relay,将被视为垃圾邮件服务器

设置发件人的规则

1
2
smtpd_sender_restrictions = permit_mynetworks, check_sender_access hash:/etc/postfix/plugin/sender_access, permit
# 以上规则先判断是否是本域地址,如果是则允许,然后再从sender_access文件里检查发件人是否存在,拒绝存在的发件人,最后允许其他发件人。

设置收件人的规则

1
2
smtpd_recipient_restrictions = permit_mynetworks, check_recipient_access hash:/etc/postfix/plugin/recipient_access, reject
# 以上规则先判断是否是本域地址,如果是则允许,然后再从recipient_access文件里检查收件人是否存在,允许存在的收件人,最后拒绝其他收件人。
有钱任性,请我吃包辣条
0%