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.commons.logging.Log; 032 import org.apache.commons.logging.LogFactory; 033 034 /** 035 * Represents a {@link org.apache.camel.Message} for working with Mail 036 * 037 * @version $Revision:520964 $ 038 */ 039 public class MailMessage extends DefaultMessage { 040 private static final transient Log LOG = LogFactory.getLog(MailMessage.class); 041 private Message mailMessage; 042 043 public MailMessage() { 044 } 045 046 public MailMessage(Message message) { 047 this.mailMessage = message; 048 } 049 050 @Override 051 public String toString() { 052 if (mailMessage != null) { 053 return "MailMessage: " + MailUtils.dumpMessage(mailMessage); 054 } else { 055 return "MailMessage: " + getBody(); 056 } 057 } 058 059 @Override 060 public MailExchange getExchange() { 061 return (MailExchange)super.getExchange(); 062 } 063 064 public MailMessage copy() { 065 MailMessage answer = (MailMessage)super.copy(); 066 answer.mailMessage = mailMessage; 067 return answer; 068 } 069 070 /** 071 * Returns the underlying Mail message 072 */ 073 public Message getMessage() { 074 return mailMessage; 075 } 076 077 public void setMessage(Message mailMessage) { 078 this.mailMessage = mailMessage; 079 } 080 081 @Override 082 public Object getHeader(String name) { 083 Object answer = super.getHeader(name); 084 085 // mimic case insensitive search of mail message getHeader 086 if (answer == null) { 087 answer = super.getHeader(name.toLowerCase()); 088 } 089 return answer; 090 } 091 092 @Override 093 public MailMessage newInstance() { 094 return new MailMessage(); 095 } 096 097 @Override 098 protected Object createBody() { 099 if (mailMessage != null) { 100 return getExchange().getBinding().extractBodyFromMail(getExchange(), mailMessage); 101 } 102 return null; 103 } 104 105 @Override 106 protected void populateInitialHeaders(Map<String, Object> map) { 107 if (mailMessage != null) { 108 try { 109 map.putAll(getExchange().getBinding().extractHeadersFromMail(mailMessage)); 110 } catch (MessagingException e) { 111 throw new RuntimeCamelException("Error accessing headers due to: " + e.getMessage(), e); 112 } 113 } 114 } 115 116 @Override 117 protected void populateInitialAttachments(Map<String, DataHandler> map) { 118 if (mailMessage != null) { 119 try { 120 extractAttachments(mailMessage, map); 121 } catch (Exception e) { 122 throw new RuntimeCamelException("Error populating the initial mail message attachments", e); 123 } 124 } 125 } 126 127 public void copyFrom(org.apache.camel.Message that) { 128 super.copyFrom(that); 129 if (that instanceof MailMessage) { 130 MailMessage mailMessage = (MailMessage) that; 131 this.mailMessage = mailMessage.mailMessage; 132 } 133 } 134 135 /** 136 * Parses the attachments of the given mail message and adds them to the map 137 * 138 * @param message the mail message with attachments 139 * @param map the map to add found attachments (attachmentFilename is the key) 140 */ 141 protected static void extractAttachments(Message message, Map<String, DataHandler> map) 142 throws javax.mail.MessagingException, IOException { 143 144 LOG.trace("Extracting attachments +++ start +++"); 145 146 Object content = message.getContent(); 147 if (content instanceof Multipart) { 148 extractFromMultipart((Multipart)content, map); 149 } else if (content != null) { 150 LOG.trace("No attachments to extract as content is not Multipart: " + content.getClass().getName()); 151 } 152 153 LOG.trace("Extracting attachments +++ done +++"); 154 } 155 156 protected static void extractFromMultipart(Multipart mp, Map<String, DataHandler> map) 157 throws javax.mail.MessagingException, IOException { 158 159 for (int i = 0; i < mp.getCount(); i++) { 160 Part part = mp.getBodyPart(i); 161 LOG.trace("Part #" + i + ": " + part); 162 163 if (part.isMimeType("multipart/*")) { 164 LOG.trace("Part #" + i + ": is mimetype: multipart/*"); 165 extractFromMultipart((Multipart)part.getContent(), map); 166 } else { 167 String disposition = part.getDisposition(); 168 if (LOG.isTraceEnabled()) { 169 LOG.trace("Part #" + i + ": Disposition: " + part.getDisposition()); 170 LOG.trace("Part #" + i + ": Description: " + part.getDescription()); 171 LOG.trace("Part #" + i + ": ContentType: " + part.getContentType()); 172 LOG.trace("Part #" + i + ": FileName: " + part.getFileName()); 173 LOG.trace("Part #" + i + ": Size: " + part.getSize()); 174 LOG.trace("Part #" + i + ": LineCount: " + part.getLineCount()); 175 } 176 177 if (disposition != null && (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))) { 178 // only add named attachments 179 String fileName = part.getFileName(); 180 if (fileName != null) { 181 LOG.debug("Mail contains file attachment: " + fileName); 182 // Parts marked with a disposition of Part.ATTACHMENT are clearly attachments 183 CollectionHelper.appendValue(map, fileName, part.getDataHandler()); 184 } 185 } 186 } 187 } 188 } 189 190 }