Badri
Badri

Reputation: 33

Spring integration IMAP- folder closed exception

I'm trying to get basic Imapmailreceiver using spring integration and i stumbled up a sticky folder closed exception. I constantly get Folder closed exception when reading the content of the email, But the I am able to get the subject correctly.

Any help is greatly appreciated.

1. My application Context is as follows

<int:channel id="emails"/>

<util:properties id="javaMailProperties">
    <prop key="mail.imap.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
    <prop key="mail.imap.socketFactory.fallback">false</prop>
    <prop key="mail.store.protocol">imaps</prop>
    <prop key="mail.debug">false</prop>
</util:properties>
<int-mail:imap-idle-channel-adapter id="mailAdapter"
                             store-uri="ACTUALCREDENTIALHERE"
                              java-mail-properties="javaMailProperties"
                              channel="emails"
                              should-delete-messages="true"
                              auto-startup="false"
                              should-mark-messages-as-read="true" />
<int:service-activator id="receiveEmail" input-channel="emails" ref="MessageReceiver"/>
<bean id="MessageReceiver" class="org.springframework.integration.mail.imapidle.MessageReceiver" />
</beans>

2. The Main APP as follows

    ApplicationContext ac = new ClassPathXmlApplicationContext("/META-INF/spring/integration/gmail.xml");


 ImapIdleChannelAdapter ic=(ImapIdleChannelAdapter)ac
    .getBean("mailAdapter");

    ic.start();

3. The service activator is as follows

public class MessageReceiver {
    public void handle(javax.mail.Message message){
        MailToStringTransformer m2s = new MailToStringTransformer();
            m2s.setCharset("utf-8");


//payload instanceof MimeMultipart
            if (message instanceof MimeMessage) {
                try {
                 System.out.println("inside mimemessagehandler");
                   // javax.mail.Message mailMessage = (javax.mail.Message) payload;
                    System.out.println(message.getSubject());
                    System.out.println(getTextFromMessage(message));

                    Address[] receipts = message.getAllRecipients();
                    System.out.println("RECEIPIENTS MAIL ID");
                    if (receipts != null && receipts.length > 0) {
                        for (int i = 0; i < receipts.length; i++) {
                            System.out.println(((InternetAddress) receipts[i]).getAddress());
                        }
                    }

                    System.out.println("FROM MAIL ID");
                    Address[] froms = message.getFrom();
                    String email = froms == null ? null
                            : ((InternetAddress) froms[0]).getAddress();
                    System.out.println(email);

                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

        }



    private static  String getTextFromMessage(javax.mail.Message message) throws Exception {
    String result = "";
    if (message.isMimeType("text/plain")) {
        result = message.getContent().toString();
    } else if (message.isMimeType("multipart/*")) {
        MimeMultipart mimeMultipart = (MimeMultipart) message.getContent();
        result = getTextFromMimeMultipart(mimeMultipart);
    }
    return result;
}

private static String getTextFromMimeMultipart(MimeMultipart mimeMultipart) throws Exception {
    String result = "";

    int count = mimeMultipart.getCount();
    System.out.println("CCC "+count);
    for (int i = 0; i < count; i++) {
       // mimeMultipart.toString()
        BodyPart bodyPart = mimeMultipart.getBodyPart(i);
        if (bodyPart.isMimeType("text/plain")) {
           result = mimeMultipart.toString();//(String) bodyPart.getContent();

        } else if (bodyPart.isMimeType("text/html")) {
            String html = (String) bodyPart.getContent();
            // result = result + "\n" + org.jsoup.Jsoup.parse(html).text();
        } else if (bodyPart.getContent() instanceof MimeMultipart) {
            result = result + getTextFromMimeMultipart((MimeMultipart) bodyPart.getContent());
        }
    }
    return result;
}

}

--- EXCEPTION

javax.mail.FolderClosedException

      at javax.mail.internet.MimeBodyPart.getContent(MimeBodyPart.java:659)
      at org.springframework.integration.mail.imapidle.MessageReceiver.getTextFromMimeMultipart(MessageReceiver.java:101)
      at org.springframework.integration.mail.imapidle.MessageReceiver.getTextFromMessage(MessageReceiver.java:83)
      at org.springframework.integration.mail.imapidle.MessageReceiver.handle(MessageReceiver.java:41)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at 

Upvotes: 3

Views: 2976

Answers (1)

Artem Bilan
Artem Bilan

Reputation: 121272

Well, looks like we can't get content from the MimeBodyPart if Folder is closed already. And looks like we have exactly this situation in the AbstractMailReceiver.receive() :

            }
                return converted;
            }
            else {
                return filteredMessages;
            }
        }
        finally {
            MailTransportUtils.closeFolder(this.folder, this.shouldDeleteMessages);
        }

Not sure why we close folder there after receiving but before sending dowstream, nevertheless I'd suggest you to try with the DefaultMailHeaderMapper for the ImapMailReceiver. In that case the content of the MimeMessage is converted to the org.springframework.messaging.Message internally in the mentioned AbstractMailReceiver.receive():

if (this.headerMapper != null) {
                org.springframework.messaging.Message<?>[] converted =
                        new org.springframework.messaging.Message<?>[filteredMessages.length];
                int n = 0;
                for (MimeMessage message : filteredMessages) {
                    Map<String, Object> headers = this.headerMapper.toHeaders(message);
                    converted[n++] = getMessageBuilderFactory().withPayload(extractContent(message, headers))
                            .copyHeaders(headers)
                            .build();
                }
                return converted;
            }

Meanwhile, please, raise a JIRA on the matter and we consider to fix that Folder.close() inconsistency. In my best feeling that should not be done at all or we should provide it for end-user as a header to let him/her decide when and where to close the folder if that.

Upvotes: 1

Related Questions