Парсинг электронной почты - PullRequest
       10

Парсинг электронной почты

0 голосов
/ 05 сентября 2018

Я пытаюсь разбить почтовые файлы, как этот:

Message-ID: <53197.1075859003723.JavaMail.evans@thyme>
Date: Tue, 23 Oct 2001 10:31:09 -0700 (PDT)
From: scott.dozier@enron.com
To: tom.donohoe@enron.com, bonnie.chang@enron.com, m..love@enron.com
Subject: RE: CMS Deal #1027152
Cc: lisa.valderrama@enron.com, thomas.mcfatridge@enron.com
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Bcc: lisa.valderrama@enron.com, thomas.mcfatridge@enron.com
X-From: Dozier, Scott </O=ENRON/OU=NA/CN=RECIPIENTS/CN=SDOZIER>
X-To: Donohoe, Tom </O=ENRON/OU=NA/CN=RECIPIENTS/CN=Tdonoho>, Chang, Bonnie </O=ENRON/OU=NA/CN=RECIPIENTS/CN=Bchang>, Love, Phillip M. </O=ENRON/OU=NA/CN=RECIPIENTS/CN=Plove>
X-cc: Valderrama, Lisa </O=ENRON/OU=NA/CN=RECIPIENTS/CN=Lvalde2>, McFatridge, Thomas </O=ENRON/OU=NA/CN=RECIPIENTS/CN=Tmcfatri>
X-bcc: 
X-Folder: \TDONOHO (Non-Privileged)\Inbox
X-Origin: Donohoe-T
X-FileName: TDONOHO (Non-Privileged).pst

I am not sure if they have confirmed either deal.  However, deal #1034254 was never pathed by us, whereas 1027152 was.  Therefore, nothing billed out under 1034254.

Bonnie - I am including you on this note in case you can add anything about the pathing of the two deals mentioned in this note.  Niether CMS orgaination shows anything on Trunkline that matches this.  We spoke briefly about this last week.

Phillip - I am including you in case you can add any clarity or determine who we did this deal(s) with.

Thank you,
Scott
5-7213

 -----Original Message-----
From:   Donohoe, Tom  
Sent:   Tuesday, October 23, 2001 12:02 PM
To: Dozier, Scott
Subject:    RE: CMS Deal #1027152

if they are not confirming this deal are they confirming 1034254?

 -----Original Message-----
From:   Dozier, Scott  
Sent:   Tuesday, October 23, 2001 9:24 AM
To: Donohoe, Tom
Cc: Valderrama, Lisa; McFatridge, Thomas
Subject:    RE: CMS Deal #1027152
Importance: High

Tom,

In contacting our scheduler and subsequently a CMS scheduler, neither CMS Field Services nor CMS Marketing, Services, and Trading are able to identify the deal.  Currently, I am preparing to fax a copy of our confirmation on the deal to CMS Field Services,  Again, it is not an executed copy, but I am assuming they may not have sent it back.  Furthermore, the CMS Field Services scheduler has told me that they don't even schedule any Trunkline deals.

Considering all of this, I am assuming the worst - that unless we can provide a trader name etc. they will short pay on this deal.  So, do you know who represented us with CMS on this deal any one that might know who their trader is or how this deal was booked?  We are getting ready to settle for Sep prod so any help asap would be appreciated.

Scott
5-7213

 -----Original Message-----
From:   Dozier, Scott  
Sent:   Thursday, October 18, 2001 12:21 PM
To: Donohoe, Tom
Subject:    RE: CMS Deal #1027152

They do not recognize that deal at all.

The most recent name and number is a Conoco trader.  I have a confirmation on this deal with CMS.  However, it is not an executed copy (i.e. sent back or confirmed by CMS).  Is there some one who represented us with CMS on this that might know who their trader is or how this deal was booked?  I will attempt to contact the scheduler in the mean time but any help would be good.

thanks.

во многих подобных файлах:

Header
Body
Original message 1
Original message 2 
...

Я уже читал некоторые посты о разделении писем, и кажется, что использование Mime4j должно быть хорошей идеей. Итак, я сделал это:

public class test {

    public static void main(String[] args) throws IOException, MimeException {
        // TODO Auto-generated method stub
        MimeTokenStream stream = new MimeTokenStream();
        stream.parse(new FileInputStream("test"));
        File header = new File ("header");
        File body = new File ("body");
        BufferedWriter headerWriter = new BufferedWriter(new FileWriter(header));
        BufferedWriter bodyWriter = new BufferedWriter(new FileWriter(body));
        String str;
        for (EntityState state = stream.getState();
                state != EntityState.T_END_OF_STREAM;
                state = stream.next()) {
            switch (state) {
              case T_BODY:
                  str = stream.getInputStream().toString();
                  bodyWriter.write(str);
                break;
              case T_FIELD:
                  str = stream.getField().toString() + "\n";
                  headerWriter.write(str);
                break;
            }
          }
        headerWriter.close();
        bodyWriter.close();

    }

}

