KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > mail > javamail > MimeMessageHelper


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.mail.javamail;
18
19 import java.io.File JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.InputStream JavaDoc;
22 import java.io.OutputStream JavaDoc;
23 import java.io.UnsupportedEncodingException JavaDoc;
24 import java.util.Date JavaDoc;
25
26 import javax.activation.DataHandler JavaDoc;
27 import javax.activation.DataSource JavaDoc;
28 import javax.activation.FileDataSource JavaDoc;
29 import javax.activation.FileTypeMap JavaDoc;
30 import javax.mail.BodyPart JavaDoc;
31 import javax.mail.Message JavaDoc;
32 import javax.mail.MessagingException JavaDoc;
33 import javax.mail.internet.AddressException JavaDoc;
34 import javax.mail.internet.InternetAddress JavaDoc;
35 import javax.mail.internet.MimeBodyPart JavaDoc;
36 import javax.mail.internet.MimeMessage JavaDoc;
37 import javax.mail.internet.MimeMultipart JavaDoc;
38 import javax.mail.internet.MimePart JavaDoc;
39
40 import org.springframework.core.io.InputStreamSource;
41 import org.springframework.core.io.Resource;
42 import org.springframework.util.Assert;
43
44 /**
45  * Helper class for populating a {@link javax.mail.internet.MimeMessage}.
46  *
47  * <p>Mirrors the simple setters of {@link org.springframework.mail.SimpleMailMessage},
48  * directly applying the values to the underlying MimeMessage. Allows for defining
49  * a character encoding for the entire message, automatically applied by all methods
50  * of this helper class.
51  *
52  * <p>Offers support for HTML text content, inline elements such as images, and typical
53  * mail attachments. Also supports personal names that accompany mail addresses. Note that
54  * advanced settings can still be applied directly to the underlying MimeMessage object!
55  *
56  * <p>Typically used in {@link MimeMessagePreparator} implementations or
57  * {@link JavaMailSender} client code: simply instantiating it as a MimeMessage wrapper,
58  * invoking setters on the wrapper, using the underlying MimeMessage for mail sending.
59  * Also used internally by {@link JavaMailSenderImpl}.
60  *
61  * <p>Sample code for an HTML mail with an inline image and a PDF attachment:
62  *
63  * <pre class="code">
64  * mailSender.send(new MimeMessagePreparator() {
65  * public void prepare(MimeMessage mimeMessage) throws MessagingException {
66  * MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8");
67  * message.setFrom("me@mail.com");
68  * message.setTo("you@mail.com");
69  * message.setSubject("my subject");
70  * message.setText("my text &lt;img SRC='cid:myLogo'&gt;", true);
71  * message.addInline("myLogo", new ClassPathResource("img/mylogo.gif"));
72  * message.addAttachment("myDocument.pdf", new ClassPathResource("doc/myDocument.pdf"));
73  * }
74  * });</pre>
75  *
76  * Consider using {@link MimeMailMessage} (which implements the common
77  * {@link org.springframework.mail.MailMessage} interface, just like
78  * {@link org.springframework.mail.SimpleMailMessage}) on top of this helper,
79  * in order to let message population code interact with a simple message
80  * or a MIME message through a common interface.
81  *
82  * <p><b>Warning regarding multipart mails:</b> Simple MIME messages that
83  * just contain HTML text but no inline elements or attachments will work on
84  * more or less any email client that is capable of HTML rendering. However,
85  * inline elements and attachments are still a major compatibility issue
86  * between email clients: It's virtually impossible to get inline elements
87  * and attachments working across Microsoft Outlook, Lotus Notes and Mac Mail.
88  * Consider choosing a specific multipart mode for your needs: The javadoc
89  * on the MULTIPART_MODE constants contains more detailed information.
90  *
91  * @author Juergen Hoeller
92  * @since 19.01.2004
93  * @see #setText(String, boolean)
94  * @see #setText(String, String)
95  * @see #addInline(String, org.springframework.core.io.Resource)
96  * @see #addAttachment(String, org.springframework.core.io.InputStreamSource)
97  * @see #MULTIPART_MODE_MIXED_RELATED
98  * @see #MULTIPART_MODE_RELATED
99  * @see #getMimeMessage()
100  * @see JavaMailSender
101  */

