Je souhaite envoyer un e-mail avec une image en ligne à l'aide de javamail.
Je fais quelque chose comme ça.
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);
J'ai aussi essayé
bodyPart.setHeader("inline; filename=image.jpg");
et
bodyPart.setDisposition("inline");
mais quoi qu'il en soit, l'image est envoyée en pièce jointe et le Content-Dispostion se transforme en "pièce jointe".
Comment envoyer une image en ligne dans l'e-mail à l'aide de javamail?
Pour autant que je puisse voir, cela ressemble à la façon dont vous créez le message et tout va bien! Vous utilisez les bons types MIME et tout.
Je ne sais pas pourquoi vous utilisez un DataSource et DataHandler, et avez un ContentID sur l'image, mais vous devez répondre à votre question pour que je puisse résoudre plus. Surtout, la ligne suivante:
bodyPart.setContent(message, "text/html; charset=ISO-8859-1");
Que contient message
? Contient-il <img src="cid:image" />
?
Avez-vous essayé de générer le ContentID avec String cid = ContentIdGenerator.getContentId();
au lieu d'utiliser image
Cet article de blog m'a appris à utiliser le bon type de message, à joindre mon image et à se référer à la pièce jointe du corps HTML: Comment envoyer un e-mail avec des images intégrées à l'aide de Java
Vous devez créer votre contenu en utilisant la classe MimeMultipart
. Il est important d'utiliser la chaîne "related"
Comme paramètre pour le constructeur, pour indiquer à JavaMail que vos pièces "fonctionnent ensemble" .
MimeMultipart content = new MimeMultipart("related");
Vous devez générer un ContentID, c'est une chaîne utilisée pour identifier l'image que vous avez jointe à votre e-mail et vous y référer depuis le corps de l'e-mail.
String cid = ContentIdGenerator.getContentId();
Remarque: Cette classe ContentIdGenerator
est hypothétique. Vous pouvez en créer un ou incorporer la création d'ID de contenu. Dans mon cas, j'utilise une méthode simple:
import Java.util.UUID;
// ...
String generateContentId(String prefix) {
return String.format("%s-%s", prefix, UUID.randomUUID());
}
Le code HTML est une partie du contenu MimeMultipart
. Utilisez la classe MimeBodyPart
pour cela. N'oubliez pas de spécifier les encoding
et "html"
Lorsque vous définissez le texte de cette partie!
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);
Notez que comme source de l'image, nous utilisons cid:
Et le ContentID généré.
Nous pouvons en créer un autre MimeBodyPart
pour l'attachement de l'image.
MimeBodyPart imagePart = new MimeBodyPart();
imagePart.attachFile("resources/teapot.jpg");
imagePart.setContentID("<" + cid + ">");
imagePart.setDisposition(MimeBodyPart.INLINE);
content.addBodyPart(imagePart);
Notez que nous utilisons le même ContentID entre <
Et >
Et le définissons comme ContentID de l'image. Nous avons également défini la disposition sur INLINE
pour signaler que cette image est destinée à être affichée dans l'e-mail, et non en tant que pièce jointe.
C'est ça! Si vous créez un message SMTP sur la bonne session et utilisez ce contenu, votre e-mail contiendra une image intégrée! Par exemple:
SMTPMessage m = new SMTPMessage(session);
m.setContent(content);
m.setSubject("Mail with embedded image");
m.setRecipient(RecipientType.TO, new InternetAddress("[email protected]"));
Transport.send(m)
Laissez-moi savoir si cela fonctionne pour vous! ;)
Cela a fonctionné pour moi:
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;
Pourquoi n'essayez-vous pas quelque chose comme ça?
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);
dans le message, ayez un <img src="image.jpg"/>
tag et ça devrait aller.
Bonne chance
Si vous utilisez Spring utilisez MimeMessageHelper
pour envoyer des e-mails avec un contenu en ligne ( Références ).
Créez JavaMailSender bean ou configurez-le en ajoutant les propriétés correspondantes au fichier application.properties, si vous utilisez 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;
}
Créer un algorithme pour générer un ID DE CONTENU unique
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;
}
}
Envoyer un e-mail avec des inscriptions.
@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("[email protected]");
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());
}
}
La spécification RFC peut être trouvée ici ( https://tools.ietf.org/html/rfc2392 ).
Tout d'abord, le contenu HTML des e-mails doit être formaté comme: "cid: logo.png" lors de l'utilisation d'images en ligne, voir:
<td style="width:114px;padding-top: 19px">
<img src="cid:logo.png" />
</td>
Deuxièmement, l'objet MimeBodyPart doit définir la propriété "disposition" comme MimeBodyPart.INLINE, comme ci-dessous:
String filename = "logo.png"
BodyPart image = new MimeBodyPart();
image.setDisposition(MimeBodyPart.INLINE);
image.setFileName(filename);
image.setHeader("Content-ID", "<" +filename+">");
Attention, la propriété Content-ID doit préfixer et suffixer avec "<" et ">" en perspective, et la valeur du nom de fichier doit être identique avec le contenu de src de la balise img sans préfixe "cid : "
Enfin, tout le code est ci-dessous:
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("[email protected]");
InternetAddress[] recipients = { "[email protected]"};
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();
J'ai eu quelques problèmes d'affichage d'images en ligne dans GMail et Thunderbird, j'ai fait quelques tests et résolu avec le code (exemple) suivant:
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);
Quelques choses à noter:
Cela a fonctionné pour moi en créant des images en ligne pour certains clients et dans le client Web GMail, je ne veux pas dire que cela fonctionnera partout et pour toujours! :)
(Désolé pour mon anglais et pour mes fautes de frappe!)
Voici le code complet
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\"/>"
Utilisez l'extrait de code suivant:
MimeBodyPart imgBodyPart = new MimeBodyPart();
imgBodyPart.attachFile("Image.png");
imgBodyPart.setContentID('<'+"[email protected]"+'>');
imgBodyPart.setDisposition(MimeBodyPart.INLINE);
imgBodyPart.setHeader("Content-Type", "image/png");
multipart.addBodyPart(imgBodyPart);
Vous n'avez pas besoin d'encoder en ligne et en base - vous pouvez joindre traditionnellement et ajouter le lien vers le texte du message principal qui est de type text/html
.
Cependant, n'oubliez pas de définir l'en-tête de imgBodyPart
Content-Type
à image/jpg
ou à peu près avant d'ajouter au message principal (après avoir joint le fichier).