springboot发送邮件,包含附件、图片

需求:发送邮件,邮件携带附件,并需要将邮件正文中的图片链接替换;发送邮件前需提前检测邮件配置的连接性。

1、发送邮件的主方法

/**
 * 发送邮件主方法
 * @param outbox为发送邮件封装的对象,主要包括发送协议、收发人地址、密码等基本信息
 * @return
 */
public MailOutboxMsg sendEmail(MailOutboxMsg outbox) throws Exception{
    JavaMailSenderImpl javaMailSender = this.createMailSender(outbox);
    Properties props = this.initMailProp();
    javaMailSender.setJavaMailProperties(props);

    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
    mimeMessage.addHeader("uuid", "uuid");
    MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true,"UTF-8");
    helper.setSubject(outbox.getSubject());
    helper.setFrom(outbox.getSentEmail());
    //设置邮件接收人、抄送人、密送人,均为邮件地址数组
    helper.setTo(outbox.getToEmail().split(";"));
    helper.setCc(outbox.getCcEmail().split(";"));
    helper.setBcc(outbox.getBccEmail().split(";"));
    helper.setSentDate(new Date());

    //设置邮件内容,替换图片链接
    this.parseContent(helper, outbox.getContent());
    helper.setText(outbox.getContent(), true);

    //添加附件,此处文件服务器为fastdfs,可自行替换成其他获取文件流方法
    if(CollectionUtils.isNotEmpty(outbox.getAttaches())){
        for(MailAttachMsg attach : outbox.getAttaches()){
            String attachtUrl = attach.getAttachUrl();
            String relativeUrl = attachtUrl.replace(hdfsUrlPrex, "");
            String group = relativeUrl.substring(0, relativeUrl.indexOf("/"));
            String fileName = relativeUrl.substring(relativeUrl.indexOf("/") + 1);
            // 获取hdfs上传文件流
            byte[] bytes = FastDFSClient.down(group, fileName);
            File file = this.byte2File(bytes, "./" + attach.getAttachName());
            helper.addAttachment(attach.getAttachName(), file);
            files.add(file);
        }
    }
    //发送邮件
    javaMailSender.send(mimeMessage);
    //发送成功获取邮件头,后续业务操作中会使用到
    String msgId = mimeMessage.getMessageID().replace("[", "").replace("]", "");
    outbox.setMsgId(msgId);
    return outbox;
}

2、发送前邮件属性初始化

/**
 * 初始化邮件发送sender
 * @param outbox
 * @return
 */
private JavaMailSenderImpl createMailSender(MailOutboxMsg outbox){
    JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
    javaMailSender.setProtocol("smtp");
    javaMailSender.setHost(outbox.getSentAddress());
    javaMailSender.setPort(outbox.getSentPort());
    javaMailSender.setPassword(outbox.getPassword());
    javaMailSender.setUsername(outbox.getSentEmail());
    javaMailSender.setDefaultEncoding("utf-8");
    return javaMailSender;
}

/**
 * 初始化邮件发送properties
 * @return
 */
private Properties initMailProp(){
    Properties props = new Properties();
    props.setProperty("spring.mail.properties.mail.smtp.auth","true");
    props.setProperty("spring.mail.properties.mail.smtp.ssl.enable","true");
    props.setProperty("spring.mail.test-connection","true");
    //防止中文乱码
    props.setProperty("spring.mail.default-encoding", "GB2312");
    props.setProperty("mail.smtp.socketFactory.fallback", "true");
    props.setProperty("mail.smtp.starttls.enable", "true");
    props.setProperty("mail.mime.splitlongparameters", "false");
    return props;
}

3、解析邮件中的图片,进行替换。这个操作是避免将自身服务器链接直接暴露给其他人,也可以避免日后因为文件服务器访问权限变更,造成邮件中图片无法查看的情况

/**
 * 解析发送邮件内容中的图片
 * @param emailContent
 */
private String parseContent(MimeMessageHelper helper, String emailContent) throws Exception {
    // 获取正文图片地址
    Set<String> pics = getImgUrl(emailContent);
    // 处理每张图片,必须要先设置settext,再设置addinline,否则图片无法显示
    HashMap<String, File> imgMap = new HashMap<>();
    for (String imageUrl : pics) {
        // 正文图片
        String contentId = getRandomFileName(imageUrl);
        String relativeUrl = imageUrl.replace(hdfsUrlPrex, "");
        String group = relativeUrl.substring(0, relativeUrl.indexOf("/"));
        String fileName = relativeUrl.substring(relativeUrl.indexOf("/") + 1);
        // 获取hdfs上传文件流
        byte[] bytes = FastDFSClient.down(group, fileName);
        emailContent = emailContent.replace(imageUrl, "cid:" + contentId);
        File file = this.byte2File(bytes, "./" + relativeUrl.substring(relativeUrl.lastIndexOf("/")+1));
        files.add(file);
        imgMap.put(contentId, file);
    }
    helper.setText(emailContent,true);
    for(String contentId : imgMap.keySet()){
        helper.addInline(contentId, imgMap.get(contentId));
    }
    return emailContent;
}

/**
 * 获取图片链接
 * @param content
 * @return
 */
