All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.seleniumtests.connectors.mails.ImapClient Maven / Gradle / Ivy

There is a newer version: 4.23.18
Show newest version
/**
 * 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.lang.NotImplementedException;
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 getMessageParts(Multipart content) throws IOException, MessagingException {
		List 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 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 preFilteredMessages = new ArrayList<>();
		
		final LocalDateTime firstTime = firstMessageTime;
		
		// on filtre les message en fonction du mode de recherche
		if (searchMode == SearchMode.BY_INDEX || firstTime == null) {
			//preFilteredMessages = Arrays.asList(Arrays.copyOfRange(messages, firstMessageIndex, messages.length)); => to test
			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;
					}
				}
			}));
			
		}
		
		lastMessageIndex = messages.length;
		List filteredEmails = filterMessages(preFilteredMessages);
		

		folder.close(false);
		
		return filteredEmails;
	}

	/**
	 * @param preFilteredMessages
	 * @return
	 * @throws MessagingException
	 * @throws IOException
	 */
	private List filterMessages(List preFilteredMessages) throws MessagingException, IOException {
		List filteredEmails = new ArrayList<>();

		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 attachments = new ArrayList<>();

			if (contentType.toLowerCase().contains("text/html")) {
				messageContent += StringEscapeUtils.unescapeHtml4(message.getContent().toString());
			} else if (contentType.toLowerCase().contains("multipart/")) {
				List 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(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));
		}
		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;
	}

	@Override
	public void sendMessage(List to, String title, String body) throws Exception {
		throw new NotImplementedException();
		
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy