Inline images in email using JavaMail - java

I want to send an email with an inline image using javamail.
I'm doing something like this.
MimeMultipart content = new MimeMultipart("related");
BodyPart bodyPart = new MimeBodyPart();
bodyPart.setContent(message, "text/html; charset=ISO-8859-1");
content.addBodyPart(bodyPart);
bodyPart = new MimeBodyPart();
DataSource ds = new ByteArrayDataSource(image, "image/jpeg");
bodyPart.setDataHandler(new DataHandler(ds));
bodyPart.setHeader("Content-Type", "image/jpeg; name=image.jpg");
bodyPart.setHeader("Content-ID", "<image>");
bodyPart.setHeader("Content-Disposition", "inline");
content.addBodyPart(bodyPart);
msg.setContent(content);
I've also tried
bodyPart.setHeader("inline; filename=image.jpg");
and
bodyPart.setDisposition("inline");
but no matter what, the image is being sent as an attachment and the Content-Dispostion is turning into "attachment".
How do I send an image inline in the email using javamail?

Your problem
As far as I can see, it looks like the way you create the message and everything is mostly right! You use the right MIME types and everything.
I am not sure why you use a DataSource and DataHandler, and have a ContentID on the image, but you need to complete your question for me to be able to troubleshoot more. Especially, the following line:
bodyPart.setContent(message, "text/html; charset=ISO-8859-1");
What is in message? Does it contains <img src="cid:image" />?
Did you try to generate the ContentID with String cid = ContentIdGenerator.getContentId(); instead of using image
Source
This blog article taught me how to use the right message type, attach my image and refer to the attachment from the HTML body: How to Send Email with Embedded Images Using Java
Details
Message
You have to create your content using the MimeMultipart class. It is important to use the string "related" as a parameter to the constructor, to tell JavaMail that your parts are "working together".
MimeMultipart content = new MimeMultipart("related");
Content identifier
You need to generate a ContentID, it is a string used to identify the image you attached to your email and refer to it from the email body.
String cid = ContentIdGenerator.getContentId();
Note: This ContentIdGenerator class is hypothetical. You could create one or inline the creation of content IDs. In my case, I use a simple method:
import java.util.UUID;
// ...
String generateContentId(String prefix) {
return String.format("%s-%s", prefix, UUID.randomUUID());
}
HTML body
The HTML code is one part of the MimeMultipart content. Use the MimeBodyPart class for that. Don't forget to specify the encoding and "html" when you set the text of that part!
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setText(""
+ "<html>"
+ " <body>"
+ " <p>Here is my image:</p>"
+ " <img src=\"cid:" + cid + "\" />"
+ " </body>"
+ "</html>"
,"US-ASCII", "html");
content.addBodyPart(htmlPart);
Note that as a source of the image, we use cid: and the generated ContentID.
Image attachment
We can create another MimeBodyPart for the attachment of the image.
MimeBodyPart imagePart = new MimeBodyPart();
imagePart.attachFile("resources/teapot.jpg");
imagePart.setContentID("<" + cid + ">");
imagePart.setDisposition(MimeBodyPart.INLINE);
content.addBodyPart(imagePart);
Note that we use the same ContentID between < and > and set it as the image's ContentID. We also set the disposition to INLINE to signal that this image is meant to be displayed in the email, not as an attachment.
Finish message
That's it! If you create an SMTP message on the right session and use that content, your email will contain an embedded image! For instance:
SMTPMessage m = new SMTPMessage(session);
m.setContent(content);
m.setSubject("Mail with embedded image");
m.setRecipient(RecipientType.TO, new InternetAddress("your#email.com"));
Transport.send(m)
Let me know if that works for you! ;)

Why don't you try something like this?
MimeMessage mail = new MimeMessage(mailSession);
mail.setSubject(subject);
MimeBodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(message, "text/html");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(new File("complete path to image.jpg"));
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(fileAttachment.getName());
messageBodyPart.setDisposition(MimeBodyPart.INLINE);
multipart.addBodyPart(messageBodyPart);
mail.setContent(multipart);
in the message, have a
<img src="image.jpg"/>
tag and you should be ok.
Good Luck