private Set<String> getImgUrl(String content) {
    Set<String> pics = new HashSet<>();
    String img = "";
    Pattern p_image;
    Matcher m_image;
    //     String regEx_img = "<img.*src=(.*?)[^>]*?>"; //图片链接地址
    String regEx_img = "<img.*src\\s*=\\s*(.*?)[^>]*?>";
    p_image = Pattern.compile(regEx_img, Pattern.CASE_INSENSITIVE);
    m_image = p_image.matcher(content);
    while (m_image.find()) {
        // 得到<img />数据
        img = m_image.group();
        // 匹配<img>中的src数据
        Matcher m = Pattern.compile("src\\s*=\\s*\"?(.*?)(\"|>|\\s+)").matcher(img);
        while (m.find()) {
            // 地址以hdfs路径开头
            if (m.group(1).startsWith(hdfsUrlPrex)) {
                pics.add(m.group(1));
            }
        }
    }
    return pics;
}

/**
 * 设置图片id,不能重复
 * @param hdfsUrl
 * @return
 */
private String getRandomFileName(String hdfsUrl) {
    // 获取后缀名
    String suffix = hdfsUrl.substring(hdfsUrl.lastIndexOf("."));
    // 当前系统时间+5位随机数+文件后缀名生成
    return String.valueOf(new Date().getTime()) + (int)((Math.random()*9+1)*10000) + suffix;
}

4、最后一个小方法,将字节流转换为file。我这个是从fastdfs服务器获取文件,所以需要这一步,实际情况应该比这个简单,可以直接new File即可

public File byte2File(byte[] byteArray, String targetPath) {
    InputStream in = new ByteArrayInputStream(byteArray);
    File file = new File(targetPath);
    String path = targetPath.substring(0, targetPath.lastIndexOf("/"));
    if (!file.exists()) {
        new File(path).mkdir();
    }
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(file);
        int len = 0;
        byte[] buf = new byte[1024];
        while ((len = in.read(buf)) != -1) {
            fos.write(buf, 0, len);
        }
        fos.flush();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (null != fos) {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return file;
}

代码写到这里,邮件就可以发出去了,附件和正文图片也处理好了。但是有个问题,需求要求在发送邮件之前,检测邮件配置的连接性。也就是说如果你的发件协议或者密码等错误,直接连接失败,不发送邮件了。

5、检测邮箱的连接性

/**
 * 连接邮件服务器
 */
public void connect() {
	try {
		Store store = initStore();
		store.close();
	} catch (Exception e)  {
		log.error("链接失败", e);
		throw new BusinessException("邮箱授权失败,请检查邮箱密码或授权是否成功");
	}
} 

protected Store initStore()
		throws MessagingException {
	Properties props = initImapProps();
	Session session = Session.getInstance(props, null);
	URLName url = new URLName("imap", "imap.gmail.com", 993, 
			null, "xxx9@gmail.com", "xxxpassword");
	Store store = session.getStore(url);
	store.connect();
	return store;
}

protected Properties initImapProps(MailAccountDTO mailAccountDTO) {
	Properties props = new Properties();
	final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
	props.setProperty("mail.imap.host", "imap.gmail.com");
	props.setProperty("mail.imap.socketFactory.class", SSL_FACTORY);
	props.setProperty("mail.imap.socketFactory.fallback", "false");
	props.setProperty("mail.imap.port", 993);
	props.setProperty("mail.imap.socketFactory.port", 993);
	props.setProperty("mail.imap.auth", "true");
	props.setProperty("mail.imap.timeout", "300000");
	props.setProperty("mail.imap.connectiontimeout", "300000");
	props.setProperty("mail.imap.writetimeout", "300000");
	props.setProperty("mail.imap.partialfetch", "false");
	props.setProperty("mail.imaps.partialfetch", "false");

	return props;
}

最通用的Gmail和outlook邮箱,贴一张相关配置属性

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Spring Boot 中实现发送带附件的邮件,可以按照以下步骤进行设计: 1. 在 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> ``` 2. 在 application.properties 文件中配置邮件服务器的信息: ```properties # 邮件服务器地址 spring.mail.host=smtp.qq.com # 邮件服务器端口 spring.mail.port=465 # 邮箱账号 spring.mail.username=your_email@qq.com # 邮箱密码 spring.mail.password=your_password # SSL协议 spring.mail.properties.mail.smtp.ssl.enable=true ``` 3. 创建一个邮件服务类 MailService,实现发送邮件的功能: ```java @Service public class MailService { @Autowired private JavaMailSender mailSender; public void sendMailWithAttachment(String to, String subject, String text, File file) throws MessagingException { MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setTo(to); helper.setSubject(subject); helper.setText(text); // 添加附件 FileSystemResource resource = new FileSystemResource(file); helper.addAttachment(file.getName(), resource); mailSender.send(message); } } ``` 4. 在需要发送邮件的地方调用 MailService 的 sendMailWithAttachment 方法,传入收件人地址、邮件主题、邮件正文和附件文件即可: ```java // 发送带附件的邮件 File file = new File("attachment.txt"); mailService.sendMailWithAttachment("recipient@example.com", "邮件主题", "邮件正文", file); ``` 以上就是在 Spring Boot 中实现发送带附件的邮件的设计过程。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值