/**
   * Override some fields in the JavaMailer class. TODO: This needs re-factoring!
   *
   * @param mailParms
   * @param sendMailer
   */
  private void overRideDefaultProperties(
      final MailTransportParameters mailParms, final JavaMailer sendMailer) {
    sendMailer.setFrom(mailParms.getSendTestFrom());

    sendMailer.getSession().setDebug(mailParms.isSendTestDebug());
    sendMailer.setDebug(mailParms.isSendTestDebug());

    sendMailer.setEncoding(mailParms.getSendTestMessageEncoding());
    sendMailer.setMailer(mailParms.getSendTestMailer());
    sendMailer.setMailHost(mailParms.getSendTestHost());

    // char_set, encoding, m_contentType
    sendMailer.setMessageText(mailParms.getSendTestMessageBody());
    sendMailer.setCharSet(mailParms.getSendTestCharSet());
    sendMailer.setContentType(mailParms.getSendTestMessageContentType());

    sendMailer.setSmtpSsl(mailParms.isSendTestIsSslEnable());

    sendMailer.setSubject(mailParms.getComputedTestSubject());
    sendMailer.setTo(mailParms.getSendTestRecipeint());
    sendMailer.setTransport(mailParms.getSendTestTransport());
    sendMailer.setUseJMTA(mailParms.isSendTestUseJmta());
  }
  /**
   * This sets up the properties for the read mail portion of the service poll. These properties are
   * derived from configuration elements vs. being hardcoded javamail properties. Elements that
   * conflict with javamail defined properties always win.
   *
   * @param mailParms
   * @param readMailer
   */
  private void setReadMailProperties(
      final MailTransportParameters mailParms, final JavaMailer readMailer) {
    final Properties sendMailProps = readMailer.getSession().getProperties();

    final String protocol = mailParms.getReadTestProtocol();
    sendMailProps.put("mail." + protocol + ".host", mailParms.getReadTestHost());
    sendMailProps.put("mail." + protocol + ".user", mailParms.getReadTestUserName());
    sendMailProps.put("mail." + protocol + ".port", mailParms.getReadTestPort());
    sendMailProps.put(
        "mail." + protocol + ".starttls.enable", mailParms.isReadTestStartTlsEnabled());
    sendMailProps.put("mail.smtp.auth", "true");

    if (mailParms.isReadTestSslEnabled()) {
      sendMailProps.put("mail." + protocol + ".socketFactory.port", mailParms.getReadTestPort());
      sendMailProps.put(
          "mail." + protocol + ".socketFactory.class", "javax.net.ssl.SSLSocketFactory");
      sendMailProps.put("mail." + protocol + ".socketFactory.fallback", "false");
    }

    sendMailProps.put("mail." + protocol + ".connectiontimeout", mailParms.getTimeout());
    sendMailProps.put("mail." + protocol + ".timeout", mailParms.getTimeout());

    sendMailProps.put("mail.store.protocol", protocol);
  }
  private JavaMailer createMailer(final MailTransportParameters mailParms)
      throws JavaMailerException {
    final JavaMailer sendMailer = new JavaMailer(mailParms.getJavamailProperties());
    final String mailPropsPrefix =
        new StringBuilder("mail.").append(mailParms.getSendTestTransport()).append('.').toString();
    final Properties props = sendMailer.getSession().getProperties();

    // user
    props.setProperty(mailPropsPrefix + "user", mailParms.getSendTestUserName());
    sendMailer.setUser(mailParms.getSendTestUserName());
    sendMailer.setPassword(mailParms.getSendTestPassword());

    // host
    props.setProperty(mailPropsPrefix + "host", mailParms.getSendTestHost());
    sendMailer.setMailHost(mailParms.getSendTestHost());

    // port
    props.setProperty(mailPropsPrefix + "port", String.valueOf(mailParms.getSendTestPort()));
    sendMailer.setSmtpPort(mailParms.getSendTestPort());

    // connectiontimeout
    // Override this with configured javamail property because this setting is a generic timeout
    // value
    if (!props.containsKey(mailPropsPrefix + "connectiontimeout")) {
      props.setProperty(
          mailPropsPrefix + "connectiontimeout", String.valueOf(mailParms.getTimeout()));
    }

    // timeout
    // Override this with configured javamail property because this setting is a generic timeout
    // value
    if (!props.containsKey(mailPropsPrefix + "timeout")) {
      props.setProperty(mailPropsPrefix + "timeout", String.valueOf(mailParms.getTimeout()));
    }

    // from
    props.setProperty(mailPropsPrefix + "from", mailParms.getSendTestFrom());
    sendMailer.setFrom(mailParms.getSendTestFrom());

    // auth
    props.setProperty(mailPropsPrefix + "auth", String.valueOf(mailParms.isSendTestUseAuth()));
    sendMailer.setAuthenticate(mailParms.isSendTestUseAuth());

    // quitwait
    props.setProperty(
        mailPropsPrefix + "quitwait", String.valueOf(mailParms.isSendTestIsQuitWait()));
    sendMailer.setQuitWait(mailParms.isSendTestIsQuitWait());

    // socketFactory.class
    // socketFactory.port
    if (mailParms.isSendTestIsSslEnable()) {

      // override this hard coded default if this property is specified
      if (!props.containsKey(mailPropsPrefix + "socketFactory.class")) {
        props.setProperty(
            mailPropsPrefix + "socketFactory.class", "javax.net.ssl.SSLSocketFactory");
      }
      props.setProperty(
          mailPropsPrefix + "socketFactory.port", String.valueOf(mailParms.getSendTestPort()));
      sendMailer.setSmtpPort(mailParms.getSendTestPort());
    }
    sendMailer.setSmtpSsl(mailParms.isSendTestIsSslEnable());

    // starttls.enable
    props.setProperty(
        mailPropsPrefix + "starttls.enable", String.valueOf(mailParms.isSendTestStartTls()));
    sendMailer.setStartTlsEnabled(mailParms.isSendTestStartTls());
    sendMailer.addExtraHeader(MTM_HEADER_KEY, m_headerValue);

    sendMailer.setSession(Session.getInstance(props, sendMailer.createAuthenticator()));

    return sendMailer;
  }
  private PollStatus readTestMessage(final MailTransportParameters mailParms) {
    LOG.debug("readTestMessage: Beginning read mail test.");
    PollStatus status = PollStatus.unavailable("Test not completed.");

    final long interval = mailParms.getReadTestAttemptInterval();

    if (mailParms.isEnd2EndTestInProgress()) {
      LOG.debug(
          "Initially delaying read test: {} because end to end test is in progress.",
          mailParms.getReadTestAttemptInterval());

      if (delayTest(status, interval) == PollStatus.SERVICE_UNKNOWN) {
        return status;
      }
    }

    Store mailStore = null;
    Folder mailFolder = null;
    try {
      final JavaMailer readMailer = new JavaMailer(mailParms.getJavamailProperties());
      setReadMailProperties(mailParms, readMailer);

      final TimeoutTracker tracker =
          new TimeoutTracker(
              mailParms.getParameterMap(), mailParms.getRetries(), mailParms.getTimeout());
      for (tracker.reset(); tracker.shouldRetry(); tracker.nextAttempt()) {
        tracker.startAttempt();

        if (tracker.getAttempt() > 0) {
          if (delayTest(status, interval) == PollStatus.SERVICE_UNKNOWN) {
            LOG.warn("readTestMessage: Status set to: {} during delay, exiting test.", status);
            break;
          }
        }
        LOG.debug(
            "readTestMessage: reading mail attempt: {}, elapsed time: {}ms.",
            (tracker.getAttempt() + 1),
            String.format("%.2f", tracker.elapsedTimeInMillis()));
        try {
          mailStore = readMailer.getSession().getStore();
          mailFolder = retrieveMailFolder(mailParms, mailStore);
          mailFolder.open(Folder.READ_WRITE);
        } catch (final MessagingException e) {
          if (tracker.shouldRetry()) {
            LOG.warn("readTestMessage: error reading INBOX", e);
            closeStore(mailStore, mailFolder);
            continue; // try again to get mail Folder from Store
          } else {
            LOG.warn("readTestMessage: error reading INBOX", e);
            return PollStatus.down(e.getLocalizedMessage());
          }
        }
        if (mailFolder.isOpen()
            && (mailParms.getReadTest().getSubjectMatch() != null
                || mailParms.isEnd2EndTestInProgress())) {
          status = processMailSubject(mailParms, mailFolder);
          if (status.getStatusCode() == PollStatus.SERVICE_AVAILABLE) {
            break;
          }
        }
      }

    } catch (final JavaMailerException e) {
      status = PollStatus.down(e.getLocalizedMessage());
    } finally {
      closeStore(mailStore, mailFolder);
    }
    return status;
  }