2013-03-12 75 views
2

我使用的是Delphi 2006,Indy 10(ver。4957),IMAP4。如何下載郵件,存儲郵件並在不同的文件夾中重新創建郵件?

我想下載電子郵件,存儲它,幾周後我想重新創建它在不同的文件夾中。 (這是歸檔和恢復它的一種方式,所以文件夾之間的簡單移動不起作用,因爲我將刪除原始郵件。)我下載郵件並存儲,然後用AppendMsg複製它。

它的工作原理,直到這一點,當我檢查目標TEMP2文件夾,其中的大部分信息都包含

這是MIME格式

unit Mail_Test; 

interface 

uses 
    Windows, 
    Messages, 
    SysUtils, 
    Variants, 
    Classes, 
    Graphics, 
    Controls, 
    Forms, 
    Dialogs, 
    StdCtrls; 

type 
    TForm1 = class(TForm) 
    memLog: TMemo; 
    btn1: TButton; 
    procedure btn1Click(Sender: TObject); 
    private 
    procedure Log(LogMsg: string); 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

uses 
    IdIMAP4, 
    IdMessage, 
    IdExplicitTLSClientServerBase, 
    IdSSLOpenSSL; 

{$R *.dfm} 

procedure TForm1.btn1Click(Sender: TObject); 
var 
    IMAPClient: TIdIMAP4; 
    UsersFolders: TStringList; 
    OpenSSLHandler: TIdSSLIOHandlerSocketOpenSSL; 
    res: Boolean; 
    i: integer; 
    inbox, currUID: string; 
    cntMsg: integer; 
    msg, msg2: TIdMessage; 
    BodyTexts: TStringList; 
    flags: TIdMessageFlagsSet; 
    fileName_MailSource, TmpFolder: string; 
begin 

    IMAPClient := TIdIMAP4.Create(nil); 
    try 
    OpenSSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil); 
    try 
     IMAPClient.Host := 'imap.gmail.com'; 
     IMAPClient.Port := 993; 
     IMAPClient.Username := '[email protected]'; 
     IMAPClient.Password := '....'; 

     if Pos('gmail.com', IMAPClient.Host) > 0 then begin 
     OpenSSLHandler.SSLOptions.Method := sslvSSLv3; 
     IMAPClient.IOHandler := OpenSSLHandler; 
     IMAPClient.UseTLS := utUseImplicitTLS; 
     end; 

     try 
     res := IMAPClient.Connect; 
     if not res then begin 
      Log(' Unsuccessful connection.'); 
      exit; 
     end; 

     except 
     on e: Exception do begin 
      Log(' Unsuccessful connection.'); 
      Log(' (' + Trim(e.Message) + ')'); 
      exit; 
     end; 
     end; 

     try 
     UsersFolders := TStringList.Create; 
     try 
      res := IMAPClient.ListMailBoxes(UsersFolders); 
      if not res then begin 
      Log(' ListMailBoxes error.'); 
      exit 
      end; 
     except 
      on e: Exception do begin 
      Log(' ListMailBoxes error.'); 
      Log(' (' + Trim(e.Message) + ')'); 
      exit; 
      end; 

     end; 

     Log('User folders: ' + IntToStr(UsersFolders.Count)); 
     for i := 0 to UsersFolders.Count - 1 do begin 
      Log(' [' + inttostr(i + 1) + '/' + inttostr(UsersFolders.Count) + '] Folder: "' + UsersFolders[ i ] + '"'); 
     end; 

     IMAPClient.RetrieveOnSelect := rsDisabled; 
     inbox := 'INBOX'; 
     Log('Opening folder "' + inbox + '"...'); 
     res := IMAPClient.SelectMailBox(inbox); 
     cntMsg := IMAPClient.MailBox.TotalMsgs; 
     Log('E-mails to read: ' + IntToStr(cntMsg)); 

    // res := IMAPClient.RetrieveAllEnvelopes(AMsgList); 

     msg := TIdMessage.Create(nil); 
     msg2 := TIdMessage.Create(nil); 
     BodyTexts := TStringList.Create; 
     TmpFolder := 'c:\'; 
     res := IMAPClient.CreateMailBox('Temp2') 
     try 

      for I := 0 to cntMsg - 1 do begin 

      Log(' [' + inttostr(i + 1) + '/' + inttostr(cntMsg) + '] E-mail...'); 

      IMAPClient.GetUID(i + 1, currUID); 

      Log('(Downloading message...)'); 
      IMAPClient.UIDRetrieve(currUID, msg); 

      fileName_MailSource := TmpFolder + 'Log_Mail_' + currUID + '.eml'; 
      msg.SaveToFile(fileName_MailSource, false); 

      // In the final version I will delete the original message 
      // so I have to recreate it from the archived file 

      msg2.LoadFromFile(fileName_MailSource); 

      res := IMAPClient.AppendMsg('Temp2', msg2, msg2.Headers, []); 
      end; 
     finally 
      FreeAndNil(msg); 
      FreeAndNil(msg2); 
      FreeAndNil(BodyTexts) 
     end; 

     finally 
     IMAPClient.Disconnect; 
     end; 
    finally 
     OpenSSLHandler.Free; 
    end; 
    finally 
    IMAPClient.Free; 
    end; 
end; 

procedure TForm1.Log(LogMsg: string); 
begin 
    memLog.Lines.Add(LogMsg); 
    Application.ProcessMessages; 
end; 

end. 
+2

這是你斷言消息*不應該*說他們是MIME格式的多部分消息?你有什麼問題? – 2013-03-12 14:24:49

+0

當然他們是多部分消息,但上傳的消息變得混亂。例如,在電子郵件客戶端打開的消息的示出一個這樣的: 「這是MIME格式 --kQoHZj9xrCzNf77TupjT4sJi4sO2i = _bzh 內容類型的多部分消息:文本/無格式;字符集=」 US- ASCII「 內容傳輸編碼:引號的可打印 內容處置:內聯 Rondald嗨,」 如此看來,簡單的SaveToFile + loadfromfile + appendmsg序列不起作用。我希望那部分得到糾正。 – user2160569 2013-03-12 19:08:00

回答

3

你是一個多部分消息調用AppendMsg()的版本,可讓您指定替代電子郵件標題。在幾乎所有我能想到的情況下,你永遠都不會想這樣做(我甚至不知道爲什麼TIdIMAP4會公開該功能)。

的原因是因爲AppendMsg()保存TIdMessage到內部TStream,然後從TStream發送電子郵件正文到服務器。如果您指定了替代標題,它們將按原樣發送,並且與用於創建電子郵件正文的標題數據不匹配。最重要的是,用於分隔電子郵件正文中的MIME部分的MIME邊界將與實際發送到服務器的標題中指定的邊界不匹配,這將解決您所看到的症狀。該邊界值在編碼時會隨機生成TIdMessage,因此在調用AppendMsg()之前在TIdMessage.Headers屬性中不可用。

因此,隨着中說,我強烈建議你改變你的代碼來設置的AppendMsg()爲零的AAlternativeHeaders參數(或使用AppendMsg()重載版本不具有AAlternativeHeaders參數的話),這樣AppendMsg()將發送

res := IMAPClient.AppendMsg('Temp2', msg2, nil, []); 

或者:那TIdMessage本身產生當它之前編碼上傳真實頭部

res := IMAPClient.AppendMsg('Temp2', msg2, []); 
+0

謝謝,效果很好! – user2160569 2013-03-13 14:37:22

相關問題