Java tutorial
/** * Orignal work: Copyright 2015 www.seleniumtests.com * Modified work: Copyright 2016 www.infotel.com * Copyright 2017-2019 B.Hecquet * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.seleniumtests.connectors.mails; import java.io.IOException; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Properties; import javax.mail.BodyPart; import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.Session; import javax.mail.Store; import javax.mail.internet.MimeMessage; import javax.mail.search.SearchTerm; import org.apache.commons.lang3.StringEscapeUtils; public class ImapClient extends EmailClientImpl { private Store store; private Integer imapPort; public ImapClient(String host, String username, String password, String folder) throws MessagingException { this(host, username, password, folder, 143); } /** * Constructor * @param host server address * @param username login for server * @param password password for server * @param folder folder to read * @param imapPort port to use to connect * @param timeOffset workaround when server does not report the same time * @throws Exception */ public ImapClient(String host, String username, String password, String folder, Integer imapPort) throws MessagingException { super(); // connect to server this.imapPort = imapPort; connect(host, username, password); this.folder = folder; if (folder != null) { setLastMessageIndex(); } } /** * returns message parts * @param content * @return message parts * @throws IOException * @throws MessagingException */ private List<BodyPart> getMessageParts(Multipart content) throws IOException, MessagingException { List<BodyPart> partList = new ArrayList<>(); for (int partId = 0; partId < content.getCount(); partId++) { BodyPart part = content.getBodyPart(partId); if (part.getContentType().toLowerCase().contains("multipart/")) { partList.addAll(getMessageParts((Multipart) part.getContent())); } else { partList.add(part); } } return partList; } /** * connect to folder * @param host server address * @param username login for server * @param password password for server * @throws MessagingException */ private void connect(String host, String username, String password) throws MessagingException { // Create empty properties Properties props = new Properties(); // Get session Session session = Session.getDefaultInstance(props, null); // Get the store store = session.getStore("imap"); store.connect(host, imapPort, username, password); } /** * disconnect from server */ @Override public void disconnect() throws MessagingException { store.close(); } /** * get list of all emails in folder * * @param folderName folder to read * @param firstMessageTime date from which we should get messages * @param firstMessageIndex index of the firste message to find * @throws MessagingException * @throws IOException */ @Override public List<Email> getEmails(String folderName, int firstMessageIndex, LocalDateTime firstMessageTime) throws MessagingException, IOException { if (folderName == null) { throw new MessagingException("folder ne doit pas tre vide"); } // Get folder Folder folder = store.getFolder(folderName); folder.open(Folder.READ_ONLY); // Get directory Message[] messages = folder.getMessages(); List<Message> preFilteredMessages = new ArrayList<>(); final LocalDateTime firstTime = firstMessageTime; // on filtre les message en fonction du mode de recherche if (searchMode == SearchMode.BY_INDEX || firstTime == null) { for (int i = firstMessageIndex, n = messages.length; i < n; i++) { preFilteredMessages.add(messages[i]); } } else { preFilteredMessages = Arrays.asList(folder.search(new SearchTerm() { private static final long serialVersionUID = 1L; @Override public boolean match(Message msg) { try { return !msg.getReceivedDate() .before(Date.from(firstTime.atZone(ZoneId.systemDefault()).toInstant())); } catch (MessagingException e) { return false; } } })); } List<Email> filteredEmails = new ArrayList<>(); lastMessageIndex = messages.length; for (Message message : preFilteredMessages) { String contentType = ""; try { contentType = message.getContentType(); } catch (MessagingException e) { MimeMessage msg = (MimeMessage) message; message = new MimeMessage(msg); contentType = message.getContentType(); } // decode content String messageContent = ""; List<String> attachments = new ArrayList<>(); if (contentType.toLowerCase().contains("text/html")) { messageContent += StringEscapeUtils.unescapeHtml4(message.getContent().toString()); } else if (contentType.toLowerCase().contains("multipart/")) { List<BodyPart> partList = getMessageParts((Multipart) message.getContent()); // store content in list for (BodyPart part : partList) { String partContentType = part.getContentType().toLowerCase(); if (partContentType.contains("text/html")) { messageContent = messageContent .concat(StringEscapeUtils.unescapeHtml4(part.getContent().toString())); } else if (partContentType.contains("text/") && !partContentType.contains("vcard")) { messageContent = messageContent.concat((String) part.getContent().toString()); } else if (partContentType.contains("image") || partContentType.contains("application/") || partContentType.contains("text/x-vcard")) { if (part.getFileName() != null) { attachments.add(part.getFileName()); } else { attachments.add(part.getDescription()); } } else { logger.debug("type: " + part.getContentType()); } } } // create a new email filteredEmails.add(new Email(message.getSubject(), messageContent, "", message.getReceivedDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(), attachments)); } folder.close(false); return filteredEmails; } /** * define last message index on the server, so that on next request, we only get the newly received messages * @throws Exception */ @Override public void setLastMessageIndex() throws MessagingException { lastMessageIndex = getMessageNumber(folder); } /** * define last message index on the server * * @param messageIndex index for the reference message */ @Override public void setLastMessageIndex(int messageIndex) { lastMessageIndex = messageIndex; } @Override public int getLastMessageIndex() { return lastMessageIndex; } /** * Returns the number of messages on the server * * @param folderName * @return * @throws MessagingException */ private Integer getMessageNumber(String folderName) throws MessagingException { // Get folder Folder folder = store.getFolder(folderName); folder.open(Folder.READ_ONLY); Integer messageCount = folder.getMessageCount(); folder.close(false); return messageCount; } @Override public LocalDateTime getFromDate() { return fromDate; } @Override public void setFromDate(LocalDateTime fromDate) { this.fromDate = fromDate; } }