说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Email 服务器的简单实现-Delphi资料

HTML文档下载 WORD文档下载 PDF文档下载
Email 服务器的简单实现-Delphi资料

我们知道从Delphi 3 开始,它自带的控件中有基于Internet开发的控件。如果我们充分利用这些控件开发Internet程序则可以简化编程工作,提高效率。鉴于目前POP3客户端的软件的种类繁多,(如Outlook Express

Foxmail 以及Web 方式下的各免费邮局)

而服务器端(除Unix Email系统)很少公开原代码

下面我就向大家着重介绍一下利用 Delphi 4中Internet控件组的TClientSocket 和TServerSocket 控件来实现 Email POP3服务器端。如果您理解了Email POP3服务器的构造,相信也可以依葫芦画瓢写出Email SMTP服务器程序。在此基础上加入多线程技术使服务器能同时处理多个客户的连接请求,您就可以轻松地实现一个简单的Email服务器了。

---- 一. 设计思路

---- Email 系统采用C/S 结构。当用户想发送邮件时或收取邮件时在客户机上运行任意一个客户端程序,如Foxmail。在菜单’工具->选项’的邮件服务器里填上运行我们服务器程序的主机名。服务器主机24小时一直运行我们的服务器端程序,SMTP和POP3服务器程序分别在25端口和110端口侦听连接请求。当用户发信时,首先客户端会与服务器端建立Socket连接。然后开始一应一答的Client/Server间的通信。发信和收信时建立连接后服务器端分别要发送一个’250 OK’ 和’+OK pop3 server is ready ’的应答。客户端收到此应答后开始发送SMTP或POP3命令。POP3通信时一般最开始的命令是’user ‘和’pass’或’ apop’用以进行身份验证。注意由于POP3会话有3个状态,某些命令只在某特定状态下有效。当用户进行完所有的操作后发送一个’quit’命令。服务器端收到此命令即终止此次socket连接并继续侦听其他的连接请求。注意:POP3通信时客户端在Transaction状态下’quit’则进入update状态。如果从Authorization状态下’quit’则终止通信,而不进入Update状态。如果客户端不通过’quit’命令终止连接,POP3会话不会进入Update状态。而只有在Update状态下收到’quit’命令后服务器才会在断连前把标志为已删的邮件进行物理删除。

---- 二. 代码实现(以POP3为例)

---- 自定义TPOP类的描述:

SessionState = ( Init

Authorization

Transaction

Update);

TPop=class (TComponent)

public

UserName:string;//Email帐户名

PassWord:string; //Email口令

ReceText:Pchar; //server端收到的字符串

PopState:SessionState;

//pop状态:

init or authorization or transaction or update

MsgCount:integer; //邮件总数

SizeCount:integer; //邮件总大小

ReplyString:string;//服务器端发送的应答信息

DeleIndex:byte;//用户要删的邮件序号

ListIndex:byte;//list方法 的参数:

用户要列出的序号为listindex的邮件信息

RetrIndex:byte;//retr方法的参数:

用户要取序号为retrindex的邮件

TopIndex:byte; //top方法的参数

QuitFlag:boolean;//用户如果通过quit命断连则此变量为true;

反之(此时要把f_dele都置回0)

OldMsgCount:integer;//旧邮件数:Last 命令返回

//邮件头的各个域

HMsgId:string;

HReplyTo:string;

HDate:string;

HFrom:string;

HTo:string;

HSubject:string;

HMIME_Ver:real;

HContent_Type:string;

HContent_Transfer_Encoding:string;

HText:string;

//所有POP3服务器必须支持的命令

procedure user;

function pass:boolean;

procedure stat;

procedure dele;

procedure list;

procedure retr;

procedure noop;

procedure rset;

procedure aquit;

procedure tquit;

//扩展的可选择实现的POP3 命令

procedure top;

procedure last;

procedure apop;

procedure uidl;

end;

---- 1. 建立连接

---- 我们可以看到利用了Tclientsocket后客户端请求建立连接只需下面的代码。

with ClientSocket do

begin

Host := Server;

Active := True;

end;

---- 服务器端利用TserverSocket

一直在侦听110端口,若客户端有连接请求,则ServerSocketAccept事件会被激活,建立起连接。

procedure TMyForm.ServerSocketAccept(Sender: TObject;

Socket: TCustomWinSocket);

begin

Statusbar1.Panels[0].Text :=

'连接到 ' + Socket.RemoteAddress;

//pop对象初始化

pop:=TPop.Create(nil);

pop.PopState:=init;

pop.LoginResult:=false;

pop.QuitFlag:=false;

ServerSocket.Socket.Connections[0]

.sendtext('+OK ibonc pop3 server is ready'+crlf);

end;

---- 2. 通信

---- 服务器端收到客户端发来的信息,则会激活ServerSocketClientRead事件,通过ServerSocket的Socket.ReceiveText可以得到信息的内容。

