diff --git a/network/pom.xml b/network/pom.xml
index 92d538b..84a7759 100644
--- a/network/pom.xml
+++ b/network/pom.xml
@@ -52,11 +52,13 @@
- javax.mail
- mail
- jar
- compile
+ com.sun.mail
+ javax.mail
+
+ com.microsoft.ews-java-api
+ ews-java-api
+
commons-net
diff --git a/network/src/main/java/de/muehlencord/shared/network/mail/MailReaderConfiguration.java b/network/src/main/java/de/muehlencord/shared/network/mail/MailReaderConfiguration.java
index 6c01d64..628d79a 100644
--- a/network/src/main/java/de/muehlencord/shared/network/mail/MailReaderConfiguration.java
+++ b/network/src/main/java/de/muehlencord/shared/network/mail/MailReaderConfiguration.java
@@ -22,6 +22,10 @@ public class MailReaderConfiguration {
* the password to connect with
*/
private String password = null;
+ /**
+ * the email of the user
+ */
+ private String emailAddress = null;
/**
* the protocol to use, currently supported imap and imaps
*/
@@ -43,6 +47,22 @@ public class MailReaderConfiguration {
this.password = pw;
}
+ /**
+ * creates a new config
+ *
+ * @param mailHost the smtp host to connect to
+ * @param host the mailreader host (imap, exchange, pop, ...) to connect to
+ * @param user the username to connect with
+ * @param pw the password to connect with
+ */
+ public MailReaderConfiguration(String mailHost, String host, String user, String pw, String email) {
+ this.smtpHost = mailHost;
+ this.readerHost = host;
+ this.userName = user;
+ this.password = pw;
+ this.emailAddress = email;
+ }
+
/**
* @return the smtpHost
*/
@@ -71,6 +91,10 @@ public class MailReaderConfiguration {
return password;
}
+ public String getEmailAddress() {
+ return emailAddress;
+ }
+
public MailProtocol getProtocol() {
return protocol;
}
diff --git a/network/src/main/java/de/muehlencord/shared/network/mail/exchange/ExchangeMailReader.java b/network/src/main/java/de/muehlencord/shared/network/mail/exchange/ExchangeMailReader.java
new file mode 100644
index 0000000..6681bcb
--- /dev/null
+++ b/network/src/main/java/de/muehlencord/shared/network/mail/exchange/ExchangeMailReader.java
@@ -0,0 +1,249 @@
+package de.muehlencord.shared.network.mail.exchange;
+
+import de.muehlencord.shared.network.mail.MailMessage;
+import de.muehlencord.shared.network.mail.MailReader;
+import de.muehlencord.shared.network.mail.MailReaderConfiguration;
+import de.muehlencord.shared.network.mail.MailReaderConnectionException;
+import de.muehlencord.shared.network.mail.MailReaderException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import microsoft.exchange.webservices.data.autodiscover.IAutodiscoverRedirectionUrl;
+import microsoft.exchange.webservices.data.core.ExchangeService;
+import microsoft.exchange.webservices.data.core.PropertySet;
+import microsoft.exchange.webservices.data.core.service.item.Item;
+import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
+import microsoft.exchange.webservices.data.core.enumeration.property.BasePropertySet;
+import microsoft.exchange.webservices.data.core.enumeration.property.WellKnownFolderName;
+import microsoft.exchange.webservices.data.core.exception.service.local.ServiceLocalException;
+import microsoft.exchange.webservices.data.core.service.folder.Folder;
+import microsoft.exchange.webservices.data.core.service.schema.EmailMessageSchema;
+import microsoft.exchange.webservices.data.credential.ExchangeCredentials;
+import microsoft.exchange.webservices.data.credential.WebCredentials;
+import microsoft.exchange.webservices.data.property.complex.InternetMessageHeaderCollection;
+import microsoft.exchange.webservices.data.search.FindFoldersResults;
+import microsoft.exchange.webservices.data.search.FindItemsResults;
+import microsoft.exchange.webservices.data.search.FolderView;
+import microsoft.exchange.webservices.data.search.ItemView;
+import microsoft.exchange.webservices.data.search.filter.SearchFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author Joern Muehlencord
+ */
+public class ExchangeMailReader implements MailReader {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ExchangeMailReader.class);
+ private final MailReaderConfiguration configuration;
+ private ExchangeService service = null;
+
+ public ExchangeMailReader(MailReaderConfiguration config) {
+ this.configuration = config;
+ }
+
+ @Override
+ public void connect() throws MailReaderConnectionException {
+ try {
+ String hostName = getConfiguration().getReaderHost();
+ String userName = getConfiguration().getUserName();
+ String password = getConfiguration().getPassword();
+ String emailAddress = getConfiguration().getEmailAddress();
+
+ service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
+
+ ExchangeCredentials credentials = new WebCredentials(userName, password);
+ service.setCredentials(credentials);
+ service.autodiscoverUrl(emailAddress, new RedirectionUrlCallback());
+
+ LOGGER.info("Connected to " + getConnectionShortCut());
+ } catch (Exception ex) {
+ throw new MailReaderConnectionException(ex.getMessage(), ex);
+ }
+ }
+
+ @Override
+ public void disconnect() {
+ if (service != null) {
+ service.close();
+ }
+ }
+
+ private Folder findFolderByName(String folderName) throws MailReaderException {
+ String[] folderNameParts = folderName.split("/");
+ try {
+ Folder inbox = Folder.bind(service, WellKnownFolderName.Inbox);
+ int currentFolderPart = 0;
+ Folder currentFolder = inbox;
+ while ((currentFolderPart < folderNameParts.length)) {
+ FindFoldersResults findResults = service.findFolders(currentFolder.getId(), new FolderView(Integer.MAX_VALUE));
+ Iterator it = findResults.getFolders().iterator();
+ boolean nextFolderFound = false;
+ while (it.hasNext() && !nextFolderFound) {
+ Folder nextFolder = it.next();
+ if (nextFolder.getDisplayName().equalsIgnoreCase(folderNameParts[currentFolderPart])) {
+ // found next folder
+ currentFolder = nextFolder;
+ currentFolderPart++;
+ nextFolderFound = true;
+ }
+ }
+ // checked all sub folders
+ if (!nextFolderFound) {
+ throw new MailReaderException("Cannot find subfolder named " + folderNameParts[currentFolderPart] + " in folder " + currentFolder.getDisplayName());
+ }
+ }
+
+ return currentFolder;
+ } catch (Exception ex) {
+ throw new MailReaderException("Error while finding folder " + folderName + ". Reason: " + ex.getMessage(), ex);
+
+ }
+
+ }
+
+ @Override
+ public String getDefaultFolder() throws MailReaderException {
+ try {
+ Folder inbox = Folder.bind(service, WellKnownFolderName.Inbox);
+ return inbox.getDisplayName();
+ } catch (Exception ex) {
+ throw new MailReaderException("Cannot bind inbox folder", ex);
+ }
+ }
+
+ @Override
+ public List getSubFolder(String sourceFolder) throws MailReaderException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public String getFolder(String folderPath) throws MailReaderException {
+ Folder folder = findFolderByName(folderPath);
+ try {
+ return folder.getDisplayName();
+ } catch (ServiceLocalException ex) {
+ throw new MailReaderException(ex.getMessage(), ex);
+ }
+ }
+
+ @Override
+ public int getMessageCount(String holdFolder) throws MailReaderException {
+ Folder folder = findFolderByName(holdFolder);
+ try {
+ return folder.getTotalCount();
+ } catch (ServiceLocalException ex) {
+ throw new MailReaderException(ex.getMessage(), ex);
+ }
+ }
+
+ private List getMessages(String folderName, ItemView view) throws MailReaderException {
+ List returnValue = new ArrayList<>();
+ try {
+ Folder folder = findFolderByName(folderName);
+ FindItemsResults- findResults = service.findItems(folder.getId(), view);
+ PropertySet propertySet = new PropertySet(BasePropertySet.FirstClassProperties, EmailMessageSchema.InternetMessageId);
+ service.loadPropertiesForItems(findResults, propertySet);
+ for (Item item : findResults.getItems()) {
+ String subject = item.getSubject();
+ String content = item.getBody().toString();
+ InternetMessageHeaderCollection headers = item.getInternetMessageHeaders();
+ String messageId = headers.find("Message-ID").getValue();
+ MailMessage mailMessage = new MailMessage(subject, content, messageId);
+ returnValue.add(mailMessage);
+ }
+
+ return returnValue;
+ } catch (Exception ex) {
+ throw new MailReaderException(ex.getMessage(), ex);
+ }
+
+ }
+
+ @Override
+ public List getMessages(String folderName) throws MailReaderException {
+ ItemView view = new ItemView(Integer.MAX_VALUE);
+ return getMessages(folderName, view);
+ }
+
+ @Override
+ public List getMessages(String folderName, int start, int end) throws MailReaderException {
+ ItemView view = new ItemView(end - start);
+ view.setOffset(start);
+ return getMessages(folderName, view);
+ }
+
+ private Item findMessageByMessageId(String folderName, String messageId) throws MailReaderException {
+ try {
+ PropertySet propertySet = new PropertySet(BasePropertySet.FirstClassProperties, EmailMessageSchema.InternetMessageId);
+ Folder folder = findFolderByName(folderName);
+ ItemView view = new ItemView(1);
+ view.setPropertySet(propertySet);
+
+ SearchFilter searchFilter = new SearchFilter.IsEqualTo(EmailMessageSchema.InternetMessageId, messageId);
+ FindItemsResults
- findResults = service.findItems(folder.getId(), searchFilter, view);
+ service.loadPropertiesForItems(findResults, propertySet);
+
+ if (findResults.getItems().isEmpty()) {
+ return null;
+ } else {
+ return findResults.getItems().get(0);
+ }
+ } catch (Exception ex) {
+ throw new MailReaderException(ex.getMessage(), ex);
+ }
+
+ }
+
+ @Override
+ public void copyMessage(MailMessage mm, String sourceFolder, String destFolder) throws MailReaderException {
+ try {
+ Item message = findMessageByMessageId(sourceFolder, mm.getMessageId());
+
+ Folder destination = findFolderByName(destFolder);
+ service.copyItem(message.getId(), destination.getId());
+ } catch (Exception ex) {
+ throw new MailReaderException(ex.getMessage(), ex);
+ }
+ }
+
+ @Override
+ public void moveMessage(MailMessage mm, String sourceFolder, String destFolder) throws MailReaderException {
+ try {
+ Item message = findMessageByMessageId(sourceFolder, mm.getMessageId());
+ Folder destination = findFolderByName(destFolder);
+ service.moveItem(message.getId(), destination.getId());
+ } catch (Exception ex) {
+ throw new MailReaderException(ex.getMessage(), ex);
+ }
+ }
+
+ @Override
+ public void setSeenFlag(String folder, MailMessage mm, boolean flagValue) throws MailReaderException {
+ // FIXME - add implementation
+ }
+
+ /**
+ * returns userName@hostname
+ *
+ * @return userName@hostname
+ */
+ private String getConnectionShortCut() {
+ return getConfiguration().getUserName() + "@" + getConfiguration().getReaderHost();
+ }
+
+ /* *** getter / setter *** */
+ public MailReaderConfiguration getConfiguration() {
+ return configuration;
+ }
+
+}
+
+class RedirectionUrlCallback implements IAutodiscoverRedirectionUrl {
+
+ @Override
+ public boolean autodiscoverRedirectionUrlValidationCallback(String redirectionUrl) {
+ return redirectionUrl.toLowerCase().startsWith("https://");
+ }
+}
diff --git a/network/src/main/java/de/muehlencord/shared/network/mail/imap/ImapMailReader.java b/network/src/main/java/de/muehlencord/shared/network/mail/imap/ImapMailReader.java
index 6bda2da..2b10242 100644
--- a/network/src/main/java/de/muehlencord/shared/network/mail/imap/ImapMailReader.java
+++ b/network/src/main/java/de/muehlencord/shared/network/mail/imap/ImapMailReader.java
@@ -9,7 +9,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Implementation of MaiLReader to connect to an IMAP server
+ * Implementation of MailReader to connect to an IMAP server
*
* @author joern@muehlencord.de
*/
diff --git a/network/src/test/java/de/muehlencord/shared/network/mail/exchange/ExchangeMailReaderTest.java b/network/src/test/java/de/muehlencord/shared/network/mail/exchange/ExchangeMailReaderTest.java
new file mode 100644
index 0000000..0066953
--- /dev/null
+++ b/network/src/test/java/de/muehlencord/shared/network/mail/exchange/ExchangeMailReaderTest.java
@@ -0,0 +1,66 @@
+package de.muehlencord.shared.network.mail.exchange;
+
+import de.muehlencord.shared.network.mail.MailMessage;
+import de.muehlencord.shared.network.mail.MailReader;
+import de.muehlencord.shared.network.mail.MailReaderConfiguration;
+import de.muehlencord.shared.network.mail.MailReaderConnectionException;
+import de.muehlencord.shared.network.mail.MailReaderException;
+import java.util.List;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNotNull;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author Joern Muehlencord
+ */
+public class ExchangeMailReaderTest {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ExchangeMailReaderTest.class);
+
+ @Test
+ public void testConnect() {
+ try {
+ LOGGER.info("testConnect");
+ String imapHost = null;
+ String smtpHost = null;
+ String folder = null;
+ String testFolder = null;
+ String userName = null;
+ String password = null;
+ String emailaddress = null;
+
+ assumeNotNull(imapHost);
+ assumeNotNull(smtpHost);
+ assumeNotNull(folder);
+ assumeNotNull(testFolder);
+ assumeNotNull(userName);
+ assumeNotNull(emailaddress);
+ assumeNotNull(password);
+
+
+ MailReaderConfiguration config = new MailReaderConfiguration(smtpHost, imapHost, userName, password, emailaddress);
+ MailReader instance = new ExchangeMailReader(config);
+
+ instance.connect();
+ int messageCount = instance.getMessageCount(folder);
+ LOGGER.info("Found {} messages in folder {}", messageCount, folder);
+ List messages = instance.getMessages(folder, 0, 50);
+ LOGGER.info("Retrieved {} messages from folder", messages.size());
+
+ // instance.copyMessage(messages.get(0), folder, testFolder);
+ instance.disconnect();
+
+ } catch (MailReaderConnectionException | MailReaderException ex) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug(ex.toString(), ex);
+ } else {
+ LOGGER.error(ex.toString());
+ }
+ fail("An error occured");
+ }
+ }
+
+}