diff --git a/org.springframework.context.support/src/main/java/org/springframework/mail/javamail/MimeMessageHelper.java b/org.springframework.context.support/src/main/java/org/springframework/mail/javamail/MimeMessageHelper.java index b4984c693de..4184b2f3b41 100644 --- a/org.springframework.context.support/src/main/java/org/springframework/mail/javamail/MimeMessageHelper.java +++ b/org.springframework.context.support/src/main/java/org/springframework/mail/javamail/MimeMessageHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.internet.MimePart; +import javax.mail.internet.MimeUtility; import org.springframework.core.io.InputStreamSource; import org.springframework.core.io.Resource; @@ -241,7 +242,7 @@ public class MimeMessageHelper { * @see #MimeMessageHelper(javax.mail.internet.MimeMessage, int, String) */ public MimeMessageHelper(MimeMessage mimeMessage, boolean multipart, String encoding) - throws MessagingException { + throws MessagingException { this(mimeMessage, (multipart ? MULTIPART_MODE_MIXED_RELATED : MULTIPART_MODE_NO), encoding); } @@ -283,7 +284,7 @@ public class MimeMessageHelper { * @see #MULTIPART_MODE_MIXED_RELATED */ public MimeMessageHelper(MimeMessage mimeMessage, int multipartMode, String encoding) - throws MessagingException { + throws MessagingException { this.mimeMessage = mimeMessage; createMimeMultiparts(mimeMessage, multipartMode); @@ -355,7 +356,7 @@ public class MimeMessageHelper { /** * Set the given MimeMultipart objects for use by this MimeMessageHelper. * @param root the root MimeMultipart object, which attachments will be added to; - * or null to indicate no multipart at all + * or {@code null} to indicate no multipart at all * @param main the main MimeMultipart object, which text(s) and inline elements * will be added to (can be the same as the root multipart object, or an element * nested underneath the root multipart element) @@ -380,8 +381,8 @@ public class MimeMessageHelper { private void checkMultipart() throws IllegalStateException { if (!isMultipart()) { throw new IllegalStateException("Not in multipart mode - " + - "create an appropriate MimeMessageHelper via a constructor that takes a 'multipart' flag " + - "if you need to set alternative texts or add inline elements or attachments."); + "create an appropriate MimeMessageHelper via a constructor that takes a 'multipart' flag " + + "if you need to set alternative texts or add inline elements or attachments."); } } @@ -420,7 +421,7 @@ public class MimeMessageHelper { * Determine the default encoding for the given MimeMessage. * @param mimeMessage the passed-in MimeMessage * @return the default encoding associated with the MimeMessage, - * or null if none found + * or {@code null} if none found */ protected String getDefaultEncoding(MimeMessage mimeMessage) { if (mimeMessage instanceof SmartMimeMessage) { @@ -456,12 +457,12 @@ public class MimeMessageHelper { } /** - * Set the Java Activation Framework FileTypeMap to use + * Set the Java Activation Framework {@code FileTypeMap} to use * for determining the content type of inline content and attachments * that get added to the message. - *

Default is the FileTypeMap that the underlying + *

Default is the {@code FileTypeMap} that the underlying * MimeMessage carries, if any, or the Activation Framework's default - * FileTypeMap instance else. + * {@code FileTypeMap} instance else. * @see #addInline * @see #addAttachment * @see #getDefaultFileTypeMap(javax.mail.internet.MimeMessage) @@ -474,7 +475,7 @@ public class MimeMessageHelper { } /** - * Return the FileTypeMap used by this MimeMessageHelper. + * Return the {@code FileTypeMap} used by this MimeMessageHelper. */ public FileTypeMap getFileTypeMap() { return this.fileTypeMap; @@ -485,7 +486,7 @@ public class MimeMessageHelper { * Set whether to validate all addresses which get passed to this helper. * Default is "false". *

Note that this is by default just available for JavaMail >= 1.3. - * You can override the default validateAddress method for + * You can override the default {@code validateAddress method} for * validation on older JavaMail versions (or for custom validation). * @see #validateAddress */ @@ -503,7 +504,7 @@ public class MimeMessageHelper { /** * Validate the given mail address. * Called by all of MimeMessageHelper's address setters and adders. - *

Default implementation invokes InternetAddress.validate(), + *

Default implementation invokes {@code InternetAddress.validate()}, * provided that address validation is activated for the helper instance. *

Note that this method will just work on JavaMail >= 1.3. You can override * it for validation on older JavaMail versions or for custom validation. @@ -546,7 +547,7 @@ public class MimeMessageHelper { public void setFrom(String from, String personal) throws MessagingException, UnsupportedEncodingException { Assert.notNull(from, "From address must not be null"); setFrom(getEncoding() != null ? - new InternetAddress(from, personal, getEncoding()) : new InternetAddress(from, personal)); + new InternetAddress(from, personal, getEncoding()) : new InternetAddress(from, personal)); } public void setReplyTo(InternetAddress replyTo) throws MessagingException { @@ -608,8 +609,8 @@ public class MimeMessageHelper { public void addTo(String to, String personal) throws MessagingException, UnsupportedEncodingException { Assert.notNull(to, "To address must not be null"); addTo(getEncoding() != null ? - new InternetAddress(to, personal, getEncoding()) : - new InternetAddress(to, personal)); + new InternetAddress(to, personal, getEncoding()) : + new InternetAddress(to, personal)); } @@ -653,8 +654,8 @@ public class MimeMessageHelper { public void addCc(String cc, String personal) throws MessagingException, UnsupportedEncodingException { Assert.notNull(cc, "Cc address must not be null"); addCc(getEncoding() != null ? - new InternetAddress(cc, personal, getEncoding()) : - new InternetAddress(cc, personal)); + new InternetAddress(cc, personal, getEncoding()) : + new InternetAddress(cc, personal)); } @@ -698,8 +699,8 @@ public class MimeMessageHelper { public void addBcc(String bcc, String personal) throws MessagingException, UnsupportedEncodingException { Assert.notNull(bcc, "Bcc address must not be null"); addBcc(getEncoding() != null ? - new InternetAddress(bcc, personal, getEncoding()) : - new InternetAddress(bcc, personal)); + new InternetAddress(bcc, personal, getEncoding()) : + new InternetAddress(bcc, personal)); } private InternetAddress parseAddress(String address) throws MessagingException { @@ -730,7 +731,7 @@ public class MimeMessageHelper { /** * Set the sent-date of the message. - * @param sentDate the date to set (never null) + * @param sentDate the date to set (never {@code null}) * @throws MessagingException in case of errors */ public void setSentDate(Date sentDate) throws MessagingException { @@ -758,7 +759,7 @@ public class MimeMessageHelper { * Set the given text directly as content in non-multipart mode * or as default body part in multipart mode. * Always applies the default content type "text/plain". - *

NOTE: Invoke {@link #addInline} after setText; + *

NOTE: Invoke {@link #addInline} after {@code setText}; * else, mail readers might not be able to resolve inline references correctly. * @param text the text for the message * @throws MessagingException in case of errors @@ -771,7 +772,7 @@ public class MimeMessageHelper { * Set the given text directly as content in non-multipart mode * or as default body part in multipart mode. * The "html" flag determines the content type to apply. - *

NOTE: Invoke {@link #addInline} after setText; + *

NOTE: Invoke {@link #addInline} after {@code setText}; * else, mail readers might not be able to resolve inline references correctly. * @param text the text for the message * @param html whether to apply content type "text/html" for an @@ -798,7 +799,7 @@ public class MimeMessageHelper { /** * Set the given plain text and HTML text as alternatives, offering * both options to the email client. Requires multipart mode. - *

NOTE: Invoke {@link #addInline} after setText; + *

NOTE: Invoke {@link #addInline} after {@code setText}; * else, mail readers might not be able to resolve inline references correctly. * @param plainText the plain text for the message * @param htmlText the HTML text for the message @@ -860,16 +861,16 @@ public class MimeMessageHelper { /** * Add an inline element to the MimeMessage, taking the content from a - * javax.activation.DataSource. + * {@code javax.activation.DataSource}. *

Note that the InputStream returned by the DataSource implementation * needs to be a fresh one on each call, as JavaMail will invoke - * getInputStream() multiple times. - *

NOTE: Invoke addInline after {@link #setText}; + * {@code getInputStream()} multiple times. + *

NOTE: Invoke {@code addInline} after {@link #setText}; * else, mail readers might not be able to resolve inline references correctly. * @param contentId the content ID to use. Will end up as "Content-ID" header * in the body part, surrounded by angle brackets: e.g. "myId" -> "<myId>". * Can be referenced in HTML source via src="cid:myId" expressions. - * @param dataSource the javax.activation.DataSource to take + * @param dataSource the {@code javax.activation.DataSource} to take * the content from, determining the InputStream and the content type * @throws MessagingException in case of errors * @see #addInline(String, java.io.File) @@ -889,11 +890,11 @@ public class MimeMessageHelper { /** * Add an inline element to the MimeMessage, taking the content from a - * java.io.File. + * {@code java.io.File}. *

The content type will be determined by the name of the given * content file. Do not use this for temporary files with arbitrary * filenames (possibly ending in ".tmp" or the like)! - *

NOTE: Invoke addInline after {@link #setText}; + *

NOTE: Invoke {@code addInline} after {@link #setText}; * else, mail readers might not be able to resolve inline references correctly. * @param contentId the content ID to use. Will end up as "Content-ID" header * in the body part, surrounded by angle brackets: e.g. "myId" -> "<myId>". @@ -913,14 +914,14 @@ public class MimeMessageHelper { /** * Add an inline element to the MimeMessage, taking the content from a - * org.springframework.core.io.Resource. + * {@code org.springframework.core.io.Resource}. *

The content type will be determined by the name of the given * content file. Do not use this for temporary files with arbitrary * filenames (possibly ending in ".tmp" or the like)! *

Note that the InputStream returned by the Resource implementation * needs to be a fresh one on each call, as JavaMail will invoke - * getInputStream() multiple times. - *

NOTE: Invoke addInline after {@link #setText}; + * {@code getInputStream()} multiple times. + *

NOTE: Invoke {@code addInline} after {@link #setText}; * else, mail readers might not be able to resolve inline references correctly. * @param contentId the content ID to use. Will end up as "Content-ID" header * in the body part, surrounded by angle brackets: e.g. "myId" -> "<myId>". @@ -939,14 +940,14 @@ public class MimeMessageHelper { /** * Add an inline element to the MimeMessage, taking the content from an - * org.springframework.core.InputStreamResource, and + * {@code org.springframework.core.InputStreamResource}, and * specifying the content type explicitly. *

You can determine the content type for any given filename via a Java * Activation Framework's FileTypeMap, for example the one held by this helper. *

Note that the InputStream returned by the InputStreamSource implementation * needs to be a fresh one on each call, as JavaMail will invoke - * getInputStream() multiple times. - *

NOTE: Invoke addInline after setText; + * {@code getInputStream()} multiple times. + *

NOTE: Invoke {@code addInline} after {@code setText}; * else, mail readers might not be able to resolve inline references correctly. * @param contentId the content ID to use. Will end up as "Content-ID" header * in the body part, surrounded by angle brackets: e.g. "myId" -> "<myId>". @@ -960,7 +961,7 @@ public class MimeMessageHelper { * @see #addInline(String, javax.activation.DataSource) */ public void addInline(String contentId, InputStreamSource inputStreamSource, String contentType) - throws MessagingException { + throws MessagingException { Assert.notNull(inputStreamSource, "InputStreamSource must not be null"); if (inputStreamSource instanceof Resource && ((Resource) inputStreamSource).isOpen()) { @@ -974,13 +975,13 @@ public class MimeMessageHelper { /** * Add an attachment to the MimeMessage, taking the content from a - * javax.activation.DataSource. + * {@code javax.activation.DataSource}. *

Note that the InputStream returned by the DataSource implementation * needs to be a fresh one on each call, as JavaMail will invoke - * getInputStream() multiple times. + * {@code getInputStream()} multiple times. * @param attachmentFilename the name of the attachment as it will * appear in the mail (the content type will be determined by this) - * @param dataSource the javax.activation.DataSource to take + * @param dataSource the {@code javax.activation.DataSource} to take * the content from, determining the InputStream and the content type * @throws MessagingException in case of errors * @see #addAttachment(String, org.springframework.core.io.InputStreamSource) @@ -989,16 +990,21 @@ public class MimeMessageHelper { public void addAttachment(String attachmentFilename, DataSource dataSource) throws MessagingException { Assert.notNull(attachmentFilename, "Attachment filename must not be null"); Assert.notNull(dataSource, "DataSource must not be null"); - MimeBodyPart mimeBodyPart = new MimeBodyPart(); - mimeBodyPart.setDisposition(MimeBodyPart.ATTACHMENT); - mimeBodyPart.setFileName(attachmentFilename); - mimeBodyPart.setDataHandler(new DataHandler(dataSource)); - getRootMimeMultipart().addBodyPart(mimeBodyPart); + try { + MimeBodyPart mimeBodyPart = new MimeBodyPart(); + mimeBodyPart.setDisposition(MimeBodyPart.ATTACHMENT); + mimeBodyPart.setFileName(MimeUtility.encodeText(attachmentFilename)); + mimeBodyPart.setDataHandler(new DataHandler(dataSource)); + getRootMimeMultipart().addBodyPart(mimeBodyPart); + } + catch (UnsupportedEncodingException ex) { + throw new MessagingException("Failed to encode attachment filename", ex); + } } /** * Add an attachment to the MimeMessage, taking the content from a - * java.io.File. + * {@code java.io.File}. *

The content type will be determined by the name of the given * content file. Do not use this for temporary files with arbitrary * filenames (possibly ending in ".tmp" or the like)! @@ -1018,13 +1024,13 @@ public class MimeMessageHelper { /** * Add an attachment to the MimeMessage, taking the content from an - * org.springframework.core.io.InputStreamResource. + * {@code org.springframework.core.io.InputStreamResource}. *

The content type will be determined by the given filename for * the attachment. Thus, any content source will be fine, including * temporary files with arbitrary filenames. *

Note that the InputStream returned by the InputStreamSource * implementation needs to be a fresh one on each call, as - * JavaMail will invoke getInputStream() multiple times. + * JavaMail will invoke {@code getInputStream()} multiple times. * @param attachmentFilename the name of the attachment as it will * appear in the mail * @param inputStreamSource the resource to take the content from @@ -1035,7 +1041,7 @@ public class MimeMessageHelper { * @see org.springframework.core.io.Resource */ public void addAttachment(String attachmentFilename, InputStreamSource inputStreamSource) - throws MessagingException { + throws MessagingException { String contentType = getFileTypeMap().getContentType(attachmentFilename); addAttachment(attachmentFilename, inputStreamSource, contentType); @@ -1043,10 +1049,10 @@ public class MimeMessageHelper { /** * Add an attachment to the MimeMessage, taking the content from an - * org.springframework.core.io.InputStreamResource. + * {@code org.springframework.core.io.InputStreamResource}. *

Note that the InputStream returned by the InputStreamSource * implementation needs to be a fresh one on each call, as - * JavaMail will invoke getInputStream() multiple times. + * JavaMail will invoke {@code getInputStream()} multiple times. * @param attachmentFilename the name of the attachment as it will * appear in the mail * @param inputStreamSource the resource to take the content from @@ -1059,7 +1065,7 @@ public class MimeMessageHelper { */ public void addAttachment( String attachmentFilename, InputStreamSource inputStreamSource, String contentType) - throws MessagingException { + throws MessagingException { Assert.notNull(inputStreamSource, "InputStreamSource must not be null"); if (inputStreamSource instanceof Resource && ((Resource) inputStreamSource).isOpen()) { @@ -1079,7 +1085,7 @@ public class MimeMessageHelper { * @return the Activation Framework DataSource */ protected DataSource createDataSource( - final InputStreamSource inputStreamSource, final String contentType, final String name) { + final InputStreamSource inputStreamSource, final String contentType, final String name) { return new DataSource() { public InputStream getInputStream() throws IOException {