Top / Programming / C++Builder / C++Builder2009とIndy10でメールを送信する

C++Builder2009とIndy10でメールを送信する

C++Builder2009に付属のIndy10は、UnicodeString対応が不十分です。
そのため日本語メールを送信するにはちょっとしたテクニックは必要になります。

このTipsは以下のページを参考にさせていただきました。

C++Builder 2010以降をお使いの場合は、「C++Builder2010とIndy10でメールを送信する」をご覧ください。

英文メールの送信

最初は簡単に英文のメールを送信する方法を紹介します。

unique_ptr<TIdSMTP> smtp(new TIdSMTP(NULL));
smtp->Host = "localhost"; //SMTPサーバ

unique_ptr<TIdMessage> msg(new TIdMessage(NULL));
msg->From->Name = "From name";
msg->From->Address = "from@example.com";

TIdEMailAddressItem* item = msg->Recipients->Add();
item->Name = "To name";
item->Address = "to@example.com";

msg->Subject = "Subject";
msg->Body->Text = "This is e-mail.";

smtp->Connect();
smtp->Send(msg.get());
smtp->Disconnect();

日本語メールの送信

日本語メールを送信するには、次の処理が必要になります。

Indyの各プロパティはUnicodeStringを受け取るため、文字コードをISO-2022-JPに変換したUnicodeStringを作成する関数を用意します。

文字コードの変換にMECSUtilsを利用しています。

/**
 * JISコードに変換する
 */
UnicodeString ConvertJis(const UnicodeString& Str)
{
  RawByteString jis;
  Mecsutils::ConvertUnicodeToMultiByte(50220, Str, jis);

  UnicodeString body;
  body.SetLength(jis.Length());
  for (int i = 1; i <= jis.Length(); ++i)
  {
    body[i] = jis[i];
  }
  return body;
}

文字コードがISO-2022-JPの文字列をBase64エンコードする関数を用意します。

/**
 * ヘッダのBase64エンコード
 */
UnicodeString Base64Encode(const UnicodeString& Str)
{
  UnicodeString jis = ConvertJis(Str);

  unique_ptr<TIdEncoderMIME> enc(new TIdEncoderMIME(NULL));
  return L"=?ISO-2022-JP?B?" + enc->EncodeString(jis) + "?=";
}

メールのヘッダに文字コードを設定します。

unique_ptr<TIdMessage> msg(new TIdMessage(NULL));
msg->ContentType = "text/plain";
msg->CharSet = "ISO-2022-JP";
msg->ContentTransferEncoding = "7bit";

メールの送信者名、宛先名、件名の日本語をBase64エンコードします。

msg->From->Name = Base64Encode(L"メールの送信者名");

TIdEMailAddressItem* item = msg->Recipients->Add();
item->Name = Base64Encode(L"メールの宛先");

msg->Subject = Base64Encode(L"メールの件名");

メールの本文の文字コードをISO-2022-JPに変換します。

msg->Body->Text = ConvertJis(L"テストメールの本文");

全体のコードは次のようになります。

unique_ptr<TIdSMTP> smtp(new TIdSMTP(NULL));
smtp->Host = "localhost";

unique_ptr<TIdMessage> msg(new TIdMessage(NULL));
msg->ContentType = "text/plain";
msg->CharSet = "ISO-2022-JP";
msg->ContentTransferEncoding = "7bit";

msg->From->Name = Base64Encode(L"メールの送信者名");
msg->From->Address = "from@example.com";
TIdEMailAddressItem* item = msg->Recipients->Add();
item->Name = Base64Encode(L"メールの宛先");
item->Address = "to@example.com";
msg->Subject = Base64Encode(L"メールの件名");
msg->Body->Text = ConvertJis(L"テストメールの本文");

smtp->Connect();
smtp->Send(msg.get());
smtp->Disconnect();

添付ファイルのあるメールの送信

添付ファイルがある場合、メールはマルチパートになります。
メールのヘッダと本文の設定が変わります。

unique_ptr<TIdSMTP> smtp(new TIdSMTP(NULL));
smtp->Host = "localhost";

unique_ptr<TIdMessage> msg(new TIdMessage(NULL));
msg->ContentType = "multipart/mixed"; //マルチパート

