View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.transport.email.transformers;
8   
9   import org.mule.api.MuleMessage;
10  import org.mule.api.transformer.TransformerException;
11  import org.mule.transformer.simple.SerializableToByteArray;
12  import org.mule.transport.email.AbstractMailConnector;
13  import org.mule.util.StringUtils;
14  
15  import java.io.IOException;
16  import java.io.Serializable;
17  import java.util.Map;
18  
19  import javax.activation.DataHandler;
20  import javax.mail.BodyPart;
21  import javax.mail.Message;
22  import javax.mail.MessagingException;
23  import javax.mail.internet.MimeBodyPart;
24  import javax.mail.internet.MimeMultipart;
25  import javax.mail.util.ByteArrayDataSource;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  
30  /**
31   * Transforms a {@link javax.mail.Message} to a {@link MuleMessage}, with support for attachments
32   */
33  public class ObjectToMimeMessage extends StringToEmailMessage
34  {
35      private Log logger = LogFactory.getLog(getClass());
36      private boolean useInboundAttachments = true;
37      private boolean useOutboundAttachments = true;
38  
39      @Override
40      protected void setContent(Object payload, Message msg, String contentType, MuleMessage message)
41          throws Exception
42      {
43          boolean transformInboundAttachments = useInboundAttachments && message.getInboundAttachmentNames().size() > 0;
44          boolean transformOutboundAttachments = useOutboundAttachments && message.getOutboundAttachmentNames().size() > 0;
45          if (transformInboundAttachments || transformOutboundAttachments)
46          {
47              // The content type must be multipart/mixed
48              MimeMultipart multipart = new MimeMultipart("mixed");
49              multipart.addBodyPart(getPayloadBodyPart(message.getPayload(), contentType));
50              if (transformInboundAttachments)
51              {
52                  for (String name : message.getInboundAttachmentNames())
53                  {
54                      // Let outbound attachments override inbound ones
55                      if (!transformOutboundAttachments || message.getOutboundAttachment(name) == null)
56                      {
57                          BodyPart part = getBodyPartForAttachment(message.getInboundAttachment(name), name);
58                          // Check message props for extra headers
59                          addBodyPartHeaders(part, name, message);
60                          multipart.addBodyPart(part);
61                      }
62                  }
63              }
64              if (transformOutboundAttachments)
65              {
66                  for (String name : message.getOutboundAttachmentNames())
67                  {
68                      BodyPart part = getBodyPartForAttachment(message.getOutboundAttachment(name), name);
69                      // Check message props for extra headers
70                      addBodyPartHeaders(part, name, message);
71                      multipart.addBodyPart(part);
72                  }
73              }
74              // the payload must be set to the constructed MimeMultipart message
75              payload = multipart;
76              // the ContentType of the message to be sent, must be the multipart content type
77              contentType = multipart.getContentType();
78          }
79          
80          // now the message will contain the multipart payload, and the multipart
81          // contentType
82          super.setContent(payload, msg, contentType, message);
83      }
84  
85      protected void addBodyPartHeaders(BodyPart part, String name, MuleMessage message)
86      {
87          Map<String, String> headers = message.getOutboundProperty(
88              name + AbstractMailConnector.ATTACHMENT_HEADERS_PROPERTY_POSTFIX);
89  
90          if (null != headers)
91          {
92              for (String key : headers.keySet())
93              {
94                  try
95                  {
96                      part.setHeader(key, headers.get(key));
97                  }
98                  catch (MessagingException me)
99                  {
100                     logger.error("Failed to set bodypart header", me);
101                 }
102             }
103         }
104     }
105 
106     protected BodyPart getBodyPartForAttachment(DataHandler handler, String name) throws MessagingException
107     {
108         BodyPart part = new MimeBodyPart();
109         part.setDataHandler(handler);
110         part.setDescription(name);
111 
112         part.setFileName(StringUtils.defaultString(handler.getName(), name));
113         return part;
114     }
115 
116     protected BodyPart getPayloadBodyPart(Object payload, String contentType)
117         throws MessagingException, TransformerException, IOException
118     {
119         DataHandler handler;
120         if (payload instanceof String)
121         {
122             handler = new DataHandler(new ByteArrayDataSource((String) payload, contentType));
123         }
124         else if (payload instanceof byte[])
125         {
126             handler = new DataHandler(new ByteArrayDataSource((byte[])payload, contentType));
127         }
128         else if (payload instanceof Serializable)
129         {
130             handler = new DataHandler(new ByteArrayDataSource(
131                 (byte[])new SerializableToByteArray().transform(payload), contentType));
132         }
133         else
134         {
135             throw new IllegalArgumentException();
136         }
137         BodyPart part = new MimeBodyPart();
138         part.setDataHandler(handler);
139         part.setDescription("Payload");
140         return part;
141     }
142 
143     /**
144      * Set whether inbound attachments should be transformed into MIME parts
145      */
146     public void setUseInboundAttachments(boolean useInboundAttachments)
147     {
148         this.useInboundAttachments = useInboundAttachments;
149     }
150 
151     /**
152      * Set whether outbound attachments should be transformed into MIME parts
153      */
154     public void setUseOutboundAttachments(boolean useOutboundAttachments)
155     {
156         this.useOutboundAttachments = useOutboundAttachments;
157     }
158 }