This worked for me:
MimeMultipart rootContainer = new MimeMultipart();
rootContainer.setSubType("related");
rootContainer.addBodyPart(alternativeMultiPartWithPlainTextAndHtml); // not in focus here
rootContainer.addBodyPart(createInlineImagePart(base64EncodedImageContentByteArray));
...
message.setContent(rootContainer);
message.setHeader("MIME-Version", "1.0");
message.setHeader("Content-Type", rootContainer.getContentType());
...
BodyPart createInlineImagePart(byte[] base64EncodedImageContentByteArray) throws MessagingException {
InternetHeaders headers = new InternetHeaders();
headers.addHeader("Content-Type", "image/jpeg");
headers.addHeader("Content-Transfer-Encoding", "base64");
MimeBodyPart imagePart = new MimeBodyPart(headers, base64EncodedImageContentByteArray);
imagePart.setDisposition(MimeBodyPart.INLINE);
imagePart.setContentID("<image>");
imagePart.setFileName("image.jpg");
return imagePart;

If you are using Spring use MimeMessageHelper to send email with inline content (References).
Create JavaMailSender bean or configure this by adding corresponding properties to application.properties file, if you are using Spring Boot.
#Bean
public JavaMailSender getJavaMailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(host);
mailSender.setPort(port);
mailSender.setUsername(username);
mailSender.setPassword(password);
Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", authEnable);
props.put("mail.smtp.starttls.enable", starttlsEnable);
//props.put("mail.debug", "true");
mailSender.setJavaMailProperties(props);
return mailSender;
}
Create algorithm to generate unique CONTENT-ID
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Random;
public class ContentIdGenerator {
static int seq = 0;
static String hostname;
public static void getHostname() {
try {
hostname = InetAddress.getLocalHost().getCanonicalHostName();
}
catch (UnknownHostException e) {
// we can't find our hostname? okay, use something no one else is
// likely to use
hostname = new Random(System.currentTimeMillis()).nextInt(100000) + ".localhost";
}
}
/**
* Sequence goes from 0 to 100K, then starts up at 0 again. This is large
* enough,
* and saves
*
* #return
*/
public static synchronized int getSeq() {
return (seq++) % 100000;
}
/**
* One possible way to generate very-likely-unique content IDs.
*
* #return A content id that uses the hostname, the current time, and a
* sequence number
* to avoid collision.
*/
public static String getContentId() {
getHostname();
int c = getSeq();
return c + "." + System.currentTimeMillis() + "#" + hostname;
}
}
Send Email with inlines.
#Autowired
private JavaMailSender javaMailSender;
public void sendEmailWithInlineImage() {
MimeMessage mimeMessage = null;
try {
InternetAddress from = new InternetAddress(from, personal);
mimeMessage = javaMailSender.createMimeMessage();
mimeMessage.setSubject("Test Inline");
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom(from);
helper.setTo("test#test.com");
String contentId = ContentIdGenerator.getContentId();
String htmlText = "Hello,</br> <p>This is test with email inlines.</p><img src=\"cid:" + contentId + "\" />";
helper.setText(htmlText, true);
ClassPathResource classPathResource = new ClassPathResource("static/images/first.png");
helper.addInline(contentId, classPathResource);
javaMailSender.send(mimeMessage);
}
catch (Exception e) {
LOGGER.error(e.getMessage());
}
}

