4

I am managing to save simple messages containing body, subject etc. However, I am unable to save multipart messages. I logged before and after appendMessages, but noticed that the second log is absent. Interestingly, I have no Exceptions being fired at all. I have absolutely no idea about what is going wrong here.

Here is my Java code:

    Store store = null;
    Folder folder = null;
    String folderName = "sentbox";
    try {
        Session session = prepareSession(MailProtocols.IMAP, kid);
        store = session.getStore("imap");
        store.connect(myHost, user.getLogin(), user.getPassword());
        folder = store.getFolder(folderName);

        if (folder == null || !folder.exists()) {
            folder.create(Folder.HOLDS_MESSAGES);
        }
        folder.open(Folder.READ_WRITE);
        MimeMessage mimeMessage = new MimeMessage(session);
        Address[] to = null;
        if(msg.getTo() != null) { // msg is an instance of custom message class, nothing special there
            int msgSize = msg.getTo().size();
             to = new InternetAddress[msgSize];
            for (int i = 0; i < msgSize; i++) {
                to[i] = new InternetAddress(msg.getTo().get(i));
            }
        }

        mimeMessage.setRecipients(RecipientType.TO, to);
        mimeMessage.setSentDate(new Date(System.currentTimeMillis()));
        mimeMessage.setSubject(msg.getSubject());

        if (msg.getFiles() != null) {
            MimeMultipart mp = new MimeMultipart();
            MimeBodyPart newPart = new MimeBodyPart();
            newPart.setText(msg.getBody());
            mp.addBodyPart(newPart);
            for (MultipartFile multipartFile : msg.getFiles()) {
                try {
                    newPart = new MimeBodyPart(); // create new part to each files
                    newPart.addHeader("My-File-Type", multipartFile.getContentType());
                    File tmpFile = File.createTempFile("newAttachment", ".tmp");
                    multipartFile.transferTo(tmpFile);
                    FileDataSource fds = new FileDataSource(tmpFile);
                    newPart.setDataHandler(new DataHandler(fds));
                    newPart.setFileName(multipartFile.getOriginalFilename());
                    newPart.setDisposition(Part.ATTACHMENT);
                    mp.addBodyPart(newPart);
                    tmpFile.deleteOnExit();
                } catch (IOException e) {
                    logger.debug("Can not create temp file ===========>");
                    e.printStackTrace();
                }
            }
            mimeMessage.setContent(mp);
            mimeMessage.saveChanges();
        } else {
            mimeMessage.setText(msg.getBody());
        }

        folder.appendMessages(new Message[] {mimeMessage});

        Message[] allMessages = folder.getMessages();
        UIDFolder uidFolder = (UIDFolder) folder;
        long savedMsgId = uidFolder.getUID(allMessages[allMessages.length - 1]);
                    logger.info("savedMsgId",savedMsgId + "") //cannot get this output at all

    } catch (Exception e) {
        logger.error(e);

    } finally {
        closeMailStore(store, folder); // just simple method which closes the store
    }

I am using Apache James 3.0.4. Any approaches would be welcome

boburShox
  • 2,630
  • 5
  • 23
  • 35
  • can you go in debug inside the appendMessages method? – dierre Apr 09 '13 at 06:01
  • 1
    I would look for a Throwable in the suspect area of code. If you really want to get more attention to the question, you could give us more information. You look like you have ALMOST an entire method here; extract the entire method and see if you can set up a framework around it to run outside the server. I don't know if that's feasible, but if it is you could learn a lot about it without having to go through all the server stuff. Bugs are often discovered this way, even before they get to SO. – arcy Apr 12 '13 at 03:17

3 Answers3

5

I am using Apache James 3.0.4

Don't you mean Apach James 3.0-beta4? i.e. we haven't yet reached 3.0 release, so there is no 3.0.4. Any reason you're not using the stable release (2.3.2)? Just asking... :-)

I logged before and after appendMessages, but noticed that the second log is absent.

If you never get to logging code just after folder.appendMessages(new Message[] {mimeMessage});, then there are three possibilities:

  1. An Error (or Throwable) is being thrown inside javax.mail / IO code.
    Examples include IOError (nasty IO interfacing failure), LinkageError (incompatible jars/classes) or CoderMalfunctionError (thrown by CharsetDecoder or CharsetEncoder if the decoding/encoding loop throws an unexpected exception).
  2. Thread problems cause your program to reach a standstill - i.e. thread starvation or deadlock
  3. JVM process crash