procedure TMyForm.ServerSocketClientRead(Sender: TObject;

Socket: TCustomWinSocket);

var temp_command :string;

//存放接收到的命令行,并做去crlf的处理

begin

temp_command:=Socket.ReceiveText;

//to remove the crlf in command line

temp_command:=trim(copy(temp_command

1

pos(crlf

temp_command)-1));

pop.ReceText:=pchar(temp_command);

if pop.popstate=init then

if strLIComp(pop.ReceText

'user '

5)=0 then

pop.user

else

ServerSocket.Socket.Connections[0]

.sendtext('-ERR user name please')

else if pop.popstate=authorization then

begin

if strLIComp(pop.ReceText

'pass '

5)=0 then

pop.pass

else if strIComp(pop.ReceText

'quit')=0 then

pop.aquit

else

ServerSocket.Socket.Connections[0]

.sendtext('-ERR pass word please');

end

else if pop.popstate=transaction then

begin

if strIComp(pop.ReceText

'stat')=0 then

pop.stat

else if strLIComp(pop.ReceText

'dele '

5)=0 then

pop.dele

else if strLIComp(pop.ReceText

'list'

4)=0 then

pop.list

else if strLIComp(pop.ReceText

'retr '

5)=0 then

pop.retr

else if strIComp(pop.ReceText

'noop')=0 then

pop.noop

else if strIComp(pop.ReceText

'rset')=0 then

pop.rset

else if strIComp(pop.ReceText

'quit')=0 then

pop.tquit

else if strIComp(pop.ReceText

'last')=0 then

pop.last

else if strLIComp(pop.ReceText

'apop '

5)=0 then

pop.apop

else if strLIComp(pop.ReceText

'uidl '

5)=0 then

pop.uidl

else

ServerSocket.socket.connections[0]

.sendtext('-ERR no such command yet'+crlf);

end

end;

---- 3. 关闭连接

procedure TMyForm.ServerSocket

ClientDisconnect(Sender: TObject;

Socket: TCustomWinSocket);

begin

ServerSocket.Active := False;

//如果client端没有通过quit 命令断连,

则在断连时要把那些f_dele置为0

if pop.QuitFlag=False then

begin

MyForm.query11.Close;

MyForm.query11.Params[0].Asstring:=pop.UserName;

MyForm.query11.prepare;

MyForm.query11.execsql;

end;

end;

---- 三. 结语

---- 由于Email系统与数据库表结构的紧密联系

笔者没有写出各POP3命令的具体实现。相信读者在认真阅读了RFC1939之后不难写出实现函数。现在就动手为你的公司写一个自己的Email服务器吧!

