/**
   * 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);
  }
Beispiel #2
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);
   }
 }
Beispiel #3
0
  /**
   * @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);
    }
  }
Beispiel #4
0
  /**
   * @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);
    }
  }
Beispiel #5
0
  /** {@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;
  }
Beispiel #6
0
  /**
   * @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);
 }