protected void loadChildren() {
    try {
      // connect to the Store if we need to
      if (!store.isConnected()) {
        store.connect();
      }

      // get the default folder, and list the
      // subscribed folders on it
      folder = store.getDefaultFolder();
      // Folder[] sub = folder.listSubscribed();
      Folder[] sub = folder.list();

      // add a FolderTreeNode for each Folder
      int num = sub.length;
      for (int i = 0; i < num; i++) {
        FolderTreeNode node = new FolderTreeNode(sub[i]);
        // we used insert here, since add() would make
        // another recursive call to getChildCount();
        insert(node, i);
      }

    } catch (MessagingException me) {
      me.printStackTrace();
    }
  }
  /**
   * @return
   * @throws Exception
   */
  public synchronized Folder getFolder() throws Exception {
    String folder = Constants.FOLDER_INBOX(profile);

    Folder fold = (Folder) pop3Folders.get(auth.getUsername());
    if (fold != null && fold.isOpen()) {
      return fold;
    } else {
      if (folder != null && handler != null) {
        Store store = handler.getStore();
        if (store == null || !store.isConnected()) {
          System.out.println("Connection is closed. Restoring it...");
          handler = connect(Constants.CONNECTION_READ_WRITE);
          System.out.println("Connection re-established");
        }
        fold = handler.getStore().getFolder(folder);
        if (!fold.isOpen()) {
          System.out.println("Folder :" + folder + " is closed. Opening again.");
          fold.open(Constants.CONNECTION_READ_WRITE);
          System.out.println("Folder is open again.");

          pop3Folders.put(auth.getUsername(), fold);
        }
      }
    }
    return fold;
  }
  protected void checkStoreForTestConnection(final Store store) {
    if (!store.isConnected()) {
      IMAPUtils.close(store);
      throw new RuntimeException("Store not connected");
    }

    if (!store.getURLName().getUsername().toLowerCase().startsWith("es_imapriver_unittest")) {
      IMAPUtils.close(store);
      throw new RuntimeException(
          "User "
              + store.getURLName().getUsername()
              + " belongs not to a valid test mail connection");
    }
  }
 /**
  * Handy method to do the try catch try of closing a mail store and folder.
  *
  * @param mailStore
  * @param mailFolder
  */
 private void closeStore(final Store mailStore, final Folder mailFolder) {
   try {
     if (mailFolder != null && mailFolder.isOpen()) {
       mailFolder.close(true);
     }
   } catch (final MessagingException e) {
     LOG.debug("Unable to close mail folder.", e);
   } finally {
     try {
       if (mailStore != null && mailStore.isConnected()) {
         mailStore.close();
       }
     } catch (final MessagingException e1) {
       LOG.debug("Unable to close message store.", e1);
     }
   }
 }
