JavaMailでPDF添付ファイル付きのメールを送る

# 概要
JavaMailとpdfboxを使ってPDF添付ファイル付きのメールを送信します。  
PDFファイルの作成方法と、メール送信方法について説明します。

**環境**

* Java JDK 1.8.0_171
* Windows10
* JavaMail 1.4.7
* pdfbox 2.0.13
* SMTPサーバー: FakeSMTP

# PDFファイルを作成
[pdfbox](https://pdfbox.apache.org/) を使ってPDFファイルを作ります

## 準備
まずはmavenでpdfboxを利用できるようにします。

``` xml:pom.xml
<dependency>
  <groupId>org.apache.pdfbox</groupId>
  <artifactId>pdfbox</artifactId>
  <version>2.0.13</version>
</dependency>
```

## PDFファイル作成コード
ではPDFファイルを作成します。
実ファイルを利用する場合、InputStreamを利用する場合と紹介します。
今回は実ファイルを生成せずにメール送信を行いたいため、ByteArrayInputStreamを返すメソッドで書きます。

``` java
public ByteArrayInputStream createDocument() {
	PDDocument document = null;
	TrueTypeCollection collection = null;
        ByteArrayInputStream inputStream;

	try {
        // PDFのベースを作成。今回はA4で。
		document = new PDDocument();
		PDPage page = new PDPage(PDRectangle.A4);
		document.addPage(page);

        // 日本語はフォントを読み込まないと使えないので読み込みます。
        // Macはパスが違います。       
		PDFont font = PDType1Font.TIMES_BOLD;
		File file = new File("C:/Windows/Fonts/msmincho.ttc");
        collection = new TrueTypeCollection(file);
        PDFont font2 = PDType0Font.load(document, collection.getFontByName("MS-Mincho"), true);

        // ページの中身を作成
		PDPageContentStream contentStream = new PDPageContentStream(document, page);
        // フォントや位置を指定して一つのテキストを作成します。
        // ページは左下がベース(0, 0)になります。
		contentStream.beginText();
		contentStream.newLineAtOffset(0, PDRectangle.A4.getHeight() - 12f);
		contentStream.setFont(font, 12);
		contentStream.showText("firstText");
		contentStream.endText();

		contentStream.beginText();
		contentStream.newLine();
		contentStream.setFont(font2, 15);
		contentStream.showText("secondText");
		contentStream.endText();

		contentStream.close();

		// PDFファイルを作成します。
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        document.save(out);
        inputStream = new ByteArrayInputStream(out.toByteArray());

        // ---- 実ファイルを作成する場合 ----
        // document.save("sample.pdf");
        // --------------------------------
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		if (document != null) {
			try {
				document.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (collection != null) {
			try {
				collection.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
    return inputStream;
}
```

「実ファイルを実行する場合」のコードを記載した場合はこの段階でPDFファイルが生成されます。

# メール送信
次に [JavaMail](https://javaee.github.io/javamail/) を使ってメールを送信します。

## 準備
こちらもmavenで利用できるように記述を足します。

``` xml:pom.xml
<dependency>
  <groupId>javax.mail</groupId>
  <artifactId>mail</artifactId>
  <version>1.4.7</version>
</dependency>
```

### FakeSMTP をインストール

今回開発用のSMTPサーバーとして [FakeSMTP](https://github.com/Nilhcem/FakeSMTP) を使います。
利用方法は [リンク先](https://github.com/Nilhcem/FakeSMTP) を参照してください。

ちなみにGmailはセキュリティを下げないとローカル環境から認証できなかったため使うのをやめました。

## メール送信コード
ではメール送信を行うコードを書いていきます。
先程作成したPDFのInputStreamを引数で受け取って利用します。

``` java
public void sendRawMail(final String subject, ByteArrayInputStream attachement) {
        // プロパティの設定
		Properties properties = System.getProperties();
		// ホスト
		properties.put("mail.smtp.host", HOST);
		// 認証
		properties.put("mail.smtp.auth", "true");
		// ポート指定（サブミッションポート）
		properties.put("mail.smtp.port", "25");
		// STARTTLSによる暗号化
		properties.put("mail.smtp.starttls.enable", "true");
		properties.put("mail.smtp.starttls.enable", "false");
		properties.put("mail.smtp.debug", "true");
		// タイムアウト
		properties.put("mail.smtp.connectiontimeout", "10000");
		properties.put("mail.smtp.timeout", "10000");

		try {
            // セッションの作成。
			final Session session = Session.getInstance(properties , new javax.mail.Authenticator(){
                protected PasswordAuthentication getPasswordAuthentication(){
                    // Gmailなどを使う場合はユーザ名とパスワードを引数に指定。
                    return new PasswordAuthentication("", "");
                }
            });
			final Message message = new MimeMessage(session);

			// 基本情報
			message.setFrom(new InternetAddress("送信元メールアドレス"));
			message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("送信先メールアドレス", false));
            // タイトル
			message.setSubject(subject);

			// 本文
			final MimeMultipart multipart = new MimeMultipart("mixed");
            // 本文テキスト
			final MimeBodyPart textPart = new MimeBodyPart();
			textPart.setText("本文テキスト", "UTF-8");

            // 添付ファイル
			final MimeBodyPart attPart = new MimeBodyPart();
            // 実ファイルを利用する場合は実ファイルでDataSourceを作成
			final DataSource dataSource = new ByteArrayDataSource(attachement, "application/pdf");
			attPart.setDataHandler(new DataHandler(dataSource));
			attPart.setFileName("test.pdf");

			multipart.addBodyPart(textPart);
			multipart.addBodyPart(attPart);

			message.setContent(multipart);

			// 送信
			Transport.send(message);
		} catch (Exception e) {
			e.printStackTrace();
			throw new InternalServerErrorException(e);
		}
	}
```

メソッド実行でPDFが添付されたメールが送信されます。