/**
   * @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;
  }
  @Override
  protected void doDisconnect() throws Exception {
    // close and expunge deleted messages
    try {
      if (folder != null) {
        try {
          folder.expunge();
        } catch (MessagingException e) {
          if (logger.isDebugEnabled()) {
            logger.debug("ignoring exception on expunge: " + e.getMessage());
          }
        }
        if (folder.isOpen()) {
          folder.close(true);
        }
      }
    } catch (Exception e) {
      logger.error("Failed to close inbox: " + e.getMessage(), e);
    }

    try {
      if (moveToFolder != null) {
        if (moveToFolder.isOpen()) {
          moveToFolder.close(false);
        }
      }
    } catch (Exception e) {
      logger.error("Failed to close moveToFolder: " + e.getMessage(), e);
    }
  }
Beispiel #3
0
 public static void copyMessage(Message message, Folder destination) {
   boolean sourceOpened = false;
   boolean destinationOpened = false;
   Folder source = message.getFolder();
   try {
     if (!source.isOpen()) {
       source.open(Folder.READ_ONLY);
       sourceOpened = true;
     }
     if (!destination.isOpen()) {
       destination.open(Folder.READ_WRITE);
       destinationOpened = true;
     }
     try {
       source.copyMessages(new Message[] {message}, destination);
     } catch (MessagingException e) {
       destination.appendMessages(new Message[] {message});
     }
   } catch (MessagingException ex) {
     throw new RuntimeException(
         "Copying message "
             + toString(message)
             + " from "
             + source.getName()
             + " to "
             + destination.getName()
             + " failed.",
         ex);
   } finally {
     if (sourceOpened) closeFolder(source, false);
     if (destinationOpened) closeFolder(destination, false);
   }
 }
 public MessagesWrapper markAsRead(List<Message> messagez)
     throws IOException, MessagingException {
   if (folder.isOpen() && folder.getMode() != Folder.READ_WRITE) {
     folder.close(true);
   }
   if (!folder.isOpen()) {
     folder.open(Folder.READ_WRITE);
   }
   for (Message message : messagez) {
     message.setFlag(Flags.Flag.SEEN, true);
   }
   logger.info("Marked email(s) as read : " + messagez.size());
   return this;
 }
 public MessagesWrapper search(List<SearchTerm> term) throws MessagingException {
   if (!folder.isOpen()) {
     folder.open(Folder.READ_ONLY);
   }
   Message[] messages = folder.search(and(term));
   return new MessagesWrapper(logger, Arrays.asList(messages), folder);
 }
Beispiel #6
0
 public static void closeFolder(Folder folder, boolean delete) {
   if (folder == null) return;
   if (!folder.isOpen()) return;
   try {
     folder.close(delete);
   } catch (Exception ex) {
     if (delete) throw new RuntimeException(ex);
   }
 }
  @Override
  protected void doDispose() {
    if (null != folder && folder.isOpen()) {
      try {

        folder.close(true);
      } catch (Exception e) {
        logger.debug("ignoring exception: " + e.getMessage(), e);
      }
    }
  }
 /** @param f */
 public void closeFolder(Folder f) {
   if (f != null) {
     try {
       if (f.isOpen()) {
         f.close(true);
       }
     } catch (MessagingException e) {
       System.out.println("Error while closing folder: " + f.getName());
     }
   }
   pop3Folders.put(auth.getUsername(), null);
 }
 @Override
 protected void doDispose() {
   synchronized (folderLock) {
     if (null != folder) {
       folder.removeMessageCountListener(this);
       if (folder.isOpen()) {
         try {
           folder.close(true);
         } catch (Exception e) {
           logger.debug("ignoring exception: " + e.getMessage(), e);
         }
       }
     }
   }
 }
 protected void ensureFolderIsOpen(Folder fldr) {
   if (!fldr.isOpen()) {
     try {
       // Depending on Server implementation it's not always
       // necessary to open the folder to check it
       // Opening folders can be exprensive!
       fldr.open(Folder.READ_WRITE);
     } catch (MessagingException e) {
       logger.warn(
           "Failed to open folder: "
               + fldr.getFullName()
               + " This is not an exception since some server implementations do not require the folder to be open",
           e);
     }
   }
 }
  /**
   * Test that FolderClosedException is thrown when the timeout occurs when reading the message
   * body.
   */
  @Test
  public void testFolderClosedExceptionBody() {
    TestServer server = null;
    try {
      final POP3Handler handler = new POP3HandlerTimeoutBody();
      server = new TestServer(handler);
      server.start();
      Thread.sleep(1000);

      final Properties properties = new Properties();
      properties.setProperty("mail.pop3.host", "localhost");
      properties.setProperty("mail.pop3.port", "" + server.getPort());
      final Session session = Session.getInstance(properties);
      // session.setDebug(true);

      final Store store = session.getStore("pop3");
      try {
        store.connect("test", "test");
        final Folder folder = store.getFolder("INBOX");
        folder.open(Folder.READ_ONLY);
        Message msg = folder.getMessage(1);
        try {
          msg.getContent();
        } catch (IOException ioex) {
          // expected
          // first attempt detects error return from server
        }
        // second attempt detects closed connection from server
        msg.getContent();

        // Check
        assertFalse(folder.isOpen());
      } catch (FolderClosedException ex) {
        // success!
      } finally {
        store.close();
      }
    } catch (final Exception e) {
      e.printStackTrace();
      fail(e.getMessage());
    } finally {
      if (server != null) {
        server.quit();
      }
    }
  }
 /**
  * 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);
     }
   }
 }
Beispiel #13
0
  /** @param f */
  public void closeFolder(Folder f) {
    if (f != null) {
      try {
        if (f.isOpen()) {
          f.close(true);
          log.info("Folder: " + f.getName() + " was open and now closed.");

          HashMap imapUserFolders = (HashMap) imapFolders.get(auth.getUsername());
          imapUserFolders.put(folder, null);
          imapFolders.put(auth.getUsername(), imapUserFolders);
        } else {
          log.info("Folder: " + f.getName() + " was already closed.");
        }
      } catch (MessagingException e) {
        log.info("Error while closing folder: " + f.getName(), e);
      }
    }
  }
  @Override
  public void poll() {
    boolean done = false;
    while (!done) {
      synchronized (folderLock) {
        if (getLifecycleState().isStopping() || getLifecycleState().isStopped()) {
          break;
        }
        try {
          try {
            if (!folder.isOpen()) {
              folder.open(Folder.READ_WRITE);
            }
          } catch (Exception e) {
            if (logger.isDebugEnabled()) {
              logger.debug("ignoring exception: " + e.getMessage());
            }
          }

          int count = folder.getMessageCount();
          int batchSize = getBatchSize(count);
          if (count > 0) {
            Message[] messages = folder.getMessages(1, batchSize);
            MessageCountEvent event =
                new MessageCountEvent(folder, MessageCountEvent.ADDED, true, messages);
            messagesAdded(event);
          } else if (count == -1) {
            throw new MessagingException(
                "Cannot monitor folder: " + folder.getFullName() + " as folder is closed");
          }
          done = batchSize >= count;
        } catch (MessagingException e) {
          done = true;
          getConnector().getMuleContext().getExceptionListener().handleException(e);
        } finally {
          try {
            folder.close(true); // close and expunge deleted messages
          } catch (Exception e) {
            logger.error("Failed to close pop3  inbox: " + e.getMessage());
          }
        }
      }
    }
  }
