« SaveDialogを拡張してコントロールを追加する(その3:補足) | トップページ | SimpleNovelDownloader ver1.2 »

2018.03.10

Indy(IdSMTP)を用いた添付ファイル付きメール送信

SimpleNovelDownloaderに、作成したKindle用mobiファイルを自動的にSend-To-Kindleでxxxxxx@kindle.comにエール送信してしまえば後から手動でいちいち作成したmobiファイルを添付してメール送信する手間が無くなると思い立ち、DelphiでIndyのIdSMTPを用いたメール送信機能を追加することにしました。

ということで早速実装してみたものの、通常のメールアドレスに対して送信する分には添付ファイルも含めて受信出来るものの、xxxx@kindle.comに送信すると「ファイル未添付のお知らせ」メールが帰ってくるという問題が発生し、しばらく悩みました。
その結果、メールソフトを使用してmobiファイルを添付してxxxx@kindle.comに送信する場合には件名と本文がなくても問題ないが、IdSMTPを用いる場合にはネット上で紹介されている一般的な?方法(TIdAttachmentFile.Createを使用して添付ファイルを追加する)を用いた場合、件名と本文がないと「ファイル未添付のお知らせ」となる。また、件名と本文を指定しても成功する場合と失敗する場合があるようだ、ということが判りました。

で、更にネット上で調べたところ、TIdMessageBuilderを使用してメール本文と添付ファイルを追加する方法があることが判り、この方法を用いて件名と本文を追加した状態でxxxx@kindle.comに送信すると安定してmobiファイルをSend-To-Kindle出来ることが確認出来ました。
また、OpenSSLを使用したSSL接続を用いる場合に、ネット上で紹介されているIdSMTP1.UseTL := utUseExplicitTLSではうまくいかないことも判りました。

で、テスト用に作成したものが以下となります。また、一番下にサンプルプロジェクトソースも置いておきます。
Smtptest

// IdSMTPで添付ファイルを含めたメール送信を行うための一般的な方法
// DEKOさんのところのちっぷす(https://ht-deko.com/tech040.html)等で紹介されて
// いる方法
// Send-To-Kindleでhoge@kindle.comに添付ファイルを送信する場合は、Subjectと
// Body.Textが空だと必ず失敗して「ファイル未添付のお知らせ」メールが帰ってくる
procedure TForm1.Button3Click(Sender: TObject);
var
  pt: integer;
begin
	pt									:= StrToInt(SMTPPort.Text);
  IdSMTP1.Host     		:= SMTPServer.Text;
  IdSMTP1.Port     		:= StrToInt(SMTPPort.Text);
  IdSMTP1.Username 		:= SMTPUser.Text;
  IdSMTP1.Password 		:= SMTPPassw.Text;
	// SSL接続時:OpenSSL(https://www.openssl.org/)のインストールが必要
	if UseSSL.Checked then
  begin
    SSL1.Host 				:= IdSMTP1.Host;
    SSL1.Port 				:= IdSMTP1.Port;
    SSL1.Destination  := SSL1.Host + ':' + IntToStr(SSL1.Port);
    IdSMTP1.IOHandler := SSL1;
    // SSLを使用する場合、DEKOさんのちっぷすや他の情報ではUseTLS := utUseExplicitTLS
    // としているが、これでは失敗する
    // 以下の情報を元に、ポートが465の場合にはUseTLS := utUseImplicitTLSとすると
    // うまくいく
		// https://stackoverflow.com/questions/7037929/using-gmails-outgoing-smtp-from-delphiindy-using-tls
    if pt = 465 then
    	IdSMTP1.UseTLS 	:= utUseImplicitTLS
    else
    	IdSMTP1.UseTLS 	:= utUseExplicitTLS;
	end else begin
    IdSMTP1.IOHandler := nil;
    IdSMTP1.UseTLS 	  := utNoTLSSupport;
  end;
 
  try
  	IdMsg.OnInitializeISO           := IdMessage_InitializeISO;
  	IdMsg.ContentType             	:= 'multipart/mixed';
  	IdMsg.CharSet                   := 'UTF-8';
  	IdMsg.ContentTransferEncoding   := 'BASE64';
  	IdMsg.From.Name                 := SenderName.Text;
  	IdMsg.From.Address              := MailAddr.Text;
  	IdMsg.Recipients.EMailAddresses := DestAddr.Text;
  	IdMsg.Subject                 	:= UTF8Encode(MailSubject.Text);
  	IdMsg.Body.Text                 := UTF8Encode(MailBody.Text);
    IdMsg.ConvertPreamble						:= True;
    // 複数のファイルを添付する場合はこれを繰り返す
  	with TIdAttachmentFile.Create(IdMsg.MessageParts, Attached.Text) do
    begin
  		FileName 		:= UTF8Encode(ExtractFileName(Attached.Text));
  		ContentType	:= 'application/octet-stream';
    end;
 
   	IdSMTP1.Connect;