RFC Specification could be found here(https://www.rfc-editor.org/rfc/rfc2392).
Firstly, email html content needs to format like : "cid:logo.png" when using inline pictures, see:
<td style="width:114px;padding-top: 19px">
<img src="cid:logo.png" />
</td>
Secondly, MimeBodyPart object needs to set property "disposition" as MimeBodyPart.INLINE, as below:
String filename = "logo.png"
BodyPart image = new MimeBodyPart();
image.setDisposition(MimeBodyPart.INLINE);
image.setFileName(filename);
image.setHeader("Content-ID", "<" +filename+">");
Be aware, Content-ID property must prefix and suffix with "<" and ">" perspectively, and the value off filename should be same with the content of src
of img tag without prefix "cid:"
Finally the whole code is below:
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("1234#gmail.com");
InternetAddress[] recipients = { "123#gmail.com"};
msg.setRecipients(Message.RecipientType.TO, recipients);
msg.setSubject("for test");
msg.setSentDate(new Date());
BodyPart content = new MimeBodyPart();
content.setContent(<html><body> <img src="cid:logo.png" /> </body></html>, "text/html; charset=utf-8");
String fileName = "logo.png";
BodyPart image = new MimeBodyPart();
image.setHeader("Content-ID", "<" +fileName+">");
image.setDisposition(MimeBodyPart.INLINE);
image.setFileName(fileName);
InputStream stream = MailService.class.getResourceAsStream(path);
DataSource fds = new ByteArrayDataSource(IOUtils.toByteArray(stream), "image/png");
image.setDataHandler(new DataHandler(fds));
MimeMultipart multipart = new MimeMultipart("related");
multipart.addBodyPart(content);
multipart.addBodyPart(getImage(image1));
msg.setContent(multipart);
msg.saveChanges();
Transport bus = session.getTransport("smtp");
bus.connect("username", "password");
bus.sendMessage(msg, recipients);
bus.close();

I had some problems having inline images displayed in GMail and Thunderbird, made some tests and resolved with the following (sample) code:
String imagePath = "/path/to/the/image.png";
String fileName = imagePath.substring(path.lastIndexOf('/') + 1);
String htmlText = "<html><body>TEST:<img src=\"cid:img1\"></body></html>";
MimeMultipart multipart = new MimeMultipart("related");
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(htmlText, "text/html; charset=utf-8");
multipart.addBodyPart(messageBodyPart);
messageBodyPart = new MimeBodyPart();
DataSource fds = new FileDataSource(imagePath);
messageBodyPart.setDataHandler(new DataHandler(fds));
messageBodyPart.setHeader("Content-ID", "<img1>");
messageBodyPart.setDisposition(MimeBodyPart.INLINE);
messageBodyPart.setFileName(fileName);
multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);
Just some things to notice:
the "Content-ID" has to be built as specified in the RFCs (https://www.rfc-editor.org/rfc/rfc2392), so it has to be the part in the img tag src attribute, following the "cid:", enclosed by angle brackets ("<" and ">")
I had to set the file name
no need for width, height, alt or title in the img tag
I had to put the charset that way, because the one in the html was being ignored
This worked for me making inline images display for some clients and in GMail web client, I don't mean this will work everywhere and forever! :)
(Sorry for my english and for my typos!)

Below is the complete Code
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
private BodyPart createInlineImagePart() {
MimeBodyPart imagePart =null;
try
{
ByteArrayOutputStream baos=new ByteArrayOutputStream(10000);
BufferedImage img=ImageIO.read(new File(directory path,"sdf_email_logo.jpg"));
ImageIO.write(img, "jpg", baos);
baos.flush();
String base64String=Base64.encode(baos.toByteArray());
baos.close();
byte[] bytearray = Base64.decode(base64String);
InternetHeaders headers = new InternetHeaders();
headers.addHeader("Content-Type", "image/jpeg");
headers.addHeader("Content-Transfer-Encoding", "base64");
imagePart = new MimeBodyPart(headers, bytearray);
imagePart.setDisposition(MimeBodyPart.INLINE);
imagePart.setContentID("<sdf_email_logo>");
imagePart.setFileName("sdf_email_logo.jpg");
}
catch(Exception exp)
{
logError("17", "Logo Attach Error : "+exp);
}
return imagePart;
}
MimeMultipart mp = new MimeMultipart();
//mp.addBodyPart(createInlineImagePart());
mp.addBodyPart(createInlineImagePart());
String body="<img src=\"cid:sdf_email_logo\"/>"

Use the following snippet:
MimeBodyPart imgBodyPart = new MimeBodyPart();
imgBodyPart.attachFile("Image.png");
imgBodyPart.setContentID('<'+"i01#example.com"+'>');
imgBodyPart.setDisposition(MimeBodyPart.INLINE);
imgBodyPart.setHeader("Content-Type", "image/png");
multipart.addBodyPart(imgBodyPart);
You need not in-line & base encode - you can attach traditionally and add the link to the main message's text which is of type text/html.
However remember to set the imgBodyPart's header's Content-Type to image/jpg or so right before appending to the main message (after you have attached the file).

Related

Inline image shown as attachment : JavaMail

I am trying to send an email with an inline image, but the image is getting send as an attachment instead of inline.
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
String filename = "logo.jpeg";
mimeMessage.setFrom(new InternetAddress("Bridge"));
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
mimeMessage.setSubject(subject);
MimeMultipart multipart = new MimeMultipart();
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(content, "text/html");
multipart.addBodyPart(messageBodyPart);
messageBodyPart = new MimeBodyPart();
DataSource fds = new ByteArrayDataSource(IOUtils.toByteArray(resourceFile.getInputStream()), MediaType.IMAGE_JPEG_VALUE);
messageBodyPart.setDataHandler(new DataHandler(fds));
messageBodyPart.setDisposition(MimeBodyPart.INLINE);
messageBodyPart.setFileName(filename);
messageBodyPart.setHeader("Content-ID", "<logoimg>");
messageBodyPart.setHeader("Content-Type", MediaType.IMAGE_JPEG_VALUE);
multipart.addBodyPart(messageBodyPart);
mimeMessage.setContent(multipart);
mimeMessage.saveChanges();
javaMailSender.send(mimeMessage);
} catch (MailException | MessagingException | IOException e) {
log.warn("Email could not be sent to user '{}'", to, e);
}
And here is my HTML code for the image:
<img width="100" height="50" src="|cid:logoimg|" alt="phoenixlogo"/>
I have tried all the multipart types: "mixed", "relative", "alternative" but couldn't get it to work.
Here is image for same:
You don't want an inline image, you want an html body that references an attached image. For that you need a multipart/related message. See the JavaMail FAQ.
You need to add a separate MimeBodyPart: For Example
BodyPart imgPart = new MimeBodyPart();
DataSource ds = new FileDataSource("D:/image.jpg");
imgPart.setDataHandler(new DataHandler(ds));
imgPart.setHeader("Content-ID", "<the-img-1>");
multipart.addBodyPart(imgPart);
Then in the html you refer to the Image as:
<br>" + "<img src=\"cid:the-img-1\"/><br/>

