邮件html中图片发送
直接使用图片的局域网地址(此方案不可行)
1.直接使用图片的局域网内的地址,比如图片url地址为本地地址,则只有在本机上打开收到的邮件时才会显示图片,在其他机器上打开邮件发现图片不显示
解决方案:
1.为图片存储的环境映射外网地址
2.使用javamail提供的cid方式进行图片发送(可行)
使用javamail中cid方式发送html中的图片
package com.montnets.test;
import com.montnets.email.specmailgate.constant.EmailGateConstant;
import com.montnets.email.specmailgate.service.MyAuthenticator;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import javax.activation.DataHandler;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
/**
* @Author: chenlinyan
* @Date: 2019/7/8 16:40
* @Version 1.0
*/
@Slf4j
public class TestEmail {
/**
* 创建一封邮件的实例对象
*
* @param session
* @param theme 邮件主题
* @param content 邮件内容
* @param sendAccount 发送账号
* @param receiver 接收者账号
* @return
* @throws Exception
*/
public MimeMessage getMimeMessage(Session session, String theme, String content, String sendAccount, String receiver) throws Exception {
//创建一封邮件的实例对象
MimeMessage msg = new MimeMessage(session);
//设置发件人地址
msg.setFrom(new InternetAddress(sendAccount));
//单个目标收件人
msg.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiver));
//设置邮件主题
msg.setSubject(theme);
MimeMultipart multipart = new MimeMultipart();
//处理邮件内容
Document document = getHtmlDocument(content);
if (document != null) {
Set<String> imgPaths = getImgs(document);
setImageMultipart(multipart, imgPaths);
content = getHtmlContent(document);
}
//设置邮件正文
MimeBodyPart text = new MimeBodyPart();
text.setContent(content, "text/html;charset=UTF-8");
multipart.addBodyPart(text);
multipart.setSubType("related");
msg.setSentDate(new Date());
msg.setContent(multipart);
msg.saveChanges();
return msg;
}
public Document getHtmlDocument(String html) {
try {
//有些图片链接带有&符号
String content = html.replace("&", "&");
return DocumentHelper.parseText(content);
} catch (Exception e) {
log.warn("邮件html内容不符合xml格式,邮件内容为{}", html, e);
return null;
}
}
public String getHtmlContent(Document document) {
String content = document.asXML().replace("&", "&");
log.info("邮件发送内容为:{}", content);
return content;
}
/**
* 获取图片资源地址
*
* @param document
* @return
*/
public Set<String> getImgs(Document document) {
Set<String> sets = new HashSet<>();
String imgPath = null;
try {
List<Element> elements = document.selectNodes("//img");
for (Element element : elements) {
imgPath = element.attributeValue("src");
if (imgPath != null) {
element.addAttribute("src", "cid:" + imgPath);
sets.add(imgPath);
}
}
} catch (Exception e) {
log.error("获取html中img标签内图片路径异常,html内容为{}", document.asXML(), e);
}
return sets;
}
/**
* 设置图片cid至MimeMultipart中
*
* @param multipart
* @param imgPaths
*/
public void setImageMultipart(MimeMultipart multipart, Set<String> imgPaths) {
if (imgPaths == null || imgPaths.isEmpty()) {
return;
}
MimeBodyPart image = null;
URL url;
for (String imgPath : imgPaths) {
try {
url = new URL(imgPath);
//判断图片地址资源是否可访问
if (isConnect(url)) {
image = new MimeBodyPart();
DataHandler dh = new DataHandler(url);
image.setDataHandler(dh);
image.setContentID(imgPath);
multipart.addBodyPart(image);
} else {
log.warn("{}资源地址无效", imgPath);
}
} catch (Exception e) {
log.error("邮件图片发送,设置图片cid异常,异常图片为{}", imgPath, e);
}
}
}
/**
* 功能:检测当前URL是否可连接或是否有效,
* 描述:最多连接网络 n 次, 如果 n 次都不成功,视为该地址不可用
*
* @param url 指定URL网络地址
* @return boolean
*/
public synchronized static boolean isConnect(URL url) {
HttpURLConnection con;
int state = -1;
int counts = 0;
if (url == null) {
return false;
}
while (counts < EmailGateConstant.CONN_TIMES) {
try {
con = (HttpURLConnection) url.openConnection();
//连接超时时间
con.setConnectTimeout(3000);
state = con.getResponseCode();
if (state == 200) {
return true;
}
break;
} catch (Exception ex) {
counts++;
continue;
}
}
return false;
}
/**
*方法入口,测试
*/
public static void main(String[] args) {
String host = "smtp.qq.com";
String sendAccount = "xxxx@qq.com";
String receiver = "xxxx@qq.com";
String pwd = "123456";
String theme = "发送图片";
String content = "<p>图片测试<img src=\"http://192.169.1.101:8080/WebTest/file/qq.PNG\"/></p>";
Properties props = new Properties();
//设置用户的认证方式
props.setProperty("mail.smtp.auth", "true");
//设置传输协议
props.setProperty("mail.transport.protocol", "smtp");
//设置发件人的SMTP服务器地址
props.setProperty("mail.smtp.host", host);
props.setProperty("mail.smtp.port", "25");
//连接超时时间
props.put("mail.smtp.connectiontimeout", 30000);
//读超时时间
props.put("mail.smtp.timeout", 30000);
//写超时时间
props.put("mail.smtp.writetimeout", 30000);
Transport transport = null;
try {
//1、创建定义整个应用程序所需的环境信息的 Session 对象
Session session = Session.getInstance(props, new MyAuthenticator(sendAccount, pwd));
//设置调试信息在控制台打印出来
session.setDebug(true);
//根据session对象获取邮件传输对象Transport
transport = session.getTransport();
// //添加监听器
// transport.addTransportListener(mailListener);
//与服务器建立连接
transport.connect();
Message message = new TestEmail().getMimeMessage(session, theme,content,sendAccount,receiver);
//发送邮件
transport.sendMessage(message, message.getAllRecipients());
} catch (Exception e) {
e.printStackTrace();
}finally {
if(transport != null){
try {
transport.close();
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
}
}