grailsmime-mail

Mime Message could not be parsed


I have following mime message:

Return-Path: <some@adress.com>
X-Original-To: some@adress.com
Delivered-To: some@adress.com
Received: from localhost [127.0.0.1]
    by unify-prod with POP3 (fetchmail-6.3.21)
    for <other@localhost> (single-drop); Mon, 03 Aug 2015 12:42:24+0000 (UTC)
Received: from testdomain.com (testdomain.com [192.69.176.183])
    by unify.test.com (Postfix) with ESMTPS id AA3874330B
    for <test@test.com>; Mon,  3 Aug 2015 12:42:23 +0000 (UTC)
 Received: from test.call (test.call [10.3.1.49])
    by test.com (Postfix) with ESMTP id 56EC73BA8C4
    for <test@test.com>; Mon,  3 Aug 2015 12:42:23 +0000 (UTC)
Date: Mon, 3 Aug 2015 12:42:23 +0000 (UTC)
From: test@test.com
To: test@test.com
Message-ID: <385098705.398991.1438605743348.JavaMail.sd@sdapp04>
Subject: Update
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 7bit



|0004625641|
|630805367|
|NA14220388|
|03.08.2015 14:42:23|


||

I want to parse the message in grails with this code:

InputStream mailFileInputStream = new FileInputStream("/home/peter/test.msg");
    Properties props = new Properties();
    Session session = Session.getDefaultInstance(props, null);
    MimeMessage message = new MimeMessage(session, mailFileInputStream);

    MimeMessageParser parser = new MimeMessageParser(message)
    parser.parse()


    def data = [:]
    data.from = parser.getFrom()
    data.to = parser.getTo()
    data.replyTo = parser.getReplyTo()
    data.html = parser.getHtmlContent()
    data.plain = parser.getPlainContent()
    data.subject = parser.getSubject()
    data.attachments = parser.getAttachmentList()

But the message is not parsed correctly. The whole message is in the plain content. What is the problem with this message?

Best regards, Peter


Solution

  • When I tried to parse the message I got this exception:

    java.lang.ClassCastException: javax.mail.util.SharedByteArrayInputStream cannot be cast to java.lang.String
        at org.apache.commons.mail.util.MimeMessageParser.parse(MimeMessageParser.java:181)
        at org.apache.commons.mail.util.MimeMessageParser.parse(MimeMessageParser.java:96)
        at org.apache.commons.mail.util.MimeMessageParser$parse.call(Unknown Source)
    

    The problem is that MimeMessageParser is trying to coerce an Object into a String. You can see this in the source code on line 181. The object is an instance of javax.mail.util.SharedByteArrayInputStream, and it's not going to return the contents through coercion. My example uses a StringBufferInputStream as the input, so that may play a part in the problem.

    Work-around

    To work around this issue, I overrode MimeMessage.getContent() so it returns the plain-text content. So obviously, don't do this with non-plain-text content. Here's the complete script:

    @Grab('org.apache.commons:commons-email:1.4')
    
    import javax.mail.Session
    import javax.mail.internet.MimeMessage
    import org.apache.commons.mail.util.MimeMessageParser
    
    def input = '''Return-Path: <some@adress.com>
    X-Original-To: some@adress.com
    Delivered-To: some@adress.com
    Received: from localhost [127.0.0.1]
        by unify-prod with POP3 (fetchmail-6.3.21)
        for <other@localhost> (single-drop); Mon, 03 Aug 2015 12:42:24+0000 (UTC)
    Received: from testdomain.com (testdomain.com [192.69.176.183])
        by unify.test.com (Postfix) with ESMTPS id AA3874330B
        for <test@test.com>; Mon,  3 Aug 2015 12:42:23 +0000 (UTC)
     Received: from test.call (test.call [10.3.1.49])
        by test.com (Postfix) with ESMTP id 56EC73BA8C4
        for <test@test.com>; Mon,  3 Aug 2015 12:42:23 +0000 (UTC)
    Date: Mon, 3 Aug 2015 12:42:23 +0000 (UTC)
    From: test@test.com
    To: test@test.com
    Message-ID: <385098705.398991.1438605743348.JavaMail.sd@sdapp04>
    Subject: Update
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 7bit
    
    
    
    |0004625641|
    |630805367|
    |NA14220388|
    |03.08.2015 14:42:23|
    
    
    ||'''
    
    // Creates a MimeMessage that makes MimeMessageParser happy.
    MimeMessage createMimeMessage(InputStream stream) {
        def getContent = MimeMessage.metaClass.getMetaMethod('getContent')
        def message = new MimeMessage(
            Session.getDefaultInstance(new Properties()), 
            stream)
    
        /*
         * Override MimeMessage.getContent()
         * to coerce SharedByteArrayInputStream
         * into a String. Groovy does it automatically :)
         */
        message.metaClass.getContent = {
            getContent.invoke(delegate)
        }
    
        return message
    }
    
    def message = createMimeMessage(new StringBufferInputStream(input))
    def parser = new MimeMessageParser(message)
    
    parser.parse()
    
    def data = parser.with {
        [
            from: from,
            to: to,
            replyTo: replyTo,
            html: htmlContent,
            plain: plainContent,
            subject: subject,
            attachments: attachmentList,
        ]
    }
    
    assert data.from == 'test@test.com'
    assert data.to instanceof List
    assert data.replyTo == 'test@test.com'
    assert data.html == null
    assert data.attachments == []
    assert data.plain instanceof String
    

    The data Map contains the following:

    [from:test@test.com, to:[test@test.com], replyTo:test@test.com, html:null, plain:
    
    |0004625641|
    |630805367|
    |NA14220388|
    |03.08.2015 14:42:23|
    
    
    ||, subject:Update, attachments:[]]