IdSMTP1.Send(IdMsg);

except on E:Exception do
MessageDlg('ERROR: ' + E.Message, mtError, [mbOK], 0);
end;
IdSMTP1.Disconnect;
end;

// IdSMTPでTIdMessageBuilderPlain使用を使用した添付ファイルを含めたメール送信
// Send-To-Kindleでhoge@kindle.comに添付ファイルを送信する場合は、この方法の方が
// 安定しているようだ(SubjectとBody.Textが空だと失敗する場合がある)
procedure TForm1.Button1Click(Sender: TObject);
var
Bldr: TIdMessageBuilderPlain;
pt: integer;
begin
pt := StrToInt(SMTPPort.Text);
IdSMTP1.Host := SMTPServer.Text;
IdSMTP1.Port := pt;
IdSMTP1.Username := SMTPUser.Text;
IdSMTP1.Password := SMTPPassw.Text;
// SSL接続時:OpenSSL(https://www.openssl.org/)のインストールが必要
if UseSSL.Checked then
begin
SSL1.Host := IdSMTP1.Host;
SSL1.Port := IdSMTP1.Port;
SSL1.Destination := SSL1.Host + ':' + IntToStr(SSL1.Port);
IdSMTP1.IOHandler := SSL1;
// SSLを使用する場合、DEKOさんのちっぷすや他の情報ではUseTLS := utUseExplicitTLS
// としているが、これでは失敗する
// 以下の情報を元に、ポートが465の場合にはUseTLS := utUseImplicitTLSとすると
// うまくいく
// https://stackoverflow.com/questions/7037929/using-gmails-outgoing-smtp-from-delphiindy-using-tls
if pt = 465 then
IdSMTP1.UseTLS := utUseImplicitTLS
else
IdSMTP1.UseTLS := utUseExplicitTLS;
end else begin
IdSMTP1.IOHandler := nil;
IdSMTP1.UseTLS := utNoTLSSupport;
end;

try
IdMsg.OnInitializeISO := IdMessage_InitializeISO;
// ファイルを添付する場合、multipart/mixedの指定が必要
IdMsg.ContentType := 'multipart/mixed';
IdMsg.CharSet := 'UTF-8';
IdMsg.ContentTransferEncoding := 'BASE64';
IdMsg.From.Name := SenderName.Text;
IdMsg.From.Address := MailAddr.Text;
IdMsg.Recipients.EMailAddresses := DestAddr.Text;
IdMsg.Subject := UTF8Encode(MailSubject.Text);

Bldr := TIdMessageBuilderPlain.Create;
try
Bldr.PlainTextCharSet := 'UTF-8';
// メール本文
Bldr.PlainText.Text := UTF8Encode(MailBody.Text);
// 添付ファイル(複数のファイルを添付する場合はひとつづつAddする)
Bldr.Attachments.Add(Attached.Text);
// まとめてIdMessageにセットする
Bldr.FillMessage(IdMsg);
finally
// IdMessageにセットした後はBldrを開放する
Bldr.Free;
end;

IdSMTP1.Connect;

IdSMTP1.Send(IdMsg);

except on E:Exception do
MessageDlg('ERROR: ' + E.Message, mtError, [mbOK], 0);
end;
IdSMTP1.Disconnect;
end;


「idsmtpsample.zip」をダウンロード


|

« SaveDialogを拡張してコントロールを追加する(その3:補足) | トップページ | SimpleNovelDownloader ver1.2 »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/22406/66479760

この記事へのトラックバック一覧です: Indy(IdSMTP)を用いた添付ファイル付きメール送信:

« SaveDialogを拡張してコントロールを追加する(その3:補足) | トップページ | SimpleNovelDownloader ver1.2 »