You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ni...@apache.org on 2009/04/01 17:00:23 UTC

svn commit: r760909 - in /camel/trunk/components/camel-mail/src: main/java/org/apache/camel/component/mail/ test/java/org/apache/camel/component/mail/

Author: ningjiang
Date: Wed Apr  1 15:00:20 2009
New Revision: 760909

URL: http://svn.apache.org/viewvc?rev=760909&view=rev
Log:
CAMEL-1506 CAMEL-1507 Applied patch with thanks to Ryan

Added:
    camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MimeMultipartAlternativeTest.java   (with props)
Modified:
    camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java
    camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java
    camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java
    camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailUtils.java

Modified: camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java?rev=760909&r1=760908&r2=760909&view=diff
==============================================================================
--- camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java (original)
+++ camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java Wed Apr  1 15:00:20 2009
@@ -87,15 +87,20 @@
             mimeMessage.setFrom(new InternetAddress(from));
         }
 
-        if (exchange.getIn().hasAttachments()) {
-            appendAttachmentsFromCamel(mimeMessage, exchange.getIn(), endpoint.getConfiguration());
+        // if there is an alternativebody provided, set up a mime multipart alternative message
+        if (hasAlternativeBody(endpoint.getConfiguration(), exchange.getIn())) {
+            createMultipartAlternativeMessage(mimeMessage, exchange.getIn(), endpoint.getConfiguration()); 
         } else {
-            if ("text/html".equals(endpoint.getConfiguration().getContentType())) {
-                DataSource ds = new ByteArrayDataSource(exchange.getIn().getBody(String.class), "text/html");
-                mimeMessage.setDataHandler(new DataHandler(ds));
+            if (exchange.getIn().hasAttachments()) {
+                appendAttachmentsFromCamel(mimeMessage, exchange.getIn(), endpoint.getConfiguration());
             } else {
-                // its just text/plain
-                mimeMessage.setText(exchange.getIn().getBody(String.class));
+                if ("text/html".equals(endpoint.getConfiguration().getContentType())) {                  
+                    DataSource ds = new ByteArrayDataSource(exchange.getIn().getBody(String.class), "text/html");
+                    mimeMessage.setDataHandler(new DataHandler(ds));
+                } else {
+                    // its just text/plain
+                    mimeMessage.setText(exchange.getIn().getBody(String.class));
+                }
             }
         }
     }
@@ -192,16 +197,22 @@
     protected void appendAttachmentsFromCamel(MimeMessage mimeMessage, org.apache.camel.Message camelMessage,
                                               MailConfiguration configuration)
         throws MessagingException {
+        
+        // Put parts in message
+        mimeMessage.setContent(createMixedMultipartAttachments(camelMessage, configuration));
+    }
 
-        // Create a Multipart
-        MimeMultipart multipart = new MimeMultipart();
-
+    private MimeMultipart createMixedMultipartAttachments(org.apache.camel.Message camelMessage, MailConfiguration configuration) throws MessagingException {
         // fill the body with text
+        MimeMultipart multipart = new MimeMultipart();
         multipart.setSubType("mixed");
-        MimeBodyPart textBodyPart = new MimeBodyPart();
-        textBodyPart.setContent(camelMessage.getBody(String.class), configuration.getContentType());
-        multipart.addBodyPart(textBodyPart);
+        addBodyToMultipart(camelMessage, configuration, multipart);
+        String partDisposition = configuration.isUseInlineAttachments() ?  Part.INLINE : Part.ATTACHMENT;
+        addAttachmentsToMultipart(camelMessage, multipart, partDisposition);
+        return multipart;
+    }
 
+    protected void addAttachmentsToMultipart(org.apache.camel.Message camelMessage, MimeMultipart multipart, String partDisposition) throws MessagingException {
         for (Map.Entry<String, DataHandler> entry : camelMessage.getAttachments().entrySet()) {
             String attachmentFilename = entry.getKey();
             DataHandler handler = entry.getValue();
@@ -211,20 +222,66 @@
                     BodyPart messageBodyPart = new MimeBodyPart();
                     // Set the data handler to the attachment
                     messageBodyPart.setDataHandler(handler);
+                    
+                    if (attachmentFilename.toLowerCase().startsWith("cid:")) {
+                    // add a Content-ID header to the attachment
+                        messageBodyPart.addHeader("Content-ID", attachmentFilename.substring(4));
+                    }
                     // Set the filename
                     messageBodyPart.setFileName(attachmentFilename);
                     // Set Disposition
-                    messageBodyPart.setDisposition(Part.ATTACHMENT);
+                    messageBodyPart.setDisposition(partDisposition);
                     // Add part to multipart
                     multipart.addBodyPart(messageBodyPart);
                 }
             }
         }