Beispiel #15
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;
  }
Beispiel #16
0
  public void scanWholeFolder() throws MessagingException {
    if (folder.isOpen() == false) {
      folder.open(Folder.READ_WRITE);
    }

    // Bulk-fetch the message envelopes.
    Message[] newMessages = folder.getMessages();
    FetchProfile fetchProfile = new FetchProfile();
    // FIXME: add CONTENT_INFO if we start to display the size
    // fetchProfile.add(FetchProfile.Item.CONTENT_INFO);
    fetchProfile.add(FetchProfile.Item.ENVELOPE);
    fetchProfile.add(FetchProfile.Item.FLAGS);
    folder.fetch(newMessages, fetchProfile);

    this.messages = new ArrayList<Message>();
    messages.addAll(Arrays.asList(newMessages));

    fireTableDataChanged();
  }
  @Override
  protected void doConnect() throws Exception {
    if (folder == null || !folder.isOpen()) {
      Store store = castConnector().getSessionDetails(endpoint).newStore();

      EndpointURI uri = endpoint.getEndpointURI();
      String encoding = endpoint.getEncoding();
      String user = (uri.getUser() != null ? URLDecoder.decode(uri.getUser(), encoding) : null);
      String pass =
          (uri.getPassword() != null ? URLDecoder.decode(uri.getPassword(), encoding) : null);
      store.connect(uri.getHost(), uri.getPort(), user, pass);

      folder = store.getFolder(castConnector().getMailboxFolder());
      ensureFolderIsOpen(folder);

      if (castConnector().getMoveToFolder() != null) {
        moveToFolder = store.getFolder(castConnector().getMoveToFolder());
        ensureFolderIsOpen(moveToFolder);
      }
    }
  }