Example #5
0
  /**
   * @return
   * @throws Exception
   */
  public Folder getImapFolder(boolean useCache) throws Exception {
    Folder myFold = null;
    if (folder == null) {
      folder = Constants.FOLDER_INBOX(profile);
    }

    if (folder != null && handler != null) {
      Store store = handler.getStore();
      if (store == null || !store.isConnected()) {
        log.debug("Connection is closed. Restoring it...");
        handler = connect(Constants.CONNECTION_READ_WRITE);
        log.debug("Connection re-established");
      }

      HashMap imapUserFolders = null;
      if (useCache) {
        imapUserFolders = (HashMap) imapFolders.get(auth.getUsername());
        myFold = (Folder) imapUserFolders.get(folder);
      }
      if (myFold == null) {
        myFold = handler.getStore().getFolder(folder);
      }
      if (!myFold.isOpen()) {
        try {
          log.debug("Folder :" + folder + " is closed. Opening.");
          myFold.open(Constants.CONNECTION_READ_WRITE);
          log.debug("Folder is open.");
        } catch (Throwable e) {
          log.debug("nevermind go on");
          // nevermind go on...
        }
      }
      if (useCache) {
        try {
          imapUserFolders.put(folder, myFold);
          imapFolders.put(auth.getUsername(), imapUserFolders);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
    return myFold;
  }
  public Store getStore(boolean useOldStores) throws MailException {
    Store store = null;

    try {
      String storeKey = _incomingHostName.concat(_outgoingHostName).concat(_login);

      if (useOldStores) {
        store = _allStores.get(storeKey);

        if ((store != null) && !store.isConnected()) {
          store.close();

          store = null;
        }
      }

      if (store == null) {
        Session session = getSession();

        if (_incomingSecure) {
          store = session.getStore("imaps");
        } else {
          store = session.getStore("imap");
        }

        store.addConnectionListener(new ConnectionListener(storeKey));
        store.connect(_incomingHostName, _incomingPort, _login, _password);

        if (useOldStores) {
          _allStores.put(storeKey, store);
        }
      }

      return store;
    } catch (MessagingException me) {
      throw new MailException(MailException.ACCOUNT_INCOMING_CONNECTION_FAILED, me);
    }
  }
  public static Store connect2Server(URLName url, ParseContext context) throws MessagingException {

    ImapCrawlerContext imapCrawlerContext =
        context.get(ImapCrawlerContext.class, new ImapCrawlerContext());

    Properties properties = System.getProperties();

    properties.setProperty("mail.store.protocol", url.getProtocol());

    if (imapCrawlerContext.getIgnoreSSLCertificates()) {
      properties.setProperty(
          "mail.imaps.socketFactory.class", CertificateIgnoringSocketFactory.class.getName());
      properties.setProperty("mail.imaps.socketFactory.fallback", "false");
    }

    if (!StringUtils.nullOrWhitespace(imapCrawlerContext.getSSLCertificateFilePath())
        && "imaps".equalsIgnoreCase(url.getProtocol())) {
      properties.setProperty(
          "javax.net.ssl.trustStore", imapCrawlerContext.getSSLCertificateFilePath());
      properties.setProperty(
          "javax.net.ssl.trustStorePassword", imapCrawlerContext.getSSLCertificateFilePassword());
    }

    Session session = Session.getDefaultInstance(properties);
    Store mailStore = session.getStore(url.getProtocol());

    String strUserName = imapCrawlerContext.getUserName();
    if (strUserName == null) strUserName = url.getUsername();

    String strPassword = imapCrawlerContext.getPassword();
    if (strPassword == null) strPassword = url.getPassword();

    if (!mailStore.isConnected())
      mailStore.connect(url.getHost(), url.getPort(), strUserName, strPassword);

    return mailStore;
  }
    public void run() {
      Thread.currentThread().setContextClassLoader(getClass().getClassLoader());

      if (!circuitBreaker.isOn()) return; // Don't try - circuit breaker is off

      boolean expunge = config.configuration().deleteMailOnInboxClose().get();
      if (config.configuration().debug().get()) {
        logger.info("Checking email");
        logger.info("Delete mail on close - " + expunge);
      }

      Session session = javax.mail.Session.getInstance(props, authenticator);
      session.setDebug(config.configuration().debug().get());

      Usecase usecase = newUsecase("Receive Mail");
      UnitOfWork uow = null;
      Store store = null;
      Folder inbox = null;
      Folder archive = null;
      boolean archiveExists = false;
      List<Message> copyToArchive = new ArrayList<Message>();
      MimeMessage internalMessage = null;

      try {
        store = session.getStore(url);
        store.connect();

        inbox = store.getFolder("INBOX");
        inbox.open(Folder.READ_WRITE);

        javax.mail.Message[] messages = inbox.getMessages();
        FetchProfile fp = new FetchProfile();
        //            fp.add( "In-Reply-To" );
        inbox.fetch(messages, fp);

        // check if the archive folder is configured and exists
        if (!Strings.empty(config.configuration().archiveFolder().get())
            && config.configuration().protocol().get().startsWith("imap")) {
          archive = store.getFolder(config.configuration().archiveFolder().get());

          // if not exists - create
          if (!archive.exists()) {
            archive.create(Folder.HOLDS_MESSAGES);
            archiveExists = true;
          } else {
            archiveExists = true;
          }

          archive.open(Folder.READ_WRITE);
        }

        for (javax.mail.Message message : messages) {
          int tries = 0;
          while (tries < 3) {
            uow = module.unitOfWorkFactory().newUnitOfWork(usecase);

            ValueBuilder<EmailValue> builder =
                module.valueBuilderFactory().newValueBuilder(EmailValue.class);

            try {
              // Force a complete fetch of the message by cloning it to a internal MimeMessage
              // to avoid "javax.mail.MessagingException: Unable to load BODYSTRUCTURE" problems
              // f.ex. experienced if the message contains a windows .eml file as attachment!

              // Beware that all flag and folder operations have to be made on the original message
              // and not on the internal one!!
              internalMessage = new MimeMessage((MimeMessage) message);

              Object content = internalMessage.getContent();

              // Get email fields
              builder
                  .prototype()
                  .from()
                  .set(((InternetAddress) internalMessage.getFrom()[0]).getAddress());
              builder
                  .prototype()
                  .fromName()
                  .set(((InternetAddress) internalMessage.getFrom()[0]).getPersonal());
              builder
                  .prototype()
                  .subject()
                  .set(internalMessage.getSubject() == null ? "" : internalMessage.getSubject());

              // Get headers
              for (Header header :
                  Iterables.iterable((Enumeration<Header>) internalMessage.getAllHeaders())) {
                builder.prototype().headers().get().put(header.getName(), header.getValue());
              }

              // Get all recipients in order - TO, CC, BCC
              // and provide it to the toaddress method to pick the first possible valid adress
              builder
                  .prototype()
                  .to()
                  .set(
                      toaddress(
                          internalMessage.getAllRecipients(),
                          builder.prototype().headers().get().get("References")));

              builder.prototype().messageId().set(internalMessage.getHeader("Message-ID")[0]);

              // Get body and attachments
              String body = "";
              // set content initially so it never can become null
              builder.prototype().content().set(body);

              if (content instanceof String) {
                body = content.toString();
                builder.prototype().content().set(body);
                String contentTypeString = cleanContentType(internalMessage.getContentType());
                builder.prototype().contentType().set(contentTypeString);
                if (Translator.HTML.equalsIgnoreCase(contentTypeString)) {
                  builder.prototype().contentHtml().set(body);
                }

              } else if (content instanceof Multipart) {
                handleMultipart((Multipart) content, internalMessage, builder);
              } else if (content instanceof InputStream) {
                content = new MimeMessage(session, (InputStream) content).getContent();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                Inputs.byteBuffer((InputStream) content, 4096).transferTo(Outputs.byteBuffer(baos));

                String data = new String(baos.toByteArray(), "UTF-8");
                // Unknown content type - abort
                // and create failure case
                String subj = "Unkonwn content type: " + internalMessage.getSubject();
                builder
                    .prototype()
                    .subject()
                    .set(subj.length() > 50 ? subj.substring(0, 50) : subj);
                builder.prototype().content().set(body);
                builder.prototype().contentType().set(internalMessage.getContentType());
                systemDefaults.createCaseOnEmailFailure(builder.newInstance());
                copyToArchive.add(message);
                if (expunge) message.setFlag(Flags.Flag.DELETED, true);

                uow.discard();
                tries = 3;
                continue;
              } else {
                // Unknown content type - abort
                // and create failure case
                String subj = "Unkonwn content type: " + internalMessage.getSubject();
                builder
                    .prototype()
                    .subject()
                    .set(subj.length() > 50 ? subj.substring(0, 50) : subj);
                builder.prototype().content().set(body);
                builder.prototype().contentType().set(internalMessage.getContentType());
                systemDefaults.createCaseOnEmailFailure(builder.newInstance());
                copyToArchive.add(message);
                if (expunge) message.setFlag(Flags.Flag.DELETED, true);

                uow.discard();
                logger.error(
                    "Could not parse emails: unknown content type " + content.getClass().getName());
                tries = 3;
                continue;
              }

              // make sure mail content fit's into statistic database - truncate on 65.500
              // characters.
              if (builder.prototype().content().get().length() > 65000) {
                builder
                    .prototype()
                    .content()
                    .set(builder.prototype().content().get().substring(0, 65000));
              }

              // try to reveal if it is a smpt error we are looking at
              // X-Failed-Recipients is returned by Gmail
              // X-FC-MachineGenerated is returned by FirstClass
              // Exchange is following RFC 6522 -  The Multipart/Report Media Type for
              // the Reporting of Mail System Administrative Messages
              boolean isSmtpErrorReport =
                  !Strings.empty(builder.prototype().headers().get().get("X-Failed-Recipients"))
                      || (!Strings.empty(
                              builder.prototype().headers().get().get("X-FC-MachineGenerated"))
                          && "true"
                              .equals(
                                  builder.prototype().headers().get().get("X-FC-MachineGenerated")))
                      || !Strings.empty(
                          new ContentType(builder.prototype().headers().get().get("Content-Type"))
                              .getParameter("report-type"));

              if (isSmtpErrorReport) {
                // This is a mail bounce due to SMTP error - create support case.
                String subj = "Undeliverable mail: " + builder.prototype().subject().get();

                builder
                    .prototype()
                    .subject()
                    .set(subj.length() > 50 ? subj.substring(0, 50) : subj);
                systemDefaults.createCaseOnEmailFailure(builder.newInstance());
                copyToArchive.add(message);
                if (expunge) message.setFlag(Flags.Flag.DELETED, true);

                uow.discard();
                logger.error("Received a mail bounce reply: " + body);
                tries = 3;
                continue;
              }

              if (builder.prototype().to().get().equals("n/a")) {
                // This is a mail has no to address - create support case.

                String subj = "No TO address: " + builder.prototype().subject().get();

                builder
                    .prototype()
                    .subject()
                    .set(subj.length() > 50 ? subj.substring(0, 50) : subj);
                systemDefaults.createCaseOnEmailFailure(builder.newInstance());
                copyToArchive.add(message);
                if (expunge) message.setFlag(Flags.Flag.DELETED, true);

                uow.discard();
                logger.error("Received a mail without TO address: " + body);
                tries = 3;
                continue;
              }

              mailReceiver.receivedEmail(null, builder.newInstance());

              try {
                logger.debug("This is try " + tries);
                uow.complete();
                tries = 3;
              } catch (ConcurrentEntityModificationException ceme) {
                if (tries < 2) {
                  logger.debug("Encountered ConcurrentEntityModificationException - try again ");
                  // discard uow and try again
                  uow.discard();
                  tries++;
                  continue;

                } else {
                  logger.debug("Rethrowing ConcurrentEntityModification.Exception");
                  tries++;
                  throw ceme;
                }
              }

              copyToArchive.add(message);
              // remove mail on success if expunge is true
              if (expunge) message.setFlag(Flags.Flag.DELETED, true);

            } catch (Throwable e) {
              String subj = "Unknown error: " + internalMessage.getSubject();
              builder.prototype().subject().set(subj.length() > 50 ? subj.substring(0, 50) : subj);

              StringBuilder content = new StringBuilder();
              content.append("Error Message: " + e.getMessage());
              content.append("\n\rStackTrace:\n\r");
              for (StackTraceElement trace : Arrays.asList(e.getStackTrace())) {
                content.append(trace.toString() + "\n\r");
              }

              builder.prototype().content().set(content.toString());
              // since we create the content of the message our self it's ok to set content type
              // always to text/plain
              builder.prototype().contentType().set("text/plain");

              // Make sure to address has some value before vi create a case!!
              if (builder.prototype().to().get() == null) {
                builder.prototype().to().set("n/a");
              }
              systemDefaults.createCaseOnEmailFailure(builder.newInstance());
              copyToArchive.add(message);
              if (expunge) message.setFlag(Flags.Flag.DELETED, true);

              uow.discard();
              logger.error("Could not parse emails", e);
              tries = 3;
            }
          }
        }

        // copy message to archive if archive exists
        if (archiveExists) {
          inbox.copyMessages(copyToArchive.toArray(new Message[0]), archive);
          archive.close(false);
        }

        inbox.close(config.configuration().deleteMailOnInboxClose().get());

        store.close();

        if (config.configuration().debug().get()) {
          logger.info("Checked email");
        }

        circuitBreaker.success();
      } catch (Throwable e) {
        logger.error("Error in mail receiver: ", e);
        circuitBreaker.throwable(e);

        try {
          if (inbox != null && inbox.isOpen()) inbox.close(false);

          if (store != null && store.isConnected()) store.close();
        } catch (Throwable e1) {
          logger.error("Could not close inbox", e1);
        }
      }
    }