+    }
+
+    protected void createMultipartAlternativeMessage(MimeMessage mimeMessage, org.apache.camel.Message camelMessage, MailConfiguration configuration)
+        throws MessagingException { 
+
+        MimeMultipart multipartAlternative = new MimeMultipart("alternative");
+        mimeMessage.setContent(multipartAlternative);
+
+        BodyPart plainText = new MimeBodyPart();
+        plainText.setText(getAlternativeBody(configuration, camelMessage));
+        multipartAlternative.addBodyPart(plainText);
+
+        // if there are no attachments, add the body to the same mulitpart message
+        if (!camelMessage.hasAttachments()) {
+            addBodyToMultipart(camelMessage, configuration, multipartAlternative);
+        } else {
+            // if there are attachments, but they aren't set to be inline, add them to
+            // treat them as normal. It will append a multipart-mixed with the attachments and the
+            // body text
+            if (!configuration.isUseInlineAttachments()) {
+                BodyPart mixedAttachments = new MimeBodyPart();
+                mixedAttachments.setContent(createMixedMultipartAttachments(camelMessage, configuration));
+                multipartAlternative.addBodyPart(mixedAttachments);
+                //appendAttachmentsFromCamel(mimeMessage, camelMessage, configuration);
+            } else { // if the attachments are set to be inline, attach them as inline attachments
+                MimeMultipart multipartRelated = new MimeMultipart("related");
+                BodyPart related = new MimeBodyPart();
+
+                related.setContent(multipartRelated);
+                multipartAlternative.addBodyPart(related);
+
+                addBodyToMultipart(camelMessage, configuration, multipartRelated);
+
+                addAttachmentsToMultipart(camelMessage, multipartRelated, Part.INLINE);
+            }
+        }
 
-        // Put parts in message
-        mimeMessage.setContent(multipart);
     }
 
+    protected void addBodyToMultipart(org.apache.camel.Message camelMessage, MailConfiguration configuration, MimeMultipart activeMultipart) throws MessagingException {
+        BodyPart bodyMessage = new MimeBodyPart();
+        bodyMessage.setContent(camelMessage.getBody(String.class), configuration.getContentType());
+        activeMultipart.addBodyPart(bodyMessage);
+    }
+
+
     /**
      * Strategy to allow filtering of attachments which are put on the Mail message
      */
@@ -276,6 +333,15 @@
         return false;
     }
 
+    protected static boolean hasAlternativeBody(MailConfiguration configuration, org.apache.camel.Message camelMessage) {
+        return getAlternativeBody(configuration, camelMessage) != null;
+    }
+
+    protected static String getAlternativeBody(MailConfiguration configuration, org.apache.camel.Message camelMessage) {
+        String alternativeBodyHeader = configuration.getAlternateBodyHeader();
+        return camelMessage.getHeader(alternativeBodyHeader, java.lang.String.class);
+    }
+
     /**
      * Is the given key a mime message recipient header (To, CC or BCC)
      */

Modified: camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java?rev=760909&r1=760908&r2=760909&view=diff
==============================================================================
--- camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java (original)
+++ camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java Wed Apr  1 15:00:20 2009
@@ -37,6 +37,7 @@
 
     public static final String DEFAULT_FOLDER_NAME = "INBOX";
     public static final String DEFAULT_FROM = "camel@localhost";
+    public static final String DEFAULT_ALTERNATE_BODY_HEADER = "mail_alternateBody";
     public static final long DEFAULT_CONNECTION_TIMEOUT = 30000L;
 
     private Properties javaMailProperties;
