如何在线程中利用SakMail类似组件进行Pop3取信?(300分)

  • 主题发起人 主题发起人 shyj
  • 开始时间 开始时间
S

shyj

Unregistered / Unconfirmed
GUEST, unregistred user!
问题提出的原因:
SakMail组件的Pop以及SMTP示例中,进行收发信时存在问题。

procedure TForm1.CntClick(Sender: TObject);
begin
SakPOP1.Host := EditHost.text;
SakPOP1.UserId := EditUserId.text;
SakPOP1.UserPasswd := EditPasswd.text;
Application.ProcessMessages;
SakPOP1.connect;
//////////////////////////////////////////////////////////////
//进行Socket连接时,程序不能响应其他消息如Form移动等,
//加上 Application.ProcessMessages也不行
/////////////////////////////////////////////////////////////
...
...
end;

问题要求:进行Socket连接时,程序能响应其他消息如Form移动等

我的方法是使用线程。代码如下:
type
ThreadPop = class(TThread)
private
...
procedure FGetNewMail();
protected
procedure Execute; override;
published
constructor CreateIt(PriorityLevel: cardinal; ProgBar : TProgressBar; SakMsgList1:
TSakMsgList;SakPOP1: TSakPOP;shost:string;suserid:string;spassword :string);
destructor Destroy; override;
end;

procedure ThreadPop.Execute;
begin
while (Terminated = false) do
Synchronize(FGetNewMail);
end;
constructor ThreadPop.CreateIt(PriorityLevel: cardinal; ProgBar : TProgressBar;
SakMsgList1: TSakMsgList;SakPOP1: TSakPOP;shost:string;suserid:string;spassword :string);
begin
inherited Create(true); // Create thread suspended
Priority := TThreadPriority(PriorityLevel); // Set Priority Level
FreeOnTerminate := true; // Thread Free Itself when terminated
FSakMsgList1:= SakMsgList1;
FSakPOP1:= SakPOP1;
FHost:=shost;
FUserID:=suserid;
FPassword:=spassword;
Suspended := false; // Continue the thread
end;

procedure ThreadPop.FGetNewMail();
begin
FSakPOP1.Host := FHost;
FSakPOP1.UserId := FUserID;
FSakPOP1.UserPasswd := FPassword;

FSakPOP1.connect;
//???????????????? 这时倒是可以进行其他操作了,可是不进行Socket连接了。
if FSakPOP1.POPError then
begin
MessageDlg( 'Connect failed. Maybe the server is down or not responding.',
mtError, [mbOk], 0);
exit;
end;
if not FSakPOP1.login then
begin
ShowMessage('Unauthorized access...');
exit;
end;
FSakPOP1.Init;
showMessage( 'You have ' + intToStr( FSakPOP1.NewMsgsCount) + ' new msg(s) of ' +
intToStr( FSakPOP1.MsgsCount));
FsakPOP1.retrieveAllMessages( FSakMsgList1);
FSakPOP1.quit;
end;

请教各位,如何在线程中利用SakMail类似组件进行Pop3取信,
同时如何在线程中响应SakPop或其他VCL组件的各种事件。出分300,
求成功的例子或解决问题的思路.如果太长可以发到shyjun@china.com
 
各位大仙:不知SakMail这个东东,从和处获得。
 
我也正好在做这个东东
也是用sakemail+线程
你把收信的代码放在Synchronize里干吗?
Synchronize里面应该只放更新VCL的代码啊
收信的代码应该放在execute里面。
我已经运行成功,但问题是sakemail没有TimeOut,
有时候收起信来没完,非得用TerminateThread干掉才行
各位有啥好办法没?
 
