最近測試了下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,這是很不科學的做法。不能把長度交給系統去判斷,這樣只會是錯誤的。必須要提供實際的接收長度。只有這樣才能避免被系統聰明的分包和組包。