Indy 覚え書きφ(・・。)ゞ ウーン

Indy 9.0.11

自作のソースから必要部分のみコピペなので、そのままでは動きません。
完全な機能を実装するために、Indyのソースに手を加えなければならない場合もあります。


TIdMessage

 

・メールアドレス指定

TIdEMailAddressItem *item;


item = IdMessage1->Recipients->Add(); // *1
item->Address = "192.168.1.1";
item->Name = "sakura";

*1

From: IdMessage1->From
To: IdMessage1->Recipients->Add()
Reply-To: IdMessage1->ReplyTo->Add()
Cc: IdMessage1->CCList->Add()
Bcc: IdMessage1->BccList->Add()

From:以外は複数アドレス登録可能。

IdMessage1->ReceiptRecipientは既読通知を希望する場合に使用する。

 

・メールにファイル添付

    TIdMessagePart	*mp;
    TIdAttachment   *attach;
    AnsiString      file,ext,tmp;

    mp = IdMessage1->MessageParts->Add();

    // ファイル添付情報を付加
    attach = new TIdAttachment(IdMessage1->MessageParts, file); 
    attach->ContentTransfer = "base64";

    // 拡張子ごとにContentTypeを指定
    ext = ExtractFileExt(tmp).LowerCase();
    if ( ext == ".gif" )
    {
        attach->ContentType = "image/gif";
    }
    else if ( ext == ".jpeg" )
    {
        attach->ContentType = "image/jpeg";
    }
    else if ( ext == ".jpg" )
    {
        attach->ContentType = "image/jpeg";
    }
    else if ( ext == ".png" )
    {
        attach->ContentType = "image/png";
    }
    else if ( ext == ".txt" )
    {
        attach->ContentType = "text/plain";
    }
    else
    {
        attach->ContentType = "application/octet-stream";
    }

ファイル名が日本語の時、ファイル名をbase64エンコードする処理がIndyに入ってないので注意。

 

・画像を含むHTMLメール

    int i;
    TIdAttachment   *attach;
    TIdText         *text;
    AnsiString      ext,tmp;
    TStringList     *body,*files;



    IdMessage1->MessageParts->Add();

    // html body
    text = new TIdText(IdMessage1->MessageParts, NULL);
    text->Body->Assign(body);


    // 画像ファイル添付
    if ( files == NULL )
    {
        return;
    }

    for ( i = 0; i < files->Count; i++ )
    {
        attach = new TIdAttachment(IdMessage1->MessageParts, files->Strings[i]);
        attach->ContentDisposition = "inline";
        attach->ContentTransfer = "base64";

        tmp = ExtractFileName(files->Strings[i]);

        ext = ExtractFileExt(tmp).LowerCase();;
        if ( ext == ".gif" )
        {
            attach->ContentType = "image/gif";
        }
        else if ( ext == ".jpeg" )
        {
            attach->ContentType = "image/jpeg";
        }
        else if ( ext == ".jpg" )
        {
            attach->ContentType = "image/jpeg";
        }
        else if ( ext == ".png" )
        {
            attach->ContentType = "image/png";
        }
        else if ( ext == ".txt" )
        {
            attach->ContentType = "text/plain";
        }
        else
        {
            attach->ContentType = "application/octet-stream";
        }

        // 添付画像ファイルをHTMLメール内で使用するヘッダを付加
        attach->ExtraHeaders->Values["Content-ID"] = "<" + tmp + ">";
    }

これも、ファイル名が日本語の場合、Indyのソースを変更する必要がある。

