您当前的位置: 首页 >  Java

wu@55555

暂无认证

  • 2浏览

    0关注

    201博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

springboot:java实现邮件及附件发送、HTML正文的三种方式(一)【附带源码】

wu@55555 发布时间:2022-10-04 12:01:43 ,浏览量:2

0. 引言

邮件发送是我们日常开发中比较常见的功能,常用于预警信息提醒、统计数据定期发送等需求。一般该方法会由前人封装好,实际开发时只需要调用即可,但具体怎么实现的,如何从零实现邮件发送,这是我们要掌握的。

所以今天我们就整理一下java实现邮件发送的三种方式,供大家参考。

  • 基于javax.mail实现
  • 基于org.apache.commons.mail实现
  • 基于spring-boot-starter-mail实现
1. 环境准备 1.1 开发环境

以下演示均基于各组件当前最新的稳定版本实现,jdk基于1.8版本

commons-email 1.5
javax.mail 1.4.7
spring-boot-starter-mail 跟随springboot版本,文中演示的是2.3.7.RELEASE
1.2 开启邮箱协议与授权

其次我们需要了解的是,程序要发送邮件,是需要一个邮箱账号的, 并且其账号需要开启SMTP邮件协议以及邮件授权码,并不是密码。

以下我们以QQ邮箱为例,示范其开启过程,其他邮箱大同小异。

1、登陆邮箱,点击设置,进入账户,下拉页面

在这里插入图片描述

2、找到POP3/IMAP/SMTP服务设置。这里我们可以开启POP3/SMTP或者IMAP/SMTP服务,两者的区别

在这里插入图片描述

3、点击开启后,会要求你发送短信验证

在这里插入图片描述

4、发送后,点击我已发送,然后会给你一个授权码,将该码保存下来,这就是我们需要的授权码。

在这里插入图片描述

5、其次我们需要获取到邮件服务器的smtp地址,比如我们这里用的是qq邮箱,其地址就是smtp.qq.com。对应类型邮箱的smtp地址直接百度即可。

1.3 常见的邮箱服务及端口 服务商smtp服务地址smtp服务端口pop3服务地址pop3服务端口新浪 sina.comsmtp.sina.com.cn25pop3.sina.com.cn110搜狐 sohu.comsmtp.sohu.com25pop3.sohu.com110163 163.comsmtp.163.com25pop3.163.com110QQ qq.comsmtp.qq.com25pop3.qq.com110foxmail foxmail.comsmtp.foxmail.com25pop3.foxmail.com110QQ企业邮箱 exmail.qq.comsmtp.exmail.qq.com995pop3.exmail.qq.com587/465 2. 实现 2.1 javax.mail实现 2.1.1 思路

利用javax.mail实现邮件发送功能主要分成一下几步:

1、创建配置项变量Properties对象,用于声明smtp相关配置

2、重写一个Authenticator,用于声明发件人邮箱地址和授权码

3、基于上述两步创建的对象,创建一个Session

4、利用session创建一个MimeMessage对象,再利用MimeMessage创建一个MimeMessageHelper对象,该对象用于设置收件人、发件人、抄送、秘密抄送、主题、内容、附件、发送时间等属性

5、利用Transport.send方法发送邮件

在清楚了实现流程后,我们直接上代码演示

2.1.2 实操

1、引入依赖


            javax.mail
            mail
            1.4.7

2、创建工具类,实现发送功能

/**
 * @author benjamin_5
 * @Description
 * @date 2022/10/3
 */
public class EmailJavaxUtil {

    private static final Logger logger = LoggerFactory.getLogger(EmailJavaxUtil.class);

	// 发件人smtp邮箱服务地址
    private static final String senderSmtpHost = "smtp.qq.com";
    // 发件人邮箱地址
    private static final String senderEmail = "xxx@qq.com";
    // smtp邮箱授权码
    private static final String senderPassword = "xxx";
    // 端口
    private static final String senderSmtpPort = "465";

