/** * NoraUi is licensed under the license GNU AFFERO GENERAL PUBLIC LICENSE * * @author Nicolas HALLOUIN * @author Stéphane GRILLON */ package com.github.noraui.application.steps; import java.io.IOException; import java.util.List; import java.util.Properties; import javax.mail.BodyPart; import javax.mail.Flags; import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Store; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMultipart; import javax.mail.search.AndTerm; import javax.mail.search.FlagTerm; import javax.mail.search.FromTerm; import javax.mail.search.SearchTerm; import javax.mail.search.SubjectTerm; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.slf4j.Logger; import com.github.noraui.cucumber.annotation.Conditioned; import com.github.noraui.cucumber.annotation.Experimental; import com.github.noraui.cucumber.annotation.RetryOnFailure; import com.github.noraui.exception.Callbacks; import com.github.noraui.exception.FailureException; import com.github.noraui.exception.HttpServiceException; import com.github.noraui.exception.Result; import com.github.noraui.exception.TechnicalException; import com.github.noraui.gherkin.GherkinStepCondition; import com.github.noraui.log.annotation.Loggable; import com.github.noraui.service.HttpService; import com.github.noraui.utils.Context; import com.github.noraui.utils.Messages; import com.google.inject.Inject; import io.cucumber.java.en.And; import io.cucumber.java.fr.Et; /** * This class contains Gherkin callable steps that aim for expecting a specific result. */ @Loggable public class MailSteps extends Step { static Logger log; @Inject private HttpService httpService; /** * Valid activation email. * * @param mailHost * example: imap.gmail.com * @param mailUser * login of mail box * @param mailPassword * password of mail box * @param senderMail * sender of mail box * @param subjectMail * subject of mail box * @param firstCssQuery * the first matching element * @param conditions * list of 'expected' values condition and 'actual' values ({@link com.github.noraui.gherkin.GherkinStepCondition}). * @throws TechnicalException * is throws if you have a technical error (format, configuration, datas, ...) in NoraUi. * Exception with message and with screenshot and with exception if functional error but no screenshot and no exception if technical error. * @throws FailureException * if the scenario encounters a functional error */ @Experimental(name = "validActivationEmail") @RetryOnFailure(attempts = 3, delay = 60) @Conditioned @Et("Je valide le mail d'activation {string}(\\?)") @And("I valid activation email {string}(\\?)") public void validActivationEmail(String mailHost, String mailUser, String mailPassword, String senderMail, String subjectMail, String firstCssQuery, List<GherkinStepCondition> conditions) throws FailureException, TechnicalException { try { final Properties props = System.getProperties(); props.setProperty("mail.store.protocol", "imap"); final Session session = Session.getDefaultInstance(props, null); final Store store = session.getStore("imaps"); store.connect(mailHost, mailUser, mailPassword); final Folder inbox = store.getFolder("Inbox"); inbox.open(Folder.READ_ONLY); final SearchTerm filterA = new FlagTerm(new Flags(Flags.Flag.SEEN), false); final SearchTerm filterB = new FromTerm(new InternetAddress(senderMail)); final SearchTerm filterC = new SubjectTerm(subjectMail); final SearchTerm[] filters = { filterA, filterB, filterC }; final SearchTerm searchTerm = new AndTerm(filters); final Message[] messages = inbox.search(searchTerm); for (final Message message : messages) { validateActivationLink(subjectMail, firstCssQuery, message); } } catch (final Exception e) { new Result.Failure<>("", Messages.format(Messages.getMessage(Messages.FAIL_MESSAGE_MAIL_ACTIVATION), subjectMail), false, Context.getCallBack(Callbacks.RESTART_WEB_DRIVER)); } } /** * @param message * @return * @throws MessagingException * @throws IOException */ private static String getTextFromMessage(Message message) throws MessagingException, IOException { String result = ""; if (message.isMimeType("text/plain")) { result = message.getContent().toString(); } else if (message.isMimeType("multipart/*")) { final MimeMultipart mimeMultipart = (MimeMultipart) message.getContent(); result = getTextFromMimeMultipart(mimeMultipart); } return result; } /** * @param mimeMultipart * @return * @throws MessagingException * @throws IOException */ private static String getTextFromMimeMultipart(MimeMultipart mimeMultipart) throws MessagingException, IOException { final StringBuilder result = new StringBuilder(); final int count = mimeMultipart.getCount(); for (int i = 0; i < count; i++) { final BodyPart bodyPart = mimeMultipart.getBodyPart(i); if (bodyPart.isMimeType("text/plain")) { result.append("\n"); result.append(bodyPart.getContent()); } else if (bodyPart.isMimeType("text/html")) { result.append("\n"); result.append((String) bodyPart.getContent()); } else if (bodyPart.getContent() instanceof MimeMultipart) { result.append(getTextFromMimeMultipart((MimeMultipart) bodyPart.getContent())); } } return result.toString(); } private void validateActivationLink(String subjectMail, String firstCssQuery, Message message) throws MessagingException, IOException, TechnicalException, FailureException { final Document doc = Jsoup.parse(getTextFromMessage(message)); final Element link = doc.selectFirst(firstCssQuery); try { final String response = httpService.get(link.attr("href")); log.debug("response is {}.", response); } catch (final HttpServiceException e) { log.error(Messages.format(Messages.getMessage(Messages.FAIL_MESSAGE_MAIL_ACTIVATION), subjectMail), e); new Result.Failure<>("", Messages.format(Messages.getMessage(Messages.FAIL_MESSAGE_MAIL_ACTIVATION), subjectMail), false, Context.getCallBack(Callbacks.RESTART_WEB_DRIVER)); } } }