SakMail很多不完善,比如:
·connect时,会出现暂时“死机”状况而不能响应别的操作,解决方法: Connect也用一个线程
来完成。
·TimeOut没有,需要增加
·对0字节的邮件处理不好,会出现蓝屏
·RetrieveAllMessagesExt函数效果不好,占用资源太多
·TSakMsg的解码效果不好,速度慢,无法支持HZ、BIG5、GBK等解码方式
我现在已经对他进行了大量的修改,效果也不错。
有兴趣的大虾可以来信探讨这个构件的改进方法。
 
SakEMail连接以及收/发信件时出现的延迟的确是一件比较烦的事情,大上个月我也遇到了这个问
题,我的解决方法同各位一样就是将SakEMail封装到线程中去。用线程将SAKEMAIL封装起来的目
的只是为了少造成或者不造成发信时的延迟,但是如果您想把SAKEMAIL做为真正多线程发件的内
核的话,那么....嘿嘿,好像不成。当信件一大(200KB以上)&线程开得一多的时候(5个线程以
上),应用程序就特别容易出现应用程序错误(好像是Quit时有问题)。
另外SakEMail的SakPOP3的超时设置问题,可以按照SakSMTP的源码改一改。SAKEMAIL这个东西
相对于其它的E-MAIL控件的最大优秀就在于源码写的十分的清晰易懂。
 
想不到一下子碰到这么多同道,呵呵
这几天我正在跟sakemail斗智斗勇

woodstock兄:你改的控件能不能拿出来大家交流一下?
你说的那些问题正是我一直想解决的

为了解决connect时“死机”的问题和TimeOut问题,
我看过它的源码,发现比较困难。
因为它并不是用循环来收取信息的,也就是说内部没有空余
的机会来处理超时。
比如:
x := FSocket.Socket.ReceiveBuf( buff, 1024);
如果没有收到,它就会一直等,根本没有中断的机会。
我在离线包里看到,Energy大虾说Delphi自己的Socket
对象有缺陷,在Open的时候有时会象死机。
能采取的办法就是用TerminalThread这个API,强制把线程
杀掉。但这样会引起内存泄漏。:-(

我希望大家能够深入讨论一下这个问题,最好大家齐心协力,
做出一个比较完善的Email控件出来。

以前唐晓锋大虾曾经做过一个CoolMail,我在深度历险下了一
个,但没有找到源码(唐大虾说过要公开的)。

我的Email: qinghou@netease.com
几个有关问题的地址:
http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=162085
http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=162441
http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=204555
http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=259215


 
SakMail的主要的“假死”是出现在connect上,可以自己写一个
function SocketOpen( var theSocket:TClientSocket;
var Canceled:boolean;
TimeOut:longword=0): boolean;
这样的函数来调用线程,能确保连接时假死的现象。这个函数的作用是
一直在等待连接theSocket,当用户一取消的时候,直接
TerminateThread(aThread.Handle,1);
至于在这个时候的内存的泄露的现象,我觉得到是不用考虑太多,
因为一般用的不多,而且把TimeOut设置合理,用户基本上是不会去Cancel掉的。

我在写email程序的时候,到是碰到ListView的内存泄露的问题,很大的问题!
就是设置ListView的字体或者颜色的时候:
procedure TMainForm.MailListCustomDrawItem(Sender: TCustomListView;
Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
var i : integer;
begin
Exit;

// 这是 win98的 BUG,这样做泄露内存
i := StrToIntDef( Item.SubItems[3], -1);
if (i < 10) and (i<>-1) then Sender.Canvas.Font.Style := [fsBold];
end;
Borland的例子中说这是win98的BUG,不知道哪位大虾已经把这个问题解决掉了?
 
我的oicq号码是697336,欢迎联系。
 
woodstock:
你这种做法是不是还要在当前线程底下再开一个子线程?
否则没有空余的时间来检测是否已经TimeOut或cancel了啊
 
to 左轻侯: 是的。只有这种方法才能很好地解决connect的问题。
 
to shyj: i have sent the demo to your mailbox,
please check it.
 
woodstock,I have checked it.And it is really good.
thanx very much.So the question is over.
 
多人接受答案了。
 
后退
顶部