diff --git a/config/alfresco/subsystems/email/InboundSMTP/inboundSMTP-context.xml b/config/alfresco/subsystems/email/InboundSMTP/inboundSMTP-context.xml index fff5561f95..d36a80dac6 100755 --- a/config/alfresco/subsystems/email/InboundSMTP/inboundSMTP-context.xml +++ b/config/alfresco/subsystems/email/InboundSMTP/inboundSMTP-context.xml @@ -68,7 +68,8 @@ - + ${email.inbound.enabled} @@ -115,6 +116,9 @@ + + + diff --git a/source/java/org/alfresco/email/server/EmailServiceImpl.java b/source/java/org/alfresco/email/server/EmailServiceImpl.java index 57da40aca4..e1aa81a506 100644 --- a/source/java/org/alfresco/email/server/EmailServiceImpl.java +++ b/source/java/org/alfresco/email/server/EmailServiceImpl.java @@ -18,6 +18,7 @@ */ package org.alfresco.email.server; +import java.util.Collection; import java.util.Map; import javax.mail.internet.InternetAddress; @@ -31,6 +32,8 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.email.EmailDelivery; import org.alfresco.service.cmr.email.EmailMessage; import org.alfresco.service.cmr.email.EmailMessageException; @@ -45,6 +48,7 @@ import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.util.PropertyCheck; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.extensions.surf.util.ParameterCheck; @@ -70,6 +74,7 @@ public class EmailServiceImpl implements EmailService private SearchService searchService; private RetryingTransactionHelper retryingTransactionHelper; private AuthorityService authorityService; + private DictionaryService dictionaryService; /** * The authority that needs to contain the users and groups @@ -84,6 +89,15 @@ public class EmailServiceImpl implements EmailService private String unknownUser; /** List of message handlers */ private Map emailMessageHandlerMap; + + public void init() + { + PropertyCheck.mandatory(this, "namespaceService", namespaceService); + PropertyCheck.mandatory(this, "dictionaryService", getDictionaryService()); + PropertyCheck.mandatory(this, "searchService", searchService); + PropertyCheck.mandatory(this, "authorityService", authorityService); + PropertyCheck.mandatory(this, "emailMessageHandlerMap", emailMessageHandlerMap); + } /** * @@ -320,6 +334,38 @@ public class EmailServiceImpl implements EmailService QName nodeTypeQName = nodeService.getType(nodeRef); String prefixedNodeTypeStr = nodeTypeQName.toPrefixString(namespaceService); EmailMessageHandler handler = emailMessageHandlerMap.get(prefixedNodeTypeStr); + + if( handler == null) + { + if(logger.isDebugEnabled()) + { + logger.debug("did not find a handler for type:" + prefixedNodeTypeStr); + } + + // not a direct match on type + // need to check the super-types (if any) of the target node + TypeDefinition typeDef = dictionaryService.getType(nodeTypeQName); + while(typeDef != null) + { + QName parentName = typeDef.getParentName(); + if(parentName != null) + { + String prefixedSubTypeStr = parentName.toPrefixString(namespaceService); + handler = emailMessageHandlerMap.get(prefixedSubTypeStr); + if(handler != null) + { + if(logger.isDebugEnabled()) + { + logger.debug("found a handler for a subtype:" + prefixedSubTypeStr); + } + return handler; + } + } + typeDef = dictionaryService.getType(parentName); + } + + } + if (handler == null) { throw new EmailMessageException(ERR_HANDLER_NOT_FOUND, prefixedNodeTypeStr); @@ -477,4 +523,14 @@ public class EmailServiceImpl implements EmailService { return emailContributorsAuthority; } + + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + + public DictionaryService getDictionaryService() + { + return dictionaryService; + } } diff --git a/source/java/org/alfresco/email/server/EmailServiceImplTest.java b/source/java/org/alfresco/email/server/EmailServiceImplTest.java index e03c65163b..af5b8ca944 100644 --- a/source/java/org/alfresco/email/server/EmailServiceImplTest.java +++ b/source/java/org/alfresco/email/server/EmailServiceImplTest.java @@ -40,6 +40,7 @@ import org.alfresco.model.ContentModel; import org.alfresco.model.ForumModel; import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory; import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.transfer.TransferModel; import org.alfresco.service.cmr.email.EmailDelivery; import org.alfresco.service.cmr.email.EmailMessageException; import org.alfresco.service.cmr.email.EmailService; @@ -755,6 +756,107 @@ public class EmailServiceImplTest extends TestCase } // end of test sending to cm:content node + + + /** + * ENH-560 - Inbound email server not working with custom types + */ + public void testMessagesToSubTypeOfDocument() throws Exception + { + logger.debug("Start testMessagesToSubTypesOfDocument"); + + String TEST_EMAIL="buffy@sunnydale.high"; + + String TEST_SUBJECT="Practical Bee Keeping"; + + String TEST_LONG_SUBJECT = "This is a very very long name in particular it is greater than eitghty six characters which was a problem explored in ALF-9544"; + + + // TODO Investigate why setting PROP_EMAIL on createPerson does not work. + NodeRef person = personService.getPerson(TEST_USER); + if(person == null) + { + logger.debug("new person created"); + Map props = new HashMap(); + props.put(ContentModel.PROP_USERNAME, TEST_USER); + props.put(ContentModel.PROP_EMAIL, TEST_EMAIL); + person = personService.createPerson(props); + } + nodeService.setProperty(person, ContentModel.PROP_EMAIL, TEST_EMAIL); + + Set auths = authorityService.getContainedAuthorities(null, "GROUP_EMAIL_CONTRIBUTORS", true); + if(!auths.contains(TEST_USER)) + { + authorityService.addAuthority("GROUP_EMAIL_CONTRIBUTORS", TEST_USER); + } + + String companyHomePathInStore = "/app:company_home"; + String storePath = "workspace://SpacesStore"; + StoreRef storeRef = new StoreRef(storePath); + + NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef); + List nodeRefs = searchService.selectNodes(storeRootNodeRef, companyHomePathInStore, null, namespaceService, false); + NodeRef companyHomeNodeRef = nodeRefs.get(0); + assertNotNull("company home is null", companyHomeNodeRef); + String companyHomeDBID = ((Long)nodeService.getProperty(companyHomeNodeRef, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com"; +// String testUserDBID = ((Long)nodeService.getProperty(person, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com"; + NodeRef testUserHomeFolder = (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER); + assertNotNull("testUserHomeFolder is null", testUserHomeFolder); +// String testUserHomeDBID = ((Long)nodeService.getProperty(testUserHomeFolder, ContentModel.PROP_NODE_DBID)).toString() + "@Alfresco.com"; + + // Clean up old messages in test folder + List assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); + for(ChildAssociationRef assoc : assocs) + { + nodeService.deleteNode(assoc.getChildRef()); + } + + + Map properties = new HashMap(); + properties.put(ContentModel.PROP_NAME, "hamster"); + properties.put(ContentModel.PROP_DESCRIPTION, "syrian hamsters - test doc for email tests, sending to a subtype of cm:content"); + + // Transfer report is a subtype of cm:content + ChildAssociationRef testDoc = nodeService.createNode(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "bees"), TransferModel.TYPE_TRANSFER_REPORT, properties); + NodeRef testDocNodeRef = testDoc.getChildRef(); + + String testDocDBID = ((Long)nodeService.getProperty(testDocNodeRef, ContentModel.PROP_NODE_DBID)).toString(); + + /** + * Send From the test user TEST_EMAIL to the test user's home + */ + String from = TEST_EMAIL; + String to = testDocDBID + "@alfresco.com"; + String content = "hello world"; + + Session sess = Session.getDefaultInstance(new Properties()); + assertNotNull("sess is null", sess); + SMTPMessage msg = new SMTPMessage(sess); + InternetAddress[] toa = { new InternetAddress(to) }; + + msg.setFrom(new InternetAddress(TEST_EMAIL)); + msg.setRecipients(Message.RecipientType.TO, toa); + msg.setSubject(TEST_SUBJECT); + msg.setContent(content, "text/plain"); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + msg.writeTo(bos); + InputStream is = new StringInputStream(bos.toString()); + assertNotNull("is is null", is); + + SubethaEmailMessage m = new SubethaEmailMessage(is); + + /** + * Turn on overwriteDuplicates + */ + logger.debug("Step 1: send an email to a transfer report"); + + EmailDelivery delivery = new EmailDelivery(to, from, null); + + emailService.importMessage(delivery, m); + + } // end of test sending to trx:transferReport +