Outlook can't show image into MimeMessage

I prepare my message as MimeMessage and try it open in different mail clients. In all client my message looks good but in Outlook and in another one, it looks wrong
...
MimeMessage mimeMessage = new MimeMessage(session);
// Text version
final MimeBodyPart textPart = new MimeBodyPart();
textPart.setContent(email.getPlainMessage(), "text/plain");
// HTML version
final MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(email.getMessage(), "text/html");
//logo
PreencodedMimeBodyPart logo = new PreencodedMimeBodyPart(BASE_64_ENCODING);
logo.setHeader("Content-Type", IMAGE_PNG_CONTENT_TYPE + "; name=\"logo.png\"");
logo.setHeader("Content-ID", "<logo.png#01CFFF81.C72F8000>");
logo.setHeader("Content-Disposition", "inline; filename=\"logo.png\"");
logo.setHeader("Content-Transfer-Encoding", BASE_64_ENCODING);
logo.setContent(ENCODED_LOGO, IMAGE_PNG_CONTENT_TYPE);
// Create the Multipart. Add BodyParts to it.
final Multipart mp = new MimeMultipart("alternative");
mp.addBodyPart(logo);
mp.addBodyPart(textPart);
mp.addBodyPart(htmlPart);
if (Objects.nonNull(email.getFilesToAttach())) {
for (String filename : email.getFilesToAttach()) {
MimeBodyPart messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename.substring(filename.lastIndexOf(File.separator) + 1));
mp.addBodyPart(messageBodyPart);
}
}
// Set Multipart as the message's content
mimeMessage.setContent(mp);
mimeMessage.setSubject(email.getSubject());
mimeMessage.setFrom(new InternetAddress(emailConfig.getNoReplyEmailAddress()));
if (!emailConfig.getNoReplyEmailAddress().equals(email.getFromAddress())) {
List<Address> replyTo = Arrays.asList(new InternetAddress(email.getFromAddress()));
mimeMessage.setReplyTo(replyTo.toArray(new Address[replyTo.size()]));
}
mimeMessage.addRecipient(MimeMessage.RecipientType.TO, new InternetAddress(email.getToAddress()));
mimeMessage.saveChanges();
...
And when I send it in outlook I see my logo as
but in another mail clients it looks good

