Imágenes en línea en el correo electrónico usando JavaMail

Deseo enviar un correo electrónico con una imagen en línea usando javamail.

Estoy haciendo algo como esto

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", ""); bodyPart.setHeader("Content-Disposition", "inline"); content.addBodyPart(bodyPart); msg.setContent(content); 

También intenté

  bodyPart.setHeader("inline; filename=image.jpg"); 

y

  bodyPart.setDisposition("inline"); 

pero pase lo que pase, la imagen se envía como un archivo adjunto y la eliminación de contenido se está convirtiendo en “archivo adjunto”.

¿Cómo envío una imagen en línea en el correo electrónico usando javamail?

Tu problema

Por lo que puedo ver, parece que la forma en que creas el mensaje y todo está en lo cierto. Utiliza los tipos MIME correctos y todo.

No estoy seguro de por qué usa un DataSource y un DataHandler, y tengo un ContentID en la imagen, pero debe completar su pregunta para poder solucionar más problemas. Especialmente, la siguiente línea:

 bodyPart.setContent(message, "text/html; charset=ISO-8859-1"); 

¿Qué hay en el message ? ¿Contiene ?

¿Intentó generar ContentID con String cid = ContentIdGenerator.getContentId(); en lugar de usar la image


Fuente

Este artículo de blog me enseñó cómo usar el tipo de mensaje correcto, adjuntar mi imagen y consultar el archivo adjunto del cuerpo HTML: Cómo enviar correo electrónico con imágenes incrustadas utilizando Java


Detalles

Mensaje

Tienes que crear tu contenido usando la clase MimeMultipart . Es importante usar la cadena "related" como un parámetro para el constructor, decirle a JavaMail que sus partes están “trabajando juntas” .

 MimeMultipart content = new MimeMultipart("related"); 

Identificador de contenido

Necesita generar un ID de contenido, es una cadena utilizada para identificar la imagen que adjuntó a su correo electrónico y referirse a ella desde el cuerpo del correo electrónico.

 String cid = ContentIdGenerator.getContentId(); 

Nota: Esta clase ContentIdGenerator es hipotética. Puede crear uno o en línea la creación de ID de contenido. En mi caso, utilizo un método simple:

 import java.util.UUID; // ... String generateContentId(String prefix) { return String.format("%s-%s", prefix, UUID.randomUUID()); } 

Cuerpo HTML

El código HTML es una parte del contenido de MimeMultipart . Usa la clase MimeBodyPart para eso. ¡No olvide especificar la encoding y "html" cuando configure el texto de esa parte!

 MimeBodyPart htmlPart = new MimeBodyPart(); htmlPart.setText("" + "" + " " + " 

Here is my image:

" + " " + " " + "" ,"US-ASCII", "html"); content.addBodyPart(htmlPart);

Tenga en cuenta que, como fuente de la imagen, usamos cid: y ContentID generado.

Imagen adjunta

Podemos crear otro MimeBodyPart para el archivo adjunto de la imagen.

 MimeBodyPart imagePart = new MimeBodyPart(); imagePart.attachFile("resources/teapot.jpg"); imagePart.setContentID("<" + cid + ">"); imagePart.setDisposition(MimeBodyPart.INLINE); content.addBodyPart(imagePart); 

Tenga en cuenta que usamos el mismo ContentID entre < y > y lo configuramos como el ContentID de la imagen. También configuramos la disposición en INLINE para indicar que esta imagen debe mostrarse en el correo electrónico, no como un archivo adjunto.

Terminar mensaje

¡Eso es! Si crea un mensaje SMTP en la sesión correcta y utiliza ese contenido, ¡su correo electrónico contendrá una imagen incrustada! Por ejemplo:

 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) 

¡Hazme saber si eso funciona para ti! 😉

¿Por qué no intentas algo como esto?

  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 https://stackoverflow.com/questions/2996514/inline-images-in-email-using-javamail/image.jpg")); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName(fileAttachment.getName()); messageBodyPart.setDisposition(MimeBodyPart.INLINE); multipart.addBodyPart(messageBodyPart); mail.setContent(multipart); 

en el mensaje, tenga una y debería estar bien.

Buena suerte

Esto funcionó para mí:

  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("http://sofes.miximages.com/java/image.jpg"); return imagePart; 

Si está usando Spring, use MimeMessageHelper para enviar correos electrónicos con contenido en línea ( Referencias ).

Cree el bean JavaMailSender o configúrelo agregando las propiedades correspondientes al archivo application.properties, si está utilizando 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; } 

Crear algoritmo para generar CONTENT-ID único

 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; } } 

Enviar correo electrónico con en línea.

 @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, 

This is test with email inlines.

"; 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()); } }

Use el siguiente fragmento:

 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); 

No necesita la encoding en línea y la base: puede adjuntar tradicionalmente y agregar el enlace al texto del mensaje principal que es de tipo text/html .
Sin embargo, recuerde configurar el imgBodyPart de Content-Type del encabezado de imgBodyPart en image/jpg o más o menos justo antes de anexar el mensaje principal (después de haber adjuntado el archivo).

A continuación está el código completo

  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="" 

messageBodyPart.setContent (htmlText, “text / html”); multipart.addBodyPart (messageBodyPart);

  messageBodyPart = new MimeBodyPart(); DataSource fds = new FileDataSource("resources/Images/bday.jpg"); messageBodyPart.setDataHandler(new DataHandler(fds)); messageBodyPart.setHeader("Content-ID", ""); // add image to the multipart multipart.addBodyPart(messageBodyPart); msg.setContent(multipart); Transport.send(msg);