From a13c8cbf7ef1c45bd62d62317bde236f2c825f44 Mon Sep 17 00:00:00 2001 From: Mark Rogers Date: Thu, 7 Jul 2011 13:11:06 +0000 Subject: [PATCH] ALF-6772 - IMAP: User metadata viewed in Outlook git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28848 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../alfresco/messages/imap-service.properties | 3 + .../imap/default/imap-server-context.xml | 3 + .../imap/default/imap-server.properties | 1 + .../repo/imap/AbstractMimeMessage.java | 94 +--------- .../repo/imap/ContentModelMessage.java | 167 ++++++++++++++++++ .../org/alfresco/repo/imap/ImapService.java | 5 + .../alfresco/repo/imap/ImapServiceImpl.java | 40 ++++- 7 files changed, 221 insertions(+), 92 deletions(-) diff --git a/config/alfresco/messages/imap-service.properties b/config/alfresco/messages/imap-service.properties index ce2e6c5a1e..5be64596db 100644 --- a/config/alfresco/messages/imap-service.properties +++ b/config/alfresco/messages/imap-service.properties @@ -11,4 +11,7 @@ imap.server.error.permission_denied = "Cannot create folder - Permission denied. imap.server.error.folder_already_exist = "Folder already exists." imap.server.error.mailbox_name_is_mandatory = "Mailbox name is mandatory parameter." imap.server.error.cannot_get_a_folder = "Cannot get a folder with name ''{0}''." +imap.server.error.cannot_parse_default_email = "Cannot parse default e-mail address ''{0}''." + + diff --git a/config/alfresco/subsystems/imap/default/imap-server-context.xml b/config/alfresco/subsystems/imap/default/imap-server-context.xml index 575a508a43..e1e16ad96a 100644 --- a/config/alfresco/subsystems/imap/default/imap-server-context.xml +++ b/config/alfresco/subsystems/imap/default/imap-server-context.xml @@ -162,6 +162,9 @@ ${imap.mail.from.default} + + ${imap.mail.to.default} + ${spaces.store}/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.imapConfig.childname}/${spaces.imap_templates.childname} diff --git a/config/alfresco/subsystems/imap/default/imap-server.properties b/config/alfresco/subsystems/imap/default/imap-server.properties index 94b9bded53..36d5aa6a2a 100644 --- a/config/alfresco/subsystems/imap/default/imap-server.properties +++ b/config/alfresco/subsystems/imap/default/imap-server.properties @@ -3,6 +3,7 @@ imap.server.port=143 imap.server.host=0.0.0.0 imap.mail.from.default=alfresco@demo.alfresco.org +imap.mail.to.default=alfresco@demo.alfresco.org imap.config.home.store=${protocols.storeName} imap.config.home.rootPath=${protocols.rootPath} diff --git a/source/java/org/alfresco/repo/imap/AbstractMimeMessage.java b/source/java/org/alfresco/repo/imap/AbstractMimeMessage.java index ac36a190ed..144a1fef9c 100644 --- a/source/java/org/alfresco/repo/imap/AbstractMimeMessage.java +++ b/source/java/org/alfresco/repo/imap/AbstractMimeMessage.java @@ -55,11 +55,7 @@ import org.apache.commons.logging.LogFactory; * @author Arseny Kovalchuk */ public abstract class AbstractMimeMessage extends MimeMessage -{ - /** Used if imapHelper.getDefaultFromAddress is not set */ - protected static final String DEFAULT_EMAIL_FROM = "alfresco@alfresco.org"; - protected static final String DEFAULT_EMAIL_TO = DEFAULT_EMAIL_FROM; - +{ protected static int MAX_RETRIES = 1; private Log logger = LogFactory.getLog(AbstractMimeMessage.class); @@ -133,53 +129,7 @@ public abstract class AbstractMimeMessage extends MimeMessage // setHeader(X_ALF_SERVER_UID, imapService.getAlfrescoServerUID()); } - /** - * Builds the InternetAddress from the Content Author name if provided. If name not specified, it takes Content Creator name. If content creator does not exists, the default - * from address will be returned. - * - * @param contentAuthor The content author full name. - * @return Generated InternetAddress[] array. - * @throws AddressException - */ - protected InternetAddress[] buildSenderFromAddress() throws AddressException - { - // Generate FROM address (Content author) - InternetAddress[] addressList = null; - Map properties = messageFileInfo.getProperties(); - String prop = (String) properties.get(ContentModel.PROP_AUTHOR); - String defaultFromAddress = imapService.getDefaultFromAddress(); - defaultFromAddress = defaultFromAddress == null ? DEFAULT_EMAIL_FROM : defaultFromAddress; - try - { - - if (prop != null) - { - StringBuilder contentAuthor = new StringBuilder(); - contentAuthor.append("\"").append(prop).append("\" <").append(defaultFromAddress).append(">"); - addressList = InternetAddress.parse(contentAuthor.toString()); - } - else - { - prop = (String) properties.get(ContentModel.PROP_CREATOR); - if (prop != null) - { - StringBuilder creator = new StringBuilder(); - creator.append("\"").append(prop).append("\" <").append(defaultFromAddress).append(">"); - addressList = InternetAddress.parse(creator.toString()); - } - else - { - throw new AddressException(I18NUtil.getMessage("imap.server.error.properties_dont_exist")); - } - } - } - catch (AddressException e) - { - addressList = InternetAddress.parse(DEFAULT_EMAIL_FROM); - } - return addressList; - } - + /** * Returns {@link FileInfo} object representing message in Alfresco. * @@ -228,43 +178,7 @@ public abstract class AbstractMimeMessage extends MimeMessage createEmailTemplateModel(messageFileInfo.getNodeRef())); } - /** - * TODO USE CASE 2: "The To/addressee will be the first email alias found in the parent folders or a default one (TBD)". - * It seems to be more informative as alike {@code @}... - * - * @return Generated TO address {@code @} - * @throws AddressException - */ - protected InternetAddress[] buildRecipientToAddress() throws AddressException - { - InternetAddress[] result = null; - String defaultEmailTo = null; - final String escapedUserName = AuthenticationUtil.getFullyAuthenticatedUser().replaceAll("[/,\\,@]", "."); - final String userDomain = DEFAULT_EMAIL_TO.split("@")[1]; - defaultEmailTo = escapedUserName + "@" + userDomain; - try - { - result = InternetAddress.parse(defaultEmailTo); - } - catch (AddressException e) - { - logger.error(String.format("Wrong email address '%s'.", defaultEmailTo), e); - result = InternetAddress.parse(DEFAULT_EMAIL_TO); - } - return result; - } - protected void addFromInternal(String addressesString) throws MessagingException - { - if (addressesString != null) - { - addFrom(InternetAddress.parse(addressesString)); - } - else - { - addFrom(new Address[] { new InternetAddress(DEFAULT_EMAIL_FROM) }); - } - } /** * Builds default email template model for TemplateProcessor @@ -325,7 +239,5 @@ public abstract class AbstractMimeMessage extends MimeMessage protected void updateMessageID() throws MessagingException { setHeader("Message-ID", this.messageFileInfo.getNodeRef().getId()); - } - - + } } diff --git a/source/java/org/alfresco/repo/imap/ContentModelMessage.java b/source/java/org/alfresco/repo/imap/ContentModelMessage.java index 33a911eb4d..b23564a0d3 100644 --- a/source/java/org/alfresco/repo/imap/ContentModelMessage.java +++ b/source/java/org/alfresco/repo/imap/ContentModelMessage.java @@ -25,7 +25,9 @@ import java.util.Map; import javax.mail.Address; import javax.mail.MessagingException; import javax.mail.Multipart; +import javax.mail.internet.AddressException; import javax.mail.internet.ContentType; +import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; @@ -33,12 +35,20 @@ import javax.mail.internet.MimeUtility; import org.alfresco.model.ContentModel; import org.alfresco.repo.imap.ImapService.EmailBodyFormat; +import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.I18NUtil; public class ContentModelMessage extends AbstractMimeMessage { + private Log logger = LogFactory.getLog(ContentModelMessage.class); + + protected static final String DEFAULT_EMAIL_FROM = "alfresco@alfresco.org"; + protected static final String DEFAULT_EMAIL_TO = "alfresco@alfresco.org"; public ContentModelMessage(FileInfo fileInfo, ServiceRegistry serviceRegistry, boolean generateBody) throws MessagingException { @@ -143,6 +153,163 @@ public class ContentModelMessage extends AbstractMimeMessage return s.toString(); } } + + /** + * Generate the "to" address. + * + * Step 1: Use PROP_ADDRESSEE + * + * Last Step: Use the default address + * + * @return Generated TO address {@code @} + * @throws AddressException + */ + private InternetAddress[] buildRecipientToAddress() throws AddressException + { + InternetAddress[] result = null; + + + Map properties = messageFileInfo.getProperties(); + + /** + * Step 1 : Get the ADDRESSEE if it exists + */ + if(properties.containsKey(ContentModel.PROP_ADDRESSEE)) + { + String addressee = (String)properties.get(ContentModel.PROP_ADDRESSEE); + try + { + result = InternetAddress.parse(addressee); + return result; + } + catch (AddressException e) + { + // try next step + } + } + +// final String escapedUserName = AuthenticationUtil.getFullyAuthenticatedUser().replaceAll("[/,\\,@]", "."); +// final String userDomain = DEFAULT_EMAIL_TO.split("@")[1]; +// String userName = escapedUserName + "@" + userDomain; +// try +// { +// result = InternetAddress.parse(userName); +// return result; +// } +// catch (AddressException e) +// { +// } + + /** + * Last Step : Get the Default address + */ + String defaultToAddress = imapService.getDefaultToAddress(); + + try + { + result = InternetAddress.parse(defaultToAddress); + return result; + } + catch (AddressException e) + { + logger.warn(String.format("Wrong email address '%s'.", defaultToAddress), e); + } + result = InternetAddress.parse(DEFAULT_EMAIL_TO); + return result; + + } + + /** + * Builds the InternetAddress for the sender (from) + * + * Step 1: use PROP_ORIGINATOR + * + * Last Step : Use the default address. + * + * Content Author name if provided. If name not specified, it takes Content Creator name. + * If content creator does not exists, the default from address will be returned. + * + * @param contentAuthor The content author full name. + * @return Generated InternetAddress[] array. + * @throws AddressException + */ + private InternetAddress[] buildSenderFromAddress() throws AddressException + { + // Generate FROM address (Content author) + InternetAddress[] result = null; + Map properties = messageFileInfo.getProperties(); + String defaultFromAddress = imapService.getDefaultFromAddress(); + + /** + * Step 1 : Get the ORIGINATOR if it exists + */ + if(properties.containsKey(ContentModel.PROP_ORIGINATOR)) + { + String addressee = (String)properties.get(ContentModel.PROP_ORIGINATOR); + try + { + result = InternetAddress.parse(addressee); + return result; + } + catch (AddressException e) + { + // try next step + } + } + /** + * Go for the author property + */ + if(properties.containsKey(ContentModel.PROP_AUTHOR)) + { + String author = (String) properties.get(ContentModel.PROP_AUTHOR); + try + { + StringBuilder contentAuthor = new StringBuilder(); + contentAuthor.append("\"").append(author).append("\" <").append(defaultFromAddress).append(">"); + result = InternetAddress.parse(contentAuthor.toString()); + return result; + + } + catch (AddressException e) + { + // try next step + } + } + + if(properties.containsKey(ContentModel.PROP_CREATOR)) + { + String author = (String) properties.get(ContentModel.PROP_CREATOR); + try + { + + StringBuilder contentAuthor = new StringBuilder(); + contentAuthor.append("\"").append(author).append("\" <").append(defaultFromAddress).append(">"); + result = InternetAddress.parse(contentAuthor.toString()); + return result; + + } + catch (AddressException e) + { + // try next step + } + } + + /** + * Last Step : Get the Default address + */ + try + { + result = InternetAddress.parse(defaultFromAddress); + return result; + } + catch (AddressException e) + { + logger.warn(String.format("Wrong email address '%s'.", defaultFromAddress), e); + } + result = InternetAddress.parse(DEFAULT_EMAIL_FROM); + return result; + + } } diff --git a/source/java/org/alfresco/repo/imap/ImapService.java b/source/java/org/alfresco/repo/imap/ImapService.java index 3069a99474..49c5d84b91 100644 --- a/source/java/org/alfresco/repo/imap/ImapService.java +++ b/source/java/org/alfresco/repo/imap/ImapService.java @@ -228,6 +228,11 @@ public interface ImapService * @return Default From addreses */ public String getDefaultFromAddress(); + + /** + * @return Default To addreses + */ + public String getDefaultToAddress(); /** * @return Path to the folder containing templates, that will be used for generating body of message in VIRTUAL and MIXED views. diff --git a/source/java/org/alfresco/repo/imap/ImapServiceImpl.java b/source/java/org/alfresco/repo/imap/ImapServiceImpl.java index 7f9c96f364..f9ab9508aa 100644 --- a/source/java/org/alfresco/repo/imap/ImapServiceImpl.java +++ b/source/java/org/alfresco/repo/imap/ImapServiceImpl.java @@ -20,6 +20,8 @@ package org.alfresco.repo.imap; import static org.alfresco.repo.imap.AlfrescoImapConst.DICTIONARY_TEMPLATE_PREFIX; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.OutputStream; @@ -111,7 +113,8 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol private static final String ERROR_FOLDER_ALREADY_EXISTS = "imap.server.error.folder_already_exist"; private static final String ERROR_MAILBOX_NAME_IS_MANDATORY = "imap.server.error.mailbox_name_is_mandatory"; private static final String ERROR_CANNOT_GET_A_FOLDER = "imap.server.error.cannot_get_a_folder"; - + private static final String ERROR_CANNOT_PARSE_DEFAULT_EMAIL = "imap.server.error.cannot_parse_default_email"; + private static final String CHECKED_NODES = "imap.flaggable.aspect.checked.list"; private static final String FAVORITE_SITES = "imap.favorite.sites.list"; private static final String UIDVALIDITY_LISTENER_ALREADY_BOUND = "imap.uidvalidity.already.bound"; @@ -139,6 +142,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol private Set ignoreExtractionFolders; private String defaultFromAddress; + private String defaultToAddress; private String repositoryTemplatePath; private boolean extractAttachmentsEnabled = true; @@ -261,6 +265,16 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol { this.defaultFromAddress = defaultFromAddress; } + + public String getDefaultToAddress() + { + return defaultToAddress; + } + + public void setDefaultToAddress(String defaultToAddress) + { + this.defaultToAddress = defaultToAddress; + } public String getWebApplicationContextUrl() { @@ -324,9 +338,33 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol PropertyCheck.mandatory(this, "permissionService", permissionService); PropertyCheck.mandatory(this, "serviceRegistry", serviceRegistry); PropertyCheck.mandatory(this, "defaultFromAddress", defaultFromAddress); + PropertyCheck.mandatory(this, "defaultToAddress", defaultToAddress); PropertyCheck.mandatory(this, "repositoryTemplatePath", repositoryTemplatePath); PropertyCheck.mandatory(this, "policyBehaviourFilter", policyBehaviourFilter); PropertyCheck.mandatory(this, "mimetypeService", mimetypeService); + + // be sure that a default e-mail is correct + try + { + InternetAddress.parse(defaultFromAddress); + } + catch (AddressException ex) + { + throw new AlfrescoRuntimeException( + ERROR_CANNOT_PARSE_DEFAULT_EMAIL, + new Object[] {defaultFromAddress}); + } + + try + { + InternetAddress.parse(defaultToAddress); + } + catch (AddressException ex) + { + throw new AlfrescoRuntimeException( + ERROR_CANNOT_PARSE_DEFAULT_EMAIL, + new Object[] {defaultToAddress}); + } } public void startup()