c++ builder > 添付ファイルをつけたメールを送信 / MIME Content-Type | 10.2 Tokyoの場合

```txt:動作確認
C++ Builder XE4
```

ベース http://qiita.com/7of9/items/5d0117a0802cca97f5f9

上記のメール処理に対して、添付ファイルをつけたメールを送信するように変更する。

参考 http://www.gesource.jp/programming/bcb/97.html

## 変更箇所

以下の`#if 1 // attach`の処理がファイル添付に必要になった処理

### include追加

```
#if 1 // attach
#include <IdAttachmentFile.hpp>
#endif
```

### ContentTypeを"multipart/mixed"にする

```
#if 1 // attach
	msg->ContentType = "multipart/mixed";
#else
	msg->ContentType = "text/plain";
#endif
```

### ファイル添付処理

```
#if 1 // attach
	TIdAttachmentFile *attmnt;
	attmnt = new TIdAttachmentFile(msg->MessageParts, L"tmp.jpg");
	attmnt->FileName = L"tmp.jpg";
	attmnt->ContentType = L"image/jpeg";
#endif
```

### 手仕舞い

```
#if 1 // attach
	delete attmnt;
#endif
```

## コード

コード全体は以下となる。

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

// メール送信用
#include <Idglobal.hpp>
#include <IdSMTP.hpp>
#include <IdSSLOpenSSL.hpp>
// POP before SMTP
#include <IdPOP3.hpp>

// メール本文の文字化けの対応
#include <IdHeaderCoder2022JP.hpp>
#pragma link "IdHeaderCoder2022JP"

#include "Unit1.h"

#include "mailInfo.h" // メールサーバーなどの設定


#if 1 // attach
#include <IdAttachmentFile.hpp>
#endif

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::sendTestMailSMTP()
{
    // 1. POP before SMTP
	TIdPOP3 *idPop3 = new TIdPOP3();
	idPop3->Host = kPopServerAdr;
	idPop3->Port = kPopPort; // int
    idPop3->Username = kMyUserName;
	idPop3->Password = kMyPassword;

    // command is not valid in this state
	TIdSSLIOHandlerSocketOpenSSL *idSSL = new TIdSSLIOHandlerSocketOpenSSL();
    if (useTLS) {
        idSSL->Host = kPopServerAdr;
        idSSL->Port = kPopPort;
        idSSL->Destination = idSSL->Host + L":" + IntToStr(kPopPort);
        idPop3->IOHandler = idSSL;
        idPop3->UseTLS = utUseImplicitTLS;
    }

    try {
        idPop3->Connect();
        idPop3->Disconnect();
    } catch (const Exception &e) {
        String msg = e.Message;
        delete idPop3;
        delete idSSL;
        return; // fail
    }
    delete idSSL;
    delete idPop3;

    // 2. sending e-mail using SMTP

    TIdSMTP* smtp = new TIdSMTP(NULL);
    TIdSSLIOHandlerSocketOpenSSL * sslHandler = new TIdSSLIOHandlerSocketOpenSSL(NULL);

    smtp->Host = kSmtpHost;
//  sslHandler->Host = smtp->Host;
//  sslHandler->Port = smtp->Port;
//  sslHandler->Destination = sslHandler->Host + L":"
//      + IntToStr(sslHandler->Port);
    smtp->IOHandler = sslHandler;
    smtp->Username = kMyUserName;
    smtp->Password = kMyPassword;
    smtp->Port = 587;
    smtp->UseTLS = utUseExplicitTLS;

	try {
		smtp->Connect();
	} catch (const Exception &e) {
		String msg = e.Message;
	}


	TIdMessage* msg = new TIdMessage(NULL);

	msg->OnInitializeISO = IdMessage1InitializeISO;
#if 1 // attach
	msg->ContentType = "multipart/mixed";
#else
	msg->ContentType = "text/plain";
#endif
	msg->CharSet = "ISO-2022-JP";
	msg->ContentTransferEncoding = "BASE64";
	msg->From->Name = kFromName;
	msg->From->Address = kFromAddr;
	msg->Recipients->EMailAddresses = kRecipients;

	// TODO: 件名は日本語だと文字化けする
	msg->Subject = "test mail from XE4 on " + Now().FormatString(L"hh:nn:ss");

	msg->Body->Text = "テストメールの本文です";

#if 1 // attach
	TIdAttachmentFile *attmnt;
	attmnt = new TIdAttachmentFile(msg->MessageParts, L"tmp.jpg");
	attmnt->FileName = L"tmp.jpg";
	attmnt->ContentType = L"image/jpeg";
#endif

	try {
        smtp->Send(msg);
    } catch (const Exception &e) {
        String msg = e.Message;
    }

	smtp->Disconnect();
#if 1 // attach
	delete attmnt;
#endif
	delete msg;
    delete smtp;
}

void __fastcall TForm1::IdMessage1InitializeISO(System::WideChar &VHeaderEncoding, UnicodeString &VCharSet)
{
    VHeaderEncoding = L'B';
    VCharSet = "ISO-2022-JP";
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	sendTestMailSMTP();
}
//---------------------------------------------------------------------------
```

```Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TButton *Button1;
	void __fastcall Button1Click(TObject *Sender);
private:	// ユーザー宣言
	void __fastcall TForm1::IdMessage1InitializeISO(System::WideChar &VHeaderEncoding, UnicodeString &VCharSet);
	void __fastcall TForm1::sendTestMailSMTP();
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
```

## 必要なヘッダ

上記の実行には mailInfo.h が必要

mailInfo.hにはメールサーバーなどの設定を記載する。

```
#ifndef MAIL_INFO_H
#define MAIL_INFO_H

String kMyUserName = L"yamada@xxx.com";
String kSmtpHost = L"smtp.xxx.com";
String kPopServerAdr = L"pop.xxx.com";
int kPopPort = 995;
bool useTLS = true;

String kFromName = L"yamada"; // e.g. yamada
String kFromAddr = kMyUserName; // 
String kRecipients = "tanii@xxx.com"; // 送信先メールアドレス
String kMyPassword = L"1234567"; 
#endif
```

## 添付するファイルの準備

適当にキャプチャして保存したtmp.jpgファイルを.exeと同じフォルダに置く。

## 各種ファイルのContent-Type

jpg以外のファイルを添付する場合のContentTypeについては以下に整理されている。

http://www.kyoto-su.ac.jp/ccinfo/use_web/mine_contenttype/

## 複数ファイルの添付
(追記 2016/07/07)

複数のファイルを添付するのはどうしたらいいかというと、以下ようにすればいいようだ。
送信後にattmnt1とattmnt2をdeleteすること。

```
#if 1 // attach
	TIdAttachmentFile *attmnt1;
	attmnt1 = new TIdAttachmentFile(msg->MessageParts, L"tmp1.jpg");
	attmnt1->FileName = L"tmp1.jpg";
	attmnt1->ContentType = L"image/jpeg";

	TIdAttachmentFile *attmnt2;
	attmnt2 = new TIdAttachmentFile(msg->MessageParts, L"tmp2.jpg");
	attmnt2->FileName = L"tmp2.jpg";
	attmnt2->ContentType = L"image/jpeg";
#endif
```

### 10.2 Tokyo対応
(追記 2018/01/10)

10.2 Tokyoの場合は以下の方法で送信できた。

- [C++ Builder 10.2 Tokyo > Indy > OpenSSL > Error: Could not load SSL library > libeay32.dllとssleay32.dllが関連](https://qiita.com/7of9/items/ac616e9bc593c270b5f2)