CustomMailActionExecuter
We need to extend the default MailActionExecuter code provided in alfresco since the attachments are not handled in the code.
In your CustomMailActionExecuter add the PARAM_ATTACHEMENTS attachment action parameter parameter as shown in the code extract below. Note I simplified the code to send the actionedUponNodeRef itself as attachment, using the PARAM_ATTACHEMENTS modify the code to attach any amount of documents you need.
public class CustomMailActionExecuter extends ActionExecuterAbstractBase
implements InitializingBean
{
private static Log logger = LogFactory.getLog(CustomMailActionExecuter.class);
/**
* Action executor constants
*/
public static final String NAME = "abimail";
public static final String PARAM_TO = "to";
public static final String PARAM_TO_MANY = "to_many";
public static final String PARAM_SUBJECT = "subject";
public static final String PARAM_TEXT = "text";
public static final String PARAM_FROM = "from";
public static final String PARAM_TEMPLATE = "template";
public static final String PARAM_ATTACHEMENTS = "attachements";
/**
* From address
*/
private static final String FROM_ADDRESS = "alfresco@alfresco.org";
private static final String REPO_REMOTE_URL = "http://localhost:8080/alfresco";
/**
* The java mail sender
*/
private JavaMailSender javaMailSender;
/**
...
Now Let's modify the prepare method of the MimeMessagePreparator as such
public void prepare(MimeMessage mimeMessage) throws MessagingException
{
if (logger.isDebugEnabled())
{
logger.debug(ruleAction.getParameterValues());
}
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
// set header encoding if one has been supplied
if (headerEncoding != null && headerEncoding.length() != 0)
{
mimeMessage.setHeader("Content-Transfer-Encoding", headerEncoding);
}
....
String text = null;
String templateClassPath = (String) ruleAction.getParameterValue(PARAM_TEMPLATE);
if(templateClassPath != null ){
String comment = (String)ruleAction.getParameterValue(PARAM_TEXT);
Map<String, Object> model = createEmailTemplateModel(actionedUponNodeRef, comment);
text = templateService.processTemplate("freemarker", templateClassPath , model);
}
// set the text body of the message
if (text == null)
{
text = (String)ruleAction.getParameterValue(PARAM_TEXT);
}
MimeMultipart content = new MimeMultipart("mixed");
MimeBodyPart textPart = new MimeBodyPart();
textPart.setText(text);
content.addBodyPart(textPart);
MimeBodyPart attachment = new MimeBodyPart();
attachment.setDataHandler(new DataHandler(new DataSource() {
public InputStream getInputStream() throws IOException {
ContentReader reader = serviceRegistry.getContentService().getReader(actionedUponNodeRef, ContentModel.PROP_CONTENT);
return reader.getContentInputStream();
}
public OutputStream getOutputStream() throws IOException {
throw new IOException("Read-only data");
}
public String getContentType() {
return serviceRegistry.getContentService().getReader(actionedUponNodeRef, ContentModel.PROP_CONTENT).getMimetype();
}
public String getName() {
return nodeService.getProperty(actionedUponNodeRef, ContentModel.PROP_NAME).toString();
}
}));
content.addBodyPart(attachment);
mimeMessage.setContent(content);
// set the from address
NodeRef person = personService.getPerson(authService.getCurrentUserName());
String fromActualUser = null;
if (person != null)
{
fromActualUser = (String) nodeService.getProperty(person, ContentModel.PROP_EMAIL);
}
if( fromActualUser != null && fromActualUser.length() != 0)
{
message.setFrom(fromActualUser);
}
else
{
...
}
}
};
try
{
// Send the message unless we are in "testMode"
if(!testMode)
{
javaMailSender.send(mailPreparer);
}
else
{
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
mailPreparer.prepare(mimeMessage);
lastTestMessage = mimeMessage;
} catch(Exception e) {
System.err.println(e);
}
}
}
catch (MailException e)
{
String to = (String)ruleAction.getParameterValue(PARAM_TO);
if (to == null)
{
Object obj = ruleAction.getParameterValue(PARAM_TO_MANY);
if (obj != null)
{
to = obj.toString();
}
}
logger.error("Failed to send email to " + to, e);
throw new AlfrescoRuntimeException("Failed to send email to:" + to, e);
}
}
You need to be carefull here with two things.
1 - Create the content of the mail as a MimeMultipart and inititize the default content encoding as "mixed".
2 - Create two MimeBodyPart one for holding the text and another one that will hold the attachment. Set the Attachment MimeBodyPart content handler by using its method "setDataHandler" initialized with a an implementation of the "DataSource" Interface that actually reads the repository node reference content property, the content mimetype and its name.
That's all folks!!!
bonus: For those who are interested in creating their own Email template. Just very easy too.
The templateService "processTemplate" method is able to read template definition not only from the repository but also from a node in the class path. So simply create your templates in "
...
String templateClassPath = (String) ruleAction.getParameterValue(PARAM_TEMPLATE);
if(templateClassPath != null ){
String comment = (String)ruleAction.getParameterValue(PARAM_TEXT);
Map<String, Object> model = createEmailTemplateModel(actionedUponNodeRef, comment);
text = templateService.processTemplate("freemarker", templateClassPath , model);
}
...
where here PARAM_TEMPLATE holds the class path of a template for instance
extension/mails/my-custom-mail-template.ftl
Do not forget to configure your CustomMailActionExecuter in the spring context. You might also need to add a "mailService" bean from the class "org.springframework.mail.javamail.JavaMailSenderImpl" to configure your internal javaMailSender.
Okay we are done here. Enjoy!!!