diff --git a/EasyContact.app/server/pom.xml b/EasyContact.app/server/pom.xml index 6f55b95..4999ef8 100644 --- a/EasyContact.app/server/pom.xml +++ b/EasyContact.app/server/pom.xml @@ -1,61 +1,68 @@ - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.7.4 - - - app.EasyContact.server - EasyContact.server - 0.0.1-SNAPSHOT - EasyContact.server - EasyContact Backend Java Server - - 17 - - - - org.springframework.boot - spring-boot-starter-web - - - org.projectlombok - lombok - true - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-starter-mail - 2.7.4 - - - com.sun.mail - javax.mail - 1.6.2 - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - org.projectlombok - lombok - - - - - - + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.4 + + + app.EasyContact.server + EasyContact.server + 0.0.1-SNAPSHOT + EasyContact.server + EasyContact Backend Java Server + + 17 + + + + org.springframework.boot + spring-boot-starter-web + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + com.sun.mail + javax.mail + 1.6.2 + + + org.junit.jupiter + junit-jupiter-engine + 5.9.1 + test + + + org.mockito + mockito-all + 1.10.19 + test + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + diff --git a/EasyContact.app/server/src/main/java/app/easycontact/server/imap/Email.java b/EasyContact.app/server/src/main/java/app/easycontact/server/imap/Email.java new file mode 100644 index 0000000..259ff71 --- /dev/null +++ b/EasyContact.app/server/src/main/java/app/easycontact/server/imap/Email.java @@ -0,0 +1,16 @@ +package app.easycontact.server.imap; + +import lombok.Data; +import lombok.experimental.SuperBuilder; + +@SuperBuilder +@Data +public abstract class Email { + public final long id; + public final String from; + public final String subject; + public final String toList; + public final String ccList; + public final String sendDate; + public final String message; +} diff --git a/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailImplementation.java b/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailImplementation.java new file mode 100644 index 0000000..24c002b --- /dev/null +++ b/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailImplementation.java @@ -0,0 +1,9 @@ +package app.easycontact.server.imap; + +import lombok.Data; +import lombok.experimental.SuperBuilder; + +@SuperBuilder +@Data +public final class EmailImplementation extends Email { +} diff --git a/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailReceiver.java b/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailReceiver.java index 8700afa..f0318e4 100644 --- a/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailReceiver.java +++ b/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailReceiver.java @@ -1,138 +1,19 @@ package app.easycontact.server.imap; -import javax.mail.*; -import java.util.Properties; +import lombok.NonNull; +import lombok.experimental.SuperBuilder; -public class EmailReceiver { - - /** - * Test downloading e-mail messages - */ - public static void main(String[] args) { - // for IMAP - String protocol = "imap"; - String host = "mail.rpi.edu"; - String port = "993"; - - String userName = "usrName"; - String password = "password"; - - EmailReceiver receiver = new EmailReceiver(); - receiver.downloadEmails(protocol, host, port, userName, password); - } - - /** - * Returns a Properties object which is configured for a POP3/IMAP server - * - * @param protocol either "imap" or "pop3" - * @param host - * @param port - * @return a Properties object - */ - private Properties getServerProperties(String protocol, String host, String port) { - Properties properties = new Properties(); - - // server setting - properties.put(String.format("mail.%s.host", protocol), host); - properties.put(String.format("mail.%s.port", protocol), port); - - // SSL setting - properties.setProperty(String.format("mail.%s.socketFactory.class", protocol), "javax.net.ssl.SSLSocketFactory"); - properties.setProperty(String.format("mail.%s.socketFactory.fallback", protocol), "false"); - properties.setProperty(String.format("mail.%s.socketFactory.port", protocol), String.valueOf(port)); - - return properties; - } +@SuperBuilder +public abstract class EmailReceiver { + @NonNull String userName; + @NonNull String userPassword; + @NonNull String serverName; + @NonNull String serverPort; /** * Downloads new messages and fetches details for each message. * - * @param protocol - * @param host - * @param port - * @param userName - * @param password - */ - public void downloadEmails(String protocol, String host, String port, String userName, String password) { - Properties properties = getServerProperties(protocol, host, port); - Session session = Session.getDefaultInstance(properties); - - try { - // connects to the message store - Store store = session.getStore(protocol); - store.connect(userName, password); - - // opens the inbox folder - Folder folderInbox = store.getFolder("INBOX"); - folderInbox.open(Folder.READ_ONLY); - - // fetches new messages from server - Message[] messages = folderInbox.getMessages(); - - for (int i = 0; i < messages.length; i++) { - Message msg = messages[i]; - Address[] fromAddress = msg.getFrom(); - String from = fromAddress[0].toString(); - String subject = msg.getSubject(); - String toList = parseAddresses(msg.getRecipients(Message.RecipientType.TO)); - String ccList = parseAddresses(msg.getRecipients(Message.RecipientType.CC)); - String sentDate = msg.getSentDate().toString(); - - String contentType = msg.getContentType(); - String messageContent = ""; - - if (contentType.contains("text/plain") || contentType.contains("text/html")) { - try { - Object content = msg.getContent(); - if (content != null) { - messageContent = content.toString(); - } - } catch (Exception ex) { - messageContent = "[Error downloading content]"; - ex.printStackTrace(); - } - } - - // print out details of each message - System.out.println("Message #" + (i + 1) + ":"); - System.out.println("\t From: " + from); - System.out.println("\t To: " + toList); - System.out.println("\t CC: " + ccList); - System.out.println("\t Subject: " + subject); - System.out.println("\t Sent Date: " + sentDate); - System.out.println("\t Message: " + messageContent); - } - - // disconnect - folderInbox.close(false); - store.close(); - } catch (NoSuchProviderException ex) { - System.out.println("No provider for protocol: " + protocol); - ex.printStackTrace(); - } catch (MessagingException ex) { - System.out.println("Could not connect to the message store"); - ex.printStackTrace(); - } - } - - /** - * Returns a list of addresses in String format separated by comma - * - * @param address an array of Address objects - * @return a string represents a list of addresses + * @param folder name of the email folder */ - private String parseAddresses(Address[] address) { - String listAddress = ""; - - if (address != null) { - for (int i = 0; i < address.length; i++) { - listAddress += address[i].toString() + ", "; - } - } - if (listAddress.length() > 1) { - listAddress = listAddress.substring(0, listAddress.length() - 2); - } - - return listAddress; - } + public abstract void downloadEmails(String folder); } diff --git a/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailReceiverImplementation.java b/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailReceiverImplementation.java new file mode 100644 index 0000000..0bf2fdc --- /dev/null +++ b/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailReceiverImplementation.java @@ -0,0 +1,122 @@ +package app.easycontact.server.imap; + +import lombok.NonNull; +import lombok.experimental.SuperBuilder; + +import javax.mail.*; +import java.util.Properties; + +@SuperBuilder +public final class EmailReceiverImplementation extends EmailReceiver { + /** + * Downloads new messages and fetches details for each message. + * + * @param folder name of the email folder + */ + public void downloadEmails(@NonNull String folder) { + Properties properties = getServerProperties(EmailReceiverProtocol.IMAP, serverName, serverPort); + Session session = Session.getDefaultInstance(properties); + + try { + // connects to the message store + Store store = session.getStore(EmailReceiverProtocol.IMAP.toString()); + store.connect(userName, userPassword); + + // opens the inbox folder + Folder folderInbox = store.getFolder(folder); + folderInbox.open(Folder.READ_ONLY); + + // fetches new messages from server + Message[] messages = folderInbox.getMessages(); + + for (int i = 0; i < messages.length; ++i) { + Message msg = messages[i]; + Address[] fromAddress = msg.getFrom(); + String from = fromAddress[0].toString(); + String subject = msg.getSubject(); + String toList = parseAddresses(msg.getRecipients(Message.RecipientType.TO)); + String ccList = parseAddresses(msg.getRecipients(Message.RecipientType.CC)); + String sentDate = msg.getSentDate().toString(); + + String contentType = msg.getContentType(); + String messageContent = ""; + + if (contentType.contains("text/plain") || contentType.contains("text/html")) { + try { + Object content = msg.getContent(); + if (content != null) { + messageContent = content.toString(); + } + } catch (Exception ex) { + messageContent = "[Error downloading content]"; + ex.printStackTrace(); + } + } + + // create a Email object for each message + Email email = EmailImplementation.builder().id(i).from(from).toList(toList).ccList(ccList).subject(subject).sendDate(sentDate).message(messageContent).build(); + System.out.println("Message #" + email.getId() + ":"); + System.out.println("\t From: " + email.getFrom()); + System.out.println("\t To: " + email.getToList()); + System.out.println("\t CC: " + email.getCcList()); + System.out.println("\t Subject: " + email.getCcList()); + System.out.println("\t Sent Date: " + email.getSendDate()); + System.out.println("\t Message: " + email.getMessage()); + } + + // disconnect + folderInbox.close(false); + store.close(); + } catch (NoSuchProviderException ex) { + System.out.println("No provider for protocol: " + EmailReceiverProtocol.IMAP); + ex.printStackTrace(); + } catch (MessagingException ex) { + System.out.println("Could not connect to the message store"); + ex.printStackTrace(); + } + } + + /** + * Returns a list of addresses in String format separated by comma + * + * @param address an array of Address objects + * @return a string represents a list of addresses + */ + private String parseAddresses(Address[] address) { + String listAddress = ""; + + if (address != null) { + for (int i = 0; i < address.length; i++) { + listAddress += address[i].toString() + ", "; + } + } + if (listAddress.length() > 1) { + listAddress = listAddress.substring(0, listAddress.length() - 2); + } + + return listAddress; + } + + /** + * Returns a Properties object which is configured for a POP3/IMAP server + * + * @param protocol either "imap" or "pop3" + * @param host + * @param port + * @return a Properties object + */ + private Properties getServerProperties(EmailReceiverProtocol protocol, String host, String port) { + Properties properties = new Properties(); + + // server setting + properties.put(String.format("mail.%s.host", protocol), host); + properties.put(String.format("mail.%s.port", protocol), port); + + // SSL setting + properties.setProperty(String.format("mail.%s.socketFactory.class", protocol), "javax.net.ssl.SSLSocketFactory"); + properties.setProperty(String.format("mail.%s.socketFactory.fallback", protocol), "false"); + properties.setProperty(String.format("mail.%s.socketFactory.port", protocol), String.valueOf(port)); + + return properties; + } +} diff --git a/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailReceiverProtocol.java b/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailReceiverProtocol.java new file mode 100644 index 0000000..f235cdb --- /dev/null +++ b/EasyContact.app/server/src/main/java/app/easycontact/server/imap/EmailReceiverProtocol.java @@ -0,0 +1,15 @@ +package app.easycontact.server.imap; + +public enum EmailReceiverProtocol { + IMAP("imap"), POP3("pop3"); + private final String enumText; + + EmailReceiverProtocol(final String enumText) { + this.enumText = enumText; + } + + @Override + public String toString() { + return this.enumText; + } +} diff --git a/EasyContact.app/server/src/main/java/app/easycontact/server/imap/README.md b/EasyContact.app/server/src/main/java/app/easycontact/server/imap/README.md new file mode 100644 index 0000000..88b3ad1 --- /dev/null +++ b/EasyContact.app/server/src/main/java/app/easycontact/server/imap/README.md @@ -0,0 +1,26 @@ +# EasyContact IMAP Client + +- Package `app.easycontact.server.imap` + +## Usage + +- Create an `EmailReceiver` instance using `EmailReceiverImplementation.builder()` + - `serverName`: IMAP server's domain name + - `serverPort`: IMAP server's port + - `userName`: Username used for authentication + - `userPassword`: Password used for authentication + + ```java + EmailReceiver emailReceiver = EmailReceiverImplementation.builder() + .serverName("mail.rpi.edu") + .serverPort("993") + .userName("rcsid") + .userPassword("password") + .build(); + ``` + +- Download emails from `INBOX` folder + + ```java + emailReceiver.downloadEmails("INBOX"); + ``` diff --git a/EasyContact.app/server/src/test/java/app/easycontact/server/imap/EmailTest.java b/EasyContact.app/server/src/test/java/app/easycontact/server/imap/EmailTest.java new file mode 100644 index 0000000..70dca21 --- /dev/null +++ b/EasyContact.app/server/src/test/java/app/easycontact/server/imap/EmailTest.java @@ -0,0 +1,64 @@ +package app.easycontact.server.imap; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class EmailTest { + final long id = 1; + final String from = "from@example.com"; + final String toList = "to@example.com"; + final String ccList = "cc@example.com"; + final String subject = "Example Subject"; + final String sendDate = "Example Date"; + final String message = "Example Message"; + Email email; + + @BeforeEach + void setUp() { + email = EmailImplementation.builder().id(id).from(from).toList(toList).ccList(ccList).subject(subject).sendDate(sendDate).message(message).build(); + } + + @Test + public void testCreateEmail() { + assertNotNull(email); + } + + @Test + public void testGetId() { + assertEquals(email.getId(), id); + } + + @Test + public void testGetFrom() { + assertEquals(email.getFrom(), from); + } + + @Test + public void testGetSubject() { + assertEquals(email.getSubject(), subject); + } + + @Test + public void testGetToList() { + assertEquals(email.getToList(), toList); + } + + @Test + public void testGetCcList() { + assertEquals(email.getCcList(), ccList); + } + + @Test + public void testGetSendDate() { + assertEquals(email.getSendDate(), sendDate); + } + + @Test + public void testGetMessage() { + assertEquals(email.getMessage(), message); + } +}