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 := '....@gmail.com';
      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.
4

1 に答える 1

3

AppendMsg()代替電子メール ヘッダーを指定できるバージョンの を呼び出しています。私が考えることができるほとんどすべての状況で、あなたは決してそれをしたくないでしょう (なぜ TIdIMAP4 がその機能を公開するのかさえわかりません)。

その理由は、 を内部にAppendMsg()保存し、そこからメール本文をサーバーに送信するためです。代替ヘッダーを指定すると、それらはそのまま送信され、メール本文の作成に使用されたヘッダー データと一致しなくなります。最も重要なことは、電子メール本文内の MIME 部分を分離するために使用される MIME 境界が、実際にサーバーに送信されるヘッダーで指定された境界と一致しないことです。これが、発生している症状の原因となります。その境界値は、エンコードされるたびに によってランダムに生成されるため、を呼び出す前にプロパティで使用することはできません。TIdMessageTStreamTStreamTIdMessageTIdMessage.HeadersAppendMsg()

そうは言っても、コードを変更して のAAlternativeHeadersパラメーターAppendMsg()を nil に設定する (またはパラメーターをまったくAppendMsg()持たないオーバーロードされたバージョンを使用する) ことを強くお勧めします。これにより、エンコード時にそれ自体が生成する実際のヘッダーが送信されます。アップロード前:AAlternativeHeadersAppendMsg()TIdMessage

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

または:

res := IMAPClient.AppendMsg( 'Temp2', msg2, [] );
于 2013-03-12T21:17:24.950 に答える