Этот код корректно разделяет почту на два файла: заголовок и текст. Возможно, есть лучший способ сделать это, но я нахожу, что Javadoc Mime4j не очень полезен ... ну, я все еще пытаюсь полностью понять, как это работает.

Однако у меня есть две проблемы:

1) Тело начинается с линии, явно созданной Mime, которая выглядит следующим образом:

[LineReaderInputStreamAdaptor: [pos: 937][limit: 4096][

и я не знаю, как от этого избавиться.

2) «Оригинальные сообщения» находятся в теле. Я не знаю, как разделить тело на несколько частей в соответствии с этими «оригинальными сообщениями». Более того, все письма не имеют этого формата. Иногда исходные сообщения «открываются» только через табуляцию, или символ> перед каждой строкой, или просто с помощью небольшого заголовка «от, до», или с другой строкой, такой как ------- перенаправлено ----- --- и т.д ... Так что я не могу разделить его, используя формат.

Я думал, что Mime4j должен распознавать эти части как сообщения "Multipart", но, похоже, нет (был случай T_START_MULTIPART, но он ничего не нашел.)

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Вы получаете этот странно выглядящий текст из stream.getInputStream().toString();, который вы записываете в заголовочный файл.

Метод toString() в основном предназначен для отладки. Вызывая это на InputStream, вы получите не содержимое потока (а это может быть много), а просто описание этого потока, и вот что вы видите.

Чтобы получить данные этого потока, вам необходимо прочитать их из входного потока и скопировать в выходной поток. См. этот ответ для различных способов сделать это.

Что касается исходных сообщений: ваш пример - одно сообщение электронной почты. Он имеет только 1 часть MIME, часть с открытым текстом. Люди просто скопировали исходное сообщение и поместили свой ответ поверх сообщения, на которое они отвечают.

Если бы они перенаправили сообщение как вложение, структура MIME выглядела бы иначе: вы бы увидели Content-Type: multipart/mixed; boundary="...", а затем этот граничный текст разделил бы отдельные сообщения. Возможно, Apache James обнаружит их и правильно с ними справится.

MIME multipart используется для вложений или для альтернативных частей электронного письма (простой текст или html). Это не относится к тем, кто публикует свои ответы.

Поскольку в вашем электронном письме-примере отсутствует структура MIME, лучше всего вручную проанализировать тело письма и найти -----Original Message-----. Обратите внимание, что это хрупко (вы не знаете, что могут использовать почтовые клиенты людей, люди могут изменить это вручную (может быть, случайно)).

import org.apache.james.mime4j.stream.*;
import static org.apache.james.mime4j.stream.MimeTokenStream.*;
import java.io.*;

public class Library {
    private static final String SEP = " -----Original Message-----";
    private static final String CRLF = "\r\n";

    static int fileNo = 0;

    public static void main(String[] args) throws Exception {
        MimeTokenStream stream = new MimeTokenStream();
        stream.parse(new FileInputStream(args[0]));
        try (BufferedWriter headerWriter = new BufferedWriter(new FileWriter("header"))) {
            for (EntityState state = stream.getState();
                    state != EntityState.T_END_OF_STREAM;
                    state = stream.next()) {
                switch (state) {
                case T_BODY:
                    writePart(new BufferedReader(new InputStreamReader(stream.getInputStream())));
                    break;
                case T_FIELD:
                    headerWriter.write(stream.getField().toString());
                    headerWriter.write(CRLF);
                    break;
                }
            }
        }
    }

    private static void writePart(BufferedReader in) throws Exception {
        BufferedWriter out = null;
        try {
            out = new BufferedWriter(new FileWriter(fileNo + ".eml"));
            String line = in.readLine();
            while (line != null) {
                if (SEP.equals(line)) {
                    out.close();
                    fileNo++;
                    out = new BufferedWriter(new FileWriter(fileNo + ".eml"));
                }
                out.write(line);
                out.write(CRLF);
                line = in.readLine();
            }
        }
        finally {
            out.close();
        }
    }
}
0 голосов
/ 05 сентября 2018

В вашем примере все, что находится после последнего заголовка, является частью тела. Почтовый клиент имеет контроль над этим (то есть outlook может добавить этот оригинальный разделитель сообщений, куда другие клиенты могут добавлять отступы ... и это будет меняться в зависимости от настроек клиента и / или языка), поэтому ваше решение может легко сломаться. Проверьте тип контента. Если это простой текст, вам нужно отсканировать тело, чтобы выяснить, как оно сегментировано. (Исходное сообщение НЕ является границей пантомимы.) Затем вы примените другие правила для разделения сообщения (см. Ресурс outlook ниже). Вам также нужно будет поддерживать multipart (потому что встроенные электронные письма, вероятно, будут проходить таким образом). И затем вы поймете, что у вас может вообще не быть заголовков контента.

Вот несколько ресурсов для вас

...