javajakarta-mailimap

Java Mail IMAP taking lot of time to getting messages in mail box, 25s to get 20 messages


There is a way to improve the performance for getting messages from the Javamail IMAP server? i found some tips, but couldn't improve the performance. This method will get about 20 messages from a folder, and returning the formatted messages to a DTO, I tried to comment the lines to get attachments, and getting the recipients, but it doensnt change anything in the performance.

/**
 * Get all the emails that are inside the param folder
 *
 * @param folderId   folder to return the emails from the informed folder.
 * @param pageToken  pageToken to be used as pagination
 * @param maxResults maxResults to create a limit to the number of registers
 * @return {@link EmailsDTO} with all the messages
 */
public EmailsDTO getMessages(final String folderId, final String pageToken, final Integer maxResults) {
    final Properties properties = getServerInputProperties();
    final Session session = Session.getDefaultInstance(properties);
    try {
        final EmailsDTO emailsDTO = new EmailsDTO();
        final List<EmailDTO> emailDTOList = new ArrayList<>();

        // connects to the message store
        final Store store = session.getStore(IMAP);
        store.connect(email, password);

        // opens the folder to search the messages
        final Folder folder = store.getFolder(folderId);
        folder.open(Folder.READ_ONLY);

        //set a pagination used to get the results in JavaMail
        final int pageStart = nonNull(pageToken) ? Integer.valueOf(pageToken) : 1;
        final int pageEnd = (pageStart + maxResults) > folder.getMessageCount() ? folder.getMessageCount() : pageStart + maxResults;


        // fetches new messages from server, starts with 1
        final Message[] messages = folder.getMessages(pageStart, pageEnd);

        final FetchProfile fetchProfile  = new FetchProfile();
        fetchProfile.add(FetchProfile.Item.ENVELOPE);
        folder.fetch(messages, fetchProfile); // Load the profile of the messages in 1 fetch.

        for (final Message msg : messages) {
            final EmailDTO emailDTO = new EmailDTO();
            emailDTO.setId(msg.getHeader(MESSAGE_ID)[0]);
            emailDTO.setCc(this.parseAddresses(msg.getRecipients(Message.RecipientType.CC)));
            emailDTO.setTo(this.parseAddresses(msg.getRecipients(Message.RecipientType.TO)));
            emailDTO.setBcc(this.parseAddresses(msg.getRecipients(Message.RecipientType.BCC)));

            emailDTO.setFrom(this.getFrom(msg.getFrom()));
            emailDTO.setRead(msg.getFlags().contains(Flags.Flag.SEEN));
            emailDTO.setHasAttachments(this.hasAttachments(msg));
            emailDTO.setSubject(msg.getSubject());
            emailDTO.setMessage(this.getMessageContent(msg));

            emailDTO.setAttachments(this.getAttachements(msg));
            emailDTO.setDate(msg.getReceivedDate().toString());
            emailDTO.setParentFolder(msg.getFolder().getName());
            //TODO: see what need to put here emailDTO.setLabels();
            emailDTOList.add(emailDTO);
        }

        // disconnect
        folder.close(false);
        store.close();

        emailsDTO.setEstimatedNumberOfMessages(folder.getMessageCount());
        emailsDTO.setNextPageToken(String.valueOf(emailDTOList.size()));
        emailsDTO.setMessages(emailDTOList);
        return emailsDTO;
    } catch (final MessagingException | IOException e) {
        throw new RuntimeException(String.format("couldn't get messages from the folder with id: %s", folderId), e);
    }
}

Solution

  • In for (final Message msg : messages), change messages to folder.getMessages().

    messages -> loads multiple times

    folder.getMessages() -> loads in a single fetch, because you have used fetchProfile in this.