Author: davsclaus Date: Tue Nov 10 07:19:08 2009 New Revision: 834370 URL: http://svn.apache.org/viewvc?rev=834370&view=rev Log: CAMEL-2152: Workaround for consuming mails with unsupported charset. Thanks to Dan for patch.
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/MailConsumer.java camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailMessage.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=834370&r1=834369&r2=834370&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 Tue Nov 10 07:19:08 2009 @@ -32,6 +32,7 @@ import javax.mail.Header; import javax.mail.Message; import javax.mail.MessagingException; +import javax.mail.Multipart; import javax.mail.Part; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; @@ -209,29 +210,29 @@ /** * Extracts the body from the Mail message */ - public Object extractBodyFromMail(Exchange exchange, Message message) { - return doExtractBodyFromMail(exchange, message, true); - } - - /** - * Extracts the body from the Mail message - */ - protected Object doExtractBodyFromMail(Exchange exchange, Message message, boolean firstAttempt) { + public Object extractBodyFromMail(Exchange exchange, MailMessage mailMessage) { + Message message = mailMessage.getMessage(); try { return message.getContent(); } catch (Exception e) { // try to fix message in case it has an unsupported encoding in the Content-Type header UnsupportedEncodingException uee = ObjectHelper.getException(UnsupportedEncodingException.class, e); - if (firstAttempt && uee != null) { + if (uee != null) { LOG.debug("Unsupported encoding detected: " + uee.getMessage()); try { String contentType = message.getContentType(); String type = ObjectHelper.before(contentType, "charset="); if (type != null) { - message.setHeader("Content-Type", type); // try again with fixed content type LOG.debug("Trying to extract mail message again with fixed Content-Type: " + type); - return doExtractBodyFromMail(exchange, message, false); + // Since message is read-only, we need to use a copy + MimeMessage messageCopy = new MimeMessage((MimeMessage)message); + messageCopy.setHeader("Content-Type", type); + Object body = messageCopy.getContent(); + // If we got this far, our fix worked... + // Replace the MailMessage's Message with the copy + mailMessage.setMessage(messageCopy); + return body; } } catch (Exception e2) { // fall through and let original exception be thrown @@ -244,6 +245,61 @@ } /** + * Parses the attachments of the given mail message and adds them to the map + * + * @param message the mail message with attachments + * @param map the map to add found attachments (attachmentFilename is the key) + */ + public void extractAttachmentsFromMail(Message message, Map<String, DataHandler> map) + throws javax.mail.MessagingException, IOException { + + LOG.trace("Extracting attachments +++ start +++"); + + Object content = message.getContent(); + if (content instanceof Multipart) { + extractAttachmentsFromMultipart((Multipart)content, map); + } else if (content != null) { + LOG.trace("No attachments to extract as content is not Multipart: " + content.getClass().getName()); + } + + LOG.trace("Extracting attachments +++ done +++"); + } + + protected void extractAttachmentsFromMultipart(Multipart mp, Map<String, DataHandler> map) + throws javax.mail.MessagingException, IOException { + + for (int i = 0; i < mp.getCount(); i++) { + Part part = mp.getBodyPart(i); + LOG.trace("Part #" + i + ": " + part); + + if (part.isMimeType("multipart/*")) { + LOG.trace("Part #" + i + ": is mimetype: multipart/*"); + extractAttachmentsFromMultipart((Multipart)part.getContent(), map); + } else { + String disposition = part.getDisposition(); + if (LOG.isTraceEnabled()) { + LOG.trace("Part #" + i + ": Disposition: " + part.getDisposition()); + LOG.trace("Part #" + i + ": Description: " + part.getDescription()); + LOG.trace("Part #" + i + ": ContentType: " + part.getContentType()); + LOG.trace("Part #" + i + ": FileName: " + part.getFileName()); + LOG.trace("Part #" + i + ": Size: " + part.getSize()); + LOG.trace("Part #" + i + ": LineCount: " + part.getLineCount()); + } + + if (disposition != null && (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))) { + // only add named attachments + String fileName = part.getFileName(); + if (fileName != null) { + LOG.debug("Mail contains file attachment: " + fileName); + // Parts marked with a disposition of Part.ATTACHMENT are clearly attachments + CollectionHelper.appendValue(map, fileName, part.getDataHandler()); + } + } + } + } + } + + /** * Appends the Mail headers from the Camel {...@link MailMessage} */ protected void appendHeadersFromCamelMessage(MimeMessage mimeMessage, MailConfiguration configuration, Exchange exchange) Modified: camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java?rev=834370&r1=834369&r2=834370&view=diff ============================================================================== --- camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java (original) +++ camel/trunk/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java Tue Nov 10 07:19:08 2009 @@ -200,7 +200,8 @@ */ protected void processCommit(Exchange exchange) throws MessagingException { MailMessage msg = (MailMessage) exchange.getIn(); - Message message = msg.getMessage(); + // Use the "original" Message, in case a copy ended up being made + Message message = msg.getOriginalMessage(); if (endpoint.getConfiguration().isDelete()) { LOG.debug("Exchange processed, so flagging message as DELETED"); 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=834370&r1=834369&r2=834370&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 Tue Nov 10 07:19:08 2009 @@ -16,21 +16,14 @@ */ package org.apache.camel.component.mail; -import java.io.IOException; import java.util.Map; - import javax.activation.DataHandler; import javax.mail.Message; import javax.mail.MessagingException; -import javax.mail.Multipart; -import javax.mail.Part; import org.apache.camel.RuntimeCamelException; import org.apache.camel.impl.DefaultMessage; -import org.apache.camel.util.CollectionHelper; import org.apache.camel.util.ExchangeHelper; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; /** * Represents a {...@link org.apache.camel.Message} for working with Mail @@ -38,14 +31,16 @@ * @version $Revision:520964 $ */ public class MailMessage extends DefaultMessage { - private static final transient Log LOG = LogFactory.getLog(MailMessage.class); + // we need a copy of the original message in case we need to workaround a charset issue when extracting + // mail content, see more in MailBinding + private Message originalMailMessage; private Message mailMessage; public MailMessage() { } public MailMessage(Message message) { - this.mailMessage = message; + this.originalMailMessage = this.mailMessage = message; } @Override @@ -59,11 +54,19 @@ public MailMessage copy() { MailMessage answer = (MailMessage)super.copy(); + answer.originalMailMessage = originalMailMessage; answer.mailMessage = mailMessage; return answer; } /** + * Returns the original underlying Mail message + */ + public Message getOriginalMessage() { + return originalMailMessage; + } + + /** * Returns the underlying Mail message */ public Message getMessage() { @@ -71,6 +74,9 @@ } public void setMessage(Message mailMessage) { + if (this.originalMailMessage == null) { + this.originalMailMessage = mailMessage; + } this.mailMessage = mailMessage; } @@ -83,7 +89,7 @@ protected Object createBody() { if (mailMessage != null) { MailBinding binding = ExchangeHelper.getBinding(getExchange(), MailBinding.class); - return binding != null ? binding.extractBodyFromMail(getExchange(), mailMessage) : null; + return binding != null ? binding.extractBodyFromMail(getExchange(), this) : null; } return null; } @@ -106,7 +112,10 @@ protected void populateInitialAttachments(Map<String, DataHandler> map) { if (mailMessage != null) { try { - extractAttachments(mailMessage, map); + MailBinding binding = ExchangeHelper.getBinding(getExchange(), MailBinding.class); + if (binding != null) { + binding.extractAttachmentsFromMail(mailMessage, map); + } } catch (Exception e) { throw new RuntimeCamelException("Error populating the initial mail message attachments", e); } @@ -117,63 +126,9 @@ super.copyFrom(that); if (that instanceof MailMessage) { MailMessage mailMessage = (MailMessage) that; + this.originalMailMessage = mailMessage.originalMailMessage; this.mailMessage = mailMessage.mailMessage; } } - /** - * Parses the attachments of the given mail message and adds them to the map - * - * @param message the mail message with attachments - * @param map the map to add found attachments (attachmentFilename is the key) - */ - protected static void extractAttachments(Message message, Map<String, DataHandler> map) - throws javax.mail.MessagingException, IOException { - - LOG.trace("Extracting attachments +++ start +++"); - - Object content = message.getContent(); - if (content instanceof Multipart) { - extractFromMultipart((Multipart)content, map); - } else if (content != null) { - LOG.trace("No attachments to extract as content is not Multipart: " + content.getClass().getName()); - } - - LOG.trace("Extracting attachments +++ done +++"); - } - - 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); - LOG.trace("Part #" + i + ": " + part); - - if (part.isMimeType("multipart/*")) { - LOG.trace("Part #" + i + ": is mimetype: multipart/*"); - extractFromMultipart((Multipart)part.getContent(), map); - } else { - String disposition = part.getDisposition(); - if (LOG.isTraceEnabled()) { - LOG.trace("Part #" + i + ": Disposition: " + part.getDisposition()); - LOG.trace("Part #" + i + ": Description: " + part.getDescription()); - LOG.trace("Part #" + i + ": ContentType: " + part.getContentType()); - LOG.trace("Part #" + i + ": FileName: " + part.getFileName()); - LOG.trace("Part #" + i + ": Size: " + part.getSize()); - LOG.trace("Part #" + i + ": LineCount: " + part.getLineCount()); - } - - if (disposition != null && (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))) { - // only add named attachments - String fileName = part.getFileName(); - if (fileName != null) { - LOG.debug("Mail contains file attachment: " + fileName); - // Parts marked with a disposition of Part.ATTACHMENT are clearly attachments - CollectionHelper.appendValue(map, fileName, part.getDataHandler()); - } - } - } - } - } - }