最近測試了下delphi的Indy控件包中的TIdPOP3接收郵件功能,由於有些郵件服務器必須支持加密方式,所以,本測試直接使用的是加密方式(SSL),如果不需要加密方式,只需要更改服務端口以及斷開POP3控件的IOHandler即可。
使用中應該先連接服務器,然後在進行讀取或者刪除處理,之後要斷開服務器。
程序代碼如下:
{新的POP3郵件接收函數包,使用POP3的協議
對於沒有加密(SLL)的端口為:110
如果使用SSL加密協議,端口號:995
函數包提供 連接,讀取,刪除,斷開 四個函數
在使用前一定要先連接,連接好以後才可以進行讀取,刪除等操作,最後需要斷開
直接使用加密的協議SSL.
}
unit uPOP3_Email;
interface
uses
IdPOP3,IdMessage,IdBaseComponent,SysUtils,
IdAttachment, Classes, IdSSLOpenSSL,
IdText,Windows,IdExplicitTLSClientServerBase;
//連接POP3服務器函數
//入口參數:
// Host : POP3服務器的地址,采用SLL加密,端口默認為995
//Account: 郵件賬戶(郵件地址)
//PSW : 賬戶密碼
//出口參數:連接成功,返回True,失敗返回False
function ConnectPOP3Server(Host,Account,PSW : string; var ErrMsg : string) : Boolean;
//斷開POP3郵件服務器
procedure DisconnectPOP3Server;
//取得郵件數量,返回當前郵件的數量
function Mail_GetCount : Integer;
//刪除郵件
//入口參數:
// Index : 郵件索引號
//出口參數:成功True,失敗False
function Mail_Delete(Index : integer) : Boolean;
{取得郵件標題信息函數
入口參數:
Index : 對應的郵件索引號,從1開始
EmailTime : 郵件發送時間
EmailSubject: 郵件標題
EmailBody : 郵件的正式內容
EmailSendAddress : 發送者地址
ErrMsg : 返回錯誤信息
返回參數:
True : 表示返回成功,False : 表示返回失敗
}
function Mail_GetEmailInfo(Index : integer; var EmailTime : TDateTime; var EmailSubject, EmailBody, EmailSendAddress, EmailAttachFileName, ErrMsg : string) : Boolean;
var
POP3 : TIdPOP3;
OpenSSLHandler: TIdSSLIOHandlerSocketOpenSSL;
IdMessage : TIdMessage;
ConnectOK : Boolean;
implementation
function ConnectPOP3Server(Host,Account,PSW : string; var ErrMsg : string) : Boolean;
begin
if POP3.Connected then
POP3.Disconnect;
POP3.Host := Host;
POP3.Username := Account;
POP3.Password := PSW;
try
POP3.Connect;
if POP3.Connected then Result := True;
except on E: Exception do
begin
Result := False;
ErrMsg := E.Message;
end;
end;
ConnectOK := Result;
end;
//斷開POP3郵件服務器
procedure DisconnectPOP3Server;
begin
POP3.Disconnect;
ConnectOK := False;
end;
//取得郵件數量,返回當前郵件的數量
function Mail_GetCountA : Integer;
begin
Result := 0;
if not ConnectOK then Exit;
try
Result := POP3.CheckMessages; //取得郵件數量
except on E: Exception do
Result := -10; //出現錯誤
end;
end;
//刪除郵件
//入口參數:
// Index : 郵件索引號
//出口參數:成功True,失敗False
function Mail_Delete(Index : integer) : Boolean;
begin
Result := False;
if not ConnectOK then Exit;
try
POP3.Delete(Index);
Result := True;
except on E: Exception do
end;
end;
{取得郵件標題信息函數
入口參數:
Index : 對應的郵件索引號,從1開始
EmailTime : 郵件發送時間
EmailSubject: 郵件標題
EmailBody : 郵件的正式內容
EmailSendAddress : 發送者地址
EmailAttachFileName : 附件文件名稱,附件直接保存在當前目錄下的TMP目錄中
ErrMsg : 返回錯誤信息
返回參數:
True : 表示返回成功,False : 表示返回失敗
}
function Mail_GetEmailInfo(Index : integer; var EmailTime : TDateTime; var EmailSubject, EmailBody, EmailSendAddress, EmailAttachFileName, ErrMsg : string) : Boolean;
var
Count,i : integer;
FileName : string;
begin
Result := False;
if not ConnectOK then Exit;
try
IdMessage.Clear;
//讀取內容
EmailBody := '';
if POP3.Retrieve(Index,IdMessage) then
begin
EmailSubject := IdMessage.Subject; //標題
EmailSendAddress := IdMessage.Sender.Text; //發送郵件地址
EmailTime := IdMessage.Date; //郵件發送時間
EmailSendAddress := IdMessage.From.Address;
//取得當前郵件的附件數量
Count := IdMessage.MessageParts.Count;
if Count = 0 then //說明沒有附件
begin
EmailBody := IdMessage.Body.Text
end
else //說明有附件
begin
for i := 0 to Count- 1 do
begin
if (IdMessage.MessageParts.Items[i] is TidText) then
begin
EmailBody := TidText(IdMessage.MessageParts.Items[1]).Body.Text;
end;
if (IdMessage.MessageParts.Items[i] is TIdAttachment) then
begin
EmailAttachFileName := TIdAttachment(IdMessage.MessageParts.Items[i]).FileName; //附件文件名稱
FileName := ExtractFilePath(ParamStr(0));
ForceDirectories(FileName + '\TMP');
FileName := FileName + '\TMP\' + EmailAttachFileName;
TIdAttachment(IdMessage.MessageParts.Items[i]).SaveToFile(FileName); //保存附件
Continue;
end;
end;
end;
Result := True;
end;
except on E: Exception do
end;
end;
initialization
POP3 := TIdPOP3.Create(nil);
OpenSSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
OpenSSLHandler.SSLOptions.Method := sslvTLSv1; //sslvSSLv23 ;//sslvSSLv3;
POP3.IOHandler := OpenSSLHandler;
POP3.Port := 995; //加密的端口號
POP3.UseTLS := utUseImplicitTLS;
POP3.ReadTimeout := 1000 * 60 * 5; //5分鐘
POP3.ConnectTimeout := 1000 * 60 * 5; //連接超時5分鐘
IdMessage := TIdMessage.Create(nil);
ConnectOK := False;
finalization
IdMessage.Free;
POP3.Free;
OpenSSLHandler.Free;
end.
由於使用Live Writer的【代碼插入】插件
,對於delphi代碼注釋的著色並不是很徹底,所以,又手工修改了下,導致顏色不一致。
是的,就在oncommandget事件裡面接收
傳輸過來的數據在ARequestInfo.FormParams這個參數裡面
你可以直接把這個參數的值賦給你的變量
以我10年delphi經驗來看,絕對不能用indy,這是一套華而不實,從頭爛到腳的控件。編程的時候覺得還好,一旦實際使用,會發現根本無法勝任工作。只適合當當教學工具。
你要做發送和接收,給你推薦2個方法是我平常用的
1. 直接用api,網上有類似代碼,阻塞模式很簡單也很實用,要非阻塞就用線程。
2. 用自帶的TServerSocket 和 TClientSocket,這套控件簡單、實用。做簡單的收發很有效。
中文亂碼問題處理也很簡單。
看你是用的什麼編碼類型,不要直接發送string,應該轉換成連續內存塊再發送。
Ansi、UTF8、Unicode,這些處理方式不一樣
Ansi可以直接轉換成pchar,
UTF8的話,要先用UTF8toString函數轉換成Ansi,然後再轉換成pchar發送
unicode也同樣如此。
另外,你用的delphi版本也很重要,Delphi7以下的,只支持ansi,不用特別轉換
從delphi2009開始,所有string都默認是unicode長度會有變化。
再者,我看到你的代碼裡面,發送和接收都沒有實際長度,都是 -1,這是很不科學的做法。不能把長度交給系統去判斷,這樣只會是錯誤的。必須要提供實際的接收長度。只有這樣才能避免被系統聰明的分包和組包。