可穿戴领域,创业公司的掘金点?还是滑铁卢? 搜狐SendCloud2014运维技术沙龙拉开帷幕 一周热点:选择Go语言的12个理由,九头蛇与大象之争 中国云计算大会PPT集萃(二):十位技术大牛分享平台打造技术 延迟250毫秒损失数百万美元,Hadoop系统该如何应对实时任务 IBM成立展示中心扩展大型主机的Linux开放生态系统 SDN解决方案总结:OpenFlow、虚拟机、OpenStack和VXLAN/NVGRE 第六届中国云计算大会将于5月20-23日在京隆重召开 大数据实战:站在JMP分析平台上的FIT足迹识别技术 首届SAP d-code大会在上海举办 【OSTC讲师专访】ZoomQuiet:因商业化而开源是中国开源界最大的囧处 亿元资金扶持+联手100家VC,腾讯的雄心壮志 美国史上最大IPO 能给阿里巴巴带来什么? 买Windows平板而非iPad或Android的十大理由 Framework7:不会Objective-C,也能开发iOS7应用 CocoaChina开发者大会 全新引擎Cocos 3d-x开源 Oracle和微软的抱团,以及对抗Amazon霸主的5个可用点 Agile已死 Agility长存? 论程序员的自我修炼 Github女员工因遭性别歧视离职 继七年iPhone、四年iPad后,苹果的下一城:Healthbook 普元CTO焦烈焱:专注于基础软件 在Spark上的深入实践 Python 3.4.0正式发布 未添加任何新语法特性 谷歌受困邮件挖掘丑闻,企图抹掉庭审记录 Python 3.4.0发布,增加了多个功能模块 美的+阿里,“云端”战略第一把火是智慧家居 对产业互联网战略的战术思考——争夺企业信息入口的战争 加入Cassandra,OpenStack发力DBaaS生态圈 死磕Google Keep,微软正式发布Mac免费版OneNote 《近匠》安管云CTO石磊:降维安全的开放平台 2014 Unity亚洲开发者大会·中国站讲师名单议题全部出炉 在线等急盼tomcat启动问题 我的奔4电脑不能装oracle8。1。7 java 与oracle数值类型转换问题 请教“数字权利管理”(digital rights management)和P3P的实现问题? IBM DDYS-TO9170M SCSI 硬盘,如何看它的CACHE,写者10000转的, 数据插入速度问题 一个关于自定义类的问题,请帮助! 如何使用DBchart? DELPHI+CORBA 求救!!!! 请问java中如何获得windows的系统目录? 大家看看这台服务是出了什么问题?帮帮忙!!! 一个想把控件内容打印出来的小问题! 如何查看表中各字段的长度? 谁能给出一个ASP.NET应用存储过程的例子 self::node()是否就是 . 高分求救::关于分类显示的问题. c#里的编辑列的激活事件写在哪里? 一个基础小测验 如何获取客户端机器物理内存大小?急!!! 急问:我的VC6.0里的Icon编辑器为什么只有16种颜色 谁有这样的曲线绘图源码,一定重分相谢! 怎样去除启动菜单? 调用自建文件时,报错“重复定义”,为什么? Rave做报表时,要求preview时,不出现那个OutPut Options,并且预览时,要求全屏显示 请问映射文件里添加纪录应该怎么做阿 怎样让下拉列表中选定的值对应为数据库中的值~! 怎样去除启动菜单? asp.net 怎样学习 请问我的要存放含有‘年月日时分秒毫秒微秒’的数据能否用date类型存储? 谁来帮我解决一下问题——解决者另外加分100 问:sys/wait.h 是unix下的一个宏吗? 救命! 请问高手 网页问题 再次跪求教物资进库表和物资库存表的问题! 请问高手,如何在asp中调用,在线等候… 关于局域网的一个问题 一个表的记录写到另一个表中的问题??UP有分 蔡鸟求助:如何用vc++把一个文件(比如图纸)存到局域网中别的机器上 我有IIS的服务器的网站,我用什么软件能知道有谁正在下载什么文件?? 求MICROSOFT VISUAL STUDIO.NET 2002 中文企业版,2003不要,谢谢~ MySQL JDBC 驱动程序在哪里下载? 请教八数码难题的解法! 有在ASP 下 用过regexp类的吗?? 急救!关于ON_WM_ACTIVEAPP的问题 MySQL JDBC 驱动程序在哪里下载? mysql for linux 启动问题? 51job的动态简历预览功能暴快,有谁知道采用了什么样的技术? 请教为什么KeyUp事件不响应? 程序有两个线程时,如果子线程是个死循环,永远不停(如监听一个Socket),那当我的主线程return了后,程序会不会退出呢? 我重载了WM_NCPAINT来画窗体边框和标题栏,可是菜单就不见了,如何给画出来? 写了绪论还能写前言吗?感觉绪论的内容包括了前言了.. 旬邑县有哪些名人旬邑县现代有哪些名人? 旬邑县有多少人口? 论文 写作中:绪论 就是 引言 两者是一个意思吗? 理论上,水电解时产生氢气戚和氧气的体积比应为2比1,但在实验时却发现,氢气和氧气的体积比大于2比1这是什么原因 如何写序言? 方法序説怎么样 直线3x+my+1 = 0与直线y=3x平行,则m等于 一项工作甲队5人8天可以完成,乙队10人4天可以完成,现甲队4人和乙队6人合作几天完成? 我要获得post数据啊post哪部分才是实体啊 某项工程,甲队每天做8时,5天可以完成,乙队每天做10时,6天可完成.两队合作,每天工作6时,几天可完成? 俄总理七小时“安徽印象”澳洲一名男子涉嫌逼迫未婚妻致其死亡接韩考虑增加新一代战机项目预算 现为4浙江省政协公开征集提案线索 侧重群众湖北阳新县:两名女干部上班时间互殴难美国一女子梦游跌落地铁仅擦伤(图)美军将撤离阿富汗 价值70亿美元军需美国男孩携玩具枪街头把玩不肯放下 被美国扶贫粮食券遭诈领 部分受惠人折价调查称8成法国选民认为2017年大选日本最古老农村歌舞伎舞台将公演 祈祷养成之女喀什农业博览会上海站招商推介会举办洛杉矶餐馆午夜枪战,3死12伤“世界第一”在他眼中当国家进入 “紧急状态”大叔快递8年零投诉大师名团空降“艺术天空”秋意正浓美国蔓越莓,河马节上的“红色海洋”百种菜肴,菜谱5天不重样 做六休一,朱茵为何 让女儿曝光?兽厄恋爱碟中谍国家意志是女神沐雨灵归超星联学院超脑天医火影之盗帅传奇天天称霸宠物小精灵之拂晓司夜轮回黄天化三国重生梦山胜迹旅游恩施土司城旅游达里诺尔湖旅游曼陀山庄旅游白音敖包旅游阿斯哈图石林旅游黄岗梁旅游热水温泉旅游小七孔风景区旅游基督教东山堂旅游东山少爷公园旅游
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