mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-07 18:25:23 +00:00
92231: Merged 5.0.N (5.0.1) to HEAD-BUG-FIX (5.1/Cloud) 91995: MNT-12925: Merged V4.2-BUG-FIX (4.2.5) to 5.0.N (5.0.1) 91709 : MNT-12896: Merged V4.2.1 (4.2.1.17) to V4.2-BUG-FIX (4.2.5) 89881: Merged DEV to PATCHES/V4.2.1 (4.2.1.16) 89858 : MNT-12584 : Files are multiplying themselves when do a move out and move in - UIDPLUS extension implemented : UID EXPUNGE command and APPENDUID and COPYUID response codes 88997,89016 : MNT-12584 : Files are multiplying themselves when do a move out and move in - UID SEARCH HEADER Message-Id implemented 88824 : MNT-12585 : All files disappear from a folder if one file is moved out + one file is deleted - greenmail-1.3-patched.jar was patched again to implement DELETED flag search. - Updated source files and diff file for greenmail-1.3-patched.jar library. 88774 : MNT-12546: Deleting a file in Share may not be reflected in IMAP Outlook 2011, then sync may create EML attachments in Share - Removed force change of UID validity as it is not required. 88585 : MNT-12518 : Outlook 2013: moving files to a folder and back to original leads to view discrepancies - Test changed according to new delete/append behavior 88360 : Merged DEV to DEV (V4.2.1-IMAP) 88280: MNT-12575: IMAP Needs to RETRY - Incremented MAX-RETRIS parameter up to 20, wrapped Timer to RetryingTransactionHelper. 88294,88343,88345 : MNT-12546: Deleting a file in Share may not be reflected in IMAP Outlook 2011, then sync may create EML attachments in Share - Fixed IMAP caching of deleted files via Share. 88291 : MNT-12518 : Outlook 2013: moving files to a folder and back to original leads to view discrepancies - Implement Outlook 2013 move shuffle as copy 90106: Merged DEV to PATCHES/V4.2.1 (4.2.1.16) 89996 : MNT-12584 : Files are multiplying themselves when do a move out and move in - Green mail source files have been updated 90109: Merged DEV to PATCHES/V4.2.1 (4.2.1.16) 90105 : MNT-12518 : Outlook 2013: moving files to a folder and back to original leads to view discrepancies - Do not use APPENDUID response code to avoid usage of cached messages in Outlook 2013 90307: Merged DEV to PATCHES/V4.2.1 (4.2.1.16) 90268,90271 : MNT-12585 : All files disappear from a folder if one file is moved out + one file is deleted - Squeeze UIDVALIDITY. Implement untagged EXPUNGE response 91371: MNT-12856 : User cannot see document in repository if content was not checked by admin from IMAP - AccessDeniedException should not break IMAP response 91708: MNT-12585 : All files disappear from a folder if one file is moved out + one file is deleted - Change reference to greenmail in the pom file. Should have been when the jar changed, however this is not used in the build used to create the artefacts. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@94859 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
249 lines
8.9 KiB
Java
249 lines
8.9 KiB
Java
/*
|
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
|
*
|
|
* This file is part of Alfresco
|
|
*
|
|
* Alfresco is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Alfresco is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package org.alfresco.repo.imap;
|
|
|
|
import static org.alfresco.repo.imap.AlfrescoImapConst.MIME_VERSION;
|
|
import static org.alfresco.repo.imap.AlfrescoImapConst.X_ALF_NODEREF_ID;
|
|
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Properties;
|
|
|
|
import javax.mail.Flags;
|
|
import javax.mail.MessagingException;
|
|
import javax.mail.Session;
|
|
import javax.mail.internet.MimeMessage;
|
|
|
|
import org.alfresco.model.ImapModel;
|
|
import org.alfresco.repo.imap.ImapService.EmailBodyFormat;
|
|
import org.alfresco.repo.template.TemplateNode;
|
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
|
import org.alfresco.service.ServiceRegistry;
|
|
import org.alfresco.service.cmr.model.FileInfo;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.NodeService;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
/**
|
|
* @author Arseny Kovalchuk
|
|
*/
|
|
public abstract class AbstractMimeMessage extends MimeMessage
|
|
{
|
|
protected static final String DEFAULT_SUFFIX = "@alfresco.org";
|
|
|
|
protected static int MAX_RETRIES = 1;
|
|
|
|
private Log logger = LogFactory.getLog(AbstractMimeMessage.class);
|
|
|
|
protected boolean generateBody = true;
|
|
|
|
protected ServiceRegistry serviceRegistry;
|
|
protected ImapService imapService;
|
|
protected FileInfo messageFileInfo;
|
|
protected MimeMessage wrappedMessage;
|
|
protected boolean isMessageInSitesLibrary;
|
|
|
|
protected AbstractMimeMessage(Session session)
|
|
{
|
|
super(session);
|
|
}
|
|
|
|
protected AbstractMimeMessage(FileInfo fileInfo, ServiceRegistry serviceRegistry, boolean generateBody) throws MessagingException
|
|
{
|
|
super(Session.getDefaultInstance(new Properties()));
|
|
this.generateBody = generateBody;
|
|
buildMessage(fileInfo, serviceRegistry);
|
|
}
|
|
|
|
protected void buildMessage(FileInfo fileInfo, ServiceRegistry serviceRegistry) throws MessagingException
|
|
{
|
|
checkParameter(serviceRegistry, "ServiceRegistry");
|
|
this.content = null;
|
|
this.serviceRegistry = serviceRegistry;
|
|
this.imapService = serviceRegistry.getImapService();
|
|
this.messageFileInfo = fileInfo;
|
|
this.isMessageInSitesLibrary = imapService.isNodeInSitesLibrary(messageFileInfo.getNodeRef());
|
|
RetryingTransactionHelper txHelper = serviceRegistry.getTransactionService().getRetryingTransactionHelper();
|
|
txHelper.setMaxRetries(MAX_RETRIES);
|
|
txHelper.setReadOnly(false);
|
|
txHelper.doInTransaction(new RetryingTransactionCallback<Object>() {
|
|
public Object execute() throws Throwable
|
|
{
|
|
buildMessageInternal();
|
|
return null;
|
|
}
|
|
}, false);
|
|
|
|
}
|
|
|
|
/**
|
|
* Method must be implemented in subclasses. It usually should be used to generate message body.
|
|
*
|
|
* @throws MessagingException
|
|
*/
|
|
public abstract void buildMessageInternal() throws MessagingException;
|
|
|
|
/**
|
|
* Method that checks mandatory parameter.
|
|
* @param The parameter instance to check.
|
|
* @param The name of the parameter.
|
|
*/
|
|
protected void checkParameter(Object parameter, String name)
|
|
{
|
|
if (parameter == null)
|
|
{
|
|
throw new IllegalArgumentException(name + " parameter is null.");
|
|
}
|
|
}
|
|
|
|
protected void setMessageHeaders() throws MessagingException
|
|
{
|
|
setHeader(MIME_VERSION, "1.0");
|
|
// Optional headers for further implementation of multiple Alfresco server support.
|
|
setHeader(X_ALF_NODEREF_ID, messageFileInfo.getNodeRef().getId());
|
|
// setHeader(X_ALF_SERVER_UID, imapService.getAlfrescoServerUID());
|
|
|
|
setPersistedHeaders();
|
|
}
|
|
|
|
private void setPersistedHeaders() throws MessagingException
|
|
{
|
|
NodeService nodeService = serviceRegistry.getNodeService();
|
|
if (nodeService.hasAspect(messageFileInfo.getNodeRef(), ImapModel.ASPECT_IMAP_MESSAGE_HEADERS))
|
|
{
|
|
@SuppressWarnings("unchecked")
|
|
List<String> messageHeaders = (List<String>)nodeService.getProperty(messageFileInfo.getNodeRef(), ImapModel.PROP_MESSAGE_HEADERS);
|
|
|
|
if (messageHeaders == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (String header : messageHeaders)
|
|
{
|
|
String headerValue = header.substring(header.indexOf(ImapModel.MESSAGE_HEADER_TO_PERSIST_SPLITTER) + 1);
|
|
String headerName = header.substring(0, header.indexOf(ImapModel.MESSAGE_HEADER_TO_PERSIST_SPLITTER));
|
|
|
|
setHeader(headerName, headerValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns {@link FileInfo} object representing message in Alfresco.
|
|
*
|
|
* @return reference to the {@link FileInfo} object.
|
|
*/
|
|
public FileInfo getMessageInfo()
|
|
{
|
|
return messageFileInfo;
|
|
}
|
|
|
|
/**
|
|
* Returns message flags.
|
|
*
|
|
* @return {@link Flags}
|
|
*/
|
|
@Override
|
|
public Flags getFlags()
|
|
{
|
|
return imapService.getFlags(messageFileInfo);
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets message flags.
|
|
*
|
|
* @param flags - {@link Flags} object.
|
|
* @param value - flags value.
|
|
*/
|
|
@Override
|
|
public void setFlags(Flags flags, boolean value) throws MessagingException
|
|
{
|
|
imapService.setFlags(messageFileInfo, flags, value);
|
|
}
|
|
|
|
/**
|
|
* Returns the text representing email body for ContentModel node.
|
|
*
|
|
* @param nodeRef NodeRef of the target content.
|
|
* @param type The type of the returned body. May be the one of {@link EmailBodyFormat}.
|
|
* @return Text representing email body for ContentModel node.
|
|
*/
|
|
public String getEmailBodyText(EmailBodyFormat type)
|
|
{
|
|
return serviceRegistry.getTemplateService().processTemplate(
|
|
imapService.getDefaultEmailBodyTemplate(type),
|
|
createEmailTemplateModel(messageFileInfo.getNodeRef()));
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Builds default email template model for TemplateProcessor
|
|
*
|
|
* @param ref NodeRef of the target content.
|
|
* @return Map that includes template model objects.
|
|
*/
|
|
private Map<String, Object> createEmailTemplateModel(NodeRef ref)
|
|
{
|
|
Map<String, Object> model = new HashMap<String, Object>(8, 1.0f);
|
|
TemplateNode tn = new TemplateNode(ref, serviceRegistry, null);
|
|
model.put("document", tn);
|
|
NodeRef parent = serviceRegistry.getNodeService().getPrimaryParent(ref).getParentRef();
|
|
model.put("space", new TemplateNode(parent, serviceRegistry, null));
|
|
model.put("date", new Date());
|
|
model.put("contextUrl", new String(imapService.getWebApplicationContextUrl()));
|
|
model.put("alfTicket", new String(serviceRegistry.getAuthenticationService().getCurrentTicket()));
|
|
if (isMessageInSitesLibrary)
|
|
{
|
|
String pathFromSites = imapService.getPathFromSites(parent);
|
|
StringBuilder parsedPath = new StringBuilder();
|
|
String[] pathParts = pathFromSites.split("/");
|
|
if (pathParts.length > 2)
|
|
{
|
|
parsedPath.append(pathParts[0]).append("/").append(pathParts[1]);
|
|
parsedPath.append("?filter=path|");
|
|
for (int i = 2; i < pathParts.length; i++)
|
|
{
|
|
parsedPath.append("/").append(pathParts[i]);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
parsedPath.append(pathFromSites);
|
|
}
|
|
model.put("shareContextUrl", new String(imapService.getShareApplicationContextUrl()));
|
|
model.put("parentPathFromSites", parsedPath.toString());
|
|
}
|
|
return model;
|
|
}
|
|
|
|
protected void updateMessageID() throws MessagingException
|
|
{
|
|
setHeader("Message-ID", "<" + this.messageFileInfo.getNodeRef().getId() + DEFAULT_SUFFIX + ">");
|
|
}
|
|
}
|