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