关于邮件服务器的请教?(200分)

  • 主题发起人 主题发起人 zmj94
  • 开始时间 开始时间
Z

zmj94

Unregistered / Unconfirmed
GUEST, unregistred user!
[?][red]用delphi/bcb如何写邮件服务器,请各位帮忙,先谢了!!![/red][?]
[blue]请提供思路、参考资料、源代码.....不胜感谢!!![/blue]
 
一. 设计思路
---- 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 ClientSocketdo
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;
 
卷起千堆雪tyn,谢谢!!!
听说李维的《delphi2 开发人员指南》有相关的内容,
但现在找不到该书,哪位有该电子书籍?
请各位继续关注!!!
 
用delphi写client还可以,服务器端玩玩还行,如果真的要写的话,建议先看看RFC
 
www.51soft.com有你想要的书。
 
悲酥清风:找不到该书?

另:我的邮箱是:zmj94@sina.com
 
D6中的indy已经有这方面的组件,完全可以写个mailserver,且有demo
我还建议先看看RFC,至少你得对邮件服务器了解,否则,没有任何意义
 
我关注!我也将要做。
 
我写了一个,实现smtp和pop3协议,web功能正在实现,可能要到web实现了才会推出。
有问题咱们共同研究。
mail:huajiyong@gazx.com
[:)][:)]
 
老兄,你记错了吧,李维好像没出过《delphi2 开发人员指南》 吧。
这书是机械工业出版社引进外国的。
 
难道《delphi2 开发人员指南》里有的
《delphi5 开发人员指南》里没有么?
 
谢谢各位,现在正看有关邮件服务器的资料,RFC1939-POP3协议、多线程...
 
我也在用Delphi 6开发邮件服务器,大家可以多多交流啊
 
to:hua8hua
我现在正想开发一个邮件服务器,请指点一二。
谢谢!
 
我做了一个邮件服务器,不过客户端是用汇编写的(在单片机上)当然也可以在局域网收发邮件
服务器端很简单可以用一个ServerSocket控建,不是玩玩,他封装了所有winsocket的api
RFC的协议也很简单如下(服务器收邮件)
客户端发起连接
服务器端:发出‘220‘,客户端受到后发出‘Helo',
...............'250', ...................'...'
...............'250',.....................'...'
...............'250'......................'Data'
...............'354'......................'邮件内容'
...............'250'.......................'Quit'
...............'221'.......................断开连接
tcp/ip的应用是很简单的
但是Tcp/ip的实现是很复杂的
我这有有人用4500多行汇编实现一套tcp/ip很精彩
 
我做了个发信机,可现在好多邮件服务器都要求认证,怎么样把认证信息交互上去呢????
 
为什么我也收不到大富翁发来的信呢?
 
邮件服务器中邮件的转发?
 
多人接受答案了。
 
后退
顶部