开通CSDN已经有一段时间了,但一直没有来篇文章赏赏。现在刚刚结束了一个不大不小的项目,就抽空写下来吧。算是给自己这两个月来的努力做下总结。
1.系统简介
此为邮件处理类项目。WEB类型,基于邮件服务器的一套web application外壳。缘起于公司与客户的实际需求与合作方式的差别。故需要开发出一款WEB形式的收发邮件处理程序。
开发环境与技术采用:VS2010 + XML + jQuery + POP3 + SMTP。界面采用jQuery UI,方便统一布局。人机交互采用ajax + httphandler与后台服务执行请求/响应。系统与邮件服务器交互采用TCP+ NetWorkStream技术获取邮件数据。本地只保存邮件的head,故使用XML存储就OK了。
在系统与邮件服务器之间互连的通讯方式采用POP3 + SMTP。POP3为邮局协议第三版,主要是实现邮件的接收,协议规定了客户端如何通过internet与指定的邮件服务器连接并读取数据。系统的收取邮件就是采用的此种协议。POP3的底层命令大致有十多个,但常用的也就五六个,如 USER:邮件帐户,PASS:帐户密码,LIST:获取所有邮件的统计数据(大小,数量等), DELE:标记邮件为删除状态,QUIT:退出,TOP n m:获取第n封邮件的前m行数据,m为0时则表示只获取邮件头数据。还有其它的一些命令,不怎么常用,故不作解释。
本系统在发送邮件时,采用SMTP(简单邮件传输协议)协议来处理,由于asp.net中在 system.net命名空间下已有相应的smtp处理类,可以直接使用。但此类在发送时,由其是有附件或邮件过大时速度,效率上不尽人意,所以直接使用SMPT协议的命令,来自己实现发送。SMTP的底层命令与POP3差不多,实现过程也都是选建立连接,然后验证帐户与密码,之后就可以执行各种命令,最后退出连接。
2.技术说明
系统中某些地方,在处理上还是存在一点的难度的。如邮件的列表展示,列表中的分页(此分页的数据源不是从DB中读取,而是邮件服务器数据+本地XML存储的邮件数据),查看邮件内容,删除等等。
邮件列表的分页在本系统中确实有一点难度,还好本人c#功底还凑合,花了半天时间搞定。说它有难度是因为分页通常是用在DB的数据中。由于数据的来源是一个固定的地方,故方便很多,而且DB中都有相应的SQL语法,可以方便的处理分页。而此系统中的邮件数据来源是不固定的,大致有以下三种情况:
1,数据来源于网络。也就是来自于邮件服务器中,那么在从服务器读取到数据并返回,再经本地处理,分页等等过程,所消耗的计算机资源成本是很高的。
2数据来源于本地XML。为了提高邮件的访问速度,本人作了些处理。在邮件接收到后缓存到本地的XML中,当然只是缓存部分数据(信封头数据),其它不做处理,这样在下次访问时,只需要去服务器中读取相应的邮件内容就OK,信封头就不必了,从而减少网络流量的传输,提高访问速度。
3.数据来源于网络+本地XML。既有网络上的邮件数据,又有本地XML邮件数据。
以上无论是哪种情况,在分页时都会有相应的延迟,也就是会影响接收的效率。所以分页时,直接通过分页的算法(TOP n +正排 +倒排的方式)只取到当前第n页的m行数据,无论是来源于网络还是来源于XML都采用此方式,从而避免了把所有数据读取到再分页的低效率处理方式。比如来源于网络的数据中,通过分页算法得到当前需要获取到第n页的m条数据时,直接通过pop3的 top n m命令获取。也就是只获取到当前页的数据,其它的不接收,翻页时再通过算法得到下一页的 top n m数据就OK了。数据来源于XML时,也是同样的道理。
但数据的来源既有网络又有本地XML时,该如何处理呢?本人的实现方式是:通过分页算法得到当前n(第n页)与 m(前m行)两个参数,再通过UIDL命令获取所有邮件的唯一序列号,并得到数量,如果服务器上的邮件数量,已经能满足分页的数据需要了,那么就只从服务器上获取第n页m行数据即可,如果服务器上的数据不能满足分页的需要,那么就再加上本地的XML存储的邮件数据与服务器邮件数据合并,来满足分页需要,并返回分页后的数据。
所以这种数据来源的分页方式最繁杂头疼。还好本人给搞定了。
邮件的内容展示上(包括回复,转发,删除等),上边介绍过会把邮件的信封头缓存到本地XML中,由于邮件的body大小不确定,而XML又不适合于存储大数据,所以在具体展示时,信封头内容从本地XML读取,body内容根据信封头里的UIDL,也就是邮件服务器自动为每封邮件分配的一个唯一序列号来从服务器上读取,以此展示邮件的详细内容。
在删除邮件时由于服务器为每封邮件自动分配唯一且顺序的自动序列号,所以在删除一封邮件时,当前帐户中的所有邮件的唯一序列号会自动的重新被编排。如有三封邮件,唯一序列号为:1,2,3。在执行删除第2封邮件且成功后,邮件服务器中就只有两封邮件了,那么邮件服务器会重新为这两封邮件编排唯一序列号,原来1的还为1,原来的3,此时会被编排成2。
由于此种机制,导致了删除邮件后服务器上的唯一序列号与本地存储的唯一序列号不同,会出现分页混乱,失效,读取邮件失败,甚至出错等情况。所以为了解决此问题,本人做了如下的处理:删除服务器的邮件成功后,再重新通过POP3的UIDL命令读取到所有的唯一序列号与唯一编号。再根据此新的唯一序列号来重新更新本地的XML序列号,以实现数据的同步对应,以此来解决分页混乱或展示邮件内容时出错的问题。
还有其它的一些技术难点,如多次的输入错误帐户与密码的控制(邮件服务器有一种机制:如果多次连接失败,服务器会自动拒绝继续连接的请求,直接到被拒绝的时间过期后,才会再次接受连接请求)
多连接情况下如何避免服务器的自动拒绝,标记邮件为删除后如何撤销等等。限于篇幅,故不在此解释了。
3.系统配置
系统支持POP3,SMTP两种协议,以提供对邮件收发的支持。对于IMAP协议,由于没有用到更多的命令,实现更多更繁杂的功能,所以就没有提供对它的支持。但作为更高级的协议,在后续的版本升级中会考虑加入。
系统中允许更改邮件服务器的配置数据,如POP3地址,SMTP地址,端口等,原则上只限于本公司的mailserver,但经本人的努力,扩展到了可以支持目前主流的mailserver,如新浪邮箱,搜狐邮箱,网易邮箱等。只需要在系统中配置好相应的收发邮件地址就OK。经本人的新浪邮箱测试过,发收邮件一切正常,没问题。
展示一下自己的代码吧,怎么说也是自己一点一滴查网页,找资料,求教同事,高人等努力出来的成果。就当是炫耀一下吧。 嘿嘿~~~~~
(1) 邮件服务器的连接:
(2) POP3 SMPT 命令的执行:
(3) 获取响应后的数据信息:
(4) 执行标记邮件为删除状态的命令:
(5) 获取所有邮件的统计信息(大小,数量,每封信息的大小等):
(6) 断开与服务连接并退出:
(7) 获取第n封邮件的前m行数据(m为0时表示只获取信封头):
(8) 获取所有邮件的uidl(唯一序列号与唯一编号):
(9) 撤销状态为删除标记的邮件的状态,还原为正常的邮件数据:
(10) 检测邮件帐户:
(11) 检测邮件密码:
以上是本人写的底层代码片断,写的一般,还望各位大牛不吝赐教。
展示下系统的界面与功能:
(1) 登录:
(2) 主页:
(3) 发送页面:
(4) 邮件列表页面:
(5) 展示邮件内容页面:
(6) 快捷回复页面:
(7) 转发页面:
(8) 邮件服务器配置页面:
以上就是本系统的整体内容了。虽然还少了些许功能,如垃圾箱,草稿箱等,后期会一一加上。对于本系统中的一些不尽人意的地方,小弟也在此做下说明:比如邮件的收发速度与效率上还存在不足,需提高。功能上还有些不太人性化,所以在后期调整优化中会处理掉。还望有邮件处理方面经验的高手们,多多指教,共同研究学习啊。
我的QQ:137467392