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.io.UnsupportedEncodingException;
021 import java.nio.charset.Charset;
022 import java.nio.charset.IllegalCharsetNameException;
023 import java.util.ArrayList;
024 import java.util.Enumeration;
025 import java.util.HashMap;
026 import java.util.Iterator;
027 import java.util.Map;
028
029 import javax.activation.DataHandler;
030 import javax.activation.DataSource;
031 import javax.mail.Address;
032 import javax.mail.BodyPart;
033 import javax.mail.Header;
034 import javax.mail.Message;
035 import javax.mail.MessagingException;
036 import javax.mail.Multipart;
037 import javax.mail.Part;
038 import javax.mail.internet.InternetAddress;
039 import javax.mail.internet.MimeBodyPart;
040 import javax.mail.internet.MimeMessage;
041 import javax.mail.internet.MimeMultipart;
042 import javax.mail.util.ByteArrayDataSource;
043
044 import org.apache.camel.Exchange;
045 import org.apache.camel.RuntimeCamelException;
046 import org.apache.camel.converter.IOConverter;
047 import org.apache.camel.converter.ObjectConverter;
048 import org.apache.camel.impl.DefaultHeaderFilterStrategy;
049 import org.apache.camel.spi.HeaderFilterStrategy;
050 import org.apache.camel.util.CollectionHelper;
051 import org.apache.camel.util.ObjectHelper;
052 import org.slf4j.Logger;
053 import org.slf4j.LoggerFactory;
054
055 /**
056 * A Strategy used to convert between a Camel {@link Exchange} and {@link Message} to and
057 * from a Mail {@link MimeMessage}
058 *
059 * @version
060 */
061 public class MailBinding {
062
063 private static final transient Logger LOG = LoggerFactory.getLogger(MailBinding.class);
064 private HeaderFilterStrategy headerFilterStrategy;
065 private ContentTypeResolver contentTypeResolver;
066
067 public MailBinding() {
068 headerFilterStrategy = new DefaultHeaderFilterStrategy();
069 }
070
071 public MailBinding(HeaderFilterStrategy headerFilterStrategy, ContentTypeResolver contentTypeResolver) {
072 this.headerFilterStrategy = headerFilterStrategy;
073 this.contentTypeResolver = contentTypeResolver;
074 }
075
076 public void populateMailMessage(MailEndpoint endpoint, MimeMessage mimeMessage, Exchange exchange)
077 throws MessagingException, IOException {
078
079 // camel message headers takes precedence over endpoint configuration
080 if (hasRecipientHeaders(exchange)) {
081 setRecipientFromCamelMessage(mimeMessage, exchange);
082 } else {
083 // fallback to endpoint configuration
084 setRecipientFromEndpointConfiguration(mimeMessage, endpoint);
085 }
086
087 // set the replyTo if it was passed in as an option in the uri. Note: if it is in both the URI
088 // and headers the headers win.
089 String replyTo = exchange.getIn().getHeader("Reply-To", String.class);
090 if (replyTo == null) {
091 replyTo = endpoint.getConfiguration().getReplyTo();
092 }
093 if (replyTo != null) {
094 ArrayList<InternetAddress> replyToAddresses = new ArrayList<InternetAddress>();
095 for (String reply : splitRecipients(replyTo)) {
096 replyToAddresses.add(new InternetAddress(reply.trim()));
097 }
098 mimeMessage.setReplyTo(replyToAddresses.toArray(new InternetAddress[replyToAddresses.size()]));
099 }
100
101 // must have at least one recipients otherwise we do not know where to send the mail
102 if (mimeMessage.getAllRecipients() == null) {
103 throw new IllegalArgumentException("The mail message does not have any recipients set.");
104 }
105
106 // set the subject if it was passed in as an option in the uri. Note: if it is in both the URI
107 // and headers the headers win.
108 String subject = endpoint.getConfiguration().getSubject();
109 if (subject != null) {
110 mimeMessage.setSubject(subject, IOConverter.getCharsetName(exchange, false));
111 }
112
113 // append the rest of the headers (no recipients) that could be subject, reply-to etc.
114 appendHeadersFromCamelMessage(mimeMessage, endpoint.getConfiguration(), exchange);
115
116 if (empty(mimeMessage.getFrom())) {
117 // lets default the address to the endpoint destination
118 String from = endpoint.getConfiguration().getFrom();
119 mimeMessage.setFrom(new InternetAddress(from));
120 }
121
122 // if there is an alternative body provided, set up a mime multipart alternative message
123 if (hasAlternativeBody(endpoint.getConfiguration(), exchange)) {
124 createMultipartAlternativeMessage(mimeMessage, endpoint.getConfiguration(), exchange);
125 } else {
126 if (exchange.getIn().hasAttachments()) {
127 appendAttachmentsFromCamel(mimeMessage, endpoint.getConfiguration(), exchange);
128 } else {
129 populateContentOnMimeMessage(mimeMessage, endpoint.getConfiguration(), exchange);
130 }
131 }
132 }
133
134 protected String determineContentType(MailConfiguration configuration, Exchange exchange) {
135 // see if we got any content type set
136 String contentType = configuration.getContentType();
137 if (exchange.getIn().getHeader("contentType") != null) {
138 contentType = exchange.getIn().getHeader("contentType", String.class);
139 } else if (exchange.getIn().getHeader(Exchange.CONTENT_TYPE) != null) {
140 contentType = exchange.getIn().getHeader(Exchange.CONTENT_TYPE, String.class);
141 }
142
143 // fix content-type to have space after semi colons, otherwise some mail servers will choke
144 if (contentType != null && contentType.contains(";")) {
145 contentType = MailUtils.padContentType(contentType);
146 }
147
148 if (contentType != null) {
149 // no charset in content-type, then try to see if we can determine one
150 String charset = determineCharSet(configuration, exchange);
151 // must replace charset, even with null in case its an unsupported charset
152 contentType = MailUtils.replaceCharSet(contentType, charset);
153 }
154
155 LOG.trace("Determined Content-Type: {}", contentType);
156
157 return contentType;
158 }
159
160 protected String determineCharSet(MailConfiguration configuration, Exchange exchange) {
161
162 // see if we got any content type set
163 String contentType = configuration.getContentType();
164 if (exchange.getIn().getHeader("contentType") != null) {
165 contentType = exchange.getIn().getHeader("contentType", String.class);
166 } else if (exchange.getIn().getHeader(Exchange.CONTENT_TYPE) != null) {
167 contentType = exchange.getIn().getHeader(Exchange.CONTENT_TYPE, String.class);
168 }
169
170 // look for charset
171 String charset = MailUtils.getCharSetFromContentType(contentType);
172 if (charset != null) {
173 charset = IOConverter.normalizeCharset(charset);
174 if (charset != null) {
175 boolean supported;
176 try {
177 supported = Charset.isSupported(charset);
178 } catch (IllegalCharsetNameException e) {
179 supported = false;
180 }
181 if (supported) {
182 return charset;
183 } else if (!configuration.isIgnoreUnsupportedCharset()) {
184 return charset;
185 } else if (configuration.isIgnoreUnsupportedCharset()) {
186 LOG.warn("Charset: " + charset + " is not supported and cannot be used as charset in Content-Type header.");
187 return null;
188 }
189 }
190 }
191
192 // Using the charset header of exchange as a fall back
193 return IOConverter.getCharsetName(exchange, false);
194 }
195
196 protected String populateContentOnMimeMessage(MimeMessage part, MailConfiguration configuration, Exchange exchange)
197 throws MessagingException, IOException {
198
199 String contentType = determineContentType(configuration, exchange);
200
201 LOG.trace("Using Content-Type {} for MimeMessage: {}", contentType, part);
202
203 String body = exchange.getIn().getBody(String.class);
204 if (body == null) {
205 body = "";
206 }
207
208 // always store content in a byte array data store to avoid various content type and charset issues
209 DataSource ds = new ByteArrayDataSource(body, contentType);
210 part.setDataHandler(new DataHandler(ds));
211
212 // set the content type header afterwards
213 part.setHeader("Content-Type", contentType);
214
215 return contentType;
216 }
217
218 protected String populateContentOnBodyPart(BodyPart part, MailConfiguration configuration, Exchange exchange)
219 throws MessagingException, IOException {
220
221 String contentType = determineContentType(configuration, exchange);
222
223 LOG.trace("Using Content-Type {} for BodyPart: {}", contentType, part);
224
225 // always store content in a byte array data store to avoid various content type and charset issues
226 DataSource ds = new ByteArrayDataSource(exchange.getIn().getBody(String.class), contentType);
227 part.setDataHandler(new DataHandler(ds));
228
229 // set the content type header afterwards
230 part.setHeader("Content-Type", contentType);
231
232 return contentType;
233 }
234
235 /**
236 * Extracts the body from the Mail message
237 */
238 public Object extractBodyFromMail(Exchange exchange, MailMessage mailMessage) {
239 Message message = mailMessage.getMessage();
240 try {
241 if (((MailEndpoint)exchange.getFromEndpoint()).getConfiguration().isMapMailMessage()) {
242 return message.getContent();
243 }
244 return message; // raw message
245 } catch (Exception e) {
246 // try to fix message in case it has an unsupported encoding in the Content-Type header
247 UnsupportedEncodingException uee = ObjectHelper.getException(UnsupportedEncodingException.class, e);
248 if (uee != null) {
249 LOG.debug("Unsupported encoding detected: " + uee.getMessage());
250 try {
251 String contentType = message.getContentType();
252 String type = ObjectHelper.before(contentType, "charset=");
253 if (type != null) {
254 // try again with fixed content type
255 LOG.debug("Trying to extract mail message again with fixed Content-Type: " + type);
256 // Since message is read-only, we need to use a copy
257 MimeMessage messageCopy = new MimeMessage((MimeMessage)message);
258 messageCopy.setHeader("Content-Type", type);
259 Object body = messageCopy.getContent();
260 // If we got this far, our fix worked...
261 // Replace the MailMessage's Message with the copy
262 mailMessage.setMessage(messageCopy);
263 return body;
264 }
265 } catch (Exception e2) {
266 // fall through and let original exception be thrown
267 }
268 }
269
270 throw new RuntimeCamelException("Failed to extract body due to: " + e.getMessage()
271 + ". Exchange: " + exchange + ". Message: " + message, e);
272 }
273 }
274
275 /**
276 * Parses the attachments of the given mail message and adds them to the map
277 *
278 * @param message the mail message with attachments
279 * @param map the map to add found attachments (attachmentFilename is the key)
280 */
281 public void extractAttachmentsFromMail(Message message, Map<String, DataHandler> map)
282 throws javax.mail.MessagingException, IOException {
283
284 LOG.trace("Extracting attachments +++ start +++");
285
286 Object content = message.getContent();
287 if (content instanceof Multipart) {
288 extractAttachmentsFromMultipart((Multipart)content, map);
289 } else if (content != null) {
290 LOG.trace("No attachments to extract as content is not Multipart: " + content.getClass().getName());
291 }
292
293 LOG.trace("Extracting attachments +++ done +++");
294 }
295
296 protected void extractAttachmentsFromMultipart(Multipart mp, Map<String, DataHandler> map)
297 throws javax.mail.MessagingException, IOException {
298
299 for (int i = 0; i < mp.getCount(); i++) {
300 Part part = mp.getBodyPart(i);
301 LOG.trace("Part #" + i + ": " + part);
302
303 if (part.isMimeType("multipart/*")) {
304 LOG.trace("Part #" + i + ": is mimetype: multipart/*");
305 extractAttachmentsFromMultipart((Multipart)part.getContent(), map);
306 } else {
307 String disposition = part.getDisposition();
308 if (LOG.isTraceEnabled()) {
309 LOG.trace("Part #{}: Disposition: {}", i, part.getDisposition());
310 LOG.trace("Part #{}: Description: {}", i, part.getDescription());
311 LOG.trace("Part #{}: ContentType: {}", i, part.getContentType());
312 LOG.trace("Part #{}: FileName: {}", i, part.getFileName());
313 LOG.trace("Part #{}: Size: {}", i, part.getSize());
314 LOG.trace("Part #{}: LineCount: {}", i, part.getLineCount());
315 }
316
317 if (disposition != null && (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))) {
318 // only add named attachments
319 String fileName = part.getFileName();
320 if (fileName != null) {
321 LOG.debug("Mail contains file attachment: " + fileName);
322 if (!map.containsKey(fileName)) {
323 // Parts marked with a disposition of Part.ATTACHMENT are clearly attachments
324 map.put(fileName, part.getDataHandler());
325 } else {
326 LOG.warn("Cannot extract duplicate attachment: " + fileName);
327 }
328 }
329 }
330 }
331 }
332 }
333
334 /**
335 * Appends the Mail headers from the Camel {@link MailMessage}
336 */
337 protected void appendHeadersFromCamelMessage(MimeMessage mimeMessage, MailConfiguration configuration, Exchange exchange)
338 throws MessagingException {
339
340 for (Map.Entry<String, Object> entry : exchange.getIn().getHeaders().entrySet()) {
341 String headerName = entry.getKey();
342 Object headerValue = entry.getValue();
343 if (headerValue != null) {
344 if (headerFilterStrategy != null
345 && !headerFilterStrategy.applyFilterToCamelHeaders(headerName, headerValue, exchange)) {
346 if (headerName.equalsIgnoreCase("subject")) {
347 mimeMessage.setSubject(asString(exchange, headerValue), IOConverter.getCharsetName(exchange, false));
348 continue;
349 }
350 if (isRecipientHeader(headerName)) {
351 // skip any recipients as they are handled specially
352 continue;
353 }
354
355 // alternative body should also be skipped
356 if (headerName.equalsIgnoreCase(configuration.getAlternativeBodyHeader())) {
357 // skip alternative body
358 continue;
359 }
360
361 // Mail messages can repeat the same header...
362 if (ObjectConverter.isCollection(headerValue)) {
363 Iterator iter = ObjectHelper.createIterator(headerValue);
364 while (iter.hasNext()) {
365 Object value = iter.next();
366 mimeMessage.addHeader(headerName, asString(exchange, value));
367 }
368 } else {
369 mimeMessage.setHeader(headerName, asString(exchange, headerValue));
370 }
371 }
372 }
373 }
374 }
375
376 private void setRecipientFromCamelMessage(MimeMessage mimeMessage, Exchange exchange) throws MessagingException {
377 for (Map.Entry<String, Object> entry : exchange.getIn().getHeaders().entrySet()) {
378 String headerName = entry.getKey();
379 Object headerValue = entry.getValue();
380 if (headerValue != null && isRecipientHeader(headerName)) {
381 // special handling of recipients
382 if (ObjectConverter.isCollection(headerValue)) {
383 Iterator iter = ObjectHelper.createIterator(headerValue);
384 while (iter.hasNext()) {
385 Object recipient = iter.next();
386 appendRecipientToMimeMessage(mimeMessage, headerName, asString(exchange, recipient));
387 }
388 } else {
389 appendRecipientToMimeMessage(mimeMessage, headerName, asString(exchange, headerValue));
390 }
391 }
392 }
393 }
394
395 /**
396 * Appends the Mail headers from the endpoint configuration.
397 */
398 protected void setRecipientFromEndpointConfiguration(MimeMessage mimeMessage, MailEndpoint endpoint)
399 throws MessagingException {
400
401 Map<Message.RecipientType, String> recipients = endpoint.getConfiguration().getRecipients();
402 if (recipients.containsKey(Message.RecipientType.TO)) {
403 appendRecipientToMimeMessage(mimeMessage, Message.RecipientType.TO.toString(), recipients.get(Message.RecipientType.TO));
404 }
405 if (recipients.containsKey(Message.RecipientType.CC)) {
406 appendRecipientToMimeMessage(mimeMessage, Message.RecipientType.CC.toString(), recipients.get(Message.RecipientType.CC));
407 }
408 if (recipients.containsKey(Message.RecipientType.BCC)) {
409 appendRecipientToMimeMessage(mimeMessage, Message.RecipientType.BCC.toString(), recipients.get(Message.RecipientType.BCC));
410 }
411 }
412
413 /**
414 * Appends the Mail attachments from the Camel {@link MailMessage}
415 */
416 protected void appendAttachmentsFromCamel(MimeMessage mimeMessage, MailConfiguration configuration, Exchange exchange)
417 throws MessagingException, IOException {
418
419 // Put parts in message
420 mimeMessage.setContent(createMixedMultipartAttachments(configuration, exchange));
421 }
422
423 private MimeMultipart createMixedMultipartAttachments(MailConfiguration configuration, Exchange exchange)
424 throws MessagingException, IOException {
425
426 // fill the body with text
427 MimeMultipart multipart = new MimeMultipart();
428 multipart.setSubType("mixed");
429 addBodyToMultipart(configuration, multipart, exchange);
430 String partDisposition = configuration.isUseInlineAttachments() ? Part.INLINE : Part.ATTACHMENT;
431 if (exchange.getIn().hasAttachments()) {
432 addAttachmentsToMultipart(multipart, partDisposition, exchange);
433 }
434 return multipart;
435 }
436
437 protected void addAttachmentsToMultipart(MimeMultipart multipart, String partDisposition, Exchange exchange) throws MessagingException {
438 LOG.trace("Adding attachments +++ start +++");
439 int i = 0;
440 for (Map.Entry<String, DataHandler> entry : exchange.getIn().getAttachments().entrySet()) {
441 String attachmentFilename = entry.getKey();
442 DataHandler handler = entry.getValue();
443
444 if (LOG.isTraceEnabled()) {
445 LOG.trace("Attachment #{}: Disposition: {}", i, partDisposition);
446 LOG.trace("Attachment #{}: DataHandler: {}", i, handler);
447 LOG.trace("Attachment #{}: FileName: {}", i, attachmentFilename);
448 }
449 if (handler != null) {
450 if (shouldAddAttachment(exchange, attachmentFilename, handler)) {
451 // Create another body part
452 BodyPart messageBodyPart = new MimeBodyPart();
453 // Set the data handler to the attachment
454 messageBodyPart.setDataHandler(handler);
455
456 if (attachmentFilename.toLowerCase().startsWith("cid:")) {
457 // add a Content-ID header to the attachment
458 // must use angle brackets according to RFC: http://www.ietf.org/rfc/rfc2392.txt
459 messageBodyPart.addHeader("Content-ID", "<" + attachmentFilename.substring(4) + ">");
460 // Set the filename without the cid
461 messageBodyPart.setFileName(attachmentFilename.substring(4));
462 } else {
463 // Set the filename
464 messageBodyPart.setFileName(attachmentFilename);
465 }
466
467 LOG.trace("Attachment #" + i + ": ContentType: " + messageBodyPart.getContentType());
468
469 if (contentTypeResolver != null) {
470 String contentType = contentTypeResolver.resolveContentType(attachmentFilename);
471 LOG.trace("Attachment #" + i + ": Using content type resolver: " + contentTypeResolver + " resolved content type as: " + contentType);
472 if (contentType != null) {
473 String value = contentType + "; name=" + attachmentFilename;
474 messageBodyPart.setHeader("Content-Type", value);
475 LOG.trace("Attachment #" + i + ": ContentType: " + messageBodyPart.getContentType());
476 }
477 }
478
479 // Set Disposition
480 messageBodyPart.setDisposition(partDisposition);
481 // Add part to multipart
482 multipart.addBodyPart(messageBodyPart);
483 } else {
484 LOG.trace("shouldAddAttachment: false");
485 }
486 } else {
487 LOG.warn("Cannot add attachment: " + attachmentFilename + " as DataHandler is null");
488 }
489 i++;
490 }
491 LOG.trace("Adding attachments +++ done +++");
492 }
493
494 protected void createMultipartAlternativeMessage(MimeMessage mimeMessage, MailConfiguration configuration, Exchange exchange)
495 throws MessagingException, IOException {
496
497 MimeMultipart multipartAlternative = new MimeMultipart("alternative");
498 mimeMessage.setContent(multipartAlternative);
499
500 MimeBodyPart plainText = new MimeBodyPart();
501 plainText.setText(getAlternativeBody(configuration, exchange), determineCharSet(configuration, exchange));
502 // remove the header with the alternative mail now that we got it
503 // otherwise it might end up twice in the mail reader
504 exchange.getIn().removeHeader(configuration.getAlternativeBodyHeader());
505 multipartAlternative.addBodyPart(plainText);
506
507 // if there are no attachments, add the body to the same mulitpart message
508 if (!exchange.getIn().hasAttachments()) {
509 addBodyToMultipart(configuration, multipartAlternative, exchange);
510 } else {
511 // if there are attachments, but they aren't set to be inline, add them to
512 // treat them as normal. It will append a multipart-mixed with the attachments and the body text
513 if (!configuration.isUseInlineAttachments()) {
514 BodyPart mixedAttachments = new MimeBodyPart();
515 mixedAttachments.setContent(createMixedMultipartAttachments(configuration, exchange));
516 multipartAlternative.addBodyPart(mixedAttachments);
517 } else {
518 // if the attachments are set to be inline, attach them as inline attachments
519 MimeMultipart multipartRelated = new MimeMultipart("related");
520 BodyPart related = new MimeBodyPart();
521
522 related.setContent(multipartRelated);
523 multipartAlternative.addBodyPart(related);
524
525 addBodyToMultipart(configuration, multipartRelated, exchange);
526
527 addAttachmentsToMultipart(multipartRelated, Part.INLINE, exchange);
528 }
529 }
530 }
531
532 protected void addBodyToMultipart(MailConfiguration configuration, MimeMultipart activeMultipart, Exchange exchange)
533 throws MessagingException, IOException {
534
535 BodyPart bodyMessage = new MimeBodyPart();
536 populateContentOnBodyPart(bodyMessage, configuration, exchange);
537 activeMultipart.addBodyPart(bodyMessage);
538 }
539
540 /**
541 * Strategy to allow filtering of attachments which are added on the Mail message
542 */
543 protected boolean shouldAddAttachment(Exchange exchange, String attachmentFilename, DataHandler handler) {
544 return true;
545 }
546
547 protected Map<String, Object> extractHeadersFromMail(Message mailMessage, Exchange exchange) throws MessagingException {
548 Map<String, Object> answer = new HashMap<String, Object>();
549 Enumeration names = mailMessage.getAllHeaders();
550
551 while (names.hasMoreElements()) {
552 Header header = (Header) names.nextElement();
553 String value = header.getValue();
554 if (headerFilterStrategy != null && !headerFilterStrategy.applyFilterToExternalHeaders(header.getName(), value, exchange)) {
555 CollectionHelper.appendValue(answer, header.getName(), value);
556 }
557 }
558
559 return answer;
560 }
561
562 private static void appendRecipientToMimeMessage(MimeMessage mimeMessage, String type, String recipient) throws MessagingException {
563 for (String line : splitRecipients(recipient)) {
564 mimeMessage.addRecipients(asRecipientType(type), line.trim());
565 }
566 }
567
568 private static String[] splitRecipients(String recipients) {
569 // we support that multi recipient can be given as a string separated by comma or semicolon
570 // regex ignores comma and semicolon inside of double quotes
571 return recipients.split("[,;]++(?=(?:(?:[^\\\"]*+\\\"){2})*+[^\\\"]*+$)");
572 }
573
574 /**
575 * Does the given camel message contain any To, CC or BCC header names?
576 */
577 private static boolean hasRecipientHeaders(Exchange exchange) {
578 for (String key : exchange.getIn().getHeaders().keySet()) {
579 if (isRecipientHeader(key)) {
580 return true;
581 }
582 }
583 return false;
584 }
585
586 protected static boolean hasAlternativeBody(MailConfiguration configuration, Exchange exchange) {
587 return getAlternativeBody(configuration, exchange) != null;
588 }
589
590 protected static String getAlternativeBody(MailConfiguration configuration, Exchange exchange) {
591 String alternativeBodyHeader = configuration.getAlternativeBodyHeader();
592 return exchange.getIn().getHeader(alternativeBodyHeader, java.lang.String.class);
593 }
594
595 /**
596 * Is the given key a mime message recipient header (To, CC or BCC)
597 */
598 private static boolean isRecipientHeader(String key) {
599 if (Message.RecipientType.TO.toString().equalsIgnoreCase(key)) {
600 return true;
601 } else if (Message.RecipientType.CC.toString().equalsIgnoreCase(key)) {
602 return true;
603 } else if (Message.RecipientType.BCC.toString().equalsIgnoreCase(key)) {
604 return true;
605 }
606 return false;
607 }
608
609 /**
610 * Returns the RecipientType object.
611 */
612 private static Message.RecipientType asRecipientType(String type) {
613 if (Message.RecipientType.TO.toString().equalsIgnoreCase(type)) {
614 return Message.RecipientType.TO;
615 } else if (Message.RecipientType.CC.toString().equalsIgnoreCase(type)) {
616 return Message.RecipientType.CC;
617 } else if (Message.RecipientType.BCC.toString().equalsIgnoreCase(type)) {
618 return Message.RecipientType.BCC;
619 }
620 throw new IllegalArgumentException("Unknown recipient type: " + type);
621 }
622
623
624 private static boolean empty(Address[] addresses) {
625 return addresses == null || addresses.length == 0;
626 }
627
628 private static String asString(Exchange exchange, Object value) {
629 return exchange.getContext().getTypeConverter().convertTo(String.class, exchange, value);
630 }
631
632 }