Ejemplo n.º 1
0
    public void activate() throws Exception {
      circuitBreaker = descriptor.metaInfo(CircuitBreaker.class);

      logger = LoggerFactory.getLogger(ReceiveMailService.class);

      if (config.configuration().enabled().get()) {
        UnitOfWork uow =
            module
                .unitOfWorkFactory()
                .newUnitOfWork(newUsecase("Create Streamflow support structure"));
        RoleMap.newCurrentRoleMap();
        RoleMap.current().set(uow.get(UserAuthentication.class, UserEntity.ADMINISTRATOR_USERNAME));
        RoleMap.current().set(new UserPrincipal(UserEntity.ADMINISTRATOR_USERNAME));

        Organizations.Data orgs =
            uow.get(OrganizationsEntity.class, OrganizationsEntity.ORGANIZATIONS_ID);
        OrganizationEntity org = (OrganizationEntity) orgs.organization().get();
        // check for the existance of support structure for mails that cannot be parsed
        RoleMap.current().set(org.getAdministratorRole());

        OrganizationalUnit ou = null;
        Project project = null;
        CaseType caseType = null;

        try {
          try {
            ou =
                org.getOrganizationalUnitByName(
                    systemDefaults.config().configuration().supportOrganizationName().get());
          } catch (IllegalArgumentException iae) {
            ou =
                org.createOrganizationalUnit(
                    systemDefaults.config().configuration().supportOrganizationName().get());
          }

          try {
            project =
                ou.getProjectByName(
                    systemDefaults.config().configuration().supportProjectName().get());
          } catch (IllegalArgumentException iae) {
            project =
                ou.createProject(
                    systemDefaults.config().configuration().supportProjectName().get());
          }

          try {
            caseType =
                project.getCaseTypeByName(
                    systemDefaults
                        .config()
                        .configuration()
                        .supportCaseTypeForIncomingEmailName()
                        .get());
          } catch (IllegalArgumentException iae) {
            caseType =
                ou.createCaseType(
                    systemDefaults
                        .config()
                        .configuration()
                        .supportCaseTypeForIncomingEmailName()
                        .get());
            project.addSelectedCaseType(caseType);
            project.addMember(RoleMap.current().get(Member.class));
          }
        } finally {
          uow.complete();
          RoleMap.clearCurrentRoleMap();
        }

        // Authenticator
        authenticator =
            new javax.mail.Authenticator() {
              protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(
                    config.configuration().user().get(), config.configuration().password().get());
              }
            };

        props = new Properties();

        String protocol = config.configuration().protocol().get();
        props.put("mail." + protocol + ".host", config.configuration().host().get());
        props.put("mail.transport.protocol", protocol);
        props.put("mail." + protocol + ".auth", "true");
        props.put("mail." + protocol + ".port", config.configuration().port().get());

        if (config.configuration().useSSL().get()) {

          props.setProperty(
              "mail." + protocol + ".socketFactory.class", "javax.net.ssl.SSLSocketFactory");
          props.setProperty("mail." + protocol + ".socketFactory.fallback", "false");
          props.setProperty(
              "mail." + protocol + ".socketFactory.port", "" + config.configuration().port().get());
        }

        url =
            new URLName(
                protocol,
                config.configuration().host().get(),
                config.configuration().port().get(),
                "",
                config.configuration().user().get(),
                config.configuration().password().get());

        circuitBreaker.addVetoableChangeListener(this);
        circuitBreaker.turnOn();

        long sleep = config.configuration().sleepPeriod().get();
        logger.info(
            "Starting scheduled mail receiver thread. Checking every: "
                + (sleep == 0 ? 10 : sleep)
                + " min");
        receiverExecutor =
            Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("ReceiveMail"));
        receiverExecutor.scheduleWithFixedDelay(
            this, 0, (sleep == 0 ? 10 : sleep), TimeUnit.MINUTES);
      }
    }
      public void receivedEmail(ApplicationEvent event, EmailValue email) {
        UnitOfWork uow =
            module
                .unitOfWorkFactory()
                .newUnitOfWork(UsecaseBuilder.newUsecase("Receive email in conversation"));

        try {
          String references = email.headers().get().get("References");

          if (hasStreamflowReference(references)) {
            // This is a response - handle it!

            List<String> refs =
                (List<String>)
                    Iterables.addAll(
                        (Collection<String>) new ArrayList<String>(),
                        Iterables.iterable(references.split("[ \r\n\t]")));

            // Hotmail handles refs a bit differently...
            String hotmailRefs =
                Iterables.first(
                    Iterables.filter(
                        new Specification<String>() {
                          public boolean satisfiedBy(String item) {
                            return item.contains(",") && item.endsWith("@Streamflow>");
                          }
                        },
                        refs));

            String lastRef = null;
            if (!Strings.empty(hotmailRefs)) {
              lastRef = hotmailRefs.split(",")[1];
            } else {
              Collections.reverse(refs);
              Iterable<String> filter =
                  Iterables.filter(
                      new Specification<String>() {
                        public boolean satisfiedBy(String item) {
                          return item.endsWith("@Streamflow>");
                        }
                      },
                      refs);
              lastRef = Iterables.first(filter);
            }

            if (lastRef == null) {
              ValueBuilder<EmailValue> builder =
                  module
                      .valueBuilderFactory()
                      .newValueBuilder(EmailValue.class)
                      .withPrototype(email);
              String subj = "Msg Ref missing: " + builder.prototype().subject().get();
              builder.prototype().subject().set(subj.length() > 50 ? subj.substring(0, 50) : subj);

              systemDefaults.createCaseOnEmailFailure(builder.newInstance());
              logger.error("Could not find message reference in email header:" + lastRef);
              uow.discard();
              return;
            }

            Matcher matcher = Pattern.compile("<([^/]*)/([^@]*)@[^>]*>").matcher(lastRef);

            if (matcher.find()) {
              String conversationId = matcher.group(1);
              String participantId = URLDecoder.decode(matcher.group(2), "UTF-8");

              if (!"".equals(conversationId) && !"".equals(participantId)) {
                ConversationParticipant from =
                    uow.get(ConversationParticipant.class, participantId);
                Conversation conversation = uow.get(Conversation.class, conversationId);

                CaseEntity caze = (CaseEntity) conversation.conversationOwner().get();
                String content = email.content().get();

                // If we have an assignee, ensure it is a member of the conversation first
                if (caze.isAssigned()) {
                  if (!conversation.isParticipant(
                      (ConversationParticipant) caze.assignedTo().get()))
                    conversation.addParticipant((ConversationParticipant) caze.assignedTo().get());
                }

                // Create a new role map and fill it with relevant objects
                if (RoleMap.current() == null) RoleMap.newCurrentRoleMap();
                RoleMap.current().set(from, ConversationParticipant.class);
                RoleMap.current().set(caze, CaseLoggable.Data.class);
                RoleMap.current().set(caze, Case.class);

                Message message = null;

                if (Translator.HTML.equalsIgnoreCase(email.contentType().get())) {
                  message =
                      conversation.createMessage(email.contentHtml().get(), MessageType.HTML, from);
                } else {
                  message =
                      conversation.createMessage(email.content().get(), MessageType.PLAIN, from);
                }
                // Create attachments
                for (AttachedFileValue attachedFileValue : email.attachments().get()) {
                  if (!(attachedFileValue.mimeType().get().contains("text/x-vcard")
                      || attachedFileValue.mimeType().get().contains("text/directory"))) {
                    Attachment attachment = message.createAttachment(attachedFileValue.uri().get());
                    attachment.changeDescription("New Attachment");
                    attachment.changeName(attachedFileValue.name().get());
                    attachment.changeMimeType(attachedFileValue.mimeType().get());
                    attachment.changeModificationDate(attachedFileValue.modificationDate().get());
                    attachment.changeSize(attachedFileValue.size().get());
                    attachment.changeUri(attachedFileValue.uri().get());
                  }
                }

                try {
                  if (caze.isStatus(CaseStates.CLOSED)) {
                    RoleMap.newCurrentRoleMap();
                    RoleMap.current().set(caze);
                    if (caze.assignedTo().get() != null) {
                      RoleMap.current().set(caze.assignedTo().get());
                    } else {
                      RoleMap.current()
                          .set(uow.get(UserEntity.class, UserEntity.ADMINISTRATOR_USERNAME));
                    }
                    CaseCommandsContext caseCommands =
                        module.transientBuilderFactory().newTransient(CaseCommandsContext.class);
                    caseCommands.reopen();
                    caseCommands.unassign();
                    RoleMap.clearCurrentRoleMap();
                  }
                } catch (Throwable e) {
                  ValueBuilder<EmailValue> builder =
                      module
                          .valueBuilderFactory()
                          .newValueBuilder(EmailValue.class)
                          .withPrototype(email);
                  String subj = "Create Case failed: " + builder.prototype().subject().get();
                  builder
                      .prototype()
                      .subject()
                      .set(subj.length() > 50 ? subj.substring(0, 50) : subj);

                  systemDefaults.createCaseOnEmailFailure(builder.newInstance());
                  // throw new IllegalStateException("Could not open case through new message.", e);
                }
              }
            }
          }

          uow.complete();
        } catch (Exception ex) {
          ValueBuilder<EmailValue> builder =
              module.valueBuilderFactory().newValueBuilder(EmailValue.class).withPrototype(email);
          String subj = "Conversation Response Error: " + builder.prototype().subject().get();
          builder.prototype().subject().set(subj.length() > 50 ? subj.substring(0, 50) : subj);

          StringBuilder content = new StringBuilder();
          content.append("Error Message: " + ex.getMessage());
          content.append("\n\rStackTrace:\n\r");
          for (StackTraceElement trace : Arrays.asList(ex.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());
          uow.discard();
          // throw new ApplicationEventReplayException(event, ex);
        }
      }