procedure TIdMessageClient.SendBody(AMsg: TIdMEssage);
var
  i: Integer;
  LAttachment: TIdAttachment;
  LBoundary: string;
  LDestStream: TIdTCPStream;
  LMIMEAttachments: boolean;
  ISOCharset: string;
  HeaderEncoding: Char;  { B | Q }
  TransferEncoding: TTransfer;

  { Abe Added }
  TmpFilename: String;
{  LEncoder:   TIdEncoderMIME;   }
  { Abe }

  procedure WriteTextPart(ATextPart: TIdText);
  var
    Data: string;
    i: Integer;
  begin
    if Length(ATextPart.ContentType) = 0 then
      ATextPart.ContentType := 'text/plain'; {do not localize}
    if Length(ATextPart.ContentTransfer) = 0 then
      ATextPart.ContentTransfer := 'quoted-printable'; {do not localize}
    WriteLn('Content-Type: ' + ATextPart.ContentType); {do not localize}
    WriteLn('Content-Transfer-Encoding: ' + ATextPart.ContentTransfer); {do not localize}
    WriteStrings(ATextPart.ExtraHeaders);
    WriteLn('');

    // TODO: Provide B64 encoding later
    // if AnsiSameText(ATextPart.ContentTransfer, 'base64') then begin
    //  LEncoder := TIdEncoder3to4.Create(nil);

    if AnsiSameText(ATextPart.ContentTransfer, 'quoted-printable') then
    begin
      for i := 0 to ATextPart.Body.Count - 1 do
      begin
        if Copy(ATextPart.Body[i], 1, 1) = '.' then
        begin
          ATextPart.Body[i] := '.' + ATextPart.Body[i];
        end;
        Data := TIdEncoderQuotedPrintable.EncodeString(ATextPart.Body[i] + EOL);
        if TransferEncoding = iso2022jp then
          Write(Encode2022JP(Data))
        else
          Write(Data);
      end;
    end

    else begin
      WriteStrings(ATextPart.Body);
    end;
    WriteLn('');
  end;

begin
  LMIMEAttachments := AMsg.Encoding = meMIME;
  LBoundary := '';

  InitializeISO(TransferEncoding, HeaderEncoding, ISOCharSet);
  BeginWork(wmWrite);
  try
    if AMsg.MessageParts.AttachmentCount > 0 then
    begin
      if LMIMEAttachments then
      begin
        WriteLn('This is a multi-part message in MIME format'); {do not localize}
        WriteLn('');
        if AMsg.MessageParts.RelatedPartCount > 0 then
        begin
          LBoundary := IndyMultiPartRelatedBoundary;
        end
        else begin
          LBoundary := IndyMIMEBoundary;
        end;
        WriteLn('--' + LBoundary);
      end
      else begin
        // It's UU, write the body
        WriteBodyText(AMsg);
        WriteLn('');
      end;

      if AMsg.MessageParts.TextPartCount > 1 then
      begin
        WriteLn('Content-Type: multipart/alternative; '); {do not localize}
        WriteLn('        boundary="' + IndyMultiPartAlternativeBoundary + '"'); {do not localize}
        WriteLn('');
        for i := 0 to AMsg.MessageParts.Count - 1 do
        begin
          if AMsg.MessageParts.Items[i] is TIdText then
          begin
            WriteLn('--' + IndyMultiPartAlternativeBoundary);
            DoStatus(hsStatusText,  [RSMsgClientEncodingText]);
            WriteTextPart(AMsg.MessageParts.Items[i] as TIdText);
            WriteLn('');
          end;
        end;
        WriteLn('--' + IndyMultiPartAlternativeBoundary + '--');
      end
      else begin
        if LMIMEAttachments then
        begin
          WriteLn('Content-Type: text/plain'); {do not localize}
          WriteLn('Content-Transfer-Encoding: 7bit'); {do not localize}
          WriteLn('');
          WriteBodyText(AMsg);
        end;
      end;

      // Send the attachments
      for i := 0 to AMsg.MessageParts.Count - 1 do
      begin
        if AMsg.MessageParts[i] is TIdAttachment then
        begin
          LAttachment := TIdAttachment(AMsg.MessageParts[i]);
          DoStatus(hsStatusText, [RSMsgClientEncodingAttachment]);
          if LMIMEAttachments then
          begin
            WriteLn('');
            WriteLn('--' + LBoundary);
            if Length(LAttachment.ContentTransfer) = 0 then
            begin
              LAttachment.ContentTransfer := 'base64'; {do not localize}
            end;
            if Length(LAttachment.ContentDisposition) = 0 then
            begin
              LAttachment.ContentDisposition := 'attachment'; {do not localize}
            end;
            if (LAttachment.ContentTransfer = 'base64') {do not localize}
              and (Length(LAttachment.ContentType) = 0) then
            begin
              LAttachment.ContentType := 'application/octet-stream'; {do not localize}
            end;

            if TransferEncoding = iso2022jp then
            begin
                 TmpFilename := EncodeHeader(ExtractFileName(LAttachment.FileName), [], HeaderEncoding, TransferEncoding, ISOCharSet);
            end
            else begin
                TmpFilename := ExtractFileName(LAttachment.FileName);
            end;

