邮件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("&", "&amp;");
            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("&amp;", "&");
        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();
                }
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值