Javamail doesn't send email with larger attachments

I want to send an email using Javamail with 2 attachments. One of them is a json file, and the other one is a txt file (logcat.txt). The logcat.txt is about 1mb in size.
It doesn't send any email if I have the addAttachment(multipart,reportPath,"logcat.txt"); in my code. If I remove addAttachment(multipart,reportPath,"logcat.txt"); it works.
When the json file gets larger, at one point about 500kb, it doesn't send either.
My code:
public synchronized void sendReport(String subject, String body, String filepath, String filename, String reportPath, String sender, String recipients){
try {
Multipart multipart = new MimeMultipart("mixed"); //try adding "mixed" here as well but it doesn't work
MimeMessage message = new MimeMessage(session);
message.setSender(new InternetAddress(sender));
message.setSubject(subject);
//body
BodyPart messageBodyPart2 = new MimeBodyPart();
messageBodyPart2.setText(body);
Log.d(TAG, "sendReport: " + reportPath);
//this prints sendReport: /storage/emulated/0/Android/data/**app package name**/files/LOG-1472631395.json
Log.d(TAG, "sendReport: " + filepath);
//sendReport: /storage/emulated/0/Android/data/**app package name**/files/logcat.txt
addAttachment(multipart,filepath,filename);
addAttachment(multipart,reportPath,"logcat.txt");
multipart.addBodyPart(messageBodyPart2);
message.setContent(multipart);
if (recipients.indexOf(',') > 0)
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients));
else
message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients));
Transport.send(message);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void addAttachment(Multipart multipart, String filepath, String filename) throws MessagingException
{
DataSource source = new FileDataSource(filepath);
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
}
I also use another method to send attachments but it doesn't work either:
private static void addAttachment(Multipart multipart, String filepath, String filename) throws Exception
{
MimeBodyPart mimeBodyPart = new MimeBodyPart();
mimeBodyPart.attachFile(filepath);
mimeBodyPart.setFileName(filename);
multipart.addBodyPart(mimeBodyPart);
}
Does anyone have an idea how to fix this? Thank you in advance.
//In this list set the path from the different files you want to attach
String[] attachments;
Multipart multipart = new MimeMultipart();
//Add attachments
if(attachments != null && attachments.length > 0) {
for (String str : attachments) {
MimeBodyPart messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(str);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(source.getName());
multipart.addBodyPart(messageBodyPart);
}
}
message.setContent(multipart);
I don't have problems uploading huge files, you can try this code.
I used a private mail server of my customer to send emails, and it doesn't show any errors that I can see (because it is a public mail server). I then use Google Mail server, and this is a reply from gmail server to my email account:
Technical details of permanent failure: Google tried to deliver your
message, but it was rejected by the server for the recipient domain
mailinator.com by mail2.mailinator.com. [45.79.147.26].
The error that the other server returned was: 552 5.3.4 Message size
exceeds fixed limit
So this is because the domain mailinator.com has some message size limit so it doesn't appear. I then send things to a gmail email account and it works.