{            WriteLn('Content-Type: ' + LAttachment.ContentType + ';'); {do not localize}
{            WriteLn('        name="' + ExtractFileName(LAttachment.FileName) + '"'); {do not localize}
{            WriteLn('Content-Transfer-Encoding: ' + LAttachment.ContentTransfer); {do not localize}
{            WriteLn('Content-Disposition: ' + LAttachment.ContentDisposition +';'); {do not localize}
{            WriteLn('        filename="' + ExtractFileName(LAttachment.FileName) + '"'); {do not localize}

            WriteLn('Content-Type: ' + LAttachment.ContentType + ';'); {do not localize}
            WriteLn('        name="' + TmpFilename + '"'); {do not localize}
            WriteLn('Content-Transfer-Encoding: ' + LAttachment.ContentTransfer); {do not localize}
            WriteLn('Content-Disposition: ' + LAttachment.ContentDisposition +';'); {do not localize}
            WriteLn('        filename="' + TmpFilename + '"'); {do not localize}

            WriteStrings(LAttachment.ExtraHeaders);
            WriteLn('');
          end;
          LDestStream := TIdTCPStream.Create(Self);
          try
            TIdAttachment(AMsg.MessageParts[i]).Encode(LDestStream);
          finally
            FreeAndNil(LDestStream);
          end;
          WriteLn('');
        end;
      end;
      if LMIMEAttachments then
      begin
        WriteLn('--' + LBoundary + '--');
      end;
    end

    else if AMsg.MessageParts.TextPartCount > 1 then
    begin
      WriteLn('This is a multi-part message in MIME format'); {do not localize}
      WriteLn('');
      for i := 0 to AMsg.MessageParts.Count - 1 do
      begin
        if AMsg.MessageParts.Items[i] is TIdText then
        begin
          WriteLn('--' + IndyMIMEBoundary);
          DoStatus(hsStatusText, [RSMsgClientEncodingText]);
          WriteTextPart(AMsg.MessageParts.Items[i] as TIdText);
        end;
      end;
      WriteLn('--' + IndyMIMEBoundary + '--');
    end

    else begin
      DoStatus(hsStatusText, [RSMsgClientEncodingText]);
      // Write out Body
      //TODO: Why just iso2022jp? Why not someting generic for all MBCS? Or is iso2022jp special?
      if TransferEncoding = iso2022jp then
      begin
        for i := 0 to AMsg.Body.Count - 1 do
        begin
          if Copy(AMsg.Body[i], 1, 1) = '.' then
          begin
            WriteLn('.' + Encode2022JP(AMsg.Body[i]));
          end

          else begin
            WriteLn(Encode2022JP(AMsg.Body[i]));
          end;
        end;
      end

      else begin
        WriteBodyText(AMsg);
      end;
    end;
  finally
    EndWork(wmWrite);
  end;
end;

 


TIdSMTP

 

・送信時エラー処理

    int error;
    AnsiString ErrMsg;


    try
    {
    	IdSMTP1->Send(IdMessage1);
    }
    catch(EIdProtocolReplyError &E)
    {
        // SMTPに関するエラーが発生した場合
        error = E.ReplyErrorCode;
        ErrMsg = E.Message;
        return false;
    }
    catch(EIdConnClosedGracefully &E)
    {
        // すでにサーバーへの接続が切れていた場合
        return false;
    }
    catch(EFOpenError &E)
    {
        // 添付ファイル等が開けなかった場合
        return false;
    }
    catch(...)
    {
        // その他回避不能なエラーの場合
        return false;
    }
    return true;

 


情報提供、間違い指摘はこちらまで。