Java Utility for sending reading emails - yoss123/test-automation-repo GitHub Wiki
Add the next dependency to pom.xml
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>package com.[project-name].utils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.jupiter.api.DisplayName;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Paths;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* Turn POP and IMAP on for users: Settings -> Forwarding and POP/IMAP -> POP download -> set to enabled ; IMAP access -> Enabled IMAP
*
* Important note !!!
* Since May 30, 2022 Google is no longer provide access to less secure applications.
* In other words, applications cannot simply authenticate with a user's username and password to send emails.
* So that existing applications that send or receive emails using Google accounts continue to work without requiring changes in their programming,
* there is the possibility of using an 'App Password.'
*
* Steps to obtain an App Password:
* 1. Turn on two-step verification for your Google account
* 2. Create an app password (https://support.google.com/mail/answer/185833?hl=en)
* 3. Use that password in the application (assigning it to the corresponding password property).
* (https://www.genexus.com/en/read-news/anuncio-el-30-de-mayo-google-deja-de-soportar-el-mecanismo-habitual-de-autenticacion-para-mails)
*/
/**
* SMTP – Simple Mail Transfer Protocol is used for sending e-mails.
* POP3 – Post Office Protocol is used to receive e-mails. It provides one to one mapping for users and mailboxes, which is one mailbox for one user.
* IMAP – Internet Message Access Protocol is also used to receive e-mails. It supports multiple mailboxes for a single user.
*/
public class MailUtil {
public static boolean sendMessage(String emailAddress, String emailPassword, String mailSentFromAddress,
String mailRecipientslist, String mailSubject, String mailMessage, File file2attach) {
try {
Properties prop = new Properties();
prop.put("mail.smtp.host", "smtp.gmail.com");
prop.put("mail.smtp.port", "587");
prop.put("mail.smtp.auth", "true");
prop.put("mail.smtp.starttls.enable", "true"); // Transport Layer Security (TLS)
Session mailSession = Session.getInstance(prop,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(emailAddress, emailPassword);
}
});
Message message = new MimeMessage(mailSession);
message.setFrom(new InternetAddress(mailSentFromAddress));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(mailRecipientslist));
message.setSubject(mailSubject);
// String htmlMessage = "This is my <b style='color:red;'>bold-red email</b> using JavaMailer";
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.setContent(mailMessage, "text/html");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(mimeBodyPart);
message.setContent(multipart);
// Alternatively you can set the email content with the next line:
// message.setText(mailMessage);
if(Objects.nonNull(file2attach)) {
MimeBodyPart attachmentBodyPart = new MimeBodyPart();
attachmentBodyPart.attachFile(file2attach);
multipart.addBodyPart(attachmentBodyPart);
}
Transport.send(message);
return true;
} catch (MessagingException | IOException e) {
e.printStackTrace();
return false;
}
}
private static Session getSession2readEmails() {
Properties prop = new Properties();
prop.put("mail.pop3.host", "pop.gmail.com");
prop.put("mail.pop3.port", "995");
prop.put("mail.pop3.starttls.enable", "true");
return Session.getDefaultInstance(prop);
}
private static void printEmailMessage(Message message) {
try {
System.out.println("------------ Start of email message -----------------");
System.out.println("Email subject: " + message.getSubject());
System.out.println("Sender: ");
List.of(message.getFrom()).stream().forEach(sender -> System.out.print(sender+" "));
System.out.println();
System.out.print("Recipients: ");
List.of(message.getAllRecipients()).stream().forEach(recipient -> System.out.print(recipient+" "));
System.out.println();
System.out.print("Reply to: ");
List.of(message.getReplyTo()).stream().forEach(reply2 -> System.out.print(reply2+" "));
System.out.println();
System.out.println("Sent date: " + message.getSentDate());
System.out.println("Recieved date: " + message.getReceivedDate());
System.out.println("Message number: " + message.getMessageNumber());
System.out.println("Content type: " + message.getContentType());
System.out.println("Description: " + message.getDescription());
System.out.println("Flags: " + message.getFlags());
System.out.println("Content: " + getTextFromMessage(message));
System.out.println("------------ End of email message -------------------");
} catch(MessagingException | IOException e) {
e.printStackTrace();
}
}
public static boolean isExpectedEmailInInbox(String userName, String password, String expectedEmailMessageContent,
String mentionedUserMailSubject, String mentionedUserMailFrom, long timeoutInSeconds) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
Timestamp timeoutInTimestamp = Timestamp.from(new Timestamp(System.currentTimeMillis()).toInstant().plusSeconds(timeoutInSeconds));
String formatedTimeout = simpleDateFormat.format(new Date(timeoutInTimestamp.getTime()));
System.out.println("Current time is "+simpleDateFormat.format(new Date())+" while timeout to recieve expected email is "+formatedTimeout);
while(System.currentTimeMillis() < timeoutInTimestamp.getTime()) {
if(isExpectedEmailInInbox(userName, password, expectedEmailMessageContent, mentionedUserMailSubject, mentionedUserMailFrom)) {
System.out.println("Expected email was found in the Inbox of "+userName+" at "
+simpleDateFormat.format(new Date())+".");
return true;
}
else {
System.out.println("Expected email wasn't found in the Inbox of "+userName+" at "
+simpleDateFormat.format(new Date())+". Trying until timeout ("+formatedTimeout+")");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {e.printStackTrace();}
}
}
return false;
}
public static boolean isExpectedEmailInInbox(String userName, String password, String expectedEmailMessageContent,
String expectedMailSubject, String expectedMailFrom) {
Session mailSession = null;
Store store = null;
Folder inbox = null;
try {
mailSession = getSession2readEmails();
store = mailSession.getStore("pop3s");
store.connect("pop.gmail.com", userName, password);
inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_ONLY);
Message[] messages = inbox.getMessages();
return Arrays.stream(messages).anyMatch(message -> {
try {
if(message.getSubject().equals(expectedMailSubject) && message.getFrom()[0].toString().equals(expectedMailFrom)) {
System.out.println("Email with EXPECTED subject '"+expectedMailSubject
+"' and sender '"+expectedMailFrom+"' was found in Inbox.");
String contentFromMessage = MailUtil.getTextFromMessage(message);
// Saving the 2 results (actual & expected) to further inquiry in case of a test failure
Files.write(Paths.get("contentFromMessage.txt"), contentFromMessage.getBytes());
contentFromMessage = Files.lines(Paths.get("contentFromMessage.txt")).collect(Collectors.joining(System.lineSeparator()));
Files.write(Paths.get("expectedCommentsEmail.txt"), expectedEmailMessageContent.getBytes(), new OpenOption[0]);
String expectedEmailMessageContentStr = Files.lines(Paths.get("expectedCommentsEmail.txt")).collect(Collectors.joining(System.lineSeparator()));
return contentFromMessage.equals(expectedEmailMessageContentStr);
} else {
return false;
}
} catch (MessagingException | IOException e) {
e.printStackTrace();
return false;
}
});
} catch (MessagingException e) {
e.printStackTrace();
return false;
} finally {
try {
if (Objects.nonNull(inbox)) inbox.close(false);
if(Objects.nonNull(store)) store.close();
} catch(MessagingException e) {
e.printStackTrace();
}
}
}
public static String getTextFromMessage(Message message) throws MessagingException, IOException {
if(message.isMimeType("text/plain")) {
return message.getContent().toString();
} else if (message.isMimeType("text/html")){
return message.getContent().toString();
} else if (message.isMimeType("multipart/*")) {
MimeMultipart mimeMultipart = (MimeMultipart) message.getContent();
return getTextFromMimeMultipart(mimeMultipart);
} else {
System.out.println("Error -> Unknown MimeType");
return null;
}
}
private static String getTextFromMimeMultipart(
MimeMultipart mimeMultipart) throws MessagingException, IOException{
String result = "";
int mimeMultipartCount = mimeMultipart.getCount();
for (int counter = 0; counter < mimeMultipartCount; counter++) {
BodyPart bodyPart = mimeMultipart.getBodyPart(counter);
if (bodyPart.isMimeType("text/plain")) {
result = result + "\n" + bodyPart.getContent();
// break; // without break same text appears twice in my tests
} else if (bodyPart.isMimeType("text/html")) {
result = result + "\n" + bodyPart.getContent();
} else if (bodyPart.getContent() instanceof MimeMultipart){
result = result + getTextFromMimeMultipart((MimeMultipart)bodyPart.getContent());
}
}
return result;
}
@Test
@DisplayName("Test send & recieve email")
public void testSendAndRecieveEmail() {
String testUserEmail = "[email protected]";
String testUserEmailPassword = "Rami12levy";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyy hh:mm:ss");
String mailSubject = "Test send & recieve email on "+simpleDateFormat.format(new Date());
String emailMessage = "<b style='color:blue;'>Dear recipient,</b><br><br> "
+"This is a <b>TEST</b> email to test SEND & RECIEVE emails via JAVA API<br><br>"
+"Thanks<br><br>"
+"Tester";
sendMessage(testUserEmail, testUserEmailPassword, testUserEmail, testUserEmail, mailSubject,
emailMessage, null);
System.out.println("Email with subject '"+mailSubject+"' was sent. Now testing if its arrived to Inbox...");
Assert.assertTrue("Sent email wasn't found in Inbox",
isExpectedEmailInInbox(testUserEmail, testUserEmailPassword, emailMessage, mailSubject, testUserEmail, 120));
}
}