class SimpleEmailService implements EmailService {

    @Override
    public CompletableFuture<Set<String>> sendEmail(String subject, String htmlMessage, String... userEmails) {
        CompletableFuture<Set<String>> emailSendResult = CompletableFuture.supplyAsync(() -> setUpEmail())
                .thenApply(email -> {
                    Set<String> invalidEmails = new HashSet<>();
                    email.setSubject(subject);
                    String htmlMsg = emailTemplate.replace(emailTemplate.substring(emailTemplate.indexOf(BODY_BINDING),
                            emailTemplate.lastIndexOf(BODY_BINDING) + BODY_BINDING.length()), htmlMessage);
                    htmlMsg = htmlMsg.replace(LOGO_BINDING, logo.toString());
                    if (mobiServer.getHostName().endsWith("/")) {
                        htmlMsg = htmlMsg.replace(HOSTNAME_BINDING, mobiServer.getHostName());
                    } else {
                        htmlMsg = htmlMsg.replace(HOSTNAME_BINDING, mobiServer.getHostName() + "/");
                    }
                    try {
                        email.setHtmlMsg(htmlMsg);
                    } catch (EmailException e) {
                        throw new MobiException("Unable to set HTML Message content", e);
                    }
                    if (userEmails.length == 1) {
                        try {
                            email.addTo(userEmails[0]);
                        } catch (EmailException e) {
                            invalidEmails.add(userEmails[0]);
                            LOGGER.info("Invalid email address.", e);
                            return invalidEmails;
                        }
                    } else {
                        for (String userEmail : userEmails) {
                            try {
                                email.addBcc(userEmail);
                            } catch (EmailException e) {
                                invalidEmails.add(userEmail);
                                LOGGER.info("Invalid email address.", e);
                            }
                        }
                    }
                    try {
                        email.buildMimeMessage();
                        LOGGER.debug("Sending email to: " + Arrays.toString(userEmails));
                        LOGGER.debug("With a subject of: " + subject);
                        LOGGER.debug("And a body of: " + htmlMsg);
                    } catch (EmailException e) {
                        LOGGER.error("Unable to buld MIME message", e);
                        throw new MobiException("Unable to build MIME message.", e);
                    }
                    int repeatTries = 2;
                    while (repeatTries > 0) {
                        try {
                            Thread.currentThread().setContextClassLoader(javax.mail.Session.class.getClassLoader());
                            email.sendMimeMessage();
                            break;
                        } catch (EmailException e) {
                            if (--repeatTries < 1) {
                                LOGGER.error("Could not send email.", e);
                                throw new MobiException("Could not send email.", e);
                            }
                            LOGGER.info("Could not send email. Attempting retry.");
                        }
                    }

                    return invalidEmails;
                });
        return emailSendResult;
    }

}