Exim 如何接收和投递邮件(一)
Posted in Linux on 十二月 23rd, 2007 by admin – 1 Comment基本原理
Exim 的设计目的是为永久连接到互联网的主机提供高效的处理邮件的系统。这种情况下,大多数信息可以被立即投递出去。因此,Exim 并不为个体的域或主机维护独立的消息队列,尽管在某个主机关闭后,它的确会尝试在单一的 SMTP 连接中重发这些消息,并且为每个主机维护重投信息。
控制策略
控制策略是现在连接到互联网上的 MTA 的重要功能部件。它最重要的功能就是防止垃圾邮件了。Exim 提供了灵活的功能来控制进入的邮件:
- Exim 4 (不同于先前版本的 Exim )使用存取控制表(ACL)来过滤收到的邮件。存取控制表可以出现在 SMTP 对话中的很多地方,但最常用的是把它放在 RCPT 命令之后以及整个消息的最后。这两个地方,系统管理员可以设定条件允许或拒绝个别收件人或者整条消息。
- ACL 也可用于本地产生的非 SMTP 消息。这种情况下,唯一可用的操作是接受或拒绝整条消息。
- 如果 Exim 编译进了内容扫描扩展,ACL 还会提供额外的机制来将消息传递给外部的杀毒软件或垃圾邮件扫描程序,扫描结果重新被传回 ACL 以便决定下一步的动作。
- 对于收到的消息,无论是来自远程主机或是本地主机,在正式确认送抵之前,都可以运行一个叫 local_scan() 的 C 函数来审查这些消息,来决定是否接受。如果接受消息,还可以使用该函数来修改收件人列表。
- local_scan() 机制也可以用来调用外部扫描程序。SA-Exim 扩展包就是以这种方式工作的。它并不需要 Exim 编译进内容扫描扩展。
- 消息被接受后,还要经过系统过滤的进一步审查。它会在每个投递进程运行之前运行。
用户过滤
常规的 Exim 配置状态下,用户可以通过在他们的家目录下设置 .forward 文件来指定他们自己的过滤条件。有两套可用的过滤方式:
- Sieve 过滤。这是 RFC 3028 中定义的标准过滤语言。
- Exim 过滤。这是 Exim 独有的方式,功能比前者要强大。
消息识别
在 Exim 中,每条消息都被给定了一个 ID。它由一个十六位的字符串组成,被连字符分成三部分,如:16VDhn-0001bo-D3。其中的每一部分都是字母与数字的组合,通常情况下以 base 62 编码。但在 Darwin 系统(如苹果系统)上则使用 base 36,这是因为消息 ID 会被用来构成文件名,但这类系统并不总是区别大小写。
消息 ID 的具体内容随 Exim 版本的演化已经发生了变化。早先版本的 消息 ID 基于操作系统在一秒内不会重复使用同一个进程 ID (PID)这样一个“事实”。但对现代的操作系统来说,上述“事实”事实上已经不再是事实了。但为了保持向后兼容性,消息 ID 的格式得以保留。这也是下面的规则有些反常的原因:
- 消息 ID 的前六个字符是开始收取消息的时间,精确到秒。
- 接下来连字符后的六个字符是接收该消息的进程的 ID。
- 最后的两个字符有两种可能:
- 如果没有设置 localhost_number,是接收消息的时间的小数部分,通常单位是 1/2000 秒,但对于必须使用 base 36 的操作系统来说,单位是 1/1000 秒。
- 如果设置了 localhost_number,则是 1/200(1/100)秒。
消息收到后,Exim 会等待一段适当的时间再来处理,以保证如果同一进程或拥有同样 PID 的其它进程接受了别的消息,它们的时间是不一样的。事实上大多数情况下,当消息收完后,这段“适当的时间”已经过了。
接收邮件
Exim 要从其它主机接收邮件只有一种途径就是通过 SMTP,发送器和接收器使用 SMTP 命令传输寻址。然而,对来自本地其它进程(比如用户的 MUA)的消息,则有几种可能:
- 如果该进程使用 -bm 选项运行 Exim,消息以非交互式的方式读取(通常是通过管道),收件人从命令行读取或者从消息本身读取如果 -t 被同时使用的话。
- 如果该进程使用 -bS 选项,消息仍旧以非交互方式读取,不同的是,收件人以一系列 SMTP RCPT 命令在消息开头列出,以 DATA 命令终止。因此也被称为“批量 SMTP”格式,但它并不真的是 SMTP。SMTP 命令只是在非交互情况下传递地址封包的另外一种途径而已。
- 如果该进程使用 -bs 选项,消息以交互方式读取,使用 SMTP 协议。通常使用一个双向的管道来在本地进程与 Exim 进程之间传递数据。这是“真” SMTP,工作方式与 TCP/IP 上的 SMTP 一样。
- 本地进程也可以向主机的回环地址(127.0.0.1)发起一个 TCP/IP 请求。当收到消息时,Exim 以处理来自其它主机连接相同的方式来处理该连接请求。
在三种不涉及 TCP/IP 的情形中,发件人地址由调用 Exim 的用户的登陆名和默认的限定域(可以通过 qualify_domain 配置项来设置)组成。对本地批量 SMTP 这种方式,用 SMTP MAIL 命令传递的发件人地址将被忽略。然而,系统管理员可以允许某些用户(可信赖用户)指定不同的发件人地址,或者允许所有用户指定某种形式的发件人地址。-f 选项或 SMTP MAIL 命令可以用来指定这些地址。
所有这些非交互方式收到的消息都可以被非 SMTP ACL 审查,如果定义的话。使用 SMTP 收到的消息可以在 SMTP 会话期间的不同地方被 ACL 审查。而 local_scan() 函数则对所有进入的消息审查。
Exim 可以被配置成收到消息时不立即投递,这可以直接指定,也可以根据系统装入的 SMTP 连接数来指定。但标准的配置中,一旦收到消息就会被立即开始投递。