@@ -59,6 +60,8 @@
     private long connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
     private boolean dummyTrustManager;
     private String contentType = "text/plain";
+    private String alternateBodyHeader = DEFAULT_ALTERNATE_BODY_HEADER;
+    private boolean useInlineAttachments;
 
     public MailConfiguration() {
     }
@@ -409,4 +412,20 @@
     public void setContentType(String contentType) {
         this.contentType = contentType;
     }
+
+    public String getAlternateBodyHeader() {
+        return alternateBodyHeader;
+    }
+
+    public void setAlternateBodyHeader(String alternateBodyHeader) {
+        this.alternateBodyHeader = alternateBodyHeader;
+    }
+
+    public boolean isUseInlineAttachments() {
+        return useInlineAttachments;
+    }
+
+    public void setUseInlineAttachments(boolean useInlineAttachments) {
+        this.useInlineAttachments = useInlineAttachments;
+    }
 }

Modified: camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java?rev=760909&r1=760908&r2=760909&view=diff
==============================================================================
--- camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java (original)
+++ camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.java Wed Apr  1 15:00:20 2009
@@ -140,22 +140,31 @@
 
         Object content = message.getContent();
         if (content instanceof Multipart) {
-            // mail with attachment
-            Multipart mp = (Multipart)content;
-            for (int i = 0; i < mp.getCount(); i++) {
-                Part part = mp.getBodyPart(i);
+            extractFromMultipart((Multipart)content, map);
+        }
+    }
+    
+    protected static void extractFromMultipart(Multipart mp, Map<String, DataHandler> map) 
+        throws javax.mail.MessagingException, IOException {
+
+        for (int i = 0; i < mp.getCount(); i++) {
+            Part part = mp.getBodyPart(i);           
+            if (part.isMimeType("multipart/*")) {
+                extractFromMultipart((Multipart)part.getContent(), map);
+            } else {
                 String disposition = part.getDisposition();
                 if (disposition != null) {
                     if (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE)) {
                         // only add named attachments
                         if (part.getFileName() != null) {
-                            // Parts marked with a disposition of Part.ATTACHMENT are clearly attachments
+                            // Parts marked with a disposition of Part.ATTACHMENT
+                            // are clearly attachments
                             CollectionHelper.appendValue(map, part.getFileName(), part.getDataHandler());
                         }
                     }
                 }
             }
         }
-    }
+    }    
 
 }

Modified: camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailUtils.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailUtils.java?rev=760909&r1=760908&r2=760909&view=diff
==============================================================================
--- camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailUtils.java (original)
+++ camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailUtils.java Wed Apr  1 15:00:20 2009
@@ -135,4 +135,5 @@
 
     }
 
+   
 }

