001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.component.mail; 018 019 import java.io.IOException; 020 import java.util.Map; 021 022 import javax.activation.DataHandler; 023 import javax.mail.Message; 024 import javax.mail.MessagingException; 025 import javax.mail.Multipart; 026 import javax.mail.Part; 027 028 import org.apache.camel.RuntimeCamelException; 029 import org.apache.camel.impl.DefaultMessage; 030 import org.apache.camel.util.CollectionHelper; 031 import org.apache.camel.util.ExchangeHelper; 032 import org.apache.commons.logging.Log; 033 import org.apache.commons.logging.LogFactory; 034 035 /** 036 * Represents a {@link org.apache.camel.Message} for working with Mail 037 * 038 * @version $Revision:520964 $ 039 */ 040 public class MailMessage extends DefaultMessage { 041 private static final transient Log LOG = LogFactory.getLog(MailMessage.class); 042 private Message mailMessage; 043 044 public MailMessage() { 045 } 046 047 public MailMessage(Message message) { 048 this.mailMessage = message; 049 } 050 051 @Override 052 public String toString() { 053 if (mailMessage != null) { 054 return "MailMessage: " + MailUtils.dumpMessage(mailMessage); 055 } else { 056 return "MailMessage: " + getBody(); 057 } 058 } 059 060 public MailMessage copy() { 061 MailMessage answer = (MailMessage)super.copy(); 062 answer.mailMessage = mailMessage; 063 return answer; 064 } 065 066 /** 067 * Returns the underlying Mail message 068 */ 069 public Message getMessage() { 070 return mailMessage; 071 } 072 073 public void setMessage(Message mailMessage) { 074 this.mailMessage = mailMessage; 075 } 076 077 @Override 078 public MailMessage newInstance() { 079 return new MailMessage(); 080 } 081 082 @Override 083 protected Object createBody() { 084 if (mailMessage != null) { 085 MailBinding binding = ExchangeHelper.getBinding(getExchange(), MailBinding.class); 086 return binding != null ? binding.extractBodyFromMail(getExchange(), mailMessage) : null; 087 } 088 return null; 089 } 090 091 @Override 092 protected void populateInitialHeaders(Map<String, Object> map) { 093 if (mailMessage != null) { 094 try { 095 MailBinding binding = ExchangeHelper.getBinding(getExchange(), MailBinding.class); 096 if (binding != null) { 097 map.putAll(binding.extractHeadersFromMail(mailMessage, getExchange())); 098 } 099 } catch (MessagingException e) { 100 throw new RuntimeCamelException("Error accessing headers due to: " + e.getMessage(), e); 101 } 102 } 103 } 104 105 @Override 106 protected void populateInitialAttachments(Map<String, DataHandler> map) { 107 if (mailMessage != null) { 108 try { 109 extractAttachments(mailMessage, map); 110 } catch (Exception e) { 111 throw new RuntimeCamelException("Error populating the initial mail message attachments", e); 112 } 113 } 114 } 115 116 public void copyFrom(org.apache.camel.Message that) { 117 super.copyFrom(that); 118 if (that instanceof MailMessage) { 119 MailMessage mailMessage = (MailMessage) that; 120 this.mailMessage = mailMessage.mailMessage; 121 } 122 } 123 124 /** 125 * Parses the attachments of the given mail message and adds them to the map 126 * 127 * @param message the mail message with attachments 128 * @param map the map to add found attachments (attachmentFilename is the key) 129 */ 130 protected static void extractAttachments(Message message, Map<String, DataHandler> map) 131 throws javax.mail.MessagingException, IOException { 132 133 LOG.trace("Extracting attachments +++ start +++"); 134 135 Object content = message.getContent(); 136 if (content instanceof Multipart) { 137 extractFromMultipart((Multipart)content, map); 138 } else if (content != null) { 139 LOG.trace("No attachments to extract as content is not Multipart: " + content.getClass().getName()); 140 } 141 142 LOG.trace("Extracting attachments +++ done +++"); 143 } 144 145 protected static void extractFromMultipart(Multipart mp, Map<String, DataHandler> map) 146 throws javax.mail.MessagingException, IOException { 147 148 for (int i = 0; i < mp.getCount(); i++) { 149 Part part = mp.getBodyPart(i); 150 LOG.trace("Part #" + i + ": " + part); 151 152 if (part.isMimeType("multipart/*")) { 153 LOG.trace("Part #" + i + ": is mimetype: multipart/*"); 154 extractFromMultipart((Multipart)part.getContent(), map); 155 } else { 156 String disposition = part.getDisposition(); 157 if (LOG.isTraceEnabled()) { 158 LOG.trace("Part #" + i + ": Disposition: " + part.getDisposition()); 159 LOG.trace("Part #" + i + ": Description: " + part.getDescription()); 160 LOG.trace("Part #" + i + ": ContentType: " + part.getContentType()); 161 LOG.trace("Part #" + i + ": FileName: " + part.getFileName()); 162 LOG.trace("Part #" + i + ": Size: " + part.getSize()); 163 LOG.trace("Part #" + i + ": LineCount: " + part.getLineCount()); 164 } 165 166 if (disposition != null && (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))) { 167 // only add named attachments 168 String fileName = part.getFileName(); 169 if (fileName != null) { 170 LOG.debug("Mail contains file attachment: " + fileName); 171 // Parts marked with a disposition of Part.ATTACHMENT are clearly attachments 172 CollectionHelper.appendValue(map, fileName, part.getDataHandler()); 173 } 174 } 175 } 176 } 177 } 178 179 }