Mime4j: DefaultMessageBuilder не в состоянии проанализировать содержимое mbox

Я скачал mime4j 0.8.0 снимок с subversion и построил его с maven, Соответствующие банки, которые я создал, можно найти здесь.

Теперь я пытаюсь разобрать файл игрушки mbox из mime4j тестовое задание.

Я использую этот пример кода. Кратко:

final File mbox = new File("c:\\mbox.rlug");
int count = 0;
for (CharBufferWrapper message : MboxIterator.fromFile(mbox).charset(ENCODER.charset()).build()) {
    System.out.println(messageSummary(message.asInputStream(ENCODER.charset())));
    count++;
}
System.out.println("Found " + count + " messages");

+

private static String messageSummary(InputStream messageBytes) throws IOException, MimeException {
    MessageBuilder builder = new DefaultMessageBuilder();
    Message message = builder.parseMessage(messageBytes);
    return String.format("\nMessage %s \n" +
            "Sent by:\t%s\n" +
            "To:\t%s\n",
            message.getSubject(),
            message.getSender(),
            message.getTo());
}

Выход:

Сообщение null Отправлено: null Кому: null

Сообщение null Отправлено: null Кому: null

Сообщение null Отправлено: null Кому: null

Сообщение null Отправлено: null Кому: null

Сообщение null Отправлено: null Кому: null

Найдено 5 сообщений

Сообщений действительно 5, но почему все поля пусты?

3 ответа

Решение

Я нашел проблему.

DefaultMessageBuilder не в состоянии анализировать файлы mbox, которые имеют разделитель строк Windows \r\n, При замене их на разделитель строк UNIX \n разбора работает.

Это критическая проблема, так как файлы mbox, загруженные с Gmail использование \r\n,

Основываясь на ответе @zvisofer, я нашел виновный кусок кода в BufferedLineReaderInputStream:

@Override
public int readLine(final ByteArrayBuffer dst)
        throws MaxLineLimitException, IOException {
    if (dst == null) {
        throw new IllegalArgumentException("Buffer may not be null");
    }
    if (!readAllowed()) return -1;

    int total = 0;
    boolean found = false;
    int bytesRead = 0;
    while (!found) {
        if (!hasBufferedData()) {
            bytesRead = fillBuffer();
            if (bytesRead == -1) {
                break;
            }
        }
        int i = indexOf((byte)'\n');
        int chunk;
        if (i != -1) {
            found = true;
            chunk = i + 1 - pos();
        } else {
            chunk = length();
        }
        if (chunk > 0) {
            dst.append(buf(), pos(), chunk);
            skip(chunk);
            total += chunk;
        }
        if (this.maxLineLen > 0 && dst.length() >= this.maxLineLen) {
            throw new MaxLineLimitException("Maximum line length limit exceeded");
        }
    }
    if (total == 0 && bytesRead == -1) {
        return -1;
    } else {
        return total;
    }
}

Лучше всего сообщить об ошибке, но здесь есть исправление, немного грязное, но работает нормально

Создать класс org.apache.james.mime4j.io.BufferedLineReaderInputStream в вашем проекте

Заменить метод public int readLine(final ByteArrayBuffer dst) этим:

@Override
public int readLine(final ByteArrayBuffer dst)
        throws MaxLineLimitException, IOException {
    if (dst == null) {
        throw new IllegalArgumentException("Buffer may not be null");
    }
    if (!readAllowed()) return -1;

    int total = 0;
    boolean found = false;
    int bytesRead = 0;
    while (!found) {
        if (!hasBufferedData()) {
            bytesRead = fillBuffer();
            if (bytesRead == -1) {
                break;
            }
        }

        int chunk;
        int i = indexOf((byte)'\r');
        if (i != -1) {
            found = true;
            chunk = i + 2 - pos();
        } else {
            i = indexOf((byte)'\n');
            if (i != -1) {
                found = true;
                chunk = i + 1 - pos();
            } else {
                chunk = length();
            }
        }
        if (chunk > 0) {
            dst.append(buf(), pos(), chunk);
            skip(chunk);
            total += chunk;
        }
        if (this.maxLineLen > 0 && dst.length() >= this.maxLineLen) {
            throw new MaxLineLimitException("Maximum line length limit exceeded");
        }
    }
    if (total == 0 && bytesRead == -1) {
        return -1;
    } else {
        return total;
    }
}

Наслаждайтесь как Unix, так и DOS файлами:)

Я скачал ваши jar-файлы, пример кода, на который вы указали, и пример файла mbox, на который вы указали, скомпилировал образец (без изменений) и запустил его для файла примера mbox.

Он работал как ожидалось (поля содержали ожидаемые данные, а не нули). Это было на Mac с Java 1.6_0_65, а также с 1.8.0_11

Вывод был следующим:

$ java -cp.: apache-mime4j-core-0.8.0-SNAPSHOT.jar: apache-mime4j-dom-0.8.0-SNAPSHOT.jar: apache-mime4j-mbox-iterator-0.8.0-SNAPSHOT.jar IterateOverMbox mbox.rlug.txt

Сообщение Din windows ma pot, din LINUX NU ma pot conecta (la ZAPP) Отправлено: rlug-bounce@lug.ro Кому: [rlug@lug.ro]

Сообщение Re: загрузочная дискета RH 8.0. Отправлено: rlug-bounce@lug.ro Кому: [rlug@lug.ro]

Сообщение Qmail mysql virtualusers +ssl + smtp auth +pop3 Отправлено: rlug-bounce@lug.ro Кому: [rlug@lug.ro]

Сообщение Re: Din windows ma pot, din LINUX NU ma pot conecta (la ZAPP) Отправлено: rlug-bounce@lug.ro Кому: [rlug@lug.ro]

Сообщение LSTP проблема - решена Отправлено: rlug-bounce@lug.ro Кому: [rlug@lug.ro]

Найдено 5 сообщений Сделано в: 108 milis

Другие вопросы по тегам