Added: camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MimeMultipartAlternativeTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MimeMultipartAlternativeTest.java?rev=760909&view=auto
==============================================================================
--- camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MimeMultipartAlternativeTest.java (added)
+++ camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MimeMultipartAlternativeTest.java Wed Apr  1 15:00:20 2009
@@ -0,0 +1,148 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.mail;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Map;
+
+import javax.activation.DataHandler;
+import javax.activation.FileDataSource;
+import javax.mail.internet.MimeMultipart;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.Producer;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+
+
+public class MimeMultipartAlternativeTest extends ContextTestSupport {
+    private String alternativeBody = "hello world! (plain text)";
+    private String htmlBody = "<html><body><h1>Hello</h1>World<img src=\"cid:0001\"></body></html>";
+
+    public void testMultipartEmailWithInlineAttachments() throws Exception {
+        // START SNIPPET: e1
+
+        // create an exchange with a normal body and attachment to be produced as email
+        MailEndpoint endpoint = context.getEndpoint("smtp://ryan@mymailserver.com?password=secret", MailEndpoint.class);
+        endpoint.getConfiguration().setUseInlineAttachments(true);
+        endpoint.getConfiguration().setAlternateBodyHeader(MailConfiguration.DEFAULT_ALTERNATE_BODY_HEADER);
+
+        // create the exchange with the mail message that is multipart with a file and a Hello World text/plain message.
+        Exchange exchange = endpoint.createExchange();
+        Message in = exchange.getIn();
+        in.setBody(htmlBody);
+        in.setHeader("mail_alternateBody", alternativeBody);
+        in.addAttachment("cid:0001", new DataHandler(new FileDataSource("src/test/data/logo.jpeg")));
+
+        // create a producer that can produce the exchange (= send the mail)
+        Producer producer = endpoint.createProducer();
+        // start the producer
+        producer.start();
+        // and let it go (processes the exchange by sending the email)
+        producer.process(exchange);
+
+        // END SNIPPET: e1
+
+        // need some time for the mail to arrive on the inbox (consumed and sent to the mock)
+        Thread.sleep(1000);
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        Exchange out = mock.assertExchangeReceived(0);
+        mock.assertIsSatisfied();
+
+        if (log.isTraceEnabled()) {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream(((MailMessage)out.getIn()).getMessage().getSize());
+            ((MailMessage)out.getIn()).getMessage().writeTo(baos);
+            String dumpedMessage = baos.toString();
+            log.trace("multipart alternative: \n" + dumpedMessage);
+        }
+         
+        // plain text
+        assertEquals(alternativeBody, out.getIn().getBody(String.class));
+
+        // attachment
+        Map<String, DataHandler> attachments = out.getIn().getAttachments();
+        assertNotNull("Should not have null attachments", attachments);
+        assertEquals(1, attachments.size());
+        assertEquals("multipart body should have 2 parts", 2, out.getIn().getBody(MimeMultipart.class).getCount());
+
+        producer.stop();
+    }
+
+    public void testMultipartEmailWithRegularAttachments() throws Exception {
+        // START SNIPPET: e1
+
+        // create an exchange with a normal body and attachment to be produced as email
+        MailEndpoint endpoint = context.getEndpoint("smtp://ryan@mymailserver.com?password=secret", MailEndpoint.class);
+        endpoint.getConfiguration().setUseInlineAttachments(false);
+        endpoint.getConfiguration().setAlternateBodyHeader(MailConfiguration.DEFAULT_ALTERNATE_BODY_HEADER);
+
+        // create the exchange with the mail message that is multipart with a file and a Hello World text/plain message.
+        Exchange exchange = endpoint.createExchange();
+        Message in = exchange.getIn();
+        in.setBody(htmlBody);
+        in.setHeader("mail_alternateBody", alternativeBody);
+        in.setHeader("sendInlineAttachments", false);
+        in.addAttachment("cid:0001", new DataHandler(new FileDataSource("src/test/data/logo.jpeg")));
+
+        // create a producer that can produce the exchange (= send the mail)
+        Producer producer = endpoint.createProducer();
+        // start the producer
+        producer.start();
+        // and let it go (processes the exchange by sending the email)
+        producer.process(exchange);
+
+        // END SNIPPET: e1
+
+        // need some time for the mail to arrive on the inbox (consumed and sent to the mock)
+        Thread.sleep(1000);
+
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        Exchange out = mock.assertExchangeReceived(0);
+        mock.assertIsSatisfied();
+
+        if (log.isTraceEnabled()) {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream(((MailMessage)out.getIn()).getMessage().getSize());
+            ((MailMessage)out.getIn()).getMessage().writeTo(baos);
+            String dumpedMessage = baos.toString();
+            log.trace("multipart alternative: \n" + dumpedMessage);
+        }
+
+        // plain text
+        assertEquals(alternativeBody, out.getIn().getBody(String.class));
+
+        // attachment
+        Map<String, DataHandler> attachments = out.getIn().getAttachments();
+        assertNotNull("Should not have null attachments", attachments);
+        assertEquals(1, attachments.size());
+        assertEquals("multipart body should have 2 parts", 2, out.getIn().getBody(MimeMultipart.class).getCount());
+
+        producer.stop();
+    }
+
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() throws Exception {
+                from("pop3://ryan@mymailserver.com?password=secret&consumer.delay=1000").to("mock:result");
+            }
+        };
+    }
+}

Propchange: camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MimeMultipartAlternativeTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: camel/trunk/components/camel-mail/src/test/java/org/apache/camel/component/mail/MimeMultipartAlternativeTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date