diff --git a/config/alfresco/subsystems/email/InboundSMTP/inboundSMTP-context.xml b/config/alfresco/subsystems/email/InboundSMTP/inboundSMTP-context.xml
index cdb4cb1ace..38634f3a8f 100755
--- a/config/alfresco/subsystems/email/InboundSMTP/inboundSMTP-context.xml
+++ b/config/alfresco/subsystems/email/InboundSMTP/inboundSMTP-context.xml
@@ -125,7 +125,12 @@
+ class="org.alfresco.email.server.handler.FolderEmailMessageHandler" >
+
+
+ ${email.handler.folder.overwriteDuplicates}
+
+
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());
+ }
+
+ /**
+ * Send From the test user TEST_EMAIL to the test user's home
+ */
+ String from = TEST_EMAIL;
+ String to = testUserHomeDBID;
+ 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: turn on Overwite Duplicates");
+ folderEmailMessageHandler.setOverwriteDuplicates(true);
+
+ emailService.importMessage(m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ assertEquals("assocs not 1", 1, assocs.size());
+ assertEquals("name of link not as expected", assocs.get(0).getQName(), QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, TEST_SUBJECT));
+ emailService.importMessage(m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ assertEquals("assocs not 1", 1, assocs.size());
+
+ /**
+ * Turn off overwrite Duplicates
+ */
+ logger.debug("Step 2: turn off Overwite Duplicates");
+ folderEmailMessageHandler.setOverwriteDuplicates(false);
+ emailService.importMessage(m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ assertEquals("assocs not 2", 2, assocs.size());
+ emailService.importMessage(m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ assertEquals("assocs not 3", 3, assocs.size());
+
+ /**
+ * Check assoc rename with long names. So truncation and rename need to work together.
+ */
+ logger.debug("Step 3: turn off Overwite Duplicates with long subject name");
+ msg.setSubject(TEST_LONG_SUBJECT);
+ ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
+ msg.writeTo(bos2);
+ is = new StringInputStream(bos2.toString());
+ assertNotNull("is is null", is);
+ m = new SubethaEmailMessage(is);
+
+ folderEmailMessageHandler.setOverwriteDuplicates(false);
+ emailService.importMessage(m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ assertEquals("assocs not 4", 4, assocs.size());
+ emailService.importMessage(m);
+ assocs = nodeService.getChildAssocs(testUserHomeFolder, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ assertEquals("assocs not 5", 5, assocs.size());
+ }
+
}
diff --git a/source/java/org/alfresco/email/server/handler/AbstractEmailMessageHandler.java b/source/java/org/alfresco/email/server/handler/AbstractEmailMessageHandler.java
index ddc9b4cfba..50cdd57fc4 100644
--- a/source/java/org/alfresco/email/server/handler/AbstractEmailMessageHandler.java
+++ b/source/java/org/alfresco/email/server/handler/AbstractEmailMessageHandler.java
@@ -24,6 +24,7 @@ import java.io.InputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException;
@@ -125,43 +126,43 @@ public abstract class AbstractEmailMessageHandler implements EmailMessageHandler
this.mimetypeService = mimetypeService;
}
- /**
- * @param to Email address which user part specifies node-dbid
- * @return Referance to requested node.
- * @throws InvalidArgumentException The exception is thrown if input string has incorrect format or empty.
- */
- protected NodeRef getTargetNode(String to) throws InvalidArgumentException
- {
- if (to == null || to.length() == 0)
- {
- throw new InvalidArgumentException("Input string has to contain email address.");
- }
- String[] parts = to.split("@");
- if (parts.length != 2)
- {
- throw new InvalidArgumentException("Incorrect email address format.");
- }
- try
- {
- Long dbId = Long.parseLong(parts[0]);
- return nodeService.getNodeRef(dbId);
- }
- catch (NumberFormatException e)
- {
- return null;
- }
- }
+// /**
+// * @param to Email address which user part specifies node-dbid
+// * @return Referance to requested node.
+// * @throws InvalidArgumentException The exception is thrown if input string has incorrect format or empty.
+// */
+// protected NodeRef getTargetNode(String to) throws InvalidArgumentException
+// {
+// if (to == null || to.length() == 0)
+// {
+// throw new InvalidArgumentException("Input string has to contain email address.");
+// }
+// String[] parts = to.split("@");
+// if (parts.length != 2)
+// {
+// throw new InvalidArgumentException("Incorrect email address format.");
+// }
+// try
+// {
+// Long dbId = Long.parseLong(parts[0]);
+// return nodeService.getNodeRef(dbId);
+// }
+// catch (NumberFormatException e)
+// {
+// return null;
+// }
+// }
- /**
- * Write the content to the node
- *
- * @param nodeRef Target node
- * @param content Content
- */
- protected void writeContent(NodeRef nodeRef, String content)
- {
- writeContent(nodeRef, content, MimetypeMap.MIMETYPE_TEXT_PLAIN);
- }
+// /**
+// * Write the content to the node as MIMETYPE TEXT PLAIN.
+// *
+// * @param nodeRef Target node
+// * @param content Content
+// */
+// protected void writeContent(NodeRef nodeRef, String content)
+// {
+// writeContent(nodeRef, content, MimetypeMap.MIMETYPE_TEXT_PLAIN);
+// }
/**
* Write the string as content to the node.
@@ -189,7 +190,7 @@ public abstract class AbstractEmailMessageHandler implements EmailMessageHandler
* @param nodeRef Target node.
* @param content Content stream.
* @param mimetype MIME content type.
- * @param encoding Encoding. Can be null for non text based content.
+ * @param encoding Encoding. Can be null for text based content, n which case the best guess.
*/
protected void writeContent(NodeRef nodeRef, InputStream content, String mimetype, String encoding)
{
@@ -266,47 +267,82 @@ public abstract class AbstractEmailMessageHandler implements EmailMessageHandler
* @param nodeService Alfresco Node Service
* @param parent Parent node
* @param name Name of the new node
+ * @param overwrite if true then overwrite an existing node with the same name. if false the name is changed to make it unique.
* @param assocType Association type that should be set between parent node and the new one.
* @return Reference to created node
*/
- protected NodeRef addContentNode(NodeService nodeService, NodeRef parent, String name, QName assocType)
+ protected NodeRef addContentNode(NodeService nodeService, NodeRef parent, String name, QName assocType, boolean overwrite)
{
- NodeRef childNodeRef = nodeService.getChildByName(parent, assocType, name);
- if (childNodeRef != null)
+ NodeRef childNodeRef = null;
+
+ String workingName = name;
+
+ for(int counter = 0; counter < 10000; counter++)
{
- // The node is present already. Make sure the name case is correct
- nodeService.setProperty(childNodeRef, ContentModel.PROP_NAME, name);
- }
- else
- {
- Map contentProps = new HashMap();
- contentProps.put(ContentModel.PROP_NAME, name);
+ QName safeQName = QName.createQNameWithValidLocalName(NamespaceService.CONTENT_MODEL_1_0_URI, workingName);
+
+ List childNodeRefs = nodeService.getChildAssocs(parent, ContentModel.ASSOC_CONTAINS, safeQName);
+
+ if (childNodeRefs.size() > 0)
+ {
+ if(overwrite)
+ {
+ childNodeRef=childNodeRefs.get(0).getChildRef();
+
+ // Node already exists
+ // The node is present already. Make sure the name case is correct
+ nodeService.setProperty(childNodeRef, ContentModel.PROP_NAME, name);
+ return childNodeRef;
+ }
- QName assocName = QName.createQNameWithValidLocalName(NamespaceService.CONTENT_MODEL_1_0_URI, name);
+ // Need to work out a new safe name.
+
+ String postFix = " (" + counter + ")";
- ChildAssociationRef associationRef = nodeService.createNode(
+ if(name.length() + postFix.length() > QName.MAX_LENGTH )
+ {
+ workingName = name.substring(0, QName.MAX_LENGTH-postFix.length()) + postFix;
+ // Need to truncate name
+ }
+ else
+ {
+ workingName = name + postFix;
+ }
+ }
+ else
+ {
+ // Here if child node ref does not already exist
+ Map contentProps = new HashMap();
+ contentProps.put(ContentModel.PROP_NAME, workingName);
+
+ ChildAssociationRef associationRef = nodeService.createNode(
parent,
assocType,
- assocName,
+ safeQName,
ContentModel.TYPE_CONTENT,
contentProps);
- childNodeRef = associationRef.getChildRef();
+ childNodeRef = associationRef.getChildRef();
+
+ return childNodeRef;
+ }
}
- return childNodeRef;
+ throw new AlfrescoRuntimeException("Unable to add new file");
}
/**
* Add new node into Alfresco repository with specified parameters.
- * Node content isn't added. New node will be created with ContentModel.ASSOC_CONTAINS association with parent.
+ * Node content isn't added.
+ *
+ * New node will be created with ContentModel.ASSOC_CONTAINS association with parent.
*
* @param nodeService Alfresco Node Service
* @param parent Parent node
* @param name Name of the new node
* @return Reference to created node
*/
- protected NodeRef addContentNode(NodeService nodeService, NodeRef parent, String name)
+ protected NodeRef addContentNode(NodeService nodeService, NodeRef parent, String name, boolean overwrite)
{
- return addContentNode(nodeService, parent, name, ContentModel.ASSOC_CONTAINS);
+ return addContentNode(nodeService, parent, name, ContentModel.ASSOC_CONTAINS, overwrite);
}
/**
@@ -320,14 +356,13 @@ public abstract class AbstractEmailMessageHandler implements EmailMessageHandler
*/
protected NodeRef addAttachment(NodeService nodeService, NodeRef folder, NodeRef mainContentNode, String fileName)
{
- fileName = getAppropriateNodeName(folder, fileName, ContentModel.ASSOC_CONTAINS);
if (log.isDebugEnabled())
{
log.debug("Adding attachment node (name=" + fileName + ").");
}
- NodeRef attachmentNode = addContentNode(nodeService, folder, fileName);
+ NodeRef attachmentNode = addContentNode(nodeService, folder, fileName, false);
// Add attached aspect
nodeService.addAspect(mainContentNode, ContentModel.ASPECT_ATTACHABLE, null);
@@ -354,6 +389,7 @@ public abstract class AbstractEmailMessageHandler implements EmailMessageHandler
if (nodeService.getChildByName(parent, assocType, name) != null)
{
name = name + "(1)";
+
while (nodeService.getChildByName(parent, assocType, name) != null)
{
diff --git a/source/java/org/alfresco/email/server/handler/AbstractForumEmailMessageHandler.java b/source/java/org/alfresco/email/server/handler/AbstractForumEmailMessageHandler.java
index b3f8082616..4e1c36dfdf 100644
--- a/source/java/org/alfresco/email/server/handler/AbstractForumEmailMessageHandler.java
+++ b/source/java/org/alfresco/email/server/handler/AbstractForumEmailMessageHandler.java
@@ -29,6 +29,7 @@ import java.util.Map;
import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel;
import org.alfresco.model.ForumModel;
+import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.email.EmailMessage;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -92,7 +93,7 @@ public abstract class AbstractForumEmailMessageHandler extends AbstractEmailMess
}
else
{
- writeContent(postNodeRef, "");
+ writeContent(postNodeRef, "", MimetypeMap.MIMETYPE_TEXT_PLAIN);
}
addEmailedAspect(postNodeRef, message);
diff --git a/source/java/org/alfresco/email/server/handler/FolderEmailMessageHandler.java b/source/java/org/alfresco/email/server/handler/FolderEmailMessageHandler.java
index 2c27dcce41..8710e45497 100644
--- a/source/java/org/alfresco/email/server/handler/FolderEmailMessageHandler.java
+++ b/source/java/org/alfresco/email/server/handler/FolderEmailMessageHandler.java
@@ -55,6 +55,8 @@ public class FolderEmailMessageHandler extends AbstractEmailMessageHandler
private static final String ERR_MAIL_READ_ERROR = "email.server.err.mail_read_error";
private static final Log log = LogFactory.getLog(FolderEmailMessageHandler.class);
+
+ private boolean overwriteDuplicates = false;
/**
* {@inheritDoc}
@@ -108,7 +110,7 @@ public class FolderEmailMessageHandler extends AbstractEmailMessageHandler
// Create main content node
NodeRef contentNodeRef;
- contentNodeRef = addContentNode(getNodeService(), spaceNodeRef, messageSubject);
+ contentNodeRef = addContentNode(getNodeService(), spaceNodeRef, messageSubject, overwriteDuplicates);
// Add titled aspect
addTitledAspect(contentNodeRef, messageSubject, message.getFrom());
// Add emailed aspect
@@ -182,4 +184,18 @@ public class FolderEmailMessageHandler extends AbstractEmailMessageHandler
log.debug("Titled aspect has been added.");
}
}
+
+ /**
+ * Set the behaviour to be done on detecting a new message with the same subject.
+ * @param overwriteDuplicates
+ */
+ public void setOverwriteDuplicates(boolean overwriteDuplicates)
+ {
+ this.overwriteDuplicates = overwriteDuplicates;
+ }
+
+ public boolean isOverwriteDuplicates()
+ {
+ return overwriteDuplicates;
+ }
}