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); } }