Item (1) is by far the most probable here. Suggestion: change tail-end of code to:

} catch (Exception e) {
    logger.error(e);

} catch (Throwable t) {
    logger.error(t);

} finally {
    closeMailStore(store, folder); // just simple method which closes the store
}

IF this then logs a throwable, you can investigate the cause in terms of app jars & configuration, OS/JVM version, or data content...

IF this doesn't log a throwable, you can investigate (2) or (3).

Glen Best
  • 22,769
  • 3
  • 58
  • 74
  • Thank you for explaining in detail. I'll check and let you know tomorrow, God willing. – boburShox Apr 14 '13 at 09:58
  • Couldn't catch through `Throwable`, and no success with **2** (I ascertain that there was no _deadlock_). In terms of **3**, my other colleagues are also getting the same issue(so maybe there is not any JVM process crash). Please, have a look at my comment in @Marvik's answer. I've found another way. Thanks! – boburShox Apr 18 '13 at 03:47
3

I was also getting the same error with James 2.3.2. I was using eclipse. In eclipse in library settings I added JDK in place of JRE. Then my problem was resolved. Try the same. It may work because your code looks fine and there is no problem with the code I think.

Mavrick
  • 505
  • 1
  • 7
  • 27
  • I've already tried that, actually. But I haven't been able to tackle with the issue. Then I decided to change the procedure, you know, using Mailets. There I am using `org.apache.james.mailbox.MessageManager` class and it has a method called `append`. That is working fine! :) – boburShox Apr 18 '13 at 03:38
2

I've found another way of doing this and I am putting here in the hope that I can help someone else. I am overriding Mailet's service method. And then by the aid of appendMessage method of org.apache.james.mailbox.MessageManager I can simply add my message to the folder I want. Here is my JAVA Code:

public class MyMailet extends GenericMailet {


@Resource(name = "mailboxmanager")
private MailboxManager mailboxManager;

private String sentbox;

@Override
public void init() throws MessagingException {
    super.init();     

    this.sentbox = getInitParameter("sent", "sentbox");
}


@SuppressWarnings("unchecked")
@Override
public void service(Mail mail) throws MessagingException {
    // Here, I am putting my logic which has to decide which folder to put
    // ...


    putToFolder(mail.getMessage(), mail.getSender().toString(), sentbox);

    mail.setState(Mail.GHOST);
}   

private long putToFolder(MimeMessage message, String userName, String folderName) throws MessagingException {
    MailboxSession session = null;
    long appendedMessageId;
    try {
        session = mailboxManager.createSystemSession(userName, new MailetContextLog(getMailetContext()));

        MessageManager mailbox = getMessageManager(session, userName, folderName);
        appendedMessageId = mailbox.appendMessage(new MimeMessageInputStream(message), new Date(), session, true, null);

    } catch (BadCredentialsException e) {
        throw new MessagingException("Unable to authenticate to mailbox", e);
    } catch (MailboxException e) {
        throw new MessagingException("Unable to access mailbox.", e);
    } finally {
        if (session != null) {
            session.close();
        }

        try {
            mailboxManager.logout(session, true);
            mailboxManager.endProcessingRequest(session);
        } catch (MailboxException e) {
            throw new MessagingException("Can logout from mailbox", e);
        }

    }

    return appendedMessageId;
}

private MessageManager getMessageManager(MailboxSession session, String userName, String folderName) throws MailboxException, MessagingException {
    mailboxManager.startProcessingRequest(session);

    MailboxPath path = new MailboxPath(MailboxConstants.USER_NAMESPACE, userName, folderName);

    if (!mailboxManager.mailboxExists(path, session)) {
        mailboxManager.createMailbox(path, session);
    }
    MessageManager messageManager = mailboxManager.getMailbox(path, session);
    if (messageManager == null) {
        throw new MessagingException("Mailbox for username " + userName + " was not found on this server.");
    }

    return messageManager;
  } 
}

As I expected it appends any multipart messages without a prob.

boburShox
  • 2,630
  • 5
  • 23
  • 35