1)邮件系统基本概述:
1.1)邮件系统的组成:
MTA:邮件传输代理,即邮箱服务器端,如:Postfix Sendmail.
MUA:邮件用户代理,即我们平时用的邮箱客户端.如:Foxmail,Outlook Express
MDA:邮箱投递代理,当确认收下邮件后,MDA将邮件信息存放在普通文件夹内,等待用户读取.
1.2)邮件发送流程:
.通过MUA创建发送邮件,此时将该邮件交给一台运行MTA的软件.
.MTA收下邮件后,它可能将邮件递送给自己系统上的用户,也可能将邮件交给另一个MTA继续传递.
.邮件终点站的MTA,在发现收件人是本地系统的用户之后,将邮件交给MDA.
.MDA可能将邮件存放在普通文件夹内,也可能存放专门存储电子邮件的特殊数据库,此时邮件被存和邮箱,等待收件人将它收走.
.收件人使用MUA来取信/读信.
1.3)E-mail的协议
SMTP(simple mail transport protocol)
规范两部主机通过网络交换E-mail的对话原则.
SMTP是用于寄信的协议,当MUA要求MTA代为送出一封邮件,以及一个MTA将邮件送到另一个MTA时,都使用SMTP协议.
原始的SMTP协议并没有身份验证的设计,在后来的ESMTP中加入了这方面的功能.
SMTP用的端口是25.
POP(Post office protocol)
POP协议允许MUA访问/读取邮件服务器的邮件.目前已经发展到第三版,也就是我们常看到的pop3,它用的端口是110.
IMAP(Internet Mail Access Protocol)
IMAP协议运行在TCP/IP协议之上,使用的端口是143.
它与POP3协议的主要区别是用户可以不用把所有的邮件全部下载,可以通过客户端直接对服务器上的邮件进行操作.
2)Postfix的运作流程
2.1)Postfix的组件
Postfix的处理流程分为三个阶段:
.接收邮件
.将邮件排入队列
.递送邮件
接收邮件分为从本地接收,从网络接收,本地转发,转寄邮件,退信通知函.
将邮件排入队列主要由队列管理员负责.
递送邮件的目的地主要是本地,虚拟别名,虚拟邮箱以及转发.
2.2)来自服务器本地的邮件
在Unix/Linux系统上发送邮件,比如通过mail程序发送邮件,mail程序在做为相关处理后会调用sendmail程序投递邮件.
注:
sendmail会让我们想起sendmail邮件服务,但这里的sendmail是与postfix兼容的同名工具.
当用户以sendmail(postfix)程序寄出邮件后,sendmail会使用postdrop程序将邮件存入postfix队列目录下的maildrop子目录.默认目录为: /var/spool/postfix/maildrop/
最后postdrop程序会打开/var/spool/postfix/public/pickup,这个文件是个管道文件,用这种IPC通讯文件告之pickup服务.
下面我们用strace来跟踪mail程序的系统调用过程来进行证实,如下:
查看打开的文件和执行的程序,如下:
egrep 'open|execve' /tmp/sendmail
2791 execve("/bin/mail", ["mail", "-s", "test", "
[email protected]"], [/* 22 vars */]) = 0
略
2792 execve("/usr/sbin/sendmail", ["send-mail", "-i", "
[email protected]"], [/* 22 vars */]) = 0
略
2793 execve("/usr/sbin/postdrop", ["/usr/sbin/postdrop", "-r"], [/* 2 vars */]) = 0
略
2793 open("maildrop/196313.2793", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0644) = 4
略
2793 open("public/pickup", O_WRONLY|O_NONBLOCK|O_LARGEFILE) = 4
上面我们知道pickup服务通过管道的方式获知有新邮件到达,此时它读取/var/spool/postfix/maildrop目录下的新邮件,并将新邮件交给cleanup服务,cleanup服务与trivial-rewrite对邮件的格式进行整理重写.
所谓的整理重写就是补足邮件中遗漏的标头字段,例如我们给root发送邮件,mail -s "test" root,这时cleanup会补全root的邮件地址,例如补全成
[email protected].
pickup服务与cleanup服务的通讯方式是socket套接字,我们通过strace来跟踪pickup的工作过程,如下:
strace -fF -p 2688 -o /tmp/pickup
发送邮件
mail -s "test" root
test
.
EOT
查看系统调用,如下:
tail -f /tmp/pickup
3246 alarm(6000) = 5975
3246 time(NULL) = 1310341018
3246 epoll_wait(8, {{EPOLLIN, {u32=6, u64=15683691556634630}}}, 100, 75000) = 1
3246 time(NULL) = 1310341028
3246 write(5, "\256\f\0\0\1\0\0\0\0\0\0\0", 12) = 12
3246 read(6, "W", 1024) = 1
3246 open("maildrop", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 9
3246 getdents64(9, /* 3 entries */, 32768) = 80
3246 lstat64("maildrop/7C3EA163C51", {st_mode=S_IFREG|0744, st_size=277, ...}) = 0
3246 open("maildrop/7C3EA163C51", O_RDONLY|O_NONBLOCK|O_LARGEFILE) = 10
3246 fstat64(10, {st_mode=S_IFREG|0744, st_size=277, ...}) = 0
3246 lstat64("maildrop/7C3EA163C51", {st_mode=S_IFREG|0744, st_size=277, ...}) = 0
3246 socket(PF_FILE, SOCK_STREAM, 0) = 11
3246 fcntl64(11, F_GETFL) = 0x2 (flags O_RDWR)
3246 fcntl64(11, F_SETFL, O_RDWR) = 0
#注意这里连接/var/spool/postfix/public/cleanup(UNIX套接字)与cleanup进行通讯
3246 connect(11, {sa_family=AF_FILE, path="public/cleanup"}, 110) = 0
3246 gettimeofday({1310341028, 532931}, NULL) = 0
3246 poll([{fd=11, events=POLLIN}], 1, 3600000) = 1 ([{fd=11, revents=POLLIN}])
3246 read(11, "queue_id\00084E5D163C55\0\0", 4096) = 22
3246 gettimeofday({1310341028, 544945}, NULL) = 0
3246 time(NULL) = 1310341028
3246 read(10, "T\0211310341028 508906A\25rewrite_con"..., 4096) = 277
3246 time(NULL) = 1310341028
3246 send(7, "<22>Jul 11 07:37:08 postfix/pick"..., 74, MSG_NOSIGNAL) = 74
3246 stat64("/etc/localtime", {st_mode=S_IFREG|0644, st_size=405, ...}) = 0
3246 _llseek(10, 0, [277], SEEK_END) = 0
3246 poll([{fd=11, events=POLLOUT}], 1, 3600000) = 1 ([{fd=11, revents=POLLOUT}])
3246 write(11, "flags\000115\0\0T\0211310341028 508906A\25"..., 398) = 398
3246 gettimeofday({1310341028, 546876}, NULL) = 0
3246 poll([{fd=11, events=POLLIN}], 1, 3600000) = 1 ([{fd=11, revents=POLLIN|POLLHUP}])
3246 read(11, "status\0000\0reason\0\0\0", 4096) = 18
3246 gettimeofday({1310341028, 571577}, NULL) = 0
3246 close(10) = 0
3246 close(11) = 0
3246 unlink("maildrop/7C3EA163C51") = 0
当postfix发现pickup连接cleanup套接字后,通过execve调用cleanup程序,并且通过socket的通讯方式进行接收处理该邮件.
下面的系统调用说明了这一点:
3321 execve("/usr/libexec/postfix/cleanup", ["cleanup", "-z", "-t", "unix", "-u"], [/* 4 vars */]) = 0
略
3321 socket(PF_NETLINK, SOCK_RAW, 0) = 8
3321 bind(8, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
3321 getsockname(8, {sa_family=AF_NETLINK, pid=3321, groups=00000000}, [12]) = 0
3321 time(NULL) = 1310341496
3321 sendto(8, "\24\0\0\0\22\0\1\3x9\32N\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
3321 recvmsg(8, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\250\1\0\0\20\0\2\0x9\32N\371\f\0\0\0\0
\4\3\1\0\0\0I\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 1292
3321 recvmsg(8, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0x9\32N\371\f\0\0\0\0\0
\0\1\0\0\0I\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 20
3321 sendto(8, "\24\0\0\0\26\0\1\3y9\32N\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
3321 recvmsg(8, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"0\0\0\0\24\0\2\0y9\32N\371\f\0\0\2\10\2
00\376\1\0\0\0\10\0\1\0\177\0\0\1"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 168
3321 recvmsg(8, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"@\0\0\0\24\0\2\0y9\32N\371\f\0\0\n\200\
200\376\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 128
3321 recvmsg(8, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0y9\32N\371\f\0\0\0\0\0
\0\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 20
然后cleanup程序通过socket(unix套接字)与trivial-rewrite服务进行通讯,即postfix检查到cleanup连接到/var/spool/postfix/private/rewrite套接字文件后,再通过execve调用trivial-rewrite程序,完成最后的清理工作.
经过cleanup处理好邮件后,邮件最后被传入收件队列,也就是/var/spool/postfix/incoming目录.
例如这样一个邮件队列:
/var/spool/postfix/incoming/711959.3321
它还要将队列名字改名,如下:
rename("incoming/711959.3321", "incoming/AE07E163C55") = 0
最后队列管理器看到有新邮件已经入队,它确定是进行转发还是发送给本地用户,是转发还是本地的区别在用它连接使用的套接字文件,如下:
本地发送:
3247 connect(10, {sa_family=AF_FILE, path="private/local"}, 110) = 0
远程转发:
3247 connect(13, {sa_family=AF_FILE, path="private/smtp"}, 110) = 0
值得注意的是队列管理器是独立的服务进程,如下:
ps -ef|grep qmgr|grep -v grep
postfix 3247 3244 0 07:36 ? 00:00:00 qmgr -l -t fifo -u
最后确认我们这里是本地发送,所以postfix会用exec调用local程序完成本地邮件发送的工序,首先它会通过/etc/passwd和/etc/aliases.db来判断是否是当前系统用户或其别名,如是当前系统用户则接收存放邮件,并将文件写入到/var/mail/root下面,完成了最后的发送过程.
2.3)来自网络的邮件
这里分为两种,一种是外界寄给postfix所控制网域的邮件,这种情况smtpd一定会收下第一种邮件,如果收件人存在的话.
第二种情况是目的地在其它网域,这种情况我们称为转发,这里先讨论第一种情况.
外界寄给postfix时,postfix用smtpd daemon来处理接收外来邮件,然后通过socket文件将邮件传输给cleanup/trivial-rewrite对邮件进行规范处理,最后根据是本地用户邮件还是其它网域用户邮件选择执行对映的程序(本地是local,转发是smtp)
首先我们在服务端用strace跟踪postfix进程,如下:
ps -ef|grep postfix
root 2505 1 0 05:38 ? 00:00:00 /usr/libexec/postfix/master
postfix 2508 2505 0 05:38 ? 00:00:00 qmgr -l -t fifo -u
postfix 3066 2505 0 07:18 ? 00:00:00 pickup -l -t fifo -u
root 3085 2569 0 07:26 pts/1 00:00:00 grep postfix
strace -fF -p 2505 -o /tmp/postfix
然后,我们在客户端用telnet命令连接服务端的postfix(MTA),发送邮件.
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 ckhitler.org ESMTP Postfix
helo ckhitler.org
250 ckhitler.org
250 2.1.0 Ok
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
test
.
250 2.0.0 Ok: queued as DA43C163C53
quit
221 2.0.0 Bye
Connection closed by foreign host.
在服务端查看postfix的exec系统调用,如下:
egrep 'exec' /tmp/postfix |grep -v set_thread_area
#注意:这里调用smtpd daemon进行邮件接收处理
2718 execve("/usr/libexec/postfix/smtpd", ["smtpd", "-n", "smtp", "-t", "inet", "-u", "-o", "stress="], [/* 4 vars */]) = 0
2719 execve("/usr/libexec/postfix/proxymap", ["proxymap", "-t", "unix", "-u"], [/* 4 vars */]) = 0
2721 execve("/usr/libexec/postfix/trivial-rewrite", ["trivial-rewrite", "-n", "rewrite", "-t", "unix", "-u"], [/* 4 vars */]) = 0
2722 execve("/usr/libexec/postfix/cleanup", ["cleanup", "-z", "-t", "unix", "-u"], [/* 4 vars */]) = 0
#注意:这里调用local程序将邮件接收至本地
2723 execve("/usr/libexec/postfix/local", ["local", "-t", "unix"], [/* 4 vars */]) = 0
下面是转发的测试:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 ckhitler.org ESMTP Postfix
helo ckhitler.org
250 ckhitler.org
250 2.1.0 Ok
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
test
.
250 2.0.0 Ok: queued as 2A525163C53
quit
221 2.0.0 Bye
Connection closed by foreign host.
如果是转发邮件,postfix进程的exec系统调用如下:
egrep 'exec' /tmp/postfix |grep -v set_thread_area
3165 execve("/usr/libexec/postfix/cleanup", ["cleanup", "-z", "-t", "unix", "-u"], [/* 4 vars */]) = 0
3166 execve("/usr/libexec/postfix/trivial-rewrite", ["trivial-rewrite", "-n", "rewrite", "-t", "unix", "-u"], [/* 4 vars */]) = 0
#注意:这里调用smtp程序将邮件转发至其它网域的邮件服务器.
3167 execve("/usr/libexec/postfix/smtp", ["smtp", "-t", "unix", "-u"], [/* 4 vars */]) = 0
注意:来自于网络的邮件也同样要入队列,由邮件队列服务qmgr来处理.最后再由postfix服务调用smtp/local程序进行邮件的发送操作.
3)postfix的队列管理
在postfix中负责队列管理的服务叫qmgr,它是整个postfix系统的中心枢纽,所有邮件,包括等待送出与从外界收进来的,都必须通过队列.
队列管理器总共设置了五个做不同用途的队列,包括:输入(incoming),活动(active),等待(deferred),故障(corrupt),保留(hold).
默认队列目录:/var/spool/postfix
目录结构如下所示:
ls -l
total 56
drwx------. 2 postfix root 4096 Jul 14 07:46 active
drwx------. 2 postfix root 4096 Jul 5 06:17 bounce
drwx------. 2 postfix root 4096 May 26 2010 corrupt
drwx------. 6 postfix root 4096 Jul 11 06:51 defer
drwx------. 6 postfix root 4096 Jul 11 06:51 deferred
drwx------. 2 postfix root 4096 May 26 2010 flush
drwx------. 2 postfix root 4096 May 26 2010 hold
drwx------. 2 postfix root 4096 Jul 14 07:46 incoming
drwx-wx---. 2 postfix postdrop 4096 Jul 11 08:11 maildrop
drwxr-xr-x. 2 root root 4096 Jul 14 05:38 pid
drwx------. 2 postfix root 4096 Jul 15 17:21 private
drwx--x---. 2 postfix postdrop 4096 Jul 15 17:21 public
drwx------. 2 postfix root 4096 May 26 2010 saved
drwx------. 2 postfix root 4096 May 26 2010 trace
首先有新邮件进入队列的第一站是incoming,qmgr收到邮件到达的通知后,将邮件从incoming队列移到active队列.
我们来看一下,这里我们采用本地收发,如下:
首先用strace监控qmgr进程,如下:
strace -fF -p 1439 -o /tmp/qmgr
打开另一个窗口,发送邮件,如下:
Subject: test
test
.
EOT
查看监控日志,如下:
grep open /tmp/qmgr
1439 open("incoming", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 9
1439 open("active/AE320163C55", O_RDWR|O_LARGEFILE) = 10
邮件从active目录队列送出到private目录队列中的local文件,local是一个socket文件
connect(10, {sa_family=AF_FILE, path="private/local"}, 110) = 0
最后postfix调用local(本地邮件)或smtp(远程转发)程序对邮件进行发送处理.
注意:这里的local和smtp也可以称为MDR
我们这里假定DNS发生故障,把resolv.conf里面的DNS去掉,如下:
cat /etc/resolv.conf
# Generated by NetworkManager
#domain localdomain
#search localdomain org
#nameserver 192.168.75.2
再次监控qmgr进程,如下:
strace -fF -p 1439 -o /tmp/qmgr
再发送如下:
Subject: test
test
.
EOT
注意:这里我们发送的域名不是ckhitler.org而是chitler.org.
我们再来看监控的结果:
1439 connect(10, {sa_family=AF_FILE, path="private/smtp"}, 110) = 0
注:因为是外网转发,qmgr队列程序将邮件从active队列取出,通过socket协议发送给private/smtp套接字文件.
1439 rename("active/34E40163C55", "deferred/3/34E40163C55") = 0
注:由于没有DNS解析,邮件不能发送,所以被放到了等待队列deferred.
我们可以查看deferred队列的文件,如下:
cat deferred/3/34E40163C55
CO 420 212 1 0 420T1310724985
187059Acreate_time=1310724985Arewrite_context=localFhitlerStest@
[email protected]@chitler.orgMN4Received: by ckhitler.org
(Postfix, from userid 500)N6 iSubject: testN'User-Agent: Heirloom mailx 12.4 7/29/08NMIME-Version: 1.0N*Content-Type: text/plain;
(hitler)NNtestXE
最后我们模拟发送不成功的情况,如下:
cat /etc/resolv.conf
# Generated by NetworkManager
domain localdomain
search localdomain org
nameserver 192.168.75.2
再次监控qmgr进程,如下:
strace -fF -p 1439 -o /tmp/qmgr
发送邮件,如下:
Subject: test
test.
.
EOT
注意:chitler.org域名不存在.
我们查看/tmp/qmgr文件,如下:
grep open /tmp/qmgr
1439 open("incoming", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 9
1439 open("active/9A428163C56", O_RDWR|O_LARGEFILE) = 10
1439 open("incoming", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 10
1439 open("active/9B1C7163C54", O_RDWR|O_LARGEFILE) = 12
注:两次进入incoming/active队列是因为chilter.org域名不存在,我们调用MDR发送了邮件,但又被退回来了.
最后我们看一下有关于邮件队列的一些工具:
显示邮件列表:
postqueue -p
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
(Host or domain name not found. Name service error for name=chitler.org type=MX: Host not found, try again)
-- 0 Kbytes in 1 Request.
显示邮件内容:
postcat -q 34E40163C55
*** ENVELOPE RECORDS deferred/3/34E40163C55 ***
message_size: 420 212 1 0 420
message_arrival_time: Fri Jul 15 18:16:25 2011
create_time: Fri Jul 15 18:16:25 2011
named_attribute: rewrite_context=local
sender_fullname: hitler
*** MESSAGE CONTENTS deferred/3/34E40163C55 ***
Received: by ckhitler.org (Postfix, from userid 500)
id 34E40163C55; Fri, 15 Jul 2011 18:16:25 +0800 (CST)
Date: Fri, 15 Jul 2011 18:16:25 +0800
Subject: test
User-Agent: Heirloom mailx 12.4 7/29/08
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
test
*** HEADER EXTRACTED deferred/3/34E40163C55 ***
*** MESSAGE FILE END deferred/3/34E40163C55 ***
将邮件转存到保存队列:
postsuper -h 34E40163C55
ls -l hold/34E40163C55
-rwx------ 1 postfix postfix 636 Jul 15 2011 hold/34E40163C55
删除队列中的邮件:
postsuper -d 34E40163C55
postsuper: 34E40163C55: removed
postsuper: Deleted: 1 message
postqueue -p
Mail queue is empty
重新排队:
postsuper -r ALL
4)postfix邮件服务器的配置项
4.1)设定邮件主机的识别身份
myhostname:设定主机名称
如果没有指定该选项,系统会以gethostname()取得当前主机的主机名.
myhostname需要使用FQDN,我们查看61.com域名的mx记录,如下:
host -t mx 61.com
61.com mail is handled by 10 mail.61.com.
在这里我们就要将myhostname设定为mail.61.com
mydomain:网域名称
预设会以myhostname第一个点之后的作为domain名称.
myorigin:发信时所显示的发信源主机
如果在配置文件中没有指定myorigin选项,则myorigin等同于myhostname.
如果我们将myorigin设置为mail.ckhitler.org,则在接收方会看到mail from是mail.ckhitler.org
如下:
mydestination:能够收信的主机名称
这个项目指定的主机名称就是对方填写的mail to中的主机名字,例如:
所以这里的mydestination就是ckhitler.org,另外我们也要把mx记录指定的域名也要填写在这里.例如:mail.ckhitler.org
这里建议的配置方案是:
myhostname = mail.ckhitler.org
mydomain = ckhitler.org
myorigin = ckhitler.org
mydestination = $myhostname,$mydomain
4.2)设定postfix使用的网络介面
inet_interfaces选项用于选择网络介面,如果设定为localhost,则绑定监听本地回环地址.
设定为all,则绑定监听到0.0.0.0
这里建议的配置方案是:
inet_interfaces = all
4.3)设定postfix的转发信任网络
mynetworks:明确设定可使用relay的主机范围
注意:如果设置mynetworks选项的话,就不需要再设置mynetworks_style选项.
我们设置只转发当前主机如下:
mynetworks = 127.0.0.0/8
这时我们在其它机器连接postfix,无法完成转发,如下:
[root@ssh-client ~]# telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo mail.ckhitler.org
250 mail.ckhitler.org
250 2.1.0 Ok
我们设置本机及同网段的信任转发,如下:
mynetworks = 127.0.0.0/8, 192.168.75.0/24
这时我们在其它机器连接postfix,可以完成转发,如下:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo mail.ckhitler.org
250 mail.ckhitler.org
250 2.1.0 Ok
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
test
.
250 2.0.0 Ok: queued as 603BF163C55
quit
221 2.0.0 Bye
Connection closed by foreign host.
relay_domains:规范可以relay的域名
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo mail.ckhitler.org
250 mail.ckhitler.org
250 2.1.0 Ok
做relay_domains的设定如下:
relay_domains = $mydomain,abc.com
再次转发则顺利的发出.如下:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo mail.ckhitler.org
250 mail.ckhitler.org
250 2.1.0 Ok
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
test
.
250 2.0.0 Ok: queued as 4EA2E163C55
quit
221 2.0.0 Bye
Connection closed by foreign host.
4.4)smtpd_client_restrictions
允许/拒绝客户端使用邮件服务器
4.4.1)check_client_access:根据客户端的主机名,父域,IP地址或部分IP来匹配.
如下:
smtpd_client_restrictions = check_client_access hash:/etc/postfix/access
编辑:
vi /etc/postfix/access
添加下面的选项,即拒绝192.168.75.129的远程连接:
192.168.75.129 REJECT
重建hash文件:
postmap /etc/postfix/access
在客户端192.168.75.129上进行测试,如下:
[root@ssh-client ~]# telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
h220 mail.ckhitler.org ESMTP Postfix
helo mail.ckhitler.org
250 mail.ckhitler.org
250 2.1.0 Ok
554 5.7.1 <unknown[192.168.75.129]>: Client host rejected: Access denied /*注意:客户端被拒绝.*/
这回我们拒绝192.168.75.0/24网段使用本邮件服务器,只允许192.168.75.129这台机器使用邮件服务器,设置如下:
vi /etc/postfix/access
postmap /etc/postfix/access
192.168.75.129 OK
192.168.75 REJECT
4.4.2)reject_unknown_client
拒绝客户的地址没有对应的DNS的A记录或PTR记录的连接
修改smtpd_client_restrictions规则如下:
smtpd_client_restrictions = reject_unknown_client
再次发送测试,提示如下的错误:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
250 2.1.0 Ok
450 4.7.1 Client host rejected: cannot find your hostname, [192.168.75.129]
quit
221 2.0.0 Bye
Connection closed by foreign host.
我们在服务端增加客户端的对映主机名,如下:
echo "192.168.75.129 client" >> /etc/hosts
再次进行发送测试,如下:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
250 2.1.0 Ok
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
test
.
250 2.0.0 Ok: queued as B4655163C49
quit
221 2.0.0 Bye
Connection closed by foreign host.
4.4.3)permit_mynetworks
允许来自其IP地址属于$mynetworks所定义的网络的客户端的连接.
我们修改配置如下:
smtpd_client_restrictions = permit_mynetworks,check_client_access hash:/etc/postfix/access,
reject_unknown_client
注意我们要删除之前加入/etc/hosts中的主机名,这样在不加入permit_mynetworks的情况下,postfix将拒绝客户端的连接,我们将permit_mynetworks加入到reject_unknown_client选项的前面.
保证以permit_mynetworks优先的顺序处理邮件.
发送测试邮件成功,如下:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
250 2.1.0 Ok
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
.
250 2.0.0 Ok: queued as DF74F163C49
quit
221 2.0.0 Bye
Connection closed by foreign host.
4.4.4)reject_rbl_client/reject_rhsbl_client
拒绝来自属于RBL和RHSBL列表中的地址进行连接,通过检查一个IP地址或域名是否存在于domain.tld的RBL或RHSBL中,可以判断该客户端是否被列入了domain.tld的实时黑名单,从而决定是否接受连接.
我们加入以下的反垃圾邮件联盟,如下:
smtpd_client_restrictions = permit_mynetworks,check_client_access hash:/etc/postfix/access,
reject_unknown_client,
reject_rbl_client cblless.anti-spam.org.cn,
reject_rbl_client sbl-xbl.spamhaus.org,
reject_rbl_client relays.ordb.org,
reject_rhsbl_client dsn.rfc-ignorant.org
4.5)smtpd_helo_required
通过smtpd_helo_required参数指定客户端在SMTP会话的开始必须发送一个HELO命令,你可以指定该参数的值为yes或no,缺省值为:
smtpd_helo_required = no
我们将smtpd_helo_required改成yes,如下:
vi /etc/postfix/main.cf
添加如下配置:
smtpd_helo_required = yes
再次发送测试邮件,如下:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
503 5.5.1 Error: send HELO/EHLO first
我们看到该参数已经起了作用,该项对反垃圾邮件有一定作用.
4.6)smtpd_helo_restrictions
通过smtpd_helo_restrictions参数在客户端在执行HELO命令时,对客户端的合法性进行检查.
4.6.1)
reject_invalid_hostname:如果HELO命令所带的主机名参数不符合语法规范则拒绝客户机的连接请求.
修改相关配置,如下:
vi /etc/postfix/main.cf
smtpd_helo_restrictions = reject_invalid_hostname
测试:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo 8888
250 mail.ckhitler.org
250 2.1.0 Ok
501 5.5.2 <8888>: Helo command rejected: Invalid name
quit
221 2.0.0 Bye
Connection closed by foreign host.
4.6.2)
reject_unknown_hostname
拒绝未知的主机名的连接.所谓未知的主机名是指该主机没有DNS的A记录或MX记录.
修改相关配置,如下:
vi /etc/postfix/main.cf
smtpd_helo_restrictions = reject_invalid_hostname,reject_unknown_hostname
测试:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo die
250 mail.ckhitler.org
250 2.1.0 Ok
450 4.7.1 <die>: Helo command rejected: Host not found
quit
221 2.0.0 Bye
Connection closed by foreign host.
注:由于无法解析die,所以发送失败.
测试:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo test.com
250 mail.ckhitler.org
250 2.1.0 Ok
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
注:由于这回用helo test.com,所以发送邮件成功.
4.6.3)
reject_non_fqdn_hostname
如果客户端执行HELO命令时的主机名不是RFC规定的完整的域名则拒绝客户端的连接请求.
修改相关配置,如下:
vi /etc/postfix/main.cf
smtpd_helo_restrictions = reject_invalid_hostname,reject_non_fqdn_hostname
测试:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo die
250 mail.ckhitler.org
250 2.1.0 Ok
504 5.5.2 <die>: Helo command rejected: need fully-qualified hostname
quit
221 2.0.0 Bye
Connection closed by foreign host.
注:我们用helo die,由于die不符合FQDN的规范,所以发送失败.
4.7)
strict_rfc821_envelopes
RFC 821对邮件的信头做了严格的规定,但是广泛使用的sendmail并不支持该规定.
strict_rfc821_envelopes选项默认是no.
修改相关配置,如下:
vi /etc/postfix/main.cf
strict_rfc821_envelopes = yes
测试:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
503 5.5.1 Error: send HELO/EHLO first
4.8)
smtpd_sender_restrictions
通过发件人在执行MAIL FROM命令时提供的地址进行限制.
4.8.1)
reject_unknown_sender_domain
如果MAIL FROM命令提供的主机名在DNS中没有相应的A或MX记录则拒绝该客户端的连接请求.
修改相关配置如下:
vi /etc/postfix/main.cf
smtpd_sender_restrictions = reject_unknown_sender_domain
测试如下:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo test.com
250 mail.ckhitler.org
250 2.1.0 Ok
因为不存在abcckhitler.org这个域名,所以失败邮件失败.
4.8.2)
reject_non_fqdn_sender
如果MAIL FROM命令提供的主机名不是RFC规定的完整的域名则拒绝客户端的连接请求.
修改相关配置如下:
vi /etc/postfix/main.cf
smtpd_sender_restrictions = reject_non_fqdn_sender
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo test.com
250 mail.ckhitler.org
mail from:<troy@abc>
250 2.1.0 Ok
504 5.5.2 <troy@abc>: Sender address rejected: need fully-qualified address
4.9)
smtpd_recipient_restrictions
可以用smtpd_recipient_restrictions参数通过发件人在执行RCPT TO命令时提供的地址进行限制.
4.9.1)
reject_unknown_recipient_domain
如果收件人的邮件地址在DNS中没有相应的A 或 MX 记录则拒绝该客户端的连接请求.
修改相关配置如下:
vi /etc/postfix/main.cf
smtpd_recipient_restrictions = reject_unknown_recipient_domain,reject_unauth_destination,permit_mynetworks
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo test.com
250 mail.ckhitler.org
250 2.1.0 Ok
注:我们看到转发被拒绝了,是因为abcckhitler.org这个域名DNS无法解析.
4.9.2)
reject_unauth_destination
不管客户端的主机名,只要符合以下的条件,就不拒绝该客户端SMTP连接请求:
* 解析后的目标地址符合$relay_domains及其子域
* 解析后的目标地址符合$inet_interfaces、$mydestination或$virtual_maps
修改相关配置如下:
vi /etc/postfix/main.cf
smtpd_recipient_restrictions = reject_unauth_destination
测试如下:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo test.com
250 mail.ckhitler.org
250 2.1.0 Ok
我们看到转发被拒绝了.这是因为abcckhitler.org不在relay_domains的列表中.
4.9.3)
reject_non_fqdn_recipient
如果发件人在执行RCPT TO命令时提供的地址不是完整的域名则拒绝其SMTP连接请求
修改相关配置如下:
vi /etc/postfix/main.cf
smtpd_recipient_restrictions = reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_mynetworks,reject_unauth_destination
测试如下:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
helo test.com
250 mail.ckhitler.org
250 2.1.0 Ok
rcpt to:<troy@abc>
504 5.5.2 <troy@abc>: Recipient address rejected: need fully-qualified address
4.9.4)
check_relay_domains
如果符合以下的条件,则接受SMTP连接请求,否则拒绝该连接
* 客户端主机名符合$relay_domains及其子域
* 目的地为$inet_interfaces、$mydestination或$virtual_maps
修改相关配置如下:
smtpd_recipient_restrictions = check_relay_domains
测试如下:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
helo test.com220 mail.ckhitler.org ESMTP Postfix
250 mail.ckhitler.org
250 2.1.0 Ok
我们看到smtp服务对目的地进行检测,因为abcckhitler.org不在mydestination选项所指定的域名,所以转发失败.
5)行为控制
5.1)发件和收件的限制
smtpd_recipient_limit
设置一封邮件允许有多少个收件人,该参数默认为1000.
我们为了测试将该值改为2,如下:
smtpd_recipient_limit = 2
进行测试:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
helo 220 mail.ckhitler.org ESMTP Postfix
501 Syntax: HELO hostname
250 2.1.0 Ok
250 2.1.5 Ok
250 2.1.5 Ok
452 4.5.3 Error: too many recipients
注:我们看到这里只能有2个收件人.
建议修改为50个收件人,即:
smtpd_recipient_limit = 50
message_size_limit
设置一封邮件大小(包括正文,附件等所有内容),该参数默认值为10MB
我们为测试将message_size_limit设为100,即只接收100个字节的邮件.
message_size_limit = 100
进行测试:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
250 2.1.0 Ok
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
ssssssssssssssssssssssssssss
ssssssssssssssssssssssssssss
ssssssssssssssssssssssssssss
eeeeeeeeeeeeeeeeeeeeeeeeeess
fffffffffffffffffffffffffffs
wwwwwwwwwwwwwwwwwwwwwwwwwwww
xxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxx
.
552 5.3.4 Error: message file too big
我们这里可以更改为20MB,即每封邮件最大为20MB,如下:
message_size_limit = 20480000
mailbox_size_limit
设置用户的邮箱大小,注意,邮箱的限额不能小于设置的邮件限额.
例如,我们这里设置用户的邮箱的限额1024
mailbox_size_limit = 1024
设置邮件的限额为1000,如下:
message_size_limit = 1000
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
250 2.1.0 Ok
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
ssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssss
.
250 2.0.0 Ok: queued as DD385163C49
quit
查看邮箱大小:
ls -l
total 4
-rw------- 1 root mail 0 Jul 19 06:21 root
-rw-rw----. 1 rpc mail 0 May 10 07:39 rpc
-rw-rw----. 1 test mail 551 Jul 19 06:41 test
-rw-rw----. 1 test1 mail 0 Jul 16 20:27 test1
我们再次发送给test相同大小的邮件,如下:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
250 2.1.0 Ok
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
ssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssss
ssssssssssssssssssssssssssssssss
.
250 2.0.0 Ok: queued as DD385163C49
quit
再次查看邮箱大小,发现邮箱还没改变,说明邮箱限额起了作用,如下:
ls -l
total 4
-rw------- 1 root mail 0 Jul 19 06:21 root
-rw-rw----. 1 rpc mail 0 May 10 07:39 rpc
-rw-rw----. 1 test mail 551 Jul 19 06:41 test
-rw-rw----. 1 test1 mail 0 Jul 16 20:27 test1
5.2)客户端连接控制
smtpd_error_sleep_time
当SMTP服务端口接收到非法的命令时,系统将缓冲处理的时间间隔,我们调整smtpd_error_sleep_time为10秒.
如下:
smtpd_error_sleep_time = 10s
smtpd_soft_error_limit
当超过smtpd_soft_error_limit参数所指定的错误次数时,系统应用smtpd_error_sleep_time参数所指定的缓冲时间.
如下:
smtpd_soft_error_limit = 2
smtpd_hard_error_limit
当超过smtpd_hard_error_limit参数所指定的错误次数时,系统强制断开客户端的连接.
如下:
smtpd_hard_error_limit = 5
注:上面的配置说明如果用户连接SMTP输入的错误指令超过2次,系统将缓冲处理10秒钟,以后每输错一种指令都延时10秒钟,直到累加超过5次,断开连接,我们做测试如下:
telnet 192.168.75.128 25
Trying 192.168.75.128...
Connected to 192.168.75.128.
Escape character is '^]'.
220 mail.ckhitler.org ESMTP Postfix
test
502 5.5.2 Error: command not recognized
test
502 5.5.2 Error: command not recognized
test /*注意:在输入第三次错误指令后,在这里延时10秒钟*/
502 5.5.2 Error: command not recognized
test /*注意:在输入第四次错误指令后,在这里延时10秒钟*/
502 5.5.2 Error: command not recognized
test /*注意:在输入第五次错误指令后,在这里延时10秒钟*/
502 5.5.2 Error: command not recognized
test /*注意:在输入第六次错误指令后,postfix断开客户端连接*/
421 4.7.0 mail.ckhitler.org Error: too many errors
Connection closed by foreign host.
6)性能控制
6.1)
default_process_limit
通过default_process_limit 参数来控制postfix系统同时可以运行的最大进程数目.缺省值是50个.
为了能提高并行处理能力,可以提高进程最大数目,如下:
default_process_limit = 300
6.2)
initial_destination_concurrency
控制对同一目标主机的初始化并发连接数目,缺省值为2.
default_destination_concurrency_limit
控制初始化连接后对同一目标主机的最大并发连接数目,缺省值为10.
local_destination_concurrency_limit
控制对同一本地收件人的最大同时投递的邮件数目,缺省值为2.
6.3)
queue_run_delay
设置队列管理进行扫描deferred邮件队列的频率,缺省值为1000秒.
这里我们建议将扫描频率改为3600秒.
maximal_queue_lifetime
设置postfix在放弃投递而返回不可投递信息前,被延迟邮件再deferred邮件队列中的生存时间.
这里我们建议将生存时间改为3天
minimal_backoff_time
当一封邮件投递失败后,邮件队列将在一段时间内忽视该邮件的存在,也就是我们前面讲的时间戳,该参数就是用来设置最小的时间戳,缺省值为1000秒.
这里我们建议将最小忽视时间改为300秒
maximal_backoff_time
设置最大的时间戳,缺省值是4000秒
最大忽视时间保持默认即可.
6.4)
line_length_limit
控制读入数据时每一行的大小,如果太长则强行将其分割成更短的行,太长的行在投递时再重组.缺省值为2048 bytes.
这里保持默认即可.
header_size_limit
限制信头长度,缺省值为102400bytes.
queue_minfree
设置整个队列目录最大使用的磁盘功能,缺省为无限制,建议该值最好时message_size_limit的数倍以便于处理大邮件.
bounce_size_limit
限制某一邮件不可投递时,返回给发件人不可投递报告的大小,缺省值为50000 bytes.
6.5)
qmgr_message_recipient_limit
设置内存中收件人地址的最大数目,缺省值为10000
qmgr_message_active_limit
设置active邮件队列中邮件数目的最大值,缺省值为1000,这里可以调整为10000.
duplicate_filter_limit
设置需要local和cleanup后台程序记住的收件人地址的最大数目,缺省值为1000.
6.6)
command_time_limit
设置local程序等待一个外部命令完成的时间,缺省值为1000秒.
6.7)
deliver_lock_attempts
设置锁定一个文件的最大尝试次数,缺省值为5次.
deliver_lock_delay
设置如果锁定一个文件失败后再次尝试的等待时间,缺省值为1秒.
6.8)
fork_attempts
试图重启动一个进程的最大尝试次数,缺省值为5次.
fork_delay
每两次尝试之间的等待时间,缺省值为1秒.
transport_retry_time
队列管理进程每两次尝试连接一个不正常的投递代理进程之间的等待时间,缺省为60秒.
7)postfix的配置模板
##########################################
#设定主机名称 myhostname
#设定发信时所显示的发信源主机 myorigin
#设定网域名称 mydomain
#设定能够收信的主机名称 mydestination
##########################################
myhostname = mail.ckhitler.org
mydomain = ckhitler.org
myorigin = ckhitler.org
mydestination = $myhostname,$mydomain
##########################################
#监听的网络地址,这里监听所有网络介质
##########################################
inet_interfaces = all
##########################################
#设定转发信任网络 mynetworks
#规范可以转发的域名 relay_domains
##########################################
mynetworks = 127.0.0.0/8, 192.168.75.0/24
relay_domains = $mydomain
###########################################
#客户端在执行HELO命令时,对客户端的合法性进行检查
#1)如果HELO命令所带的主机名参数不符合语法规范则拒绝客户机的连接请求
#2)拒绝未知的主机名的连接.所谓未知的主机名是指该主机没有DNS的A记录或MX记录
#3)如果客户端执行HELO命令时的主机名不是RFC规定的完整的域名则拒绝客户端的连接请求
###########################################
smtpd_helo_restrictions = reject_invalid_hostname,reject_unknown_hostname,reject_non_fqdn_hostname
##########################################
#允许/拒绝客户端使用邮件服务器 smtpd_client_restrictions
#1)拒绝来自属于RBL和RHSBL列表中的地址进行连接
##########################################
smtpd_client_restrictions = permit_mynetworks,check_client_access hash:/etc/postfix/access,
reject_rbl_client cblless.anti-spam.org.cn,
reject_rbl_client sbl-xbl.spamhaus.org,
reject_rbl_client relays.ordb.org,
reject_rhsbl_client dsn.rfc-ignorant.org
##########################################
#通过发件人在执行MAIL FROM命令时提供的地址进行限制
#1)如果MAIL FROM命令提供的主机名在DNS中没有相应的A或MX记录则拒绝该客户端的连接请求
#2)如果MAIL FROM命令提供的主机名不是RFC规定的完整的域名则拒绝客户端的连接请求.
##########################################
smtpd_sender_restrictions = reject_unknown_sender_domain,
reject_non_fqdn_sender
##########################################
#通过发件人在执行RCPT TO命令时提供的地址进行限制
#1)如果收件人的邮件地址在DNS中没有相应的A 或 MX 记录则拒绝该客户端的连接请求
#2)不管客户端的主机名,只要符合以下的条件,就不拒绝该客户端SMTP连接请求:
# 2.1)解析后的目标地址符合$relay_domains及其子域
# 2.2)解析后的目标地址符合$inet_interfaces,$mydestination或$virtual_maps
#3)如果发件人在执行RCPT TO命令时提供的地址不是完整的域名则拒绝其SMTP连接请求
#4)如果符合以下的条件,则接受SMTP连接请求,否则拒绝该连接
# 4.1)客户端主机名符合$relay_domains及其子域
# 4.2)目的地为$inet_interfaces、$mydestination或$virtual_maps
##########################################
smtpd_recipient_restrictions = reject_non_fqdn_recipient,
reject_unknown_recipient_domain,
reject_unauth_destination,
permit_mynetworks
check_relay_domains
###########################################
#客户端在SMTP会话的开始必须发送一个HELO命令
###########################################
smtpd_helo_required = yes
###########################################
#RFC 821对邮件的信头做了严格的规定
###########################################
strict_rfc821_envelopes = yes
###########################################
#设置一封邮件允许有多少个收件人,这里指定一封邮件可以同时发给50个人
###########################################
smtpd_recipient_limit = 50
###########################################
#设置一封邮件大小(包括正文,附件等所有内容),这里指定为20MB
###########################################
message_size_limit = 20480000
###########################################
#设置用户邮箱在大小,这里为2GB
###########################################
mailbox_size_limit = 2048000000
###########################################
#当SMTP服务端口接收到非法的命令时,系统将缓冲处理的时间间隔,这里指定为10秒
###########################################
smtpd_error_sleep_time = 10s
###########################################
#当超过该参数所指定的错误次数时,系统应用缓冲时间,即10秒,这里指定错误次数为2次
###########################################
smtpd_soft_error_limit = 2
###########################################
#当超过该参数所指定的错误次数时,系统强制断开客户端,这里指定为5次
###########################################
smtpd_hard_error_limit = 5
###########################################
#提高并行处理能力,提高进程最大数目,这里指定为300
###########################################
default_process_limit = 300
###########################################
#控制对同一目标主机的初始化并发连接数目,这里调整为10
###########################################
initial_destination_concurrency = 10
###########################################
#控制初始化连接后对同一目标主机的最大并发连接数目,这里调整为10
###########################################
default_destination_concurrency_limit = 10
###########################################
#控制对同一本地收件人的最大同时投递的邮件数目
###########################################
local_destination_concurrency_limit = 2
###########################################
#设置postfix在放弃投递而返回不可投递信息前,被延迟邮件再deferred邮件队列中的生存时间
###########################################
maximal_queue_lifetime = 3d
###########################################
#设置队列管理进行扫描deferred邮件队列的频率,这里调整为1小时
###########################################
queue_run_delay = 3600s
###########################################
#当一封邮件投递失败后,邮件队列将在一段时间内忽视该邮件的存在,最小的忽略时间为300秒
###########################################
minimal_backoff_time = 300s
###########################################
#当一封邮件投递失败后,邮件队列将在一段时间内忽视该邮件的存在,最大的忽略时间为3600秒
###########################################
maximal_backoff_time = 3600s
###########################################
#控制读入数据时每一行的大小,这里为2048个字节
###########################################
line_length_limit = 2048
###########################################
#限制信头长度
###########################################
header_size_limit = 102400
###########################################
#设置整个队列目录最大使用的磁盘功能,这里调整为2GB
###########################################
queue_minfree = 2048000000
###########################################
#限制某一邮件不可投递时,返回给发件人不可投递报告的大小
###########################################
bounce_size_limit = 50000
###########################################
#内存中收件人地址的最大数目,这里为20000个
###########################################
qmgr_message_recipient_limit = 20000
###########################################
#设置active邮件队列中邮件数目的最大值
###########################################
qmgr_message_active_limit = 20000
###########################################
#设置需要local和cleanup后台程序记住的收件人地址的最大数目
###########################################
duplicate_filter_limit = 1000
###########################################
#设置local程序等待一个外部命令完成的时间
###########################################
command_time_limit = 1000s
###########################################
#设置锁定一个文件的最大尝试次数
###########################################
deliver_lock_attempts = 5
###########################################
#设置如果锁定一个文件失败后再次尝试的等待时间
###########################################
deliver_lock_delay = 1s
###########################################
#试图重启动一个进程的最大尝试次数
###########################################
fork_attempts = 5
###########################################
#每两次尝试之间的等待时间
###########################################
fork_delay = 1s
###########################################
#队列管理进程每两次尝试连接一个不正常的投递代理进程之间的等待时间
###########################################
transport_retry_time = 60s