Milter 协议(2)

先贴一段 twisted 框架下实现 Milter 协议解析的核心函数 :)

  1. class MilterServer(Protocol):
  2.     def init_dataReceived(self):
  3.         self.lastdata = ""
  4.         self.len = 0
  5.  
  6.     def __init__(self):
  7.         self.init_dataReceived()
  8.  
  9.     # 注意:实践中发现一次 recv 中包括了两个完整的 packet; 而且理论上存在
  10.     # 一个 packet 需要两次 recv 才能取出来的可能
  11.     def dataReceived(self, data):
  12.         if len(data): print len(data)
  13.         if self.lastdata != "":
  14.             data = self.lastdata + data
  15.         if self.len != 0:
  16.             if self.len <= len(data):
  17.                 next = data[self.len:]
  18.                 self.proc(data[:self.len])
  19.                 self.init_dataReceived()
  20.                 if len(next) > 0:
  21.                     self.dataReceived(next)
  22.             else: #继续等待输入
  23.                 self.lastdata = data
  24.         else:
  25.             if len(data) < 4:
  26.                 self.lastdata = data
  27.             else:
  28.                 self.len = struct.unpack(">i", data[:4])[0]
  29.                 self.lastdata = data[4:]
  30.                 print self.len, len(self.lastdata)
  31.                 self.dataReceived("")
  32.  
  33.     def proc(self, data):
  34.         ...
  35.         ...

上述代码在线上曾短时间的跑了跑,协议解析的逻辑部分应该是没有问题滴(稳妥起见,目前我们实际用的还是 libmilter 的 python binding)

实现 Milter Server 需要注意的一个事情就是:和 SMTP 一样,是要能支持在一次
connection 中完成多次 transaction 的!!还有 abort 命令,实际上就是一次 RSET 请求。

由于相当然的以为 eom (EndOfMessage) 事件后会话就应该结束了,结果碰到了问题怎么也想不出头绪,绕了一个多星期的弯路才找到程序的毛病所在。

另外在 Postfix 实现里面,自定义的 replymsg 的格式要求严格遵循 RFC,格式是:
"%s %s %s" % (code, Enhanced-Status-Code, msg)
E-S-C 的第一个数字要和 code 的第一个数字保持一致,见 postfix 源代码 milter8.c 里 SMFIR_REPLYCODE 的处理

仔细阅读了一下 sendmail 的 Milter Technical Overview,原来在 DATA 阶段,MTA 是需要把信件整个接受下来以后,再依次发给各个 Milter 的,而且是给一个 Milter 完整的传送完一个 message 后,再接着向下一个 Milter 发送。以前一直理解有误,觉得应该是 on-the-fly 的把数据依次传递给 Milter,这样效率最高.

评论

Hi,

请问能提供一下libmilter 的 python binding 的资料吗?我亦很想学习一下milter, 谢谢!

就是 pymilter 吧.

Hi,

请问是不是指http://www.bmsi.com/python/milter.html#overview?搞了半天,这个项目看来是挺难安装的,blog主能否指点一下?

另发现一个类似的项目http://code.google.com/p/ppymilter/,可惜文档不够丰富,主要是对python 了解不深,还是不懂用。

Milter 完整的传送完一个 message 后,再接着向下一个 Milter 发送,我想这是要配合Milter 能修改邮件内容这个功能。

你说的很有道理... 请问是在那里工作啊? hehe

hahah....... 小弟目前乃是下岗人仕,我想用Milter 实现一个功能,如下:

本域用户发来的邮件,return-path 与 from 要一致,否则拒绝。

外域用户发来的邮件,return-path 与 from 不一致时,在邮件头做标记,SA 然后根据标记加分。

请问您认为以上想法,有否实现价值?

return-path 是在 MDA 投递到本地的时候,加上去的 Header,通常在用户看到的信内容第一行。在 MTA 处理的过程中,照理是不会出现 Return-Path 的

简历一份给我?qiuyingbo@sohu-inc.com

你说的没错。我主要意思是在smtp 会话阶段,利用milter 对mail from: reply-to: from: 进行一定的限制,以克制一下那种被利用作退信攻击的情况。

简历的事没有问题,下午我整理一下发给你,谢谢您!

已发送,请查收。