I am creating an attachment to MimeMessage for a Tiff image with a byte array.
ByteArrayOutputStream out = new ByteArrayOutputStream();
MimeBodyPart body = new MimeBodyPart();
body.setContent(tiffByteArray, "image/tiff");
body.setDisposition("attachment");
body.setFileName(filename);
MimeMultipart multipart = new MimeMultipart();
multipart.addBodyPart(body);
MimeMessage message = new MimeMessage(Session.getDefaultInstance(System.getProperties()));
message.setContent(multipart);
message.writeTo(out);
String mimeContent = out.toString();
This normally works. The image is converted to a base64 string in the message. However, at some point something on the system occurs and this piece of code starts using com.sun.xml.internal.messaging.saaj.soap.ImageDataContentHandler. This particular converted expects an java.awt.Image object as opposed to a byte array (relevant source). I get the following error:
Unable to encode the image to a stream ImageDataContentHandler requires Image object, was given object of type class [B
I can see that you can set the javax.activation.DataHandler on the javax.mail.internet.MimeMessage and in the DataHandler you can set the javax.activation.DataContentHandlerFactory, but I'm not sure what to set it to.
Is there a way to force a byte array to be converted to a base64 encoded String regardless of the mime type?
javax.mail provides a DataSource implementation for bytes that you can explicitly use.
ByteArrayDataSource dataSource = new ByteArrayDataSource(tiffByteArray, "image/tiff");
DataHandler byteDataHandler = new DataHandler(dataSource);
body.setDataHandler(byteDataHandler);
body.setDisposition("attachment");
body.setFileName(filename);
Related
I am trying to send inline image in a mail through java.I have byte array so I converted byte array to string using below function.
public static String getImgString(byte[] fileImg) throws IOException {
String imageString = new String(fileImg,"UTF-8");
return imageString;
}
I got an string and this string I verified through converter it displayed and image which I used.
Now I attached my image to body of mail with below code.
byte[] arr = getImageFileBytes(); // I got byte[] from this function
DataSource dataSourceImage = new ByteArrayDataSource(getImgString(arr),"image/png"");
MimeBodyPart imageBodyPart = new MimeBodyPart();
imageBodyPart.setDataHandler(new DataHandler(dataSourceImage));
I am receiving email as below.
I think there is some format I am missing in DataSource conversion or I need to add extra
data:image/png;base64 to image string??
What changes I need to do to get an image that I have in String.
Thanks in advance.
If your image data is actually in a file, you should use the attachFile method:
MimeBodyPart mbp = new MimeBodyPart();
mbp.attachFile("file.png", "image/png", "base64");
If you only have the image data in memory, you need to do something like this:
MimeBodyPart mbp = new MimeBodyPart();
ByteArrayDataSource bds = new ByteArrayDataSource(getImageFileBytes(), "image/png");
mbp.setContent(new DataHandler(bds));
Of course, if you're referencing this image from a separate html part, you'll want to make sure both are wrapped in a multipart/related part.
More information is in the JavaMail FAQ.
How can I send JsonNode as an email attachment in java.email as a json file
// Json node bit
JsonNode requestBody = request().body().asJson();
// Mail bit
messageBodyPart = new MimeBodyPart();
messageBodyPart.setDataHandler(new DataHandler( It should be passed here));
messageBodyPart.setFileName("file.json");
multipart.addBodyPart(messageBodyPart);
If you look at the DataHandler docs, it shows three constructors. One of them takes a DataSource. The javamail API has an implementation called ByteArrayDataSource
So, if you figure out how to serialize the JsonNode to a JSON String, you can do this:
String jsonStr = ...
new DataHandler(new ByteArrayDataSource(jsonStr.getBytes()));
Also, keep in mind that you should also set the MIME type of the attachment to applicatio/json.
I would like to send an email with the Java Mail API (javax.mail). The message must contain html and inside there is a reference to an image. There is a challenge, because no reference to a physical file on disk is allowed but instead I have created a base64 string (http://www.base64-image.de/step-1.php) for that image and copied that data to a static String variable.
With javax.mail I build a message of type MulitPart with two parts. The first part is the html itself and the second part is the image. The html part reference to the image via <img src="cid:image-id"/>.
Message msg = new MimeMessage(session);
Multipart multipart = new MimeMultipart("related");
BodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent("<html><body><h2>A title</h2>Some text in here<br/>" +
"<img src=\"cid:the-img-1\"/><br/> some more text<img src=\"cid:the-img-1\"/></body></html>", "text/html");
multipart.addBodyPart(htmlPart);
public static final String base64logo = "/9j/4AAQSkZJRgABAQEASABIAAD/4QBe…"; // ein ganz langer String erzeugt über http://www.base64-image.de/step-1.php
sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
byte[] imageByte = decoder.decodeBuffer(base64logo);
InternetHeaders header = new InternetHeaders();
BodyPart imgPart=new MimeBodyPart(header, imageByte);
imgPart.setHeader("Content-ID","the-img-1");
imgPart.setDisposition(MimeBodyPart.INLINE);
multipart.addBodyPart(imgPart);
msg.setContent(multipart);
Unfortunately the image is missing in the incoming email.
When I point to the file on my disk it is working:
DataSource ds=new FileDataSource("c:/temp/image001.jpg");
imgPart.setDataHandler(new DataHandler(ds));
We are developing with Talend and we cannot reference
to external files because that would make the deployment process
more complicate.
Can you find some wrong doings in my approach?
Kind regards
Hilderich
Try putting angle braces here
imgPart.setHeader("Content-ID","<the-img-1>");
I found this answer on the comments of an old post from this blog
http://www.jroller.com/eyallupu/entry/javamail_sending_embedded_image_in
In the comment of Aravind Velayudhan Nair
It worked for me!
This has been asked before a long time ago. But I will answer this as I have faced the same issue, from my own answer here.
byte[] tile = DatatypeConverter.parseBase64Binary(base64logo);
BodyPart messageBodyPart = new MimeBodyPart();
DataHandler dataHandler = new DataHandler(new ByteArrayDataSource(tile, "image/jpeg"));
messageBodyPart.setDataHandler(dataHandler);
messageBodyPart.setHeader("Content-ID", "<the-img-1>");
multipart.addBodyPart(messageBodyPart);
msg.setContent(multipart);
Hope it will help someone.
I'm trying to get the size of a MimeMessage.
The method getSize() simply always returns -1.
This is my code:
MimeMessage m = new MimeMessage(session);
m.setFrom(new InternetAddress(fromAddress, true));
m.setRecipient(RecipientType.TO, new InternetAddress(toAddress, true));
m.setSubject(subject);
MimeBodyPart bodyPart = new MimeBodyPart();
bodyPart.setContent(body, "text/html");
Multipart mp = new MimeMultipart();
mp.addBodyPart(bodyPart);
m.setContent(mp);
m.getSize(); // -1 is returned
THIS IS THE ANSWER TO MY QUESTION:
ByteArrayOutputStream os = new ByteArrayOutputStream();
m.writeTo(os);
int bytes = os.size();
A more efficient solution, but requiring an external library, is the following one:
public static long getReliableSize(MimeMessage m) throws IOException, MessagingException {
try (CountingOutputStream out = new CountingOutputStream(new NullOutputStream())) {
m.writeTo(out);
return out.getByteCount();
}
}
Both CountingOutputStream and NullOutputStream are available in Apache Common IO. That solution doesn't require to work with a temporary byte buffer (write, allocate, re-allocate, etc.)
Solution provided with Apache Commons is good, but NullOutputStream() constructor is now deprecated. Use the singleton instead:
CountingOutputStream out = new CountingOutputStream(NullOutputStream.NULL_OUTPUT_STREAM);
try calling mp.getSize() to see what it returns, MIMEMessage calls it on mp only.
Also From MIME message API
Return the size of the content of
this part in bytes. Return -1 if the
size cannot be determined.
As of now you have not passed any contents to the message,that could be the reason on -1 return value.
I want to send a Pdf as an e-mail attachment (I am using the JavaMail API ). I have the Pdf (generated by jasper) as an byte[].
public InputStream exportPdfToInputStream(User user) throws ParseErrorException, MethodInvocationException, ResourceNotFoundException, JRException, IOException{
JasperPrint jasperPrint = createJasperPrintObject(user);
byte[] pdfByteArray = JasperExportManager.exportReportToPdf(jasperPrint);
return new ByteArrayInputStream(pdfByteArray);
}
Here is the code that I am using to construct the MimeBodyPart that will be the attachment:
if (arrayInputStream != null && arrayInputStream instanceof ByteArrayInputStream) {
MimeBodyPart attachment = new MimeBodyPart(arrayInputStream);
attachment.setHeader("Content-Type", "application/pdf");
mimeMultipart.addBodyPart(attachment);
}
This code gives me this error:
javax.mail.MessagingException: IOException while sending message;
nested exception is:
java.io.IOException: Error in encoded stream: needed at least 2 valid base64 characters, but only got 1 before padding character (=), the 10 most recent characters were: "\24\163\193\n\185\194\216#\208="
I have found a solution as suggested in this thread. It seems that there is a DataSource class created just for this purpose. Hope this example will help others also.
if (arrayInputStream != null && arrayInputStream instanceof ByteArrayInputStream) {
// create the second message part with the attachment from a OutputStrean
MimeBodyPart attachment= new MimeBodyPart();
ByteArrayDataSource ds = new ByteArrayDataSource(arrayInputStream, "application/pdf");
attachment.setDataHandler(new DataHandler(ds));
attachment.setFileName("Report.pdf");
mimeMultipart.addBodyPart(attachment);
}
The constructor you used is for parsing a mime part from the transport.
Your second example should work out right. You may consider
not to convert to InputStream and back, this will make unnecessary copies
add a disposition ( e.g. bp.setDisposition(Part.ATTACHMENT); )