技术

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,这样效率最高.

今日发现之:分布式版本控制

今天发现目前开源界除了 cvs、svn、svk、git(知道 svk 和 git 的人现在恐怕也不多吧) 外,一下子又冒出 MercurialBazaarmonotone 等一大票源码控制系统...

git、svk、mercurial、bazaar、monotone 等新秀都是 distributed version control system虽然俺还没有具体了解 distributed 是个什么概念,但猜测是允许开发人员在把代码提交到远程服务器之前,可以在本地不断的 check in 来管理正在开发中的代码,确实是非常非常的有用。

linux kernel 已经开始使用 git,而 Mozilla 决定转向 mercurial ...

如果你在考虑是否把项目从 cvs 转到 svn 的话,那么这里强烈建议也评估一下这些更 IN 的东东.

Topic: 技术

FT 中文网的邮件列表服务不错

亲爱的会员:您好!

    感谢您曾经注册为FT中文网的会员。然而,在过去的两个月内,我们发现您
很少从您订阅的《今日焦点》或是《周五文摘》邮件中进入FT中文网的文章页面
进行浏览。不知道是因为繁忙的工作使您无暇阅读,还是 我们的邮件内容不够吸
引您?还是您更习惯通过自己登陆首页去浏览而不是通过邮件的标题进入文章页
面?

    虽然目前我们暂时中止了为您发送邮件,但我们希望给您善意的提醒:如果
您希望继续保留《今日焦点》邮件的订阅服务或是改为订阅 《周五文摘》,只需
点击以下按钮,我们将会重新为您发送,并在今后为您提供更多精彩的内容与丰
富多彩的会员活动。而如果您不再需要任何邮件服务,而是习惯直接通过登陆FT
中文网浏览文章,您可以直接点击以下的退订按钮,从此,我们将不再为您发送
邮件。

   在您不常登陆FT中文网的这段时间,我们增加了不少新的内容与功能:由FT
中文网经济评论员陈旭敏撰写的专栏《第一时间解读》及《财富管理》专题,
涵盖了当今经济社会中诸多热点问题,引起了读者的强烈反响;根据读者点击
量排列的十大热门文章中,与中国股市密切相关的文章内容精辟、眼光独到;
近期,我们还开设了名为"FT中文网博客"的栏目,邀请众多读者加盟。在功能
方面,我们增设了RSS功能,以便您随时定制个性化内容,把FT中文网变成完全
符合您口味的权威财经资讯源。

    我们期待您尽快回到FT中文网!

    P.S如果您有任何技术上或其它方面的疑问与意见,烦请您写信至foo@bar,
我们将立刻为您解决。

所以请放心订阅 FT 中文网的列表吧

Authentication War(续)

继 Yahoo 发布 BBAuth 将近一年之后(Authentication War),Windows Live ID Web Authentication SDK 也发布

和一年前相比,现在 Google Data API 可以说是全面开花,不再仅限于 Calendar 了

命运真是奇妙,去年我还在感叹没有机会在 CERNET 里面部署一套认证库,现在竟然又坐在了一个可能实现该服务的位置上。:)

不过 SOHU Passport 暂时的任务还是在内部打通,攘外必先安内。

不晓得网易和新浪有没有类似的计划。

Topic: 技术

Milter 协议

milter 是个好东东,但不知道出于什么样阴暗的心理,sendmail 的家伙们居然一直没有把这么重要的协议整理出正式的文档。开发者要么去使用 libmilter 函数库,要么老老实实去啃代码吧。

libmilter 应该说也实现的不错,而且还有 python binding,但它自己实现了一个事件循环,让现在酷爱 Twisted 的俺稍稍有些不爽。

感谢为 Milter 写 Perl 模块的程序员,也随代码同时提供了一封非官方的 milter protocol 说明。在这份文档的帮助下,很快就在 Twisted 框架下实现了 Milter Server 的骨架,大概 200 行代码吧。

Milter 协议最核心的就是:所有的 packet 都是首先 4 个字节表示接下来数据的长度,然后分析数据即可。另外就是在实践中发现一次 recv 中出现了两个甚至更多的 packet,协议分析需要注意。

另: twisted 2.5 的 epoll 似乎 memory leak 的厉害,本来想建议用 gc module 来试着解决的,结果换回缺省的 selectreactor 就好了

--Update--

milter protocol 说明文档目前搜索到的地址在:http://cpansearch.perl.org/src/AVAR/Sendmail-PMilter-1.00/doc/milter-protocol.txt

Firefox 3 Alpha7

今天从 Burning Edge 上看到了最新 Alpha7 加入的新特性,包括了 showModalDialog/showModelessDialog 以及 Cross-site XMLHttpRequest 这样重量级的功能。

Firefox3/Schedule 来看 Alpha7 就是 gecko feature freeze 了,那么可以认为 Firefox 3 的重要变化都在这里

从 B-S 开发的角度来说,我认为 Firefox/Gecko 已经是当前最先进的平台了;如果是开发企业应用的话,完全可以把应用绑定在 Firefox 3 上!!难道在企业桌面上部署 Firefox 比部署 .Net Framework 麻烦很多么?

