/**
  * Verify the email is signed by the given certificate.
  *
  * @param signedData
  * @param mailMsg
  * @return
  * @throws CMSException
  * @throws OperatorCreationException
  * @throws CertificateException
  */
 @SuppressWarnings({"rawtypes"})
 protected boolean isValid(CMSSignedData signedData, MailMessage mailMsg)
     throws OperatorCreationException, CMSException, CertificateException {
   boolean verify = false;
   SignerInformationStore signerStore = signedData.getSignerInfos();
   Iterator<SignerInformation> it = signerStore.getSigners().iterator();
   while (it.hasNext()) {
     SignerInformation signer = it.next();
     org.bouncycastle.util.Store store = signedData.getCertificates();
     @SuppressWarnings("unchecked")
     Collection certCollection = store.getMatches(signer.getSID());
     Iterator certIt = certCollection.iterator();
     X509CertificateHolder certHolder = (X509CertificateHolder) certIt.next();
     X509Certificate certificate =
         new JcaX509CertificateConverter().setProvider(PROVIDER_NAME).getCertificate(certHolder);
     verify =
         signer.verify(
             new JcaSimpleSignerInfoVerifierBuilder()
                 .setProvider(PROVIDER_NAME)
                 .build(certificate));
     mailMsg.setHasSignature(true);
     mailMsg.setSignaturePassed(verify);
     mailMsg.setNameOfPrincipal(certificate.getSubjectDN().getName());
   }
   return verify;
 }
  /**
   * Process the MimeMessage for simple mail with/without attachment.
   *
   * @param mime
   * @param mailMsg
   * @return
   * @throws IOException
   * @throws MessagingException
   * @throws ParseException
   */
  private String processSimpleMail(MimeMessage mime, MailMessage mailMsg)
      throws IOException, MessagingException, ParseException {
    mailMsg.setHasSignature(false);
    mailMsg.setSignaturePassed(false);
    this.setMailBasicInfoForMailMsg(mime, mailMsg);

    String txtBody = null;
    String htmlBody = null;
    if (mime.isMimeType("text/plain")) {
      txtBody = mime.getContent().toString();
    } else if (mime.isMimeType("text/html")) {
      htmlBody = mime.getContent().toString();
    } else if (mime.getContent() instanceof Multipart) {
      // Get the content of the messsage, it's an Multipart object like a package including all the
      // email text and attachments.
      Multipart multi = (Multipart) mime.getContent();
      // First, verify the quantity and size of attachments.
      boolean isValidMailMsg = this.isValidMailMsg(multi);
      if (isValidMailMsg) {
        // process each part in order.
        for (int i = 0, n = multi.getCount(); i < n; i++) {
          // unpack, get each part of Multipart, part 0 may email text and part 1 may attachment. Or
          // it is another embedded Multipart.
          Part part1 = multi.getBodyPart(i);
          if (part1.isMimeType("text/plain")
              && !Part.ATTACHMENT.equalsIgnoreCase(part1.getDisposition())) {
            txtBody = part1.getContent().toString();
          } else if (part1.isMimeType("text/html")
              && !Part.ATTACHMENT.equalsIgnoreCase(part1.getDisposition())) {
            htmlBody = part1.getContent().toString();
          } else if (part1.isMimeType("multipart/alternative")) {
            // generally if the content type multipart/alternative, it is email text.
            if (part1.getContent() instanceof Multipart) {
              Multipart multi1 = (Multipart) part1.getContent();
              for (int k = 0; k < multi1.getCount(); k++) {
                Part part2 = multi1.getBodyPart(k);
                if (part2.isMimeType("text/plain")
                    && !Part.ATTACHMENT.equalsIgnoreCase(part2.getDisposition())) {
                  txtBody = part2.getContent().toString();
                } else if (part2.isMimeType("text/html")
                    && !Part.ATTACHMENT.equalsIgnoreCase(part2.getDisposition())) {
                  htmlBody = part2.getContent().toString();
                }
              }
            }
          } else if (part1.isMimeType("multipart/related")) {
            if (part1.getContent() instanceof Multipart) {
              Multipart multi1 = (Multipart) part1.getContent();
              for (int m = 0; m < multi1.getCount(); m++) {
                Part part2 = multi1.getBodyPart(m);
                if (part2.isMimeType("multipart/alternative")) {
                  if (part2.getContent() instanceof Multipart) {
                    Multipart multi2 = (Multipart) part2.getContent();
                    for (int p = 0; p < multi2.getCount(); p++) {
                      Part part3 = multi2.getBodyPart(p);
                      if (part3.isMimeType("text/plain")
                          && !Part.ATTACHMENT.equalsIgnoreCase(part3.getDisposition())) {
                        txtBody = part3.getContent().toString();
                      } else if (part3.isMimeType("text/html")
                          && !Part.ATTACHMENT.equalsIgnoreCase(part3.getDisposition())) {
                        htmlBody = part3.getContent().toString();
                      }
                    }
                  }
                } else if (part2.isMimeType("text/plain")
                    && !Part.ATTACHMENT.equalsIgnoreCase(part2.getDisposition())) {
                  txtBody = part2.getContent().toString();
                } else if (part2.isMimeType("text/html")
                    && !Part.ATTACHMENT.equalsIgnoreCase(part2.getDisposition())) {
                  htmlBody = part2.getContent().toString();
                } else {
                  // This is an embedded picture, set it as an attachment.
                  mailMsg.setHasAttachments(true);
                }
              }
            }
          } else {
            String disposition = part1.getDisposition();
            if (disposition != null && Part.ATTACHMENT.equalsIgnoreCase(disposition)) {
              mailMsg.setHasAttachments(true);
            }
          }
        }
      }
    }
    if (!isNull(txtBody)) {
      mailMsg.setBody(txtBody);
    } else {
      mailMsg.setBody(htmlBody);
    }
    return JSONObject.fromObject(mailMsg).toString();
  }