Парсим MIME сообщение в Java

В данном уроке я хочу вам показать как можно распарсить mime сообщение присланное по email.

По просьбе одного из читателей блога я решил показать вам каким образом можно распарсить письмо полученное по email.

Шаг 1.

Для начало нам нужно как то получить подопытное письмо, для этого я воспользовался инструментом Denwer для того, что бы отправить письмо и получить его в формате *.eml вы это можете и не делать, просто скачайте прилагаемый к уроку исходник и он там есть, но кто желает делать все сам, то к делу.

Я воспользовался php скриптом для того, чтобы сформировать простое mail сообщение и отправил его, так как я использовал denwer то письмо не ушло в сеть получателю а положилось локально в c:\WebServers\tmp\!sendmail тут будут лежать все письма отправлены с denwer.

Собственно и сам php скрипт:

 <?php
    $to  = "Alex <alex@devcolibri.com>, " ;
    $to .= "Vika <vikki@devcolibri.com>";

    $subject = "This subject!";

    $message = '<h1>This is text - devcolibri.com</h1>';

    $headers  = "Content-type: text/html; charset=windows-1251 \r\n";
    $headers .= "From: Birthday Reminder <tmp@devcolibri.com>\r\n";
    $headers .= "Bcc: tmp-archive@devcolibri.com\r\n";

    mail($to, $subject, $message, $headers);
?>

После того как скрипт отработает, то вы на c:\WebServers\tmp\!sendmail найдете файл, у меня он называется так (2013-05-05_22-09-52.eml) в уже позже я его для удобства переименовал на (testmail.eml).

Содержимое файла (testmail.eml) получилось следующим:

X-Sendmail-Cmdline: sendmail.pl -t -i
To: Alex <alex@devcolibri.com>, Vika <vikki@devcolibri.com>
Subject: This subject!
X-PHP-Originating-Script: 0:index.php
Content-type: text/html; charset=windows-1251 
From: Birthday Reminder <tmp@devcolibri.com>
Bcc: tmp-archive@devcolibri.com

<h1>This is text - devcolibri.com</h1>

Шаг 2.

Для того, чтобы распарсить *.eml файл я использовал mime4j.0.6.1, более свежие версии являются урезанными.

Давайте создадим maven проект и добавим зависимость:

<dependency>
    <groupId>org.apache.james</groupId>
    <artifactId>apache-mime4j</artifactId>
    <version>0.6.1</version>
</dependency>

После чего мы можем использовать средства Mime4j.

Шаг 3.

Теперь создадим класс MailParser.java со следующим содержимым:

package com.devcolibri.utility;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.james.mime4j.message.BinaryBody;
import org.apache.james.mime4j.message.BodyPart;
import org.apache.james.mime4j.message.Entity;
import org.apache.james.mime4j.message.Message;
import org.apache.james.mime4j.message.Multipart;
import org.apache.james.mime4j.message.TextBody;
import org.apache.james.mime4j.parser.Field;

public class MailParser {

    private StringBuffer txtBody;
    private StringBuffer htmlBody;
    private ArrayList<BodyPart> attachments;

    public void parse(String fileName) {
        FileInputStream file = null;

        txtBody = new StringBuffer();
        htmlBody = new StringBuffer();
        attachments = new ArrayList<BodyPart>();

        try {
            //получаем поток из файла
            file = new FileInputStream(fileName);
            //Создаем Message на основе потока файла
            Message mimeMsg = new Message(file);

            //Получаем стандартные заголовки
            System.out.println("To: " + mimeMsg.getTo());
            System.out.println("From: " + mimeMsg.getFrom());
            System.out.println("Subject: " + mimeMsg.getSubject());

            //Получение собственных заголовков по имени
            Field priorityFld = mimeMsg.getHeader().getField("X-Priority");
            //если заголовок не найден, то возвращаем null
            if (priorityFld != null) {
                System.out.println("Priority: " + priorityFld.getBody());
            }

            //Если сообщение содержит много частей, то разбираем все части
            if (mimeMsg.isMultipart()) {
                Multipart multipart = (Multipart) mimeMsg.getBody();
                parseBodyParts(multipart);
            } else {
                //если сообщение состоит с одной части, то просто выводим тело сообщения
                String text = getTxtPart(mimeMsg);
                txtBody.append(text);
            }

            //Выводим текст сообщение и HTML теги
            System.out.println("Text body: " + txtBody.toString());
            System.out.println("Html body: " + htmlBody.toString());

            for (BodyPart attach : attachments) {
                String attName = attach.getFilename();
                //Создайте файл с указанным именем
                FileOutputStream fos = new FileOutputStream(attName);
                try {
                    //Получаем поток прикрепленных файлов и записываем из в файл
                    BinaryBody bb = (BinaryBody) attach.getBody();
                    bb.writeTo(fos);
                } finally {
                    fos.close();
                }
            }

        } catch (IOException ex) {
            ex.fillInStackTrace();
        } finally {
            if (file != null) {
                try {
                    file.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    // Этот метод парсит прикрепленные файлы
    private void parseBodyParts(Multipart multipart) throws IOException {
        for (BodyPart part : multipart.getBodyParts()) {
            if (part.isMimeType("text/plain")) {
                String txt = getTxtPart(part);
                txtBody.append(txt);
            } else if (part.isMimeType("text/html")) {
                String html = getTxtPart(part);
                htmlBody.append(html);
            } else if (part.getDispositionType() != null && !part.getDispositionType().equals("")) {
                //Если DispositionType равен null или empty, это значит, что прикреплённые файлы отсуствуют
                attachments.add(part);
            }

            //Если сообщение содержит несколько прикрепленных файлов то вызываем метод рекурсивно
            if (part.isMultipart()) {
                parseBodyParts((Multipart) part.getBody());
            }
        }
    }

    private String getTxtPart(Entity part) throws IOException {
        //Получаем тело содержимого
        TextBody tb = (TextBody) part.getBody();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        tb.writeTo(baos);
        return new String(baos.toByteArray());
    }

}

В комментариях исходного кода я попытался объяснить основные момент, что не понятно пишите в комментариях я растолкую :)

Шаг 4.

Теперь создаем класс Main.java со следующим содержимым:

package com.devcolibri.enterpoint;

import com.devcolibri.utility.MailParser;

public class Main {

    public static void main(String[] args) {

        String eml = "testmail.eml";

        MailParser parser = new MailParser();
        parser.parse(eml);
    }

}

Результат выполнения:

To: [Alex <alex@devcolibri.com>, Vika <vikki@devcolibri.com>]
From: [Birthday Reminder <tmp@devcolibri.com>]
Subject: This subject!
Text body: <h1>This is text - devcolibri.com</h1>
Html body:

p.s. Что не понятно спрашивайте в комментариях.

Урок создан: 05 мая 2013 | Просмотров: 7521 | Автор: Александр Барчук | Правила перепечатки


Добавить комментарий

Добавить комментарий

Ваш e-mail не будет опубликован.

Комментарии:

Комментариев пока нет, будьте первым.