电子邮件:原理、协议与 sendmail 管理
1. 电子邮件基础
电子邮件是网络用户常用的功能,尽管很多用户对 UNIX 了解不多,但他们喜欢使用电子邮件并从中受益。不过,用户与电子邮件之间往往是一种爱恨交织的关系,他们喜欢有电子邮件系统,但当系统出现问题时就会感到不满。而且,很多用户并不清楚电子邮件的实际工作原理,常常将其与其他网络应用(如 telnet 或 ftp)混淆。
可以将电子邮件类比为普通的地面邮件服务(蜗牛邮件),telnet 对应电话服务,ftp 对应传真服务,DNS 则像帮助解析名称、地址和电话号码关系的接线员。
1.1 电子邮件程序分类
电子邮件程序主要分为两类:
-
邮件用户代理(MUA)程序
:用户用于阅读、回复、撰写和处理电子邮件的程序,例如原始的 UNIX 邮件程序
/bin/mail
、Berkeley 邮件或其 System V 等效程序
mailx
,以及免费的
mush
、
elm
、
pine
和
mh
等,还有其他商业程序。
-
邮件传输代理(MTA)程序
:负责为多个用户处理邮件传递并在机器之间转发电子邮件的程序。目前最常用的中央邮件传输程序是
sendmail
,在 UNIX 系统中它是默认的 MTA 程序。
1.2 电子邮件的传输与存储
当一封电子邮件到达目的地时,它会被放入用户的邮箱。在 UNIX 系统中,邮箱通常是一个以用户名命名的文件,默认位于
/var/mail
目录下。用户读取邮件后,邮件会被转移到用户主目录下的另一个邮箱中。
sendmail
是电子邮件的核心,也是成功实现电子邮件通信的关键管理点。两个
sendmail
程序(借助适当的邮件传送器)通过网络在机器之间传输电子邮件,使用的协议是简单邮件传输协议(SMTP)。MUA 程序则在电子邮件用户和
sendmail
之间提供接口,从用户的角度来看,它们是最关键的环节,但对整体电子邮件的影响相对较小,其重要性主要体现在本地环境中。
1.3 电子邮件消息结构
每封电子邮件消息都有一个包含收件人和发件人地址的信封,以及由头部和正文组成的消息内容。
sendmail
会解析和分析电子邮件地址,确定目的地并决定如何传递邮件。邮件可能不会立即送达最终收件人,而是可能通过多个邮件主机进行转发,具体路由主要取决于收件人的地址,有时也会受到当前网络条件的影响。
消息内容的头部包含发件人、收件人、创建时间、主题和传递标记等信息,正文与头部由一个空行分隔,包含发件人想要传达的信息。
1.4 数据编码与传输
过去,电子邮件消息通常是纯 ASCII 文本,使用的 SMTP 协议是基于 US - ASCII 字符集的 7 位协议,只能使用低 7 位数据,第 8 位始终被视为零。对于许多外语(特别是亚洲语言)以及二进制多媒体数据(如图形、程序、音频和视频等),需要有效的第 8 位。为了无损传输这些数据,消息必须先编码为 7 位数据,MIME(多用途 Internet 邮件扩展)封装提供了解决方案。
随着多媒体消息的激增,对“真正的 8 位消息传输”的需求也随之增加。SMTP 协议已扩展为支持 8 位传输,通用扩展机制 ESMTP 在 RFC 1869 中定义,允许 8 位传输的特定扩展 8BITMIME 在 RFC 1652 中定义。如果 MTA 程序无法协商 8 位数据的正确传输,它要么使用 MIME 将消息编码为 7 位数据,要么将消息退回给发件人并说明原因。
sendmail
8.6 及更高版本支持 ESMTP,8.7 及更高版本支持 8BITMIME 扩展。
1.5 电子邮件传递时间
电子邮件的传递通常非常快,时间以秒、分钟或小时计算。然而,传递时间不是一个确定的值,因为它取决于许多因素,特别是当涉及多个邮件主机时。有时传递时间可能长达数天,甚至邮件可能会丢失,但这种情况很少发生。
1.6
sendmail
地址解析与决策
sendmail
的核心问题是“将电子邮件发送到哪里以及如何发送”,它会根据配置文件中指定的规则(算法)解析电子邮件收件人的地址并做出决策。目前没有统一的电子邮件地址解析算法,由
sendmail
管理员实现最合适的算法。许多 UNIX 系统提供了高级的
sendmail
配置模板,管理员只需提供特定于站点的信息,但在某些非标准情况下,这些模板可能不够用,需要更详细的管理。
sendmail
有时会因为收件人或发件人地址不明确而拒绝电子邮件消息,最常见的原因是收件人地址拼写错误,但在某些罕见情况下,即使地址正确,也可能由于
sendmail
配置不当或其他临时问题而被退回。
2. 简单邮件传输协议(SMTP)
SMTP 是基本的电子邮件协议,基于 TCP/IP 协议族,是
sendmail
能够理解的“语言”。两个
sendmail
程序之间的对等通信实际上是 SMTP 消息的交换。
2.1 SMTP 通信示例
以下是一个使用
sendmail
详细模式的示例,展示了两个主机之间的 SMTP 通信过程:
#/usr/lib/sendmail -v mis@apollo.ph.myschool.scps.edu < indata.mail
mis@apollo.ph.myschool.scps.edu… Connecting to apollo.ph.myschool.scps.edu via ether…
Trying 146.98.8.31… connected.
220 apollo.ph.myschool.scps.edu HP Sendmail (1.38.193.4/16.2) ready at Tue, 5 Jul 1998 17:06:13 -0400
>>> HELO patsy.myschool.scps.edu
250 apollo.ph.myschool.scps.edu Hello patsy.myschool.scps.edu, pleased to meet you
>>> MAIL From:<bjl@patsy>
250 <bjl@patsy>… Sender ok
>>> RCPT To:<mis@apollo.ph.myschool.scps.edu>
250 <mis@apollo.ph.myschool.scps.edu>… Recipient ok
>>> DATA
354 Enter mail, end with "." on a line by itself
>>>.
250 Ok
>>> QUIT
221 apollo.ph.myschool.scps.edu closing connection
mis@apollo.ph.myschool.scps.edu… Sent
这个过程可以总结为以下步骤:
1.
连接阶段
:发件方的
sendmail
尝试连接到收件方的主机,显示连接信息和收件方主机的 IP 地址。
2.
准备阶段
:收件方主机发送 220 消息,表示准备好接收邮件,并提供其域名、程序名称和版本信息,以及本地日期和时间。
3.
问候阶段
:发件方的
sendmail
发送
HELO
消息,收件方以 250 消息确认发件方的主机名可接受。
4.
发件人确认阶段
:发件方发送发件人信息,收件方以 250 消息确认发件人信息。
5.
收件人确认阶段
:发件方发送收件人信息,收件方以 250 消息确认收件人信息(或返回错误信息)。
6.
数据传输阶段
:发件方发送
DATA
消息,通知收件方准备接收数据,数据传输结束时用单独一行的一个点表示。
7.
结束阶段
:发件方发送
QUIT
消息,收件方确认关闭连接,最后确认邮件已成功发送。
2.2 SMTP 通信流程
graph LR
A[发件方 sendmail] -->|连接| B[收件方主机]
B -->|220 准备好| A
A -->|HELO 问候| B
B -->|250 确认| A
A -->|MAIL From 发件人信息| B
B -->|250 确认| A
A -->|RCPT To 收件人信息| B
B -->|250 确认| A
A -->|DATA 准备发送数据| B
B -->|354 准备接收| A
A -->|发送数据| B
A -->|. 数据结束| B
B -->|250 确认| A
A -->|QUIT 结束通信| B
B -->|221 关闭连接| A
3. MTA 程序 sendmail
3.1 sendmail 守护进程
sendmail
守护进程在每个完全支持电子邮件的主机上持续运行,监听端口 25 并处理传入的电子邮件。它通常在系统启动时从 rc 初始化脚本文件中调用,执行以下命令序列:
if [ -f /usr/lib/sendmail -a -f /etc/sendmail.cf ]; then
(cd /var/spool/mqueue; rm -f nf* lf*)
/usr/lib/sendmail -bd -q1h; echo -n "sendmail"
fi
这个脚本首先检查
sendmail
程序和配置文件
/etc/sendmail.cf
是否存在,如果存在,则清理邮件队列目录中的可能残留文件,然后以
-bd
选项启动
sendmail
作为守护进程,监听端口 25 接收传入的电子邮件,
-q
选项指定邮件队列的处理频率,对于大多数系统,设置为 1 小时是一个不错的选择。
当
sendmail
守护进程过于繁忙时,它会派生其他守护进程来协助处理电子邮件,子守护进程完成任务后会退出,但父守护进程即使空闲也会继续运行。
3.2 sendmail 命令
sendmail
是一个功能强大的 UNIX 命令,可以随时从命令行执行。“守护进程选项
-bd
”只是众多可能选项之一,它也可以像其他 UNIX 命令一样用于完成单个任务,常用于
sendmail
的测试和调试。
3.2.1 sendmail 命令的主要特点
- 可以将消息发送给一个或多个人,根据需要在网络上路由消息。
-
不是用户界面程序,其他 MUA 程序提供用户友好的前端,
sendmail仅用于传递预格式化的消息。 -
在发件方,会在本地别名文件中查找收件人地址并进行别名处理,如果收件人主目录中有
.forward文件,会将邮件转发给该文件中列出的收件人。 -
可以直接将邮件路由到网络中的其他已知主机,具体列表取决于
sendmail配置,也可以由相关文件维护。
3.2.2 sendmail 命令选项
| 选项 | 操作 |
|---|---|
-bd
| 作为守护进程运行,等待传入的 SMTP 连接。 |
-bi
| 初始化别名数据库。 |
-bm
| 以通常方式传递邮件(默认)。 |
-bp
| 打印邮件队列摘要并列出当前队列中的所有邮件。 |
-bt
| 运行地址测试模式,用于调试配置地址解析规则。 |
-bv
| 仅验证名称,不尝试收集或传递消息,通常用于验证用户或邮件列表。 |
-bz
| 创建配置冻结文件。 |
-n
| 不进行别名处理。 |
-hN
| 将跳数设置为 N,邮件每次处理时跳数增加,达到限制时邮件将返回错误消息。 |
-q [time]
| 按给定间隔处理队列中保存的消息,如果省略时间,则处理一次队列。时间可以用秒(s)、分钟(m)、小时(h)、天(d)和周(w)表示。 |
-t
| 从消息中读取收件人信息,扫描“To:”、“Cc:”和“Bcc:”行,发送前删除“Bcc:”行,并抑制参数列表中的任何地址。 |
-v
| 详细模式,显示别名扩展和 SMTP 对话等信息。 |
3.2.3 sendmail 依赖的文件
sendmail
依赖以下文件:
-
/etc/aliases
(或
/etc/mail/aliases
):别名名称的 ASCII 数据文件。
-
/etc/sendmail.cf
:配置文件。
-
/etc/sendmail.fc
:冻结配置文件。
-
/etc/sendmail.st
:收集的统计信息。
-
/usr/lib/mailhosts
:可以直接发送电子邮件的主机列表。
-
/usr/lib/sendmail.hf
:帮助文件。
-
/var/spool/mqueue/*
:临时文件和排队的邮件。
-
$HOME/.forward
:用户的个人邮件转发文件。
-
/usr/bin/mail
和
/usr/sbin/mailx
:用于本地邮件传递。
sendmail
处理传入电子邮件时会依据这些文件,其中最重要的是配置文件
/etc/sendmail.cf
,后续将详细讨论。
3.3 sendmail 的其他组成部分
3.3.1 全局邮件别名
全局邮件别名文件
/etc/aliases
(有时链接到
/etc/mail/aliases
)在系统级别提供以下功能:
- 为本地用户提供别名(昵称)。
- 将邮件转发到其他主机。
- 实现邮件列表。
别名文件的基本格式为:
alias: recipient[, recipient, …]
其中,
alias
是电子邮件所指向的名称,
recipient
可以是另一个本地用户名、另一个别名的名称或包含用户名和主机名的完整电子邮件地址,也可以是多个收件人,用于实现邮件列表。
以下是一个别名文件的示例:
$ cat /etc/aliases
##
# Aliases can have any mix of upper and lower case on the left−hand side,
# but the right−hand side should be proper case (usually lower)
#
# >>>>>>>>>> The program "newaliases" will need to be run after
# >> NOTE >> this file is updated for any changes to
# >>>>>>>>>> show through to sendmail.
#
# @(#)aliases 2.30 SMI
##
# Following alias is required by the mail protocol, RFC 822
# Set it to the address of a HUMAN who deals with this system's mail problems.
Postmaster: root
# Alias for mailer daemon; returned messages from our MAILER−DAEMON
# should be routed to our local Postmaster.
MAILER−DAEMON: postmaster
# Aliases to handle mail to programs or files, eg news or vacation
# decode: "| /usr/bin/uudecode"
nobody: /dev/null
# Sample aliases:
# Alias for distribution list, members specified here:
#staff:wnj,mosher,sam,ecc,mckusick,sklower,olson,rwh@ernie
# Alias for distribution list, members specified elsewhere:
#keyboards: :include:/usr/jfarrell/keyboards.list
# Alias for a person, so they can receive mail by several names:
#epa:eric
#############################################################################
# Local aliases below #
#############################################################################
# The list of local aliases follows
bjl blevi
需要注意的是,
sendmail
并不直接使用
/etc/aliases
文件,修改该文件后需要运行
newaliases
命令(等同于
sendmail -bi
命令)来创建
sendmail
使用的 dbm 别名文件(
aliases.dir
和
aliases.pag
),这样可以加快别名数据库的搜索速度。
3.3.2 个人邮件转发文件
除了全局邮件转发,
sendmail
允许用户在其主目录下的
.forward
文件中定义个人转发规则。
sendmail
在使用
/etc/aliases
文件后、最终将邮件传递给用户之前会检查该文件,如果存在则遵循其指令,指令格式与
/etc/aliases
条目相同。
3.3.3 邮件传递程序(Mailers)
sendmail
本身并不直接处理邮件传递,除了通过 TCP/IP 网络将邮件转发到其他远程主机的情况外,它会调用其他程序(即邮件传送器)来完成邮件传递。邮件传送器的定义包含在
sendmail
配置文件中,
sendmail
决定何时使用邮件传送器并提供必要的传递数据。
邮件传送器的定义在
sendmail
配置文件中由“M 配置条目”指定,其通用形式为:
M=mailer−name P=mailer−path F=mailer−flags S=send−rules R=receive−rules A=mailer−arguments
其中:
-
M=
:标识邮件传送器的定义配置条目,后面紧跟
sendmail
识别相应传递代理的符号名称。
-
P=
:指定执行邮件传递的邮件传送器程序的完整路径名。
-
F=
:指定某些标志,告诉
sendmail
更多关于邮件传送器的定义。
-
S=
:指定重写发件人地址时使用的规则集。
-
R=
:指定重写收件人地址时使用的规则集。
-
A=
:指定要提供给每个相应邮件传送器程序的命令行参数。
虽然可以定义任意数量的邮件传送器,名称也可以任意,但必须定义两个邮件传送器:
local
和
prog
,它们分别用于将电子邮件传递给本地用户和本地程序。如果它们不存在,
sendmail
将无法启动并会打印相应的错误消息。
3.3.4 sendmail 配置文件
sendmail
配置文件(通常是
/etc/sendmail.cf
,有时是
/usr/lib/sendmail.cf
或
/etc/mail/sendmail.cf
)是
sendmail
的核心,它完全定义了
sendmail
的行为,主要有以下三个功能:
- 定义
sendmail
环境。
- 将地址重写为适合进一步电子邮件处理的语法。
- 将地址映射为传递电子邮件所需的指令。
配置文件中包含许多不同的配置条目来实现这些功能:
- 宏定义和选项条目定义环境。
- 重写规则将电子邮件地址从一种格式转换为另一种格式。
- 邮件传送器定义指定传递电子邮件所需的程序。
配置文件的语法简洁而复杂,大多数系统管理员甚至不愿意阅读该文件,只有少数人对修改配置感到得心应手。由于
sendmail
在启动时会读取配置文件并据此运行,因此语法是为了满足程序需求而设计的,对人类来说并不容易阅读。所有配置命令、规范、选项和变量都只有一个字符长,难以识别和记忆,很容易将单个字符命令与单个字符变量混淆。然而,为了成功管理
sendmail
,必须完全理解该配置文件。
3.3.5 冻结的 sendmail 配置文件
为了加快
sendmail
启动时读取配置数据的速度,可以创建 ASCII 配置文件
/etc/sendmail.cf
的转换 dbm 映像,这个文件称为冻结配置文件
/etc/sendmail.fc
(有时是
/usr/lib/sendmail.fc
)。可以使用以下命令创建冻结配置文件:
/usr/lib/sendmail -bz
3.3.6 sendmail 配置文件的重要性及管理建议
sendmail
配置文件的重要性不言而喻,它就像是
sendmail
程序的“大脑”,决定了整个电子邮件系统的运行方式。由于其语法复杂,管理起来具有一定的挑战性,以下是一些管理建议:
-
备份与版本控制
:在对配置文件进行任何修改之前,务必进行备份。可以使用版本控制系统(如 Git)来记录配置文件的修改历史,这样在出现问题时可以方便地回滚到之前的版本。
-
逐步修改与测试
:每次只对配置文件进行少量的修改,并在修改后进行充分的测试。可以使用
sendmail
的
-bt
选项进行地址测试,确保修改不会引入新的问题。
-
参考文档与社区资源
:
sendmail
有丰富的文档和社区资源可供参考。在遇到问题时,可以查阅官方文档或在相关社区论坛上寻求帮助。
3.3.7 常见配置错误及解决方法
在管理
sendmail
配置文件时,可能会遇到一些常见的错误,以下是一些例子及解决方法:
| 错误类型 | 错误表现 | 解决方法 |
| ---- | ---- | ---- |
| 地址解析错误 | 邮件无法正常发送或接收,提示地址解析失败 | 检查配置文件中的地址解析规则,确保别名文件和相关配置正确。可以使用
-bt
选项进行调试。 |
| 邮件队列堆积 | 邮件队列中的邮件长时间未处理 | 检查
-q
选项的设置,确保邮件队列处理频率合理。同时,检查系统资源使用情况,确保
sendmail
有足够的资源来处理邮件。 |
| 权限问题 |
sendmail
无法访问某些文件或目录 | 检查相关文件和目录的权限设置,确保
sendmail
有足够的权限进行读写操作。 |
4. 电子邮件安全与性能优化
4.1 电子邮件安全
电子邮件安全是一个重要的问题,涉及到用户隐私和系统安全。以下是一些提高电子邮件安全的建议:
-
身份验证
:使用 SMTP 身份验证机制,确保只有授权用户可以发送邮件。可以通过配置
sendmail
支持 SASL 认证来实现。
-
加密传输
:使用 SSL/TLS 加密协议对邮件传输进行加密,防止邮件内容在传输过程中被窃取。可以在
sendmail
配置文件中配置 SSL/TLS 支持。
-
反垃圾邮件
:部署反垃圾邮件系统,如 SpamAssassin,对收到的邮件进行过滤,减少垃圾邮件的干扰。可以将 SpamAssassin 与
sendmail
集成,在邮件接收阶段进行过滤。
4.2 性能优化
为了提高电子邮件系统的性能,可以采取以下措施:
-
合理配置邮件队列处理频率
:根据系统的负载情况,合理调整
-q
选项的设置,确保邮件队列能够及时处理。对于高流量的邮件服务器,可以适当缩短处理间隔。
-
优化别名数据库
:定期更新别名数据库,确保别名查询的效率。可以使用
sendmail -bi
命令重新初始化别名数据库。
-
缓存机制
:使用缓存机制来减少重复查询和处理。例如,可以使用 DNS 缓存来提高域名解析的速度。
5. 总结与展望
5.1 总结
本文详细介绍了电子邮件的基本原理、SMTP 协议以及
sendmail
程序的管理。电子邮件作为网络通信的重要工具,其核心在于
sendmail
程序,它负责邮件的路由、传递和管理。通过了解
sendmail
的守护进程、命令选项、依赖文件以及配置文件的相关知识,可以更好地管理和维护电子邮件系统。同时,为了确保系统的安全和性能,还需要采取相应的安全措施和性能优化策略。
5.2 展望
随着互联网的不断发展,电子邮件系统也在不断演进。未来,电子邮件可能会朝着更加智能化、安全化和高效化的方向发展。例如,人工智能技术可能会被应用于反垃圾邮件和邮件分类,进一步提高用户体验。同时,随着 5G 等高速网络的普及,电子邮件的传输速度和性能也将得到进一步提升。作为系统管理员,需要不断学习和掌握新的技术,以适应不断变化的需求。
graph LR
A[电子邮件系统] --> B[sendmail 管理]
B --> C[配置文件管理]
B --> D[安全与性能优化]
C --> E[备份与版本控制]
C --> F[逐步修改与测试]
D --> G[身份验证]
D --> H[加密传输]
D --> I[反垃圾邮件]
D --> J[合理配置队列频率]
D --> K[优化别名数据库]
D --> L[缓存机制]
以上就是关于电子邮件系统的相关知识,希望对大家有所帮助。通过合理的管理和优化,可以确保电子邮件系统的稳定运行,为用户提供更好的服务。
超级会员免费看

被折叠的 条评论
为什么被折叠?



