/** * @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); } }
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); }
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); } } }
/** @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()); } } } } }
/** * @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 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); } } }
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); } } }