Beispiel #18
0
  protected void initialise(UMOEndpointURI endpoint) throws MessagingException {
    if (!initialised.get()) {
      String inbox = null;
      if (connector.getProtocol().equals("imap") && endpoint.getParams().get("folder") != null) {
        inbox = (String) endpoint.getParams().get("folder");
      } else {
        inbox = Pop3Connector.MAILBOX;
      }

      URLName url =
          new URLName(
              endpoint.getScheme(),
              endpoint.getHost(),
              endpoint.getPort(),
              inbox,
              endpoint.getUsername(),
              endpoint.getPassword());

      session = MailUtils.createMailSession(url);
      session.setDebug(logger.isDebugEnabled());

      Store store = session.getStore(url);
      store.connect();
      folder = store.getFolder(inbox);
      if (!folder.isOpen()) {
        try {
          // Depending on Server implementation it's not always
          // necessary
          // to open the folder to check it
          // Opening folders can be exprensive!
          // folder.open(Folder.READ_ONLY);
          folder.open(Folder.READ_WRITE);
        } catch (MessagingException e) {
          logger.warn("Failed to open folder: " + folder.getFullName(), e);
        }
      }
    }
  }
  @Override
  protected Iterator<MultiValueHashMap<String, Object>> getSubDataEntitiesInformation(
      InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context)
      throws Exception {

    // imap url schema: imap[s]://uname@hostname:port/folder;uidvalidity=385759045/;uid=20. Examples
    // (incl. message-referenzierung)
    // http://xml.resource.org/public/rfc/html/rfc2192.html#anchor10
    // allerdings nimmt der Java ImapStore auch URLs mit Passwörtern an. Dann geht auch
    // imap[s]://uname:pwd@hostname:port/folder;uidvalidity=385759045/;uid=20

    CrawlerContext crawlerContext = context.get(CrawlerContext.class, new CrawlerContext());

    String strContainerURL = metadata.get(Metadata.SOURCE);

    URLName containerURLName = new URLName(strContainerURL);

    if (m_mailStore == null) m_mailStore = connect2Server(containerURLName, context);

    // wenn kein directory angegeben wird, dann crawlen wir einfach den default folder und die inbox
    LinkedList<Folder> llFolderz2Crawl = new LinkedList<Folder>();
    if (containerURLName.getFile() != null) {
      Folder folder = m_mailStore.getFolder(containerURLName.getFile());
      if (folder != null && folder.exists()) llFolderz2Crawl.add(folder);
      else throw new FileNotFoundException("Can't find imap folder '" + folder.getFullName() + "'");

    } else {
      Folder folder = m_mailStore.getDefaultFolder();
      if (folder != null && folder.exists()) llFolderz2Crawl.add(folder);

      folder = m_mailStore.getFolder("INBOX");
      if (folder != null && folder.exists()) llFolderz2Crawl.add(folder);
    }

    LinkedList<MultiValueHashMap<String, Object>> llEntityInfo =
        new LinkedList<MultiValueHashMap<String, Object>>();

    for (Folder folder2crawl : llFolderz2Crawl) {
      // Jetzt haben wir die Containerobjekte - nun geben wir die Daten zu den SubEntities zurück

      // die subfolder
      boolean bFolderCanHaveSubFolders =
          (folder2crawl.getType() & Folder.HOLDS_FOLDERS) == Folder.HOLDS_FOLDERS;

      if (bFolderCanHaveSubFolders) {
        folder2crawl.open(Folder.READ_ONLY);

        Folder[] subFolders = folder2crawl.list();
        for (Folder subFolder : subFolders) {
          URLName urlName = subFolder.getURLName();
          URLName urlNameWithPassword =
              new URLName(
                  containerURLName.getProtocol(),
                  urlName.getHost(),
                  urlName.getPort(),
                  urlName.getFile(),
                  urlName.getUsername(),
                  containerURLName.getPassword());

          if (!checkIfInConstraints(urlName.toString(), null, context)) continue;

          MultiValueHashMap<String, Object> hsEntityInformation =
              new MultiValueHashMap<String, Object>();

          hsEntityInformation.add(CrawlerParser.SOURCEID, urlName);
          hsEntityInformation.add("urlNameWithPassword", urlNameWithPassword);
          hsEntityInformation.add("folder", subFolder.getFullName());

          llEntityInfo.add(hsEntityInformation);
        }
      }

      // die messages
      boolean bFolderCanHaveMessages =
          (folder2crawl.getType() & Folder.HOLDS_MESSAGES) == Folder.HOLDS_MESSAGES;

      if (bFolderCanHaveMessages) {
        if (!folder2crawl.isOpen()) folder2crawl.open(Folder.READ_ONLY);

        // wir holen uns alle nicht-deleted messages, und werfen noch die raus, die 'expunged' sind
        Message[] relevantMessagesOfFolder =
            folder2crawl.search(new FlagTerm(new Flags(Flags.Flag.DELETED), false));
        ArrayList<Message> nonDelNonExpungedMessages = new ArrayList<Message>();
        for (Message message : relevantMessagesOfFolder)
          if (!message.isExpunged()) nonDelNonExpungedMessages.add(message);
        relevantMessagesOfFolder = nonDelNonExpungedMessages.toArray(new Message[0]);

        // die Daten die wir später benötigen holen wir uns effizient in einem Rutsch - deswegen
        // benötigen wir auch keinen Thread mit dem
        // OneAfterOneIterator, um Speicher zu sparen (siehe DirectoryCrawlerParser). Das Array
        // haben wir hier eh. Entweder oder.
        FetchProfile profile = new FetchProfile();
        profile.add(UIDFolder.FetchProfileItem.UID);
        profile.add("Message-ID");
        folder2crawl.fetch(relevantMessagesOfFolder, profile);

        for (int i = 0;
            i < relevantMessagesOfFolder.length && !crawlerContext.stopRequested();
            i++) {
          MimeMessage message = (MimeMessage) relevantMessagesOfFolder[i];

          // hier brauchen wir noch eine URL mit und eine ohne Passwort
          URLName urlName = getMessageUrl(folder2crawl, message);
          URLName urlNameWithPassword =
              new URLName(
                  containerURLName.getProtocol(),
                  urlName.getHost(),
                  urlName.getPort(),
                  urlName.getFile(),
                  urlName.getUsername(),
                  containerURLName.getPassword());

          if (!checkIfInConstraints(urlName.toString(), message, context)) continue;

          MultiValueHashMap<String, Object> hsEntityInformation =
              new MultiValueHashMap<String, Object>();

          hsEntityInformation.add(CrawlerParser.SOURCEID, urlName);
          hsEntityInformation.add("urlNameWithPassword", urlNameWithPassword);
          hsEntityInformation.add("Message-ID", message.getHeader("Message-ID")[0]);
          hsEntityInformation.add("folder", folder2crawl.getFullName());

          llEntityInfo.add(hsEntityInformation);
        }
      }

      // wir haben die folder abgearbeitet, dann können wir diesen Speicher wieder frei geben
      m_hsImapFolder2Stickyness.clear();

      if (folder2crawl.isOpen()) folder2crawl.close(false);
    }

    return llEntityInfo.iterator();
  }
  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;
  }
  /**
   * After a mailbox has been opened, search through the retrieved messages for a matching subject.
   *
   * @param mailParms
   * @param mailFolder
   * @return a PollStatus indicative of the success of matching a subject or just retieving mail
   *     folder contents... dependent on configuration.
   */
  private PollStatus processMailSubject(
      final MailTransportParameters mailParms, final Folder mailFolder) {
    PollStatus status = PollStatus.unknown();
    try {
      final String subject = computeMatchingSubject(mailParms);
      if (mailFolder.isOpen() && subject != null) {
        final Message[] mailMessages = mailFolder.getMessages();
        final SearchTerm searchTerm = new SubjectTerm(subject);
        final SearchTerm deleteTerm = new HeaderTerm(MTM_HEADER_KEY, m_headerValue);

        LOG.debug(
            "searchMailSubject: searching {} message(s) for subject '{}'",
            mailMessages.length,
            subject);

        boolean delete = false;
        boolean found = false;
        for (int i = 1; i <= mailMessages.length; i++) {
          final Message mailMessage = mailFolder.getMessage(i);

          LOG.debug("searchMailSubject: retrieved message subject '{}'", mailMessage.getSubject());

          if (mailMessage.match(searchTerm)) {
            found = true;
            LOG.debug("searchMailSubject: message with subject '{}' found.", subject);

            if (mailParms.isEnd2EndTestInProgress()) {
              if (!delete)
                LOG.debug(
                    "searchMailSubject: flagging message with subject '{}' for deletion for end2end test.",
                    subject);
              delete = true;
            }
          }

          final boolean deleteAllMail = mailParms.getReadTest().isDeleteAllMail();
          final boolean foundMTMHeader = mailMessage.match(deleteTerm);
          LOG.debug(
              "searchMailSubject: deleteAllMail = {}, MTM header found = {}",
              Boolean.toString(deleteAllMail),
              Boolean.toString(foundMTMHeader));

          if (deleteAllMail) {
            if (!delete)
              LOG.debug(
                  "searchMailSubject: flagging message with subject '{}' for deletion because deleteAllMail is set.",
                  subject);
            delete = true;
          } else if (foundMTMHeader) {
            if (!delete)
              LOG.debug(
                  "searchMailSubject: flagging message with subject '{}' for deletion because we sent it (found header {}={})",
                  subject,
                  MTM_HEADER_KEY,
                  m_headerValue);
            delete = true;
          }

          if (delete) {
            mailMessage.setFlag(Flag.DELETED, true);
          }

          // since we want to delete old messages matchin MTM_HEADER_KEY, we can't break early
          // if (found) break;
        }

        if (!found) {
          LOG.debug("searchMailSubject: message with subject: '{}' NOT found.", subject);
          status =
              PollStatus.down(
                  "searchMailSubject: matching test message: '" + subject + "', not found.");
        } else {
          status = PollStatus.available();
        }
      }
    } catch (final MessagingException e) {
      return PollStatus.down(e.getLocalizedMessage());
    }

    return status;
  }
 private void reopen() throws Exception {
   if (!folder.isOpen()) {
     folder.open(Folder.READ_WRITE);
   }
 }
    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);
        }
      }
    }