@@ -905,12 +905,47 @@ private void setHtmlTextToMimePart(MimePart mimePart, String text) throws Messag
905
905
* @see #addInline(String, org.springframework.core.io.Resource)
906
906
*/
907
907
public void addInline (String contentId , DataSource dataSource ) throws MessagingException {
908
+ addInline (contentId , null , dataSource );
909
+ }
910
+
911
+ /**
912
+ * Add an inline element to the MimeMessage, taking the content from a
913
+ * {@code jakarta.activation.DataSource} and assigning the provided
914
+ * {@code inlineFileName} to the element.
915
+ * <p>Note that the InputStream returned by the DataSource implementation
916
+ * needs to be a <i>fresh one on each call</i>, as JavaMail will invoke
917
+ * {@code getInputStream()} multiple times.
918
+ * <p><b>NOTE:</b> Invoke {@code addInline} <i>after</i> {@link #setText};
919
+ * else, mail readers might not be able to resolve inline references correctly.
920
+ * @param contentId the content ID to use. Will end up as "Content-ID" header
921
+ * in the body part, surrounded by angle brackets: e.g. "myId" → "<myId>".
922
+ * Can be referenced in HTML source via src="cid:myId" expressions.
923
+ * @param inlineFilename the fileName to use for the inline element's part
924
+ * @param dataSource the {@code jakarta.activation.DataSource} to take
925
+ * the content from, determining the InputStream and the content type
926
+ * @throws MessagingException in case of errors
927
+ * @since 6.2
928
+ * @see #addInline(String, java.io.File)
929
+ * @see #addInline(String, org.springframework.core.io.Resource)
930
+ */
931
+ public void addInline (String contentId , @ Nullable String inlineFilename , DataSource dataSource )
932
+ throws MessagingException {
933
+
908
934
Assert .notNull (contentId , "Content ID must not be null" );
909
935
Assert .notNull (dataSource , "DataSource must not be null" );
910
936
MimeBodyPart mimeBodyPart = new MimeBodyPart ();
911
937
mimeBodyPart .setDisposition (Part .INLINE );
912
938
mimeBodyPart .setContentID ("<" + contentId + ">" );
913
939
mimeBodyPart .setDataHandler (new DataHandler (dataSource ));
940
+ if (inlineFilename != null ) {
941
+ try {
942
+ mimeBodyPart .setFileName (isEncodeFilenames () ?
943
+ MimeUtility .encodeText (inlineFilename ) : inlineFilename );
944
+ }
945
+ catch (UnsupportedEncodingException ex ) {
946
+ throw new MessagingException ("Failed to encode inline filename" , ex );
947
+ }
948
+ }
914
949
getMimeMultipart ().addBodyPart (mimeBodyPart );
915
950
}
916
951
@@ -989,14 +1024,75 @@ public void addInline(String contentId, Resource resource) throws MessagingExcep
989
1024
public void addInline (String contentId , InputStreamSource inputStreamSource , String contentType )
990
1025
throws MessagingException {
991
1026
1027
+ addInline (contentId , "inline" , inputStreamSource , contentType );
1028
+ }
1029
+
1030
+ /**
1031
+ * Add an inline element to the MimeMessage, taking the content from an
1032
+ * {@code org.springframework.core.InputStreamResource}, and
1033
+ * specifying the inline fileName explicitly.
1034
+ * <p>The content type will be determined by the name of the given
1035
+ * content file. Do not use this for temporary files with arbitrary
1036
+ * filenames (possibly ending in ".tmp" or the like)!
1037
+ * <p>Note that the InputStream returned by the InputStreamSource implementation
1038
+ * needs to be a <i>fresh one on each call</i>, as JavaMail will invoke
1039
+ * {@code getInputStream()} multiple times.
1040
+ * <p><b>NOTE:</b> Invoke {@code addInline} <i>after</i> {@code setText};
1041
+ * else, mail readers might not be able to resolve inline references correctly.
1042
+ * @param contentId the content ID to use. Will end up as "Content-ID" header
1043
+ * in the body part, surrounded by angle brackets: e.g. "myId" → "<myId>".
1044
+ * Can be referenced in HTML source via src="cid:myId" expressions.
1045
+ * @param inlineFilename the file name to use for the inline element
1046
+ * @param inputStreamSource the resource to take the content from
1047
+ * @throws MessagingException in case of errors
1048
+ * @since 6.2
1049
+ * @see #setText(String)
1050
+ * @see #getFileTypeMap
1051
+ * @see #addInline(String, org.springframework.core.io.Resource)
1052
+ * @see #addInline(String, String, jakarta.activation.DataSource)
1053
+ */
1054
+ public void addInline (String contentId , String inlineFilename , InputStreamSource inputStreamSource )
1055
+ throws MessagingException {
1056
+
1057
+ String contentType = getFileTypeMap ().getContentType (inlineFilename );
1058
+ addInline (contentId , inlineFilename , inputStreamSource , contentType );
1059
+ }
1060
+
1061
+ /**
1062
+ * Add an inline element to the MimeMessage, taking the content from an
1063
+ * {@code org.springframework.core.InputStreamResource}, and
1064
+ * specifying the inline fileName and content type explicitly.
1065
+ * <p>You can determine the content type for any given filename via a Java
1066
+ * Activation Framework's FileTypeMap, for example the one held by this helper.
1067
+ * <p>Note that the InputStream returned by the InputStreamSource implementation
1068
+ * needs to be a <i>fresh one on each call</i>, as JavaMail will invoke
1069
+ * {@code getInputStream()} multiple times.
1070
+ * <p><b>NOTE:</b> Invoke {@code addInline} <i>after</i> {@code setText};
1071
+ * else, mail readers might not be able to resolve inline references correctly.
1072
+ * @param contentId the content ID to use. Will end up as "Content-ID" header
1073
+ * in the body part, surrounded by angle brackets: e.g. "myId" → "<myId>".
1074
+ * Can be referenced in HTML source via src="cid:myId" expressions.
1075
+ * @param inlineFilename the fileName to use for the inline element's part
1076
+ * @param inputStreamSource the resource to take the content from
1077
+ * @param contentType the content type to use for the element
1078
+ * @throws MessagingException in case of errors
1079
+ * @since 6.2
1080
+ * @see #setText
1081
+ * @see #getFileTypeMap
1082
+ * @see #addInline(String, org.springframework.core.io.Resource)
1083
+ * @see #addInline(String, String, jakarta.activation.DataSource)
1084
+ */
1085
+ public void addInline (String contentId , String inlineFilename , InputStreamSource inputStreamSource , String contentType )
1086
+ throws MessagingException {
1087
+
992
1088
Assert .notNull (inputStreamSource , "InputStreamSource must not be null" );
993
1089
if (inputStreamSource instanceof Resource resource && resource .isOpen ()) {
994
1090
throw new IllegalArgumentException (
995
1091
"Passed-in Resource contains an open stream: invalid argument. " +
996
1092
"JavaMail requires an InputStreamSource that creates a fresh stream for every call." );
997
1093
}
998
- DataSource dataSource = createDataSource (inputStreamSource , contentType , "inline" );
999
- addInline (contentId , dataSource );
1094
+ DataSource dataSource = createDataSource (inputStreamSource , contentType , inlineFilename );
1095
+ addInline (contentId , inlineFilename , dataSource );
1000
1096
}
1001
1097
1002
1098
/**
0 commit comments