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; |
情報提供、間違い指摘はこちらまで。