102 public class MimeMessageHelper {
103
104     /**
105      * Constant indicating a non-multipart message.
106      */

107     public static final int MULTIPART_MODE_NO = 0;
108
109     /**
110      * Constant indicating a multipart message with a single root multipart
111      * element of type "mixed". Texts, inline elements and attachements
112      * will all get added to that root element.
113      * <p>This was Spring 1.0's default behavior. It is known to work properly
114      * on Outlook. However, other mail clients tend to misinterpret inline
115      * elements as attachments and/or show attachments inline as well.
116      */

117     public static final int MULTIPART_MODE_MIXED = 1;
118
119     /**
120      * Constant indicating a multipart message with a single root multipart
121      * element of type "related". Texts, inline elements and attachements
122      * will all get added to that root element.
123      * <p>This was the default behavior from Spring 1.1 up to 1.2 final.
124      * This is the "Microsoft multipart mode", as natively sent by Outlook.
125      * It is known to work properly on Outlook, Outlook Express, Yahoo Mail, and
126      * to a large degree also on Mac Mail (with an additional attachment listed
127      * for an inline element, despite the inline element also shown inline).
128      * Does not work properly on Lotus Notes (attachments won't be shown there).
129      */

130     public static final int MULTIPART_MODE_RELATED = 2;
131
132     /**
133      * Constant indicating a multipart message with a root multipart element
134      * "mixed" plus a nested multipart element of type "related". Texts and
135      * inline elements will get added to the nested "related" element,
136      * while attachments will get added to the "mixed" root element.
137      * <p>This is the default since Spring 1.2.1. This is arguably the most correct
138      * MIME structure, according to the MIME spec: It is known to work properly
139      * on Outlook, Outlook Express, Yahoo Mail, and Lotus Notes. Does not work
140      * properly on Mac Mail. If you target Mac Mail or experience issues with
141      * specific mails on Outlook, consider using MULTIPART_MODE_RELATED instead.
142      */

143     public static final int MULTIPART_MODE_MIXED_RELATED = 3;
144
145
146     private static final String JavaDoc MULTIPART_SUBTYPE_MIXED = "mixed";
147
148     private static final String JavaDoc MULTIPART_SUBTYPE_RELATED = "related";
149
150     private static final String JavaDoc MULTIPART_SUBTYPE_ALTERNATIVE = "alternative";
151
152     private static final String JavaDoc CONTENT_TYPE_ALTERNATIVE = "text/alternative";
153
154     private static final String JavaDoc CONTENT_TYPE_HTML = "text/html";
155
156     private static final String JavaDoc CONTENT_TYPE_CHARSET_SUFFIX = ";charset=";
157
158     private static final String JavaDoc HEADER_PRIORITY = "X-Priority";
159
160     private static final String JavaDoc HEADER_CONTENT_ID = "Content-ID";
161
162
163     private final MimeMessage JavaDoc mimeMessage;
164
165     private MimeMultipart JavaDoc rootMimeMultipart;
166
167     private MimeMultipart JavaDoc mimeMultipart;
168
169     private final String JavaDoc encoding;
170
171     private FileTypeMap JavaDoc fileTypeMap;
172
173     private boolean validateAddresses = false;
174
175
176     /**
177      * Create a new MimeMessageHelper for the given MimeMessage,
178      * assuming a simple text message (no multipart content,
179      * i.e. no alternative texts and no inline elements or attachments).
180      * <p>The character encoding for the message will be taken from
181      * the passed-in MimeMessage object, if carried there. Else,
182      * JavaMail's default encoding will be used.
183      * @param mimeMessage MimeMessage to work on
184      * @see #MimeMessageHelper(javax.mail.internet.MimeMessage, boolean)
185      * @see #getDefaultEncoding(javax.mail.internet.MimeMessage)
186      * @see JavaMailSenderImpl#setDefaultEncoding
187      */

188     public MimeMessageHelper(MimeMessage JavaDoc mimeMessage) {
189         this(mimeMessage, null);
190     }
191
192     /**
193      * Create a new MimeMessageHelper for the given MimeMessage,
194      * assuming a simple text message (no multipart content,
195      * i.e. no alternative texts and no inline elements or attachments).
196      * @param mimeMessage MimeMessage to work on
197      * @param encoding the character encoding to use for the message
198      * @see #MimeMessageHelper(javax.mail.internet.MimeMessage, boolean)
199      */

200     public MimeMessageHelper(MimeMessage JavaDoc mimeMessage, String JavaDoc encoding) {
201         this.mimeMessage = mimeMessage;
202         this.encoding = (encoding != null ? encoding : getDefaultEncoding(mimeMessage));
203         this.fileTypeMap = getDefaultFileTypeMap(mimeMessage);
204     }
205
206     /**
207      * Create a new MimeMessageHelper for the given MimeMessage,
208      * in multipart mode (supporting alternative texts, inline
209      * elements and attachments) if requested.
210      * <p>Consider using the MimeMessageHelper constructor that
211      * takes a multipartMode argument to choose a specific multipart
212      * mode other than MULTIPART_MODE_MIXED_RELATED.
213      * <p>The character encoding for the message will be taken from
214      * the passed-in MimeMessage object, if carried there. Else,
215      * JavaMail's default encoding will be used.
216      * @param mimeMessage MimeMessage to work on
217      * @param multipart whether to create a multipart message that
218      * supports alternative texts, inline elements and attachments
219      * (corresponds to MULTIPART_MODE_MIXED_RELATED)
220      * @throws MessagingException if multipart creation failed
221      * @see #MimeMessageHelper(javax.mail.internet.MimeMessage, int)
222      * @see #getDefaultEncoding(javax.mail.internet.MimeMessage)
223      * @see JavaMailSenderImpl#setDefaultEncoding
224      */

225     public MimeMessageHelper(MimeMessage JavaDoc mimeMessage, boolean multipart) throws MessagingException JavaDoc {
226         this(mimeMessage, multipart, null);
227     }
228
229     /**
230      * Create a new MimeMessageHelper for the given MimeMessage,
231      * in multipart mode (supporting alternative texts, inline
232      * elements and attachments) if requested.
233      * <p>Consider using the MimeMessageHelper constructor that
234      * takes a multipartMode argument to choose a specific multipart
235      * mode other than MULTIPART_MODE_MIXED_RELATED.
236      * @param mimeMessage MimeMessage to work on
237      * @param multipart whether to create a multipart message that
238      * supports alternative texts, inline elements and attachments
239      * (corresponds to MULTIPART_MODE_MIXED_RELATED)
240      * @param encoding the character encoding to use for the message
241      * @throws MessagingException if multipart creation failed
242      * @see #MimeMessageHelper(javax.mail.internet.MimeMessage, int, String)
243      */

244     public MimeMessageHelper(MimeMessage JavaDoc mimeMessage, boolean multipart, String JavaDoc encoding)
245         throws MessagingException JavaDoc {
246
247         this(mimeMessage, (multipart ? MULTIPART_MODE_MIXED_RELATED : MULTIPART_MODE_NO), encoding);
248     }
249
250     /**
251      * Create a new MimeMessageHelper for the given MimeMessage,
252      * in multipart mode (supporting alternative texts, inline
253      * elements and attachments) if requested.
254      * <p>The character encoding for the message will be taken from
255      * the passed-in MimeMessage object, if carried there. Else,
256      * JavaMail's default encoding will be used.
257      * @param mimeMessage MimeMessage to work on
258      * @param multipartMode which kind of multipart message to create
259      * (MIXED, RELATED, MIXED_RELATED, or NO)
260      * @throws MessagingException if multipart creation failed
261      * @see #MULTIPART_MODE_NO
262      * @see #MULTIPART_MODE_MIXED
263      * @see #MULTIPART_MODE_RELATED
264      * @see #MULTIPART_MODE_MIXED_RELATED
265      * @see #getDefaultEncoding(javax.mail.internet.MimeMessage)
266      * @see JavaMailSenderImpl#setDefaultEncoding
267      */

268     public MimeMessageHelper(MimeMessage JavaDoc mimeMessage, int multipartMode) throws MessagingException JavaDoc {
269         this(mimeMessage, multipartMode, null);
270     }
271
272     /**
273      * Create a new MimeMessageHelper for the given MimeMessage,
274      * in multipart mode (supporting alternative texts, inline
275      * elements and attachments) if requested.
276      * @param mimeMessage MimeMessage to work on
277      * @param multipartMode which kind of multipart message to create
278      * (MIXED, RELATED, MIXED_RELATED, or NO)
279      * @param encoding the character encoding to use for the message
280      * @throws MessagingException if multipart creation failed
281      * @see #MULTIPART_MODE_NO
282      * @see #MULTIPART_MODE_MIXED
283      * @see #MULTIPART_MODE_RELATED
284      * @see #MULTIPART_MODE_MIXED_RELATED
285      */

286     public MimeMessageHelper(MimeMessage JavaDoc mimeMessage, int multipartMode, String JavaDoc encoding)
287         throws MessagingException JavaDoc {
288
289         this.mimeMessage = mimeMessage;
290         createMimeMultiparts(mimeMessage, multipartMode);
291         this.encoding = (encoding != null ? encoding : getDefaultEncoding(mimeMessage));
292         this.fileTypeMap = getDefaultFileTypeMap(mimeMessage);
293     }
294
295
296     /**
297      * Return the underlying MimeMessage object.
298      */

299     public final MimeMessage JavaDoc getMimeMessage() {
300         return this.mimeMessage;
301     }
302
303
304     /**
305      * Determine the MimeMultipart objects to use, which will be used
306      * to store attachments on the one hand and text(s) and inline elements
307      * on the other hand.
308      * <p>Texts and inline elements can either be stored in the root element
309      * itself (MULTIPART_MODE_MIXED, MULTIPART_MODE_RELATED) or in a nested element
310      * rather than the root element directly (MULTIPART_MODE_MIXED_RELATED).
311      * <p>By default, the root MimeMultipart element will be of type "mixed"
312      * (MULTIPART_MODE_MIXED) or "related" (MULTIPART_MODE_RELATED).
313      * The main multipart element will either be added as nested element of
314      * type "related" (MULTIPART_MODE_MIXED_RELATED) or be identical to the root
315      * element itself (MULTIPART_MODE_MIXED, MULTIPART_MODE_RELATED).
316      * @param mimeMessage the MimeMessage object to add the root MimeMultipart
317      * object to
318      * @param multipartMode the multipart mode, as passed into the constructor
319      * (MIXED, RELATED, MIXED_RELATED, or NO)
320      * @throws MessagingException if multipart creation failed
321      * @see #setMimeMultiparts
322      * @see #MULTIPART_MODE_NO
323      * @see #MULTIPART_MODE_MIXED
324      * @see #MULTIPART_MODE_RELATED
325      * @see #MULTIPART_MODE_MIXED_RELATED
326      */

327     protected void createMimeMultiparts(MimeMessage JavaDoc mimeMessage, int multipartMode) throws MessagingException JavaDoc {
328         switch (multipartMode) {
329             case MULTIPART_MODE_NO:
330                 setMimeMultiparts(null, null);
331                 break;
332             case MULTIPART_MODE_MIXED:
333                 MimeMultipart JavaDoc mixedMultipart = new MimeMultipart JavaDoc(MULTIPART_SUBTYPE_MIXED);
334                 mimeMessage.setContent(mixedMultipart);
335                 setMimeMultiparts(mixedMultipart, mixedMultipart);
336                 break;
337             case MULTIPART_MODE_RELATED:
338                 MimeMultipart JavaDoc relatedMultipart = new MimeMultipart JavaDoc(MULTIPART_SUBTYPE_RELATED);
339                 mimeMessage.setContent(relatedMultipart);
340                 setMimeMultiparts(relatedMultipart, relatedMultipart);
341                 break;
342             case MULTIPART_MODE_MIXED_RELATED:
343                 MimeMultipart JavaDoc rootMixedMultipart = new MimeMultipart JavaDoc(MULTIPART_SUBTYPE_MIXED);
344                 mimeMessage.setContent(rootMixedMultipart);
345                 MimeMultipart JavaDoc nestedRelatedMultipart = new MimeMultipart JavaDoc(MULTIPART_SUBTYPE_RELATED);
346                 MimeBodyPart JavaDoc relatedBodyPart = new MimeBodyPart JavaDoc();
347                 relatedBodyPart.setContent(nestedRelatedMultipart);
348                 rootMixedMultipart.addBodyPart(relatedBodyPart);
349                 setMimeMultiparts(rootMixedMultipart, nestedRelatedMultipart);
350                 break;
351             default:
352                 throw new IllegalArgumentException JavaDoc("Only multipart modes MIXED_RELATED, RELATED and NO supported");
353         }
354     }
355
356     /**
357      * Set the given MimeMultipart objects for use by this MimeMessageHelper.
358      * @param root the root MimeMultipart object, which attachments will be added to;
359      * or <code>null</code> to indicate no multipart at all
360      * @param main the main MimeMultipart object, which text(s) and inline elements
361      * will be added to (can be the same as the root multipart object, or an element
362      * nested underneath the root multipart element)
363      */

364     protected final void setMimeMultiparts(MimeMultipart JavaDoc root, MimeMultipart JavaDoc main) {
365         this.rootMimeMultipart = root;
366         this.mimeMultipart = main;
367     }
368
369     /**
370      * Return whether this helper is in multipart mode,
371      * i.e. whether it holds a multipart message.
372      * @see #MimeMessageHelper(MimeMessage, boolean)
373      */

374     public final boolean isMultipart() {
375         return (this.rootMimeMultipart != null);
376     }
377
378     /**
379      * Throw an IllegalStateException if this helper is not in multipart mode.
380      */

381     private void checkMultipart() throws IllegalStateException JavaDoc {
382         if (!isMultipart()) {
383             throw new IllegalStateException JavaDoc("Not in multipart mode - " +
384                 "create an appropriate MimeMessageHelper via a constructor that takes a 'multipart' flag " +
385                 "if you need to set alternative texts or add inline elements or attachments.");
386         }
387     }
388
389     /**
390      * Return the root MIME "multipart/mixed" object, if any.
391      * Can be used to manually add attachments.
392      * <p>This will be the direct content of the MimeMessage,
393      * in case of a multipart mail.
394      * @throws IllegalStateException if this helper is not in multipart mode
395      * @see #isMultipart
396      * @see #getMimeMessage
397      * @see javax.mail.internet.MimeMultipart#addBodyPart
398      */

399     public final MimeMultipart JavaDoc getRootMimeMultipart() throws IllegalStateException JavaDoc {
400         checkMultipart();
401         return this.rootMimeMultipart;
402     }
403
404     /**
405      * Return the underlying MIME "multipart/related" object, if any.
406      * Can be used to manually add body parts, inline elements, etc.
407      * <p>This will be nested within the root MimeMultipart,
408      * in case of a multipart mail.
409      * @throws IllegalStateException if this helper is not in multipart mode
410      * @see #isMultipart
411      * @see #getRootMimeMultipart
412      * @see javax.mail.internet.MimeMultipart#addBodyPart
413      */

414     public final MimeMultipart JavaDoc getMimeMultipart() throws IllegalStateException JavaDoc {
415         checkMultipart();
416         return this.mimeMultipart;
417     }
418
419
420     /**
421      * Determine the default encoding for the given MimeMessage.
422      * @param mimeMessage the passed-in MimeMessage
423      * @return the default encoding associated with the MimeMessage,
424      * or <code>null</code> if none found
425      */

426     protected String JavaDoc getDefaultEncoding(MimeMessage JavaDoc mimeMessage) {
427         if (mimeMessage instanceof SmartMimeMessage) {
428             return ((SmartMimeMessage) mimeMessage).getDefaultEncoding();
429         }
430         return null;
431     }
432
433     /**
434      * Return the specific character encoding used for this message, if any.
435      */

436     public String JavaDoc getEncoding() {
437         return this.encoding;
438     }
439
440     /**
441      * Determine the default Java Activation FileTypeMap for the given MimeMessage.
442      * @param mimeMessage the passed-in MimeMessage
443      * @return the default FileTypeMap associated with the MimeMessage,
444      * or a default ConfigurableMimeFileTypeMap if none found for the message
445      * @see ConfigurableMimeFileTypeMap
446      */

447     protected FileTypeMap JavaDoc getDefaultFileTypeMap(MimeMessage JavaDoc mimeMessage) {
448         if (mimeMessage instanceof SmartMimeMessage) {
449             FileTypeMap JavaDoc fileTypeMap = ((SmartMimeMessage) mimeMessage).getDefaultFileTypeMap();
450             if (fileTypeMap != null) {
451                 return fileTypeMap;
452             }
453         }
454         ConfigurableMimeFileTypeMap fileTypeMap = new ConfigurableMimeFileTypeMap();
455         fileTypeMap.afterPropertiesSet();
456         return fileTypeMap;
457     }
458
459     /**
460      * Set the Java Activation Framework <code>FileTypeMap</code> to use
461      * for determining the content type of inline content and attachments
462      * that get added to the message.
463      * <p>Default is the <code>FileTypeMap</code> that the underlying
464      * MimeMessage carries, if any, or the Activation Framework's default
465      * <code>FileTypeMap</code> instance else.
466      * @see #addInline
467      * @see #addAttachment
468      * @see #getDefaultFileTypeMap(javax.mail.internet.MimeMessage)
469      * @see JavaMailSenderImpl#setDefaultFileTypeMap
470      * @see javax.activation.FileTypeMap#getDefaultFileTypeMap
471      * @see ConfigurableMimeFileTypeMap
472      */

473     public void setFileTypeMap(FileTypeMap JavaDoc fileTypeMap) {
474         this.fileTypeMap = (fileTypeMap != null ? fileTypeMap : getDefaultFileTypeMap(getMimeMessage()));
475     }
476
477     /**
478      * Return the <code>FileTypeMap</code> used by this MimeMessageHelper.
479      */

480     public FileTypeMap JavaDoc getFileTypeMap() {
481         return this.fileTypeMap;
482     }
483
484
485     /**
486      * Set whether to validate all addresses which get passed to this helper.
487      * Default is "false".
488      * <p>Note that this is by default just available for JavaMail >= 1.3.
489      * You can override the default <code>validateAddress method</code> for
490      * validation on older JavaMail versions (or for custom validation).
491      * @see #validateAddress
492      */

493     public void setValidateAddresses(boolean validateAddresses) {
494         this.validateAddresses = validateAddresses;
495     }
496
497     /**
498      * Return whether this helper will validate all addresses passed to it.
499      */

500     public boolean isValidateAddresses() {
501         return this.validateAddresses;
502     }
503
504     /**
505      * Validate the given mail address.
506      * Called by all of MimeMessageHelper's address setters and adders.
507      * <p>Default implementation invokes <code>InternetAddress.validate()</code>,
508      * provided that address validation is activated for the helper instance.
509      * <p>Note that this method will just work on JavaMail >= 1.3. You can override
510      * it for validation on older JavaMail versions or for custom validation.
511      * @param address the address to validate
512      * @throws AddressException if validation failed
513      * @see #isValidateAddresses()
514      * @see javax.mail.internet.InternetAddress#validate()
515      */

516     protected void validateAddress(InternetAddress JavaDoc address) throws AddressException JavaDoc {
517         if (isValidateAddresses()) {
518             address.validate();
519         }
520     }
521
522     /**
523      * Validate all given mail addresses.
524      * Default implementation simply delegates to validateAddress for each address.
525      * @param addresses the addresses to validate
526      * @throws AddressException if validation failed
527      * @see #validateAddress(InternetAddress)
528      */

529     protected void validateAddresses(InternetAddress JavaDoc[] addresses) throws AddressException JavaDoc {
530         for (int i = 0; i < addresses.length; i++) {
531             validateAddress(addresses[i]);
532         }
533     }
534
535
536     public void setFrom(InternetAddress JavaDoc from) throws MessagingException JavaDoc {
537         Assert.notNull(from, "From address must not be null");
538         validateAddress(from);
539         this.mimeMessage.setFrom(from);
540     }
541
542     public void setFrom(String JavaDoc from) throws MessagingException JavaDoc {
543         Assert.notNull(from, "From address must not be null");
544         setFrom(new InternetAddress JavaDoc(from));
545     }
546
547     public void setFrom(String JavaDoc from, String JavaDoc personal) throws MessagingException JavaDoc, UnsupportedEncodingException JavaDoc {
548         Assert.notNull(from, "From address must not be null");
549         setFrom(getEncoding() != null ?
550             new InternetAddress JavaDoc(from, personal, getEncoding()) : new InternetAddress JavaDoc(from, personal));
551     }
552
553     public void setReplyTo(InternetAddress JavaDoc replyTo) throws MessagingException JavaDoc {
554         Assert.notNull(replyTo, "Reply-to address must not be null");
555         validateAddress(replyTo);
556         this.mimeMessage.setReplyTo(new InternetAddress JavaDoc[] {replyTo});
557     }
558
559     public void setReplyTo(String JavaDoc replyTo) throws MessagingException JavaDoc {
560         Assert.notNull(replyTo, "Reply-to address must not be null");
561         setReplyTo(new InternetAddress JavaDoc(replyTo));
562     }
563
564     public void setReplyTo(String JavaDoc replyTo, String JavaDoc personal) throws MessagingException JavaDoc, UnsupportedEncodingException JavaDoc {
565         Assert.notNull(replyTo, "Reply-to address must not be null");
566         InternetAddress JavaDoc replyToAddress = (getEncoding() != null) ?
567                 new InternetAddress JavaDoc(replyTo, personal, getEncoding()) : new InternetAddress JavaDoc(replyTo, personal);
568         setReplyTo(replyToAddress);
569     }
570
571
572     public void setTo(InternetAddress JavaDoc to) throws MessagingException JavaDoc {
573         Assert.notNull(to, "To address must not be null");
574         validateAddress(to);
575         this.mimeMessage.setRecipient(Message.RecipientType.TO, to);
576     }
577
578     public void setTo(InternetAddress JavaDoc[] to) throws MessagingException JavaDoc {
579         Assert.notNull(to, "To address array must not be null");
580         validateAddresses(to);
581         this.mimeMessage.setRecipients(Message.RecipientType.TO, to);
582     }
583
584     public void setTo(String JavaDoc to) throws MessagingException JavaDoc {
585         Assert.notNull(to, "To address must not be null");
586         setTo(new InternetAddress JavaDoc(to));
587     }
588
589     public void setTo(String JavaDoc[] to) throws MessagingException JavaDoc {
590         Assert.notNull(to, "To address array must not be null");
591         InternetAddress JavaDoc[] addresses = new InternetAddress JavaDoc[to.length];
592         for (int i = 0; i < to.length; i++) {
593             addresses[i] = new InternetAddress JavaDoc(to[i]);
594         }
595         setTo(addresses);
596     }
597
598     public void addTo(InternetAddress JavaDoc to) throws MessagingException JavaDoc {
599         Assert.notNull(to, "To address must not be null");
600         validateAddress(to);
601         this.mimeMessage.addRecipient(Message.RecipientType.TO, to);
602     }
603
604     public void addTo(String JavaDoc to) throws MessagingException JavaDoc {
605         Assert.notNull(to, "To address must not be null");
606         addTo(new InternetAddress JavaDoc(to));
607     }
608
609     public void addTo(String JavaDoc to, String JavaDoc personal) throws MessagingException JavaDoc, UnsupportedEncodingException JavaDoc {
610         Assert.notNull(to, "To address must not be null");
611         addTo(getEncoding() != null ?
612             new InternetAddress JavaDoc(to, personal, getEncoding()) :
613             new InternetAddress JavaDoc(to, personal));
614     }
615
616
617     public void setCc(InternetAddress JavaDoc cc) throws MessagingException JavaDoc {
618         Assert.notNull(cc, "Cc address must not be null");
619         validateAddress(cc);
620         this.mimeMessage.setRecipient(Message.RecipientType.CC, cc);
621     }
622
623     public void setCc(InternetAddress JavaDoc[] cc) throws MessagingException JavaDoc {
624         Assert.notNull(cc, "Cc address array must not be null");
625         validateAddresses(cc);
626         this.mimeMessage.setRecipients(Message.RecipientType.CC, cc);
627     }
628
629     public void setCc(String JavaDoc cc) throws MessagingException JavaDoc {
630         Assert.notNull(cc, "Cc address must not be null");
631         setCc(new InternetAddress JavaDoc(cc));
632     }
633
634     public void setCc(String JavaDoc[] cc) throws MessagingException JavaDoc {
635         Assert.notNull(cc, "Cc address array must not be null");
636         InternetAddress JavaDoc[] addresses = new InternetAddress JavaDoc[cc.length];
637         for (int i = 0; i < cc.length; i++) {
638             addresses[i] = new InternetAddress JavaDoc(cc[i]);
639         }
640         setCc(addresses);
641     }
642
643     public void addCc(InternetAddress JavaDoc cc) throws MessagingException JavaDoc {
644         Assert.notNull(cc, "Cc address must not be null");
645         validateAddress(cc);
646         this.mimeMessage.addRecipient(Message.RecipientType.CC, cc);
647     }
648
649     public void addCc(String JavaDoc cc) throws MessagingException JavaDoc {
650         Assert.notNull(cc, "Cc address must not be null");
651         addCc(new InternetAddress JavaDoc(cc));
652     }
653
654     public void addCc(String JavaDoc cc, String JavaDoc personal) throws MessagingException JavaDoc, UnsupportedEncodingException JavaDoc {
655         Assert.notNull(cc, "Cc address must not be null");
656         addCc(getEncoding() != null ?
657             new InternetAddress JavaDoc(cc, personal, getEncoding()) :
658             new InternetAddress JavaDoc(cc, personal));
659     }
660
661
662     public void setBcc(InternetAddress JavaDoc bcc) throws MessagingException JavaDoc {
663         Assert.notNull(bcc, "Bcc address must not be null");
664         validateAddress(bcc);
665         this.mimeMessage.setRecipient(Message.RecipientType.BCC, bcc);
666     }
667
668     public void setBcc(InternetAddress JavaDoc[] bcc) throws MessagingException JavaDoc {
669         Assert.notNull(bcc, "Bcc address array must not be null");
670         validateAddresses(bcc);
671         this.mimeMessage.setRecipients(Message.RecipientType.BCC, bcc);
672     }
673
674     public void setBcc(String JavaDoc bcc) throws MessagingException JavaDoc {
675         Assert.notNull(bcc, "Bcc address must not be null");
676         setBcc(new InternetAddress JavaDoc(bcc));
677     }
678
679     public void setBcc(String JavaDoc[] bcc) throws MessagingException JavaDoc {
680         Assert.notNull(bcc, "Bcc address array must not be null");
681         InternetAddress JavaDoc[] addresses = new InternetAddress JavaDoc[bcc.length];
682         for (int i = 0; i < bcc.length; i++) {
683             addresses[i] = new InternetAddress JavaDoc(bcc[i]);
684         }
685         setBcc(addresses);
686     }
687
688     public void addBcc(InternetAddress JavaDoc bcc) throws MessagingException JavaDoc {
689         Assert.notNull(bcc, "Bcc address must not be null");
690         validateAddress(bcc);
691         this.mimeMessage.addRecipient(Message.RecipientType.BCC, bcc);
692     }
693
694     public void addBcc(String JavaDoc bcc) throws MessagingException JavaDoc {
695         Assert.notNull(bcc, "Bcc address must not be null");
696         addBcc(new InternetAddress JavaDoc(bcc));
697     }
698
699     public void addBcc(String JavaDoc bcc, String JavaDoc personal) throws MessagingException JavaDoc, UnsupportedEncodingException JavaDoc {
700         Assert.notNull(bcc, "Bcc address must not be null");
701         addBcc(getEncoding() != null ?
702             new InternetAddress JavaDoc(bcc, personal, getEncoding()) :
703             new InternetAddress JavaDoc(bcc, personal));
704     }
705
706
707     /**
708      * Set the priority ("X-Priority" header) of the message.
709      * @param priority the priority value;
710      * typically between 1 (highest) and 5 (lowest)
711      * @throws MessagingException in case of errors
712      */

713     public void setPriority(int priority) throws MessagingException JavaDoc {
714         this.mimeMessage.setHeader(HEADER_PRIORITY, Integer.toString(priority));
715     }
716
717     /**
718      * Set the sent-date of the message.
719      * @param sentDate the date to set (never <code>null</code>)
720      * @throws MessagingException in case of errors
721      */

722     public void setSentDate(Date JavaDoc sentDate) throws MessagingException JavaDoc {
723         Assert.notNull(sentDate, "Sent date must not be null");
724         this.mimeMessage.setSentDate(sentDate);
725     }
726
727     /**
728      * Set the subject of the message, using the correct encoding.
729      * @param subject the subject text
730      * @throws MessagingException in case of errors
731      */

732     public void setSubject(String JavaDoc subject) throws MessagingException JavaDoc {
733         Assert.notNull(subject, "Subject must not be null");
734         if (getEncoding() != null) {
735             this.mimeMessage.setSubject(subject, getEncoding());
736         }
737         else {
738             this.mimeMessage.setSubject(subject);
739         }
740     }
741
742
743     /**
744      * Set the given text directly as content in non-multipart mode
745      * or as default body part in multipart mode.
746      * Always applies the default content type "text/plain".
747      * <p><b>NOTE:</b> Invoke {@link #addInline} <i>after</i> <code>setText</code>;
748      * else, mail readers might not be able to resolve inline references correctly.
749      * @param text the text for the message
750      * @throws MessagingException in case of errors
751      */

752     public void setText(String JavaDoc text) throws MessagingException JavaDoc {
753         setText(text, false);
754     }
755
756     /**
757      * Set the given text directly as content in non-multipart mode
758      * or as default body part in multipart mode.
759      * The "html" flag determines the content type to apply.
760      * <p><b>NOTE:</b> Invoke {@link #addInline} <i>after</i> <code>setText</code>;
761      * else, mail readers might not be able to resolve inline references correctly.
762      * @param text the text for the message
763      * @param html whether to apply content type "text/html" for an
764      * HTML mail, using default content type ("text/plain") else
765      * @throws MessagingException in case of errors
766      */

767     public void setText(String JavaDoc text, boolean html) throws MessagingException JavaDoc {
768         Assert.notNull(text, "Text must not be null");
769         MimePart JavaDoc partToUse = null;
770         if (isMultipart()) {
771             partToUse = getMainPart();
772         }
773         else {
774             partToUse = this.mimeMessage;
775         }
776         if (html) {
777             setHtmlTextToMimePart(partToUse, text);
778         }
779         else {
780             setPlainTextToMimePart(partToUse, text);
781         }
782     }
783
784     /**
785      * Set the given plain text and HTML text as alternatives, offering
786      * both options to the email client. Requires multipart mode.
787      * <p><b>NOTE:</b> Invoke {@link #addInline} <i>after</i> <code>setText</code>;
788      * else, mail readers might not be able to resolve inline references correctly.
789      * @param plainText the plain text for the message
790      * @param htmlText the HTML text for the message
791      * @throws MessagingException in case of errors
792      */

793     public void setText(String JavaDoc plainText, String JavaDoc htmlText) throws MessagingException JavaDoc {
794         Assert.notNull(plainText, "Plain text must not be null");
795         Assert.notNull(htmlText, "HTML text must not be null");
796
797         MimeMultipart JavaDoc messageBody = new MimeMultipart JavaDoc(MULTIPART_SUBTYPE_ALTERNATIVE);
798         getMainPart().setContent(messageBody, CONTENT_TYPE_ALTERNATIVE);
799
800         // Create the plain text part of the message.
801
MimeBodyPart JavaDoc plainTextPart = new MimeBodyPart JavaDoc();
802         setPlainTextToMimePart(plainTextPart, plainText);
803         messageBody.addBodyPart(plainTextPart);
804
805         // Create the HTML text part of the message.
806
MimeBodyPart JavaDoc htmlTextPart = new MimeBodyPart JavaDoc();
807         setHtmlTextToMimePart(htmlTextPart, htmlText);
808         messageBody.addBodyPart(htmlTextPart);
809     }
810
811     private MimeBodyPart JavaDoc getMainPart() throws MessagingException JavaDoc {
812         MimeMultipart JavaDoc mimeMultipart = getMimeMultipart();
813         MimeBodyPart JavaDoc bodyPart = null;
814         for (int i = 0; i < mimeMultipart.getCount(); i++) {
815             BodyPart JavaDoc bp = mimeMultipart.getBodyPart(i);
816             if (bp.getFileName() == null) {
817                 bodyPart = (MimeBodyPart JavaDoc) bp;
818             }
819         }
820         if (bodyPart == null) {
821             MimeBodyPart JavaDoc mimeBodyPart = new MimeBodyPart JavaDoc();
822             mimeMultipart.addBodyPart(mimeBodyPart);
823             bodyPart = mimeBodyPart;
824         }
825         return bodyPart;
826     }
827
828     private void setPlainTextToMimePart(MimePart JavaDoc mimePart, String JavaDoc text) throws MessagingException JavaDoc {
829         if (getEncoding() != null) {
830             mimePart.setText(text, getEncoding());
831         }
832         else {
833             mimePart.setText(text);
834         }
835     }
836
837     private void setHtmlTextToMimePart(MimePart JavaDoc mimePart, String JavaDoc text) throws MessagingException JavaDoc {
838         if (getEncoding() != null) {
839             mimePart.setContent(text, CONTENT_TYPE_HTML + CONTENT_TYPE_CHARSET_SUFFIX + getEncoding());
840         }
841         else {
842             mimePart.setContent(text, CONTENT_TYPE_HTML);
843         }
844     }
845
846
847     /**
848      * Add an inline element to the MimeMessage, taking the content from a
849      * <code>javax.activation.DataSource</code>.
850      * <p>Note that the InputStream returned by the DataSource implementation
851      * needs to be a <i>fresh one on each call</i>, as JavaMail will invoke
852      * <code>getInputStream()</code> multiple times.
853      * <p><b>NOTE:</b> Invoke <code>addInline</code> <i>after</i> {@link #setText};
854      * else, mail readers might not be able to resolve inline references correctly.
855      * @param contentId the content ID to use. Will end up as "Content-ID" header
856      * in the body part, surrounded by angle brackets: e.g. "myId" -> "&lt;myId&gt;".
857      * Can be referenced in HTML source via SRC="cid:myId" expressions.
858      * @param dataSource the <code>javax.activation.DataSource</code> to take
859      * the content from, determining the InputStream and the content type
860      * @throws MessagingException in case of errors
861      * @see #addInline(String, java.io.File)
862      * @see #addInline(String, org.springframework.core.io.Resource)
863      */

864     public void addInline(String JavaDoc contentId, DataSource JavaDoc dataSource) throws MessagingException JavaDoc {
865         Assert.notNull(contentId, "Content ID must not be null");
866         Assert.notNull(dataSource, "DataSource must not be null");
867         MimeBodyPart JavaDoc mimeBodyPart = new MimeBodyPart JavaDoc();
868         mimeBodyPart.setDisposition(MimeBodyPart.INLINE);
869         // We're using setHeader here to remain compatible with JavaMail 1.2,
870
// rather than JavaMail 1.3's setContentID.
871
mimeBodyPart.setHeader(HEADER_CONTENT_ID, "<" + contentId + ">");
872         mimeBodyPart.setDataHandler(new DataHandler JavaDoc(dataSource));
873         getMimeMultipart().addBodyPart(mimeBodyPart);
874     }
875
876     /**
877      * Add an inline element to the MimeMessage, taking the content from a
878      * <code>java.io.File</code>.
879      * <p>The content type will be determined by the name of the given
880      * content file. Do not use this for temporary files with arbitrary
881      * filenames (possibly ending in ".tmp" or the like)!
882      * <p><b>NOTE:</b> Invoke <code>addInline</code> <i>after</i> {@link #setText};
883      * else, mail readers might not be able to resolve inline references correctly.
884      * @param contentId the content ID to use. Will end up as "Content-ID" header
885      * in the body part, surrounded by angle brackets: e.g. "myId" -> "&lt;myId&gt;".
886      * Can be referenced in HTML source via SRC="cid:myId" expressions.
887      * @param file the File resource to take the content from
888      * @throws MessagingException in case of errors
889      * @see #setText
890      * @see #addInline(String, org.springframework.core.io.Resource)
891      * @see #addInline(String, javax.activation.DataSource)
892      */

893     public void addInline(String JavaDoc contentId, File JavaDoc file) throws MessagingException JavaDoc {
894         Assert.notNull(file, "File must not be null");
895         FileDataSource JavaDoc dataSource = new FileDataSource JavaDoc(file);
896         dataSource.setFileTypeMap(getFileTypeMap());
897         addInline(contentId, dataSource);
898     }
899
900     /**
901      * Add an inline element to the MimeMessage, taking the content from a
902      * <code>org.springframework.core.io.Resource</code>.
903      * <p>The content type will be determined by the name of the given
904      * content file. Do not use this for temporary files with arbitrary
905      * filenames (possibly ending in ".tmp" or the like)!
906      * <p>Note that the InputStream returned by the Resource implementation
907      * needs to be a <i>fresh one on each call</i>, as JavaMail will invoke
908      * <code>getInputStream()</code> multiple times.
909      * <p><b>NOTE:</b> Invoke <code>addInline</code> <i>after</i> {@link #setText};
910      * else, mail readers might not be able to resolve inline references correctly.
911      * @param contentId the content ID to use. Will end up as "Content-ID" header
912      * in the body part, surrounded by angle brackets: e.g. "myId" -> "&lt;myId&gt;".
913      * Can be referenced in HTML source via SRC="cid:myId" expressions.
914      * @param resource the resource to take the content from
915      * @throws MessagingException in case of errors
916      * @see #setText
917      * @see #addInline(String, java.io.File)
918      * @see #addInline(String, javax.activation.DataSource)
919      */

920     public void addInline(String JavaDoc contentId, Resource resource) throws MessagingException JavaDoc {
921         Assert.notNull(resource, "Resource must not be null");
922         String JavaDoc contentType = getFileTypeMap().getContentType(resource.getFilename());
923         addInline(contentId, resource, contentType);
924     }
925
926     /**
927      * Add an inline element to the MimeMessage, taking the content from an
928      * <code>org.springframework.core.InputStreamResource</code>, and
929      * specifying the content type explicitly.
930      * <p>You can determine the content type for any given filename via a Java
931      * Activation Framework's FileTypeMap, for example the one held by this helper.
932      * <p>Note that the InputStream returned by the InputStreamSource implementation
933      * needs to be a <i>fresh one on each call</i>, as JavaMail will invoke
934      * <code>getInputStream()</code> multiple times.
935      * <p><b>NOTE:</b> Invoke <code>addInline</code> <i>after</i> <code>setText</code>;
936      * else, mail readers might not be able to resolve inline references correctly.
937      * @param contentId the content ID to use. Will end up as "Content-ID" header
938      * in the body part, surrounded by angle brackets: e.g. "myId" -> "&lt;myId&gt;".
939      * Can be referenced in HTML source via SRC="cid:myId" expressions.
940      * @param inputStreamSource the resource to take the content from
941      * @param contentType the content type to use for the element
942      * @throws MessagingException in case of errors
943      * @see #setText
944      * @see #getFileTypeMap
945      * @see #addInline(String, org.springframework.core.io.Resource)
946      * @see #addInline(String, javax.activation.DataSource)
947      */

948     public void addInline(String JavaDoc contentId, InputStreamSource inputStreamSource, String JavaDoc contentType)
949         throws MessagingException JavaDoc {
950
951         Assert.notNull(inputStreamSource, "InputStreamSource must not be null");
952         if (inputStreamSource instanceof Resource && ((Resource) inputStreamSource).isOpen()) {
953             throw new IllegalArgumentException JavaDoc(
954                     "Passed-in Resource contains an open stream: invalid argument. " +
955                     "JavaMail requires an InputStreamSource that creates a fresh stream for every call.");
956         }
957         DataSource JavaDoc dataSource = createDataSource(inputStreamSource, contentType, "inline");
958         addInline(contentId, dataSource);
959     }
960
961     /**
962      * Add an attachment to the MimeMessage, taking the content from a
963      * <code>javax.activation.DataSource</code>.
964      * <p>Note that the InputStream returned by the DataSource implementation
965      * needs to be a <i>fresh one on each call</i>, as JavaMail will invoke
966      * <code>getInputStream()</code> multiple times.
967      * @param attachmentFilename the name of the attachment as it will
968      * appear in the mail (the content type will be determined by this)
969      * @param dataSource the <code>javax.activation.DataSource</code> to take
970      * the content from, determining the InputStream and the content type
971      * @throws MessagingException in case of errors
972      * @see #addAttachment(String, org.springframework.core.io.InputStreamSource)
973      * @see #addAttachment(String, java.io.File)
974      */

975     public void addAttachment(String JavaDoc attachmentFilename, DataSource JavaDoc dataSource) throws MessagingException JavaDoc {
976         Assert.notNull(attachmentFilename, "Attachment filename must not be null");
977         Assert.notNull(dataSource, "DataSource must not be null");
978         MimeBodyPart JavaDoc mimeBodyPart = new MimeBodyPart JavaDoc();
979         mimeBodyPart.setDisposition(MimeBodyPart.ATTACHMENT);
980         mimeBodyPart.setFileName(attachmentFilename);
981         mimeBodyPart.setDataHandler(new DataHandler JavaDoc(dataSource));
982         getRootMimeMultipart().addBodyPart(mimeBodyPart);
983     }
984
985     /**
986      * Add an attachment to the MimeMessage, taking the content from a
987      * <code>java.io.File</code>.
988      * <p>The content type will be determined by the name of the given
989      * content file. Do not use this for temporary files with arbitrary
990      * filenames (possibly ending in ".tmp" or the like)!
991      * @param attachmentFilename the name of the attachment as it will
992      * appear in the mail
993      * @param file the File resource to take the content from
994      * @throws MessagingException in case of errors
995      * @see #addAttachment(String, org.springframework.core.io.InputStreamSource)
996      * @see #addAttachment(String, javax.activation.DataSource)
997      */

998     public void addAttachment(String JavaDoc attachmentFilename, File JavaDoc file) throws MessagingException JavaDoc {
999         Assert.notNull(file, "File must not be null");
1000        FileDataSource JavaDoc dataSource = new FileDataSource JavaDoc(file);
1001        dataSource.setFileTypeMap(getFileTypeMap());
1002        addAttachment(attachmentFilename, dataSource);
1003    }
1004
1005    /**
1006     * Add an attachment to the MimeMessage, taking the content from an
1007     * <code>org.springframework.core.io.InputStreamResource</code>.
1008     * <p>The content type will be determined by the given filename for
1009     * the attachment. Thus, any content source will be fine, including
1010     * temporary files with arbitrary filenames.
1011     * <p>Note that the InputStream returned by the InputStreamSource
1012     * implementation needs to be a <i>fresh one on each call</i>, as
1013     * JavaMail will invoke <code>getInputStream()</code> multiple times.
1014     * @param attachmentFilename the name of the attachment as it will
1015     * appear in the mail
1016     * @param inputStreamSource the resource to take the content from
1017     * (all of Spring's Resource implementations can be passed in here)
1018     * @throws MessagingException in case of errors
1019     * @see #addAttachment(String, java.io.File)
1020     * @see #addAttachment(String, javax.activation.DataSource)
1021     * @see org.springframework.core.io.Resource
1022     */

1023    public void addAttachment(String JavaDoc attachmentFilename, InputStreamSource inputStreamSource)
1024        throws MessagingException JavaDoc {
1025
1026        String JavaDoc contentType = getFileTypeMap().getContentType(attachmentFilename);
1027        addAttachment(attachmentFilename, inputStreamSource, contentType);
1028    }
1029
1030    /**
1031     * Add an attachment to the MimeMessage, taking the content from an
1032     * <code>org.springframework.core.io.InputStreamResource</code>.
1033     * <p>Note that the InputStream returned by the InputStreamSource
1034     * implementation needs to be a <i>fresh one on each call</i>, as
1035     * JavaMail will invoke <code>getInputStream()</code> multiple times.
1036     * @param attachmentFilename the name of the attachment as it will
1037     * appear in the mail
1038     * @param inputStreamSource the resource to take the content from
1039     * (all of Spring's Resource implementations can be passed in here)
1040     * @param contentType the content type to use for the element
1041     * @throws MessagingException in case of errors
1042     * @see #addAttachment(String, java.io.File)
1043     * @see #addAttachment(String, javax.activation.DataSource)
1044     * @see org.springframework.core.io.Resource
1045     */

1046    public void addAttachment(
1047            String JavaDoc attachmentFilename, InputStreamSource inputStreamSource, String JavaDoc contentType)
1048        throws MessagingException JavaDoc {
1049
1050        Assert.notNull(inputStreamSource, "InputStreamSource must not be null");
1051        if (inputStreamSource instanceof Resource && ((Resource) inputStreamSource).isOpen()) {
1052            throw new IllegalArgumentException JavaDoc(
1053                    "Passed-in Resource contains an open stream: invalid argument. " +
1054                    "JavaMail requires an InputStreamSource that creates a fresh stream for every call.");
1055        }
1056        DataSource JavaDoc dataSource = createDataSource(inputStreamSource, contentType, attachmentFilename);
1057        addAttachment(attachmentFilename, dataSource);
1058    }
1059
1060    /**
1061     * Create an Activation Framework DataSource for the given InputStreamSource.
1062     * @param inputStreamSource the InputStreamSource (typically a Spring Resource)
1063     * @param contentType the content type
1064     * @param name the name of the DataSource
1065     * @return the Activation Framework DataSource
1066     */

1067    protected DataSource JavaDoc createDataSource(
1068        final InputStreamSource inputStreamSource, final String JavaDoc contentType, final String JavaDoc name) {
1069
1070        return new DataSource JavaDoc() {
1071            public InputStream JavaDoc getInputStream() throws IOException JavaDoc {
1072                return inputStreamSource.getInputStream();
1073            }
1074            public OutputStream JavaDoc getOutputStream() {
1075                throw new UnsupportedOperationException JavaDoc("Read-only javax.activation.DataSource");
1076            }
1077            public String JavaDoc getContentType() {
1078                return contentType;
1079            }
1080            public String JavaDoc getName() {
1081                return name;
1082            }
1083        };
1084    }
1085
1086}
1087
Popular Tags