   private static void sendEmail(String subject, String content,boolean contentIsHtml, String fromMailPersonalName,
                                  String toMail, String ccMail, String bccMail, List fileNames)
            throws GeneralSecurityException, UnsupportedEncodingException, MessagingException {

        // 设置参数
        Properties properties = System.getProperties();
        // smtp服务地址
        properties.put("mail.smtp.host",senderSmtpHost);
        // smtp服务端口
        properties.put("mail.smtp.port", senderSmtpPort);
        // 开启验证
        properties.put("mail.smtp.auth","true");
        // 开启TLS加密
        properties.put("mail.smtp.starttls.enable","true");
        // 是否启用socketFactory,默认为true
        properties.put("mail.smtp.socketFactory.fallback", "true");
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        properties.put("mail.smtp.ssl.enable", "true");
        properties.put("mail.smtp.ssl.socketFactory", sf);
        // 建立会话,利用内部类将邮箱授权给jvm
        Session session = Session.getDefaultInstance(properties, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(senderEmail, senderPassword);
            }
        });
        // 设置为true可以在控制台打印发送过程,生产环境关闭
        session.setDebug(true);
        // 创建邮件对象
        MimeMessage message = new MimeMessage(session);
        // 通过MimeMessageHelper设置正文和附件,否则会导致两者显示不全
        MimeMessageHelper helper = new MimeMessageHelper(message,true,"utf-8");
        //设置收件人,to为收件人,cc为抄送,bcc为密送
        if (StringUtils.isEmpty(toMail)) {
            logger.error("邮件收件人为空");
            return;
        }
        //设置发件人
        helper.setFrom(new InternetAddress(senderEmail, fromMailPersonalName));
        helper.setTo(InternetAddress.parse(toMail, false));
        if (!StringUtils.isEmpty(ccMail)) {
            helper.setCc(InternetAddress.parse(ccMail, false));
        }
        if (!StringUtils.isEmpty(bccMail)) {
            helper.setBcc(InternetAddress.parse(bccMail, false));
        }
        // 设置邮件主题
        helper.setSubject(subject);
        //设置邮件正文内容
        helper.setText(content,contentIsHtml);
        //设置发送的日期
        helper.setSentDate(new Date());
        // 设置附件(注意这里的fileName必须是服务器本地文件名,不能是远程文件链接)
        if(!CollectionUtils.isEmpty(fileNames)){
            for (String fileName : fileNames) {
                FileDataSource fileDataSource = new FileDataSource(fileName);
                helper.addAttachment(fileDataSource.getName(),fileDataSource);
            }
        }
        //调用Transport的send方法去发送邮件
        Transport.send(message);

    }

}

3、调用测试

public static void main(String[] args) throws MessagingException, GeneralSecurityException, UnsupportedEncodingException {
        String fileName = "/Library/project/study/java/mail_send_demo/src/main/resources/供应商接口参数.xlsx";
        sendEmail("测试邮件1","这是一封测试邮件",false,"55555","wuhanxue5@sina.com",null,null, Collections.singletonList(fileName));
    }

4、可以看到邮件正常接收到了

在这里插入图片描述

2.1.3 补充内容

1、需要注意的是如果采用如下的方式设置附件和正文的话,会导致两者有一个不显示。如下,附件设置在后就会覆盖设置的正文内容,正文内容在后就会覆盖附件内容。

//设置邮件正文内容
message.setText(content);
if(!CollectionUtils.isEmpty(fileNames)){
            // 附件上传组件
            Multipart multipart =new MimeMultipart("mixed");
            for (String fileName : fileNames) {
                MimeBodyPart bodyPart = new MimeBodyPart();
                FileDataSource fileDataSource = new FileDataSource(fileName);
                bodyPart.setDataHandler(new DataHandler(fileDataSource));
                // 解决附件中文名乱码
                bodyPart.setFileName(MimeUtility.encodeText(fileDataSource.getName(), "utf-8", null));
                // 添加附件
                multipart.addBodyPart(bodyPart);
            }
            // 附件的设置语句必须放在设置正文内容之后,否则会导致附件设置为空
            message.setContent(multipart);
}

在这里插入图片描述

解决的办法就是使用MimeMessageHelper类来实现,如上述演示所示。

2、附件上传有多种方式,除了上述演示的使用FileDataSource形式添加附件外,还有文件、输入流的方式来添加,可以结合需求多样开发。

  • addAttachment(String attachmentFilename, DataSource dataSource)
  • addAttachment(String attachmentFilename, File file)
  • addAttachment(String attachmentFilename, InputStreamSource inputStreamSource)
  • addAttachment(String attachmentFilename, InputStreamSource inputStreamSource, String contentType)

同时看源码会发现,除了addAttachment方法外,addInline方法也能添加附件。生产开发复制粘贴上述的工具类完全足够,但是要想进一步理解,深入掌握组件,更需要大家去阅读源码,了解api方法的多样性。

2.1.3 邮件正文为html格式

有时我们需要自定义我们邮件正文的样式,也就需要发送html格式的邮件正文。那么这又怎么实现呢?

其实眼尖的同学会发现,我上述提供的工具类中已经提供了一个contentIsHtml参数,用来标识内容是否为html

其实现利用了MimeMessageHelper提供的setText方法的第二参数,通过调用setHtmlTextToMimePartsetPlainTextToMimePart来实现html正文的解析 在这里插入图片描述

话不多说,我们来测试一下

public static void main(String[] args) throws MessagingException, GeneralSecurityException, UnsupportedEncodingException {
        String fileName = "/Library/project/study/java/mail_send_demo/src/main/resources/供应商接口参数.xlsx";
        String html = "统计数据如下所示:" +
                "\n" +
                "  \n" +
                "    月度销售额\n" +
                "    年度销售额\n" +
                "  \n" +
                "  \n" +
                "    10000\n" +
                "    2000000\n" +
                "  \n" +
                "";
        sendEmail("统计数据",html,true,"55555","wuhanxue5@sina.com",null,null, Collections.singletonList(fileName));
    }

邮件正常接收并且html样式显示正常

在这里插入图片描述

源码地址

以上演示的源码可以在如下地址中下载

git源码地址

关注专栏,了解后续内容
  • 基于org.apache.commons.mail实现邮件发送

  • 基于spring-boot-starter-mail实现邮件发送

关注
打赏
1664985904
查看更多评论
立即登录/注册

微信扫码登录

0.0377s