【Java初心者】添付ファイル付きのメール処理

# ビジネスシーンでは電子メール処理は現役

前回の記事 https://qiita.com/sev01/items/6c8ea0c1a82324341fdd ではメールの送信をしましたが、受信したメールを保存し、そこからデータを抽出することは日常業務の中でよく使われます。

# マルチパートって色々あります

マルチパートの中に、さらにマルチパートとなっていることがあります。
つまり、入れ子になっていることがあるため、ある種の再起処理が必要になります。

# 添付ファイルの名前が文字化けする問題に遭遇

JavaMailのMimeUtility.decodeText を利用します。

# 例

```java

package mailreceivetest;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.StringJoiner;
import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Multipart;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

public class MailRecieveTest {

    /**
     * @param args the command line arguments
     * @throws javax.mail.NoSuchProviderException
     * @throws java.io.IOException
     */
    public static void main(String[] args) throws NoSuchProviderException, MessagingException, IOException {

        String host = "XXXXXXXX.jp";
        int port = 993;
        String user = "<ユーザー名>";
        String password = "<パスワード>";

        String target_folder = "INBOX";
        
        Properties props = System.getProperties();
        Session session = Session.getInstance(props, null);
        session.setDebug(false); // trueにするとサーバーとのやりとりが見られます

        try ( Store store = session.getStore("imaps")) {
            store.connect(host, port, user, password);
            Folder inboxFolder = store.getFolder(target_folder);
            if (inboxFolder.exists()) {
                inboxFolder.open(Folder.READ_ONLY); // Folder.READ_WRITEすると読み書き
                for (Message message : inboxFolder.getMessages()) {
                    String subject = message.getSubject();
                    System.out.println("タイトル:" + MimeUtility.decodeText(subject));
                    Object objContent = message.getContent();
                    if (objContent instanceof Multipart) {
                        System.out.println("親マルチパート");
                        MimeMultipart mmp = (MimeMultipart) message.getContent();
                        int multipartCount = mmp.getCount();
                        System.out.println("パートの数:" + multipartCount);
                        for (int i = 0; i < multipartCount; i++) {
                            System.out.println(saveMultiPart(mmp.getBodyPart(i)));
                        }
                    } else {
                        System.out.println("マルチパートではない");
                    }
                    // message.setFlag(Flags.Flag.DELETED, true); // 消去フラグ
                }
                inboxFolder.close(false); // trueにするとフラグが反映される
            } else {
                System.out.printf("%s というフォルダーはありません。", target_folder);
            }
        }

    }

    /**
     * マルチパートのファイルを保存しテキストパートの内容を出力
     *
     * @param bodyPart
     * @return
     */
    static String saveMultiPart(BodyPart bodyPart) {
        StringJoiner sj = new StringJoiner(System.lineSeparator());
        try {
            String contentType = bodyPart.getContentType();
            System.out.println("ContentType:" + contentType);
            if (bodyPart.isMimeType("text/plain")) {
                sj.add(bodyPart.getContent().toString());
            }
            if (bodyPart.isMimeType("text/html")) {
                System.out.println("HTMLパートです");
            }
            if (bodyPart.isMimeType("multipart/alternative")) {
                System.out.println("多重マルチパート");
                Object objContent = bodyPart.getContent();
                if (objContent instanceof Multipart) {
                    Multipart name = (Multipart) objContent;
                    int multiPartCount = name.getCount();
                    for (int i = 0; i < multiPartCount; i++) {
                        System.out.println("子マルチパート:" + i);
                        sj.add(saveMultiPart(name.getBodyPart(i)));
                    }

                } else {
                    System.err.println("マルチパートが抽出できませんでした");
                }
            }
            String fileName = bodyPart.getFileName();
            if (fileName != null) {
                String jfileName = MimeUtility.decodeText(fileName);
                System.out.println("保存します:" + jfileName);
                try ( InputStream ins = bodyPart.getInputStream();
                        OutputStream outs = new BufferedOutputStream(new FileOutputStream(jfileName))) {
                    int out;
                    while ((out = ins.read()) != -1) {
                        outs.write(out);
                    }
                }
            }
        } catch (IOException | MessagingException ex) {
            System.err.println("ERR:" + ex.getMessage());
        }
        return sj.toString();
    }
}

```