How to attach multiple files to an email using JavaMail?

The following Java code is used to attach a file to an email. I want to send multiple files attachments through email. Any suggestions would be appreciated.
public class SendMail {
public SendMail() throws MessagingException {
String host = "smtp.gmail.com";
String Password = "mnmnn";
String from = "xyz#gmail.com";
String toAddress = "abc#gmail.com";
String filename = "C:/Users/hp/Desktop/Write.txt";
// Get system properties
Properties props = System.getProperties();
props.put("mail.smtp.host", host);
props.put("mail.smtps.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
Session session = Session.getInstance(props, null);
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO, toAddress);
message.setSubject("JavaMail Attachment");
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText("Here's the file");
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);
try {
Transport tr = session.getTransport("smtps");
tr.connect(host, from, Password);
tr.sendMessage(message, message.getAllRecipients());
System.out.println("Mail Sent Successfully");
tr.close();
} catch (SendFailedException sfe) {
System.out.println(sfe);
}
}
}`
Well, it's been a while since I've done JavaMail work, but it looks like you could just repeat this code multiple times:
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
For example, you could write a method to do it:
private static void addAttachment(Multipart multipart, String filename)
{
DataSource source = new FileDataSource(filename);
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
}
Then from your main code, just call:
addAttachment(multipart, "file1.txt");
addAttachment(multipart, "file2.txt");
etc
UPDATE (March 2020)
With the latest JavaMail™ API (version 1.6 at the moment, JSR 919), things are much simpler:
void attachFile(File file)
void attachFile(File file, String contentType, String encoding)
void attachFile(String file)
void attachFile(String file, String contentType, String encoding)
Useful reading
Here is a nice and to the point tutorial with the complete example:
JavaMail - How to send e-mail with attachments
Multipart mp = new MimeMultipart();
MimeBodyPart mbp1 = new MimeBodyPart();
mbp1.setContent(body,"text/html");
mp.addBodyPart(mbp1);
if(filename!=null)
{
MimeBodyPart mbp2 = null;
FileDataSource fds =null;
for(int counter=0;counter<filename.length;counter++)
{
mbp2 = null;
fds =null;
mbp2=new MimeBodyPart();
fds = new FileDataSource(filename[counter]);
mbp2.setDataHandler(new DataHandler(fds));
mbp2.setFileName(fds.getName());
mp.addBodyPart(mbp2);
}
}
msg.setContent(mp);
msg.setSentDate(new Date());
Transport.send(msg);
just add another block with using the filename of the second file you want to attach and insert it before the message.setContent(multipart) command
messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
Have Array list al which has the list of attachments you need to mail and use the below given code
for(int i=0;i<al.size();i++)
{
System.out.println(al.get(i));
messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource((String)al.get(i));
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName((String)al.get(i));
multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);
}
File f = new File(filepath);
File[] attachments = f.listFiles();
// Part two is attachment
for( int i = 0; i < attachments.length; i++ ) {
if (attachments[i].isFile() && attachments[i].getName().startsWith("error")) {
messageBodyPart = new MimeBodyPart();
FileDataSource fileDataSource =new FileDataSource(attachments[i]);
messageBodyPart.setDataHandler(new DataHandler(fileDataSource));
messageBodyPart.setFileName(attachments[i].getName());
messageBodyPart.setContentID("<ARTHOS>");
messageBodyPart.setDisposition(MimeBodyPart.INLINE);
multipart.addBodyPart(messageBodyPart);
}
}
for (String fileName: files) {
MimeBodyPart messageAttachmentPart = new MimeBodyPart();
messageAttachmentPart.attachFile(fileName);
multipart.addBodyPart(messageAttachmentPart);
}
You have to make sure that you are creating a new mimeBodyPart for each attachment. The object is being passed by reference so if you only do :
MimeBodyPart messageAttachmentPart = new MimeBodyPart();
for (String fileName: files) {
messageAttachmentPart.attachFile(fileName);
multipart.addBodyPart(messageAttachmentPart);
}
it will attach the same file X number of times
#informatik01 posted an answer above with the link to the documentation where there is an example of this
Just add more files to the multipart.
This is woking 100% with Spring 4+. You will have to enable less secure option on your gmail account. Also you will need the apache commons package:
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
#GetMapping("/some-mapping")
public void mailMethod(#RequestParam CommonsMultipartFile attachFile, #RequestParam CommonsMultipartFile attachFile2) {
Properties mailProperties = new Properties();
mailProperties.put("mail.smtp.auth", true);
mailProperties.put("mail.smtp.starttls.enable", true);
mailProperties.put("mail.smtp.ssl.enable", true);
mailProperties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
mailProperties.put("mail.smtp.socketFactory.fallback", false);
JavaMailSenderImpl javaMailSenderImpl = new JavaMailSenderImpl();
javaMailSenderImpl.setJavaMailProperties(mailProperties);
javaMailSenderImpl.setHost("smtp.gmail.com");
javaMailSenderImpl.setPort(465);
javaMailSenderImpl.setProtocol("smtp");
javaMailSenderImpl.setUsername("*********#gmail.com");
javaMailSenderImpl.setPassword("*******");
javaMailSenderImpl.setDefaultEncoding("UTF-8");
List<CommonsMultipartFile> attachments = new ArrayList<>();
attachments.add(attachFile);
attachments.add(attachFile2);
javaMailSenderImpl.send(mimeMessage -> {
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
messageHelper.setTo(emailTo);
messageHelper.setSubject(subject);
messageHelper.setText(message);
if (!attachments.equals("")) {
for (CommonsMultipartFile file : attachments) {
messageHelper.addAttachment(file.getOriginalFilename(), file);
}
}
});
}
Multipart multipart = new MimeMultipart("mixed");
for (int alen = 0; attlen < attachments.length; attlen++)
{
MimeBodyPart messageAttachment = new MimeBodyPart();
fileName = ""+ attachments[attlen];
messageAttachment.attachFile(fileName);
messageAttachment.setFileName(attachment);
multipart.addBodyPart(messageAttachment);
}
After Java Mail 1.3 attaching file more simpler,
Just use MimeBodyPart methods to attach file directly or from a filepath.
MimeBodyPart messageBodyPart = new MimeBodyPart();
//messageBodyPart.attachFile(String filePath);
messageBodyPart.attachFile(File file);
multipart.addBodyPart(messageBodyPart);
Try this to read the file name from array
MimeBodyPart messageBodyPart = new MimeBodyPart();
Multipart multipart = new MimeMultipart();
for(int i = 0 ; i < FilePath.length ; i++){
info("Attching the file + "+ FilePath[i]);
messageBodyPart.attachFile(FilePath[i]);
multipart.addBodyPart(messageBodyPart);
}
message.setContent(multipart);
I do have a better alternative for sending Multiple files in a single mail off course. Mutipart class allows us to attain this feature quite easily. If you may not have any info about it then read it from here : https://docs.oracle.com/javaee/6/api/javax/mail/Multipart.html
The Multipart class provides us two same-name methods with different parameters off course, i.e. addBodyPart(BodyPart part) and addBodyPart(BodyPart part, int index). For 1 single file we may use the first method and for mutiple files we may use the second method (which takes two parameters).
MimeMessage message = new MimeMessage(session);
Multipart multipart = new MimeMultipart();
message.setFrom(new InternetAddress(username));
for (String email : toEmails) {
message.addRecipient(Message.RecipientType.BCC, new InternetAddress(email));
}
message.setSubject(subject);
BodyPart messageBodyPart1 = new MimeBodyPart();
messageBodyPart1.setText(typedMessage);
multipart.addBodyPart(messageBodyPart1, i);
i = i + 1;
for (String filename : attachedFiles) {
MimeBodyPart messageBodyPart2 = new MimeBodyPart();
messageBodyPart2.attachFile(filename);
multipart.addBodyPart(messageBodyPart2, i);
i = i + 1;
}
message.setContent(multipart);
Transport.send(message);
Below is working for me:
List<String> attachments = new ArrayList<>();
attachments.add("C:/Users/dell/Desktop/file1.txt");
attachments.add("C:/Users/dell/Desktop/file2.txt");
attachments.add("C:/Users/dell/Desktop/file3.txt");
attachments.add("C:/Users/dell/Desktop/file4.txt");
attachments.add("C:/Users/dell/Desktop/file5.txt");
MimeMessage msg = new MimeMessage(session);
if (attachments !=null && !attachments.isEmpty() ) {
MimeBodyPart attachmentPart = null;
Multipart multipart = new MimeMultipart();
for(String attachment : attachments) {
attachmentPart = new MimeBodyPart();
attachmentPart.attachFile(new File(attachment));
multipart.addBodyPart(attachmentPart);
}
multipart.addBodyPart(textBodyPart);
msg.setContent(multipart);
}
Transport.send(msg);

How to attach an object in an email with Java?

I have the following method to send an email, but I couldn't get the attached object, why ?
void Send_Email(String From,String To,String Subject,Text Message_Text,Contact_Info_Entry An_Info_Entry)
{
Properties props=new Properties();
Session session=Session.getDefaultInstance(props,null);
String htmlBody="<Html>Hi</Html>";
byte[] attachmentData;
Multipart multipart=new MimeMultipart();
BASE64Encoder BASE64_Encoder=new BASE64Encoder();
try
{
Message message=new MimeMessage(session);
message.setFrom(new InternetAddress(From,"NM-Java Admin"));
message.addRecipient(Message.RecipientType.TO,new InternetAddress(To,"Ni , Min"));
// You may need to encode the subject with this special method !
// message.setSubject(javax.mail.internet.MimeUtility.encodeText("Testing javamail with french : ��� "));
message.setSentDate(new Date());
message.setSubject(Subject);
MimeBodyPart messageBodyPart=new MimeBodyPart(); // Create the message part
messageBodyPart.setText(Message_Text.getValue()); // Fill message
multipart.addBodyPart(messageBodyPart);
MimeBodyPart htmlPart=new MimeBodyPart();
htmlPart.setContent(htmlBody,"text/html");
multipart.addBodyPart(htmlPart);
//setHTMLContent(message);
ByteArrayOutputStream bStream=new ByteArrayOutputStream();
ObjectOutputStream oStream=new ObjectOutputStream(bStream);
oStream.writeObject(An_Info_Entry);
// attachmentData=bStream.toByteArray();
// attachmentData=BASE64_Encoder.encode(bStream.toByteArray());
MimeBodyPart attachment=new MimeBodyPart();
attachment.setFileName(An_Info_Entry.Contact_Id);
attachment.setContent(BASE64_Encoder.encode(bStream.toByteArray()),"application/x-java-serialized-object");
multipart.addBodyPart(attachment);
setBinaryContent(message,BASE64_Encoder.encode(bStream.toByteArray()).getBytes());
message.setContent(multipart); // Put parts in message
message.setText(Message_Text.getValue()+" [ An_Info_Entry.Contact_Id = "+An_Info_Entry.Contact_Id+" ]");
Transport.send(message);
}
catch (Exception ex)
{
// ...
}
}
Probably because:
You're setting your content type as: text/html and you're really sending raw binary.
MimeBodyPart attachment=new MimeBodyPart();
attachment.setFileName(An_Info_Entry.Contact_Id);
attachment.setContent(attachmentData,"text/html"); // <-- Here
multipart.addBodyPart(attachment);
Even if you use the right content-type, you should encode the content as using base64 that way the attachment could make it trough the net.
// This
//attachmentData=bStream.toByteArray();
// should be something like:
attachmentData=Base64Coder.encode( bStream.toByteArray());

Categories