/** Manages a display request. */
  private void manageDisplayRequest(Mail mail) throws MessagingException {
    MailAddress senderMailAddress = mail.getSender();
    String senderUser = senderMailAddress.getLocalPart().toLowerCase(Locale.US);
    String senderHost = senderMailAddress.getDomain().toLowerCase(Locale.US);

    senderUser = getPrimaryName(senderUser);

    Connection conn = null;
    PreparedStatement selectStmt = null;
    ResultSet selectRS = null;

    StringWriter sout = new StringWriter();
    PrintWriter out = new PrintWriter(sout, true);

    try {
      out.println("Answering on behalf of: " + whitelistManagerAddress);
      out.println("Displaying white list of " + (new MailAddress(senderUser, senderHost)) + ":");
      out.println();

      conn = datasource.getConnection();
      selectStmt = conn.prepareStatement(selectBySender);
      selectStmt.setString(1, senderUser);
      selectStmt.setString(2, senderHost);
      selectRS = selectStmt.executeQuery();
      while (selectRS.next()) {
        MailAddress mailAddress = new MailAddress(selectRS.getString(1), selectRS.getString(2));
        out.println(mailAddress.toInternetAddress().toString());
      }

      out.println();
      out.println("Finished");

      sendReplyFromPostmaster(mail, sout.toString());

    } catch (SQLException sqle) {
      out.println("Error accessing the database");
      sendReplyFromPostmaster(mail, sout.toString());
      throw new MessagingException("Error accessing database", sqle);
    } finally {
      theJDBCUtil.closeJDBCResultSet(selectRS);
      theJDBCUtil.closeJDBCStatement(selectStmt);
      theJDBCUtil.closeJDBCConnection(conn);
    }
  }
  /** Manages a remove request. */
  private void manageRemoveRequest(Mail mail) throws MessagingException {
    MailAddress senderMailAddress = mail.getSender();
    String senderUser = senderMailAddress.getLocalPart().toLowerCase(Locale.US);
    String senderHost = senderMailAddress.getDomain().toLowerCase(Locale.US);

    senderUser = getPrimaryName(senderUser);

    Connection conn = null;
    PreparedStatement selectStmt = null;
    PreparedStatement deleteStmt = null;
    boolean dbUpdated = false;

    StringWriter sout = new StringWriter();
    PrintWriter out = new PrintWriter(sout, true);

    try {
      out.println("Answering on behalf of: " + whitelistManagerAddress);
      out.println(
          "Removing from the white list of " + (new MailAddress(senderUser, senderHost)) + " ...");
      out.println();

      MimeMessage message = mail.getMessage();

      Object content = message.getContent();

      if (message.getContentType().startsWith("text/plain") && content instanceof String) {
        StringTokenizer st = new StringTokenizer((String) content, " \t\n\r\f,;:<>");
        while (st.hasMoreTokens()) {
          ResultSet selectRS = null;
          try {
            MailAddress recipientMailAddress;
            try {
              recipientMailAddress = new MailAddress(st.nextToken());
            } catch (javax.mail.internet.ParseException pe) {
              continue;
            }
            String recipientUser = recipientMailAddress.getLocalPart().toLowerCase(Locale.US);
            String recipientHost = recipientMailAddress.getDomain().toLowerCase(Locale.US);

            if (getMailetContext().isLocalServer(recipientHost)) {
              // not a remote recipient, so skip
              continue;
            }

            if (conn == null) {
              conn = datasource.getConnection();
            }

            if (selectStmt == null) {
              selectStmt = conn.prepareStatement(selectByPK);
            }
            selectStmt.setString(1, senderUser);
            selectStmt.setString(2, senderHost);
            selectStmt.setString(3, recipientUser);
            selectStmt.setString(4, recipientHost);
            selectRS = selectStmt.executeQuery();
            if (!selectRS.next()) {
              // This address was not in the list
              out.println("Skipped: " + recipientMailAddress);
              continue;
            }

            if (deleteStmt == null) {
              deleteStmt = conn.prepareStatement(deleteByPK);
            }
            deleteStmt.setString(1, senderUser);
            deleteStmt.setString(2, senderHost);
            deleteStmt.setString(3, recipientUser);
            deleteStmt.setString(4, recipientHost);
            deleteStmt.executeUpdate();
            dbUpdated = true;
            out.println("Removed: " + recipientMailAddress);

          } finally {
            theJDBCUtil.closeJDBCResultSet(selectRS);
          }
        }

        if (dbUpdated) {
          log("Removal request issued by " + senderMailAddress);
        }
        // Commit our changes if necessary.
        if (conn != null && dbUpdated && !conn.getAutoCommit()) {
          conn.commit();
          dbUpdated = false;
        }
      } else {
        out.println("The message must be plain - no action");
      }

      out.println();
      out.println("Finished");

      sendReplyFromPostmaster(mail, sout.toString());

    } catch (SQLException sqle) {
      out.println("Error accessing the database");
      sendReplyFromPostmaster(mail, sout.toString());
      throw new MessagingException("Error accessing the database", sqle);
    } catch (IOException ioe) {
      out.println("Error getting message content");
      sendReplyFromPostmaster(mail, sout.toString());
      throw new MessagingException("Error getting message content", ioe);
    } finally {
      theJDBCUtil.closeJDBCStatement(selectStmt);
      theJDBCUtil.closeJDBCStatement(deleteStmt);
      // Rollback our changes if necessary.
      try {
        if (conn != null && dbUpdated && !conn.getAutoCommit()) {
          conn.rollback();
          dbUpdated = false;
        }
      } catch (Exception e) {
      }
      theJDBCUtil.closeJDBCConnection(conn);
    }
  }
  /**
   * Loops through each address in the recipient list, checks if in the senders list and inserts in
   * it otherwise.
   */
  private void checkAndInsert(MailAddress senderMailAddress, Collection<MailAddress> recipients)
      throws MessagingException {
    String senderUser = senderMailAddress.getLocalPart().toLowerCase(Locale.US);
    String senderHost = senderMailAddress.getDomain().toLowerCase(Locale.US);

    senderUser = getPrimaryName(senderUser);

    Connection conn = null;
    PreparedStatement selectStmt = null;
    PreparedStatement insertStmt = null;
    boolean dbUpdated = false;

    try {

      for (MailAddress recipient : recipients) {
        ResultSet selectRS = null;
        try {
          String recipientUser = recipient.getLocalPart().toLowerCase(Locale.US);
          String recipientHost = recipient.getDomain().toLowerCase(Locale.US);

          if (getMailetContext().isLocalServer(recipientHost)) {
            // not a remote recipient, so skip
            continue;
          }

          if (conn == null) {
            conn = datasource.getConnection();
          }

          if (selectStmt == null) {
            selectStmt = conn.prepareStatement(selectByPK);
          }
          selectStmt.setString(1, senderUser);
          selectStmt.setString(2, senderHost);
          selectStmt.setString(3, recipientUser);
          selectStmt.setString(4, recipientHost);
          selectRS = selectStmt.executeQuery();
          if (selectRS.next()) {
            // This address was already in the list
            continue;
          }

          if (insertStmt == null) {
            insertStmt = conn.prepareStatement(insert);
          }
          insertStmt.setString(1, senderUser);
          insertStmt.setString(2, senderHost);
          insertStmt.setString(3, recipientUser);
          insertStmt.setString(4, recipientHost);
          insertStmt.executeUpdate();
          dbUpdated = true;

        } finally {
          theJDBCUtil.closeJDBCResultSet(selectRS);
        }

        // Commit our changes if necessary.
        if (conn != null && dbUpdated && !conn.getAutoCommit()) {
          conn.commit();
          dbUpdated = false;
        }
      }
    } catch (SQLException sqle) {
      log("Error accessing database", sqle);
      throw new MessagingException("Exception thrown", sqle);
    } finally {
      theJDBCUtil.closeJDBCStatement(selectStmt);
      theJDBCUtil.closeJDBCStatement(insertStmt);
      // Rollback our changes if necessary.
      try {
        if (conn != null && dbUpdated && !conn.getAutoCommit()) {
          conn.rollback();
          dbUpdated = false;
        }
      } catch (Exception e) {
      }
      theJDBCUtil.closeJDBCConnection(conn);
    }
  }