Topic: 技术

装了 VirtualBox

不知道为什么,办公用机上跑 VMware Player 总是有问题,几乎是一运行就崩溃。没有一个可自由玩弄的开发环境,是非常不爽的事情;最近在 Postfix 上的一些研究,都是回家后完成的。

昨天无意中看到了对 VirtualBox 的介绍,于是试用了一下。性能还不错,反正在安装 debian etch 的过程中感觉不到和 VMware 有什么差别。如果你也碰到了和我一样的 VMware 故障,那么强烈推荐试试它。

和 VMware Player 对比优势如下:
1. VirtualBox 可自由下载版本是按 GPL 发布的,准确的说应该称为 VirtualBox Open Source Edition

2. 图形管理界面,包括创建虚拟机,还有中文语言界面。

当然问题也有:
1. 网络连接好麻烦,必须以命令行模式操作(操作步骤隐藏在 PDF 格式的用户手册中);而且必须停止虚拟机运行操作才有效果。当然 VMware 虽然自动化,可是擅自安装上的两个网络接口估计也挺让普通用户迷惑;另外访问 VirtualBox 的 NAT 虚拟机是通过配置端口转发来实现的,这样从别的机器也能访问我的 NAT 虚拟机了,貌似 VMware 就做不到这一点了。

2. 可能还是不够稳定或虚拟的还是不够好(相比较于 VMware),反正我若是使用网络安装,进行了一段时间后就停下来了,不晓得为什么。不过安装成功后的 apt-get 倒是从来没有出过错。anyway,在我的办公机器上总是比 VMware 稳定多了

Topic: 技术

Postfix 之 Milter

在整三年前,我负责亿邮反垃圾邮件网关的开发,在辛苦 Patch MTA 的同时,感到处理 SMTP 业务的代码和实现过滤的部分耦合的太紧密,而同时别的小组也在根据客户的需求时不时的修改 MTA 程序,这样长期下去势必会造成代码的不统一和高昂的维护成本。当时就开始设想一种 MTA 和 AntiSpam Engine 之间的通信机制,这样我们两个团队可以并行的高效开发,可惜在此方面一直没有琢磨太清楚,即使知道了 Milter 这个名次也没能把两个东西想到一起去,很快到了 04 年 9 月份我就离开了这个项目,也没有机会继续深入,实在是很遗憾。

Milter 就是一个 MTA 和 Filter 通信的协议。MTA 在会话的各个阶段不断把从客户端来的信息(IP、并发连接数)和数据传给 Filter,然后再根据 Filter 返回的结果返回给客户端,甚至修改信件内容!

Sendmail 不但定义了 Milter 协议,而且提供了 libmilter,它封装了一个多线程 Milter Daemon 的常规流程,帮助开发人员把更多精力放在实现过滤上。

使用 Milter 还有一个好处,就是能实现 before-queue 的过滤。这意味着我们能在 SMTP 会话处理阶段就把垃圾邮件拒绝,而不是接受下来后再弹回。

Postfix 2.4 对 Milter 已经支持的很完善,而且它还可以配置多个 Milter 的过滤,我们可以把网上那些开源的 Milter 和我们自己的 Milter 混合在一起实现更全面的防护。

这里透露一个信息:如果反垃圾邮件厂商希望在搜狐这里做测试,那提供一个 Milter 而不是 Gateway 我可是会给加分的,:)

因为要实现自定义白名单功能的话,Gateway 显然有潜在的问题。

另一方面我们也正在计划开发 SMTP-Milter,就是把防垃圾邮件网关封装成一个标准的 Milter Daemon(很奇怪,我满世界找了一圈,没有找到有这样的开源项目)。但这样也给 Gateway 提出了要求——首先是要能做到 before-queue 的过滤,另外就是最好能实现 Postfix 的 XCLIENT 扩展,如果你有自己的一套 IP 黑名单或者 HELO/EHLO 过滤机制的话。

加上 Postfix 之 tcp_tablePostfix 之 Dovecot Authencication Protocol,我们针对 Postfix 的开发就只包括这三方面,这是不是简单的有些难以置信?

Postfix 之 Dovecot Authencication Protocol

接前文 Postfix 之 tcp_table

和用户账户查询类似的一个应用就是用户身份认证。当然如果只是为了部署 MX 的话可以不考虑此点,但很多情况下我们还是需要给 SMTP 客户端用户一个连接上来认证后发信的方案

Postfix 没有内置任何形式的认证支持,必须通过第三方 SASL 服务才能达到这个目的。Postfix 2.4 支持两种认证服务,一类是链接 Cyrus-SASL 库来使用,另一类则是透过 Dovecot Authentication Protocol,连接一个 UNIX Socket 服务去认证。

虽然 Cyrus 在邮件领域更加有名,但我认为采取 Dovecot Authentication Protocol 去连接一个 Daemon 是一种更清晰的方案,编译部署也免去很多麻烦。

和 tcp_table server 一样,这个 Daemon 我们也是用 Python 完成的,为了方便描述,以后在团队内还是称之为 DAP server 吧。

订阅 RSS - 技术 | BT的花