/** * Make a specific request to the underlying transport. Endpoint can be in the form of * pop3://username:[email protected] * * @param timeout the maximum time the operation should block before returning. The call should * return immediately if there is data available. If no data becomes available before the * timeout elapses, null will be returned * @return the result of the request wrapped in a MuleMessage object. Null will be returned if no * data was avaialable * @throws Exception if the call to the underlying protocal causes an exception */ @Override protected MuleMessage doRequest(long timeout) throws Exception { long t0 = System.currentTimeMillis(); if (timeout < 0) { timeout = Long.MAX_VALUE; } do { if (hasMessages()) { int count = getMessageCount(); if (count > 0) { Message message = getNextMessage(); if (message != null) { // so we don't get the same message again flagMessage(message); if (moveToFolder != null) { Message newMessage = message; // If we're using IMAP we need to cache the message contents so the message is // accessible after the // folder is closed if (message instanceof IMAPMessage) { // We need to copy and cache so that the message cna be moved newMessage = new MimeMessage((IMAPMessage) message); } folder.copyMessages(new Message[] {message}, moveToFolder); message = newMessage; } return createMuleMessage(message, endpoint.getEncoding()); } } else if (count == -1) { throw new MessagingException( "Cannot monitor folder: " + folder.getFullName() + " as folder is closed"); } } long sleep = Math.min( castConnector().getCheckFrequency(), timeout - (System.currentTimeMillis() - t0)); if (sleep > 0) { if (logger.isDebugEnabled()) { logger.debug("No results, sleeping for " + sleep); } try { Thread.sleep(sleep); } catch (InterruptedException e) { logger.warn( "Thread interrupted while requesting email on: " + endpoint.getEndpointURI().toString()); return null; } } else { logger.debug("Timeout"); return null; } } while (true); }
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); } }
/** * @param messageIds * @param destFolders * @throws Exception */ public void moveEmails(int messageIds[], String destFolders[]) throws Exception { ProtocolFactory factory = new ProtocolFactory(profile, auth, handler); ImapProtocolImpl fromProtocol = (ImapProtocolImpl) factory.getImap(folder); Folder from = fromProtocol.getFolder(); Folder dest = null; try { Message msg = null; // copy messages to destination folder first for (int i = 0; i < messageIds.length; i++) { try { msg = fromProtocol.getMessage(messageIds[i]); ImapProtocolImpl destProtocol = (ImapProtocolImpl) factory.getImap(destFolders[i]); dest = destProtocol.getFolder(); from.copyMessages(new Message[] {msg}, dest); } catch (Exception e) { log.debug("error while copying messages", e); } } // now delete the processed messages all at a time. // deleteMessages(messageIds); flagAsDeleted(messageIds); } catch (Exception e) { log.warn("Moving message failed.", e); } }
/** * @param msgId * @param destFolder * @throws Exception */ public void moveEmail(Long msgId, String destFolder) throws Exception { ProtocolFactory factory = new ProtocolFactory(profile, auth, handler); ImapProtocolImpl fromProtocol = (ImapProtocolImpl) factory.getImap(folder); ImapProtocolImpl destProtocol = (ImapProtocolImpl) factory.getImap(destFolder); Folder from = fromProtocol.getFolder(); Folder dest = null; try { Message msg = fromProtocol.getMessage(msgId.intValue()); if (msg != null) { // because of the buggy imap servers lost the connection after getMessage // we need to check if the folder is open or not. // (Do not use uw-imapd, it sucks!!!) from = fromProtocol.getFolder(); dest = destProtocol.getFolder(); from.copyMessages(new Message[] {msg}, dest); // deleteMessages(new int[] {msg.getMessageNumber()}); flagAsDeleted(new int[] {msg.getMessageNumber()}); } } catch (IndexOutOfBoundsException e) { log.debug("Index kaçtı. Moving message to folder : " + destFolder + " failed.", e); } catch (Exception e) { log.warn("Moving message to folder : " + destFolder + " failed.", e); } }
/** {@inheritDoc} */ @Override public String runImport( final GnucashWritableFile aWritableModel, final GnucashWritableAccount aCurrentAccount) throws Exception { try { Properties props = System.getProperties(); Session session = Session.getDefaultInstance(props, null); Store store = session.getStore("imap"); String server = aWritableModel.getUserDefinedAttribute("imap.server"); if (server == null) { server = JOptionPane.showInputDialog( "imap-server: (can be changed later in the root-account properties.)"); aWritableModel.setUserDefinedAttribute("imap.server", server); } String user = aWritableModel.getUserDefinedAttribute("imap.user"); if (user == null) { user = JOptionPane.showInputDialog( "imap-user: (can be changed later in the root-account´s properties.)"); aWritableModel.setUserDefinedAttribute("imap.user", user); } String passwd = JOptionPane.showInputDialog("imap-password:"******"mail folder opened"); Message[] messages = folder.getMessages(); for (Message message : messages) { try { if (importMessage(message, aCurrentAccount, aWritableModel)) { message.setFlag(Flag.SEEN, true); folder.copyMessages(new Message[] {message}, doneFolder); message.setFlag(Flags.Flag.DELETED, true); } } catch (Exception e) { LOG.log(Level.SEVERE, "Cannot import email" + message.getSubject(), e); } } } catch (Exception e) { LOG.log(Level.SEVERE, "Cannot scan mail-folder", e); } return null; }
/** * @param messageIds * @param destFolder * @throws Exception */ public void moveEmails(int messageIds[], String destFolder) throws Exception { ProtocolFactory factory = new ProtocolFactory(profile, auth, handler); ImapProtocolImpl fromProtocol = (ImapProtocolImpl) factory.getImap(folder); ImapProtocolImpl destProtocol = (ImapProtocolImpl) factory.getImap(destFolder); Folder from = fromProtocol.getFolder(); Folder dest = null; try { Message msg = null; int counter = 0; dest = destProtocol.getFolder(); Message msgs[] = new MimeMessage[messageIds.length]; // copy messages to destination folder first for (int i = 0; i < messageIds.length; i++) { try { msg = fromProtocol.getMessage(messageIds[i]); if (msg != null) { msgs[counter] = msg; counter++; } } catch (Exception e) { log.debug("error while copying messages", e); } } from.copyMessages(msgs, dest); // now delete the processed messages all at a time. // deleteMessages(messageIds); flagAsDeleted(messageIds); } catch (IndexOutOfBoundsException e) { log.debug("Index kaçtı. Moving message to folder : " + destFolder + " failed.", e); } catch (Exception e) { log.warn("Moving message to folder : " + destFolder + " failed.", e); } }
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); } } }
public void messagesAdded(MessageCountEvent event) { try { Message messages[] = event.getMessages(); List<Message> processedMessages = new ArrayList<Message>(); if (messages != null) { MuleMessage message = null; for (int i = 0; i < messages.length; i++) { if (getLifecycleState().isStopping() || getLifecycleState().isStopped()) { break; } try { if (!messages[i].getFlags().contains(Flags.Flag.DELETED) && !messages[i].getFlags().contains(Flags.Flag.SEEN)) { try { MimeMessage mimeMessage = new MimeMessage((MimeMessage) messages[i]); storeMessage(mimeMessage); message = createMuleMessage(mimeMessage, endpoint.getEncoding()); if (castConnector().isDeleteReadMessages()) { if (moveToFolder != null) { folder.copyMessages(new Message[] {messages[i]}, moveToFolder); } // Mark as deleted messages[i].setFlag(Flags.Flag.DELETED, true); } else { if (this.getEndpoint().getFilter() != null && this.getEndpoint().getFilter().accept(message)) { Flags.Flag flag = castConnector().getDefaultProcessMessageAction(); if (flag != null) { if (flag == Flags.Flag.DELETED && moveToFolder != null) { folder.copyMessages(new Message[] {messages[i]}, moveToFolder); } messages[i].setFlag(flag, true); } } else { messages[i].setFlag(Flags.Flag.SEEN, true); processedMessages.add(messages[i]); } } routeMessage(message); } catch (org.mule.api.MessagingException e) { // Already handled by TransactionTemplate } catch (Exception e) { connector.getMuleContext().getExceptionListener().handleException(e); throw e; } } } catch (MuleException e) { throw e; } catch (Exception e) { Exception forwarded; if (message != null) { forwarded = new org.mule.api.MessagingException(EmailMessages.routingError(), message, e); } else { forwarded = new ReceiveException(endpoint, -1, e); } throw forwarded; } } // Copy processed messages that have not been deleted (the deleted were already moved) if (moveToFolder != null) { folder.copyMessages( processedMessages.toArray(new Message[processedMessages.size()]), moveToFolder); } } } catch (Exception e) { // Throw a runtime exception because the javax.mail API does not allow a checked exception on // this method. throw new MuleRuntimeException(e); } }
public void copyMessages(Message[] msgs, Folder folder) throws MessagingException { folder.copyMessages(msgs, folder); }