msg->From->Name = Base64Encode(L"メールの送信者名");
msg->From->Address = "from@example.com";
TIdEMailAddressItem* item = msg->Recipients->Add();
item->Name = Base64Encode(L"メールの宛先");
item->Address = "to@example.com";
msg->Subject = Base64Encode(L"メールの件名");

//メールの本文のパート
TIdText* text = new TIdText(msg->MessageParts, NULL);
text->ContentType = "text/plain";
text->CharSet = "ISO-2022-JP";
text->ContentTransfer = "7bit";
text->Body->Text = ConvertJis(L"メールの本文");

//添付ファイルのパート
TIdAttachmentFile* attached = new TIdAttachmentFile(
  msg->MessageParts, 
  L"C:\\test\\サンプル.jpg"); //ファイルのパス
attached->FileName = Base64Encode(L"サンプル画像.jpg"); //送信ファイル名
attached->ContentType = "image/jpeg"; //ファイルの種類によって変更します

smtp->Connect();
smtp->Send(msg.get());
smtp->Disconnect();

SMTP認証を使用したメールの送信

SMTP認証を使用してメールを送信するには、SSL関連のDLLが必要になります。
次のページからファイルをダウンロードして展開し、「libeay32.dll」と「ssleay32.dll」を実行ファイル(exeファイル)と同じディレクトリに配置します。

ソースコードには、SMTP認証の設定を追加します。

unique_ptr<TIdSMTP> smtp(new TIdSMTP(NULL));
unique_ptr<TIdSASLLogin> login(new TIdSASLLogin(smtp.get()));
unique_ptr<TIdUserPassProvider> provider(new TIdUserPassProvider(login.get()));
unique_ptr<TIdSSLIOHandlerSocketOpenSSL> sslHander(new TIdSSLIOHandlerSocketOpenSSL(NULL));
smtp->Host = "localhost"; //SMTPサーバ
smtp->Port = 465; //ポート番号
smtp->Username = "username"; //SMTP認証のユーザー名
smtp->Password = "passowrd"; //SMTP認証のパスワード
sslHander->Host = smtp->Host;
sslHander->Port = smtp->Port;
sslHander->Destination = sslHander->Host + ":" + IntToStr(sslHander->Port);
smtp->IOHandler = sslHander.get();    //TIdSSLIOHandlerSocketOpenSSL
smtp->UseTLS = utUseExplicitTLS; // Explict

//以下、メールの作成は同じ
unique_ptr<TIdMessage> msg(new TIdMessage(NULL));
msg->From->Name = "From name";
msg->From->Address = "from@example.com";

TIdEMailAddressItem* item = msg->Recipients->Add();
item->Name = "To name";
item->Address = "to@example.com";

msg->Subject = "Subject";
msg->Body->Text = "This is e-mail.";

smtp->Connect();
smtp->Send(msg.get());
smtp->Disconnect();

Gmailを使ってメールを送信する

Gmailを使ってメールを送信する方法です。
SMTP認証を使います。ポート番号に気をつけて下さい。

unique_ptr<TIdSMTP> smtp(new TIdSMTP(NULL));
unique_ptr<TIdSASLLogin> login(new TIdSASLLogin(smtp.get()));
unique_ptr<TIdUserPassProvider> provider(new TIdUserPassProvider(login.get()));
unique_ptr<TIdSSLIOHandlerSocketOpenSSL> sslHander(new TIdSSLIOHandlerSocketOpenSSL(NULL));
//Gmailの設定
smtp->Host = "smtp.gmail.com";
smtp->Port = 587;
smtp->Username = "username@gmail.com"; //Gmailのユーザ名
smtp->Password = "password";

sslHander->Host = smtp->Host;
sslHander->Port = smtp->Port;
sslHander->Destination = sslHander->Host + ":" + IntToStr(sslHander->Port);
smtp->IOHandler = sslHander.get();    //TIdSSLIOHandlerSocketOpenSSL
smtp->UseTLS = utUseExplicitTLS; // Explict

//以下、メールの作成は同じ

最後に

サンプルコードでは「using namespace std;」を省略しています。

ヘッダファイルも省略していますが、MECSUtilsを使うには

#include "MECSUtils.hpp"

が必要です。詳細は「文字コードを変換する」をご覧下さい。

Indyのヘッダは、ヘルプファイルを調べて下さい。
例えば「TIdText」の場合、ヘルプを見ると、

File
  IdText

とありますから、拡張子「.hpp」をつけて

#include "IdText.hpp"

となります。

関連