2013-03-12 77 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

相关问题