文档章节

Java 发送邮件实现(JavaMail 和 Spring 实现)

TurboSanil
 TurboSanil
发布于 01/17 15:19
字数 2036
阅读 97
收藏 3

Java 实现邮件的发送,使用 JavaMail 和 Spring 实现

一、使用 JavaMail

JavaMail 是 Java 处理电子邮件相关的编程接口,但是没有被加在标准的Java开发工具包中(Java Development Kit),所以我们使用 JavaMail 需要另外下载依赖包
javax.mail.jar包实现了 SMTP、IMAP 和 POP3 协议

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>

1、发送一个简单邮件

下面是用 qq 邮箱发送一个简单的纯文本邮件的例子

public class SentSimpleMail {

    private static final String MAIL_HOST = "smtp.qq.com"; // 发送邮件的主机
    private static final String FROM = "827952316@qq.com"; // 发件人邮箱地址

    /**
     * 用qq邮箱发送一个简单邮件
     * 
     * @param subject
     * @param text
     * @param toRecipients 接收邮件,逗号分隔
     * @throws AddressException
     * @throws MessagingException
     */
    public void sentSimpleMail(String subject, String text, String toRecipients)
        throws AddressException, MessagingException {
        /*
         * 初始化JavaMail会话
         */
        Properties props = System.getProperties(); // 获得系统属性配置,用于连接邮件服务器的参数配置
        props.setProperty("mail.smtp.host", MAIL_HOST); // 发送邮件的主机
        props.setProperty("mail.smtp.auth", "true");

        Session session = Session.getInstance(props, null);// 获得Session对象
        session.setDebug(true); // 设置是否显示debug信息,true 会在控制台显示相关信息

        /*
         * 创建邮件消息,发送邮件
         */
        Message message = new MimeMessage(session);
        message.setFrom(new InternetAddress(FROM));

        // To: 收件人
        // message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(toRecipient));
        message.setRecipients(MimeMessage.RecipientType.TO, InternetAddress.parse(toRecipients, false));
        // To: 增加收件人(可选)
        // message.addRecipient(MimeMessage.RecipientType.TO, new InternetAddress(toRecipient);
        // Cc: 抄送(可选)
        // message.setRecipient(MimeMessage.RecipientType.CC, new InternetAddress(ccRecipient));
        // Bcc: 密送(可选)
        // message.setRecipient(MimeMessage.RecipientType.BCC, new InternetAddress(bccRecipient));

        message.setSubject(subject); // 邮件标题
        message.setText(text); // 邮件内容

        // 简单发送邮件的方式
        Transport.send(message, FROM, "xxxxxxxxxxx"); // 授权码
    }

    public static void main(String[] args) throws AddressException, MessagingException {
        new SentSimpleMail().sentSimpleMail("标题", "邮件内容", "827952316@qq.com");
    }
}

授权

如果需要提供用户名和密码给e-mail服务器来达到用户认证的目的,需要另外添加授权信息

props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.user", "${user}");
props.setProperty("mail.password", "${password}");

或者在发送的时候加上用户和授权码,如

Transport.send(message, FROM, "xxxxxxxxxxx"); // 授权码

如在使用 qq 邮箱发送邮件需要获取授权码,在邮箱的“设置-账户”中设置

2、发送基于 HTML 内容的邮件

发送邮件的内容为 HTML 时,需要把 Mimemessage 的 ContentType 设为 "text/html"

message.setDataHandler(new DataHandler( new ByteArrayDataSource("<h1>This is html message</h1>", "text/html")));

或者

message.setContent("<h1>This is html message</h1>", "text/html" );

3、带有附件的邮件

MimeMessage 继承Message,表示整封邮件
MimeBodyPart 表示邮件的一个MIME消息
MimeMultipart 表示一个由多个MIME消息组合成的组合MIME消息

public class SendMail {

    public void sendMail(String subject, String text, String toRecipients)
        throws AddressException, MessagingException, IOException {
        
        String host = "smtp.qq.com"; // 发送邮件的主机
        String from = "827952316@qq.com"; // 发件人邮箱地址
        
        /*
         * 初始化JavaMail会话
         */
        Properties props = System.getProperties(); // 获得系统属性配置,用于连接邮件服务器的参数配置
        props.setProperty("mail.smtp.host", host); // 发送邮件的主机
        props.setProperty("mail.smtp.auth", "true");
        props.setProperty("mail.user", from);
        props.setProperty("mail.password", "xxxxxxxxxxxxxx");  //密码或者授权码
        
        Session session = Session.getInstance(props, null);// 获得Session对象
        session.setDebug(true); // 设置是否显示debug信息,true 会在控制台显示相关信息

        /*
         * 创建邮件消息,发送邮件
         */
        Message message = new MimeMessage(session);
        message.setFrom(new InternetAddress(from));
        message.setRecipients(MimeMessage.RecipientType.TO, InternetAddress.parse(toRecipients, false));
        message.setSubject(subject); // 邮件标题
        
        //创建多重消息
        MimeMultipart mp = new MimeMultipart();
        
        // 文本部分
        MimeBodyPart textPart = new MimeBodyPart();
        textPart.setText(text);
        
        // 附件部分
        MimeBodyPart filePart = new MimeBodyPart();
        filePart.attachFile("D:/0.jpeg");
        filePart.setFileName("0.jpeg");
        
        mp.addBodyPart(textPart);
        mp.addBodyPart(filePart);
        message.setContent(mp);
        
        Transport.send(message);
    }

    public static void main(String[] args) throws AddressException, MessagingException, IOException {
        new SendMail().sendMail("标题", "邮件内容", "827952316@qq.com");
    }
}

二、使用 Spring 发送邮件

在 spring 中,关于邮件(JavaMail)的集成 API 是在 spring-context-supprot 中的 org.springframework.mail 包中,需要 JavaMail 的类库支持。

在项目中,邮件功能可能是一个横切关注点,很可能为 AOP 的一个切面

MailSender 是发送电子邮件的核心接口。SimpleMailMessage 类封装了简单的邮件属性(例如from和to)的简单值

1、基本用法

1)MailSender 和 SimpleMailMessage 的用法

使用 MailSender 和 SimpleMailMessage 来发送邮件

@Component
public class SendMailManagerImpl implements SendMailManager {

    @Autowired
    private MailSender mailSender;
    @Autowired
    private SimpleMailMessage templateMessage;

    @Override
    public void sendMail(String[] to) {
        // SimpleMailMessage 
        SimpleMailMessage msg = new SimpleMailMessage(this.templateMessage);
        msg.setTo(to);//接收人
        msg.setText("邮件内容");  //这里的邮件内容是 文本类型
        // msg.setCc(cc);// 抄送
        // msg.setBcc(bcc);// 密送
        // msg.setReplyTo(replyTo);// 回复
        // msg.setSentDate(new Date());// 发送时间
        // msg.setSubject(subject);// 主题
        // msg.setFrom(from);// 发送人
        try{
            this.mailSender.send(msg);
        }
        catch (MailException ex) {
            System.out.println(ex.getMessage());
        }
    }
}

我们在 xml 中配置 MailSender 和 模板消息

<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="host" value="smtp.qq.com" />
    <!-- 如果需要账号密码授权 -->
    <property name="username" value="827952316@qq.com"/>
    <property name="password" value="xxxxxxxxxxxxxxxx"/>
</bean>
    
<!-- 可以做一个模板,把邮件的通用内容放到这里 -->
<bean id="templateMessage" class="org.springframework.mail.SimpleMailMessage">
    <property name="from" value="827952316@qq.com" />
    <property name="subject" value="统一标题" />
</bean>

2)使用 JavaMailSender 和 MimeMessagePreparator

上面的例子是利用了 spring 所封装的 SimpleMailMessage 类。不过 Spring 框架的邮件支持也附带了标准 JavaMail 实现,JavaMailSender 类可以使用 JavaMail 的 MimeMessage 类

@Component
public class SendMailManagerImpl2 implements SendMailManager {

    @Autowired
    private JavaMailSender mailSender;

    public void sendMail(String[] to) {

        MimeMessagePreparator preparator = (MimeMessage mimeMessage) -> {
            Arrays.asList(to).stream().forEach(x -> {
                try {
                    mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(x));
                } catch (MessagingException e) {
                     System.err.println(e.getMessage());
                }
            });
            mimeMessage.setFrom(new InternetAddress("827952316@qq.com"));
            mimeMessage.setText("邮件内容");
        };
        try {
            this.mailSender.send(preparator);
        }
        catch (MailException ex) {
            System.err.println(ex.getMessage());
        }
    }
}

2、使用 MimeMessageHelper 处理 JavaMail 消息

使用 MimeMessageHelper 可以很方便的创建处理 JavaMail 的 MimeMessage 对象

JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost("smtp.qq.com");

MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);
helper.setTo("test@qq.com");
helper.setText("邮件内容");

sender.send(message);

当我们想要邮件有附件和内联资源的时候,使用 MimeMessageHelper 就很方便了

1)发送带有附件和内联资源的邮件

我们发送邮件通常会需要有附件或者是内联资源(比如,内嵌的图片),在创建这些相当复杂的邮件,SimpleMailMessage 就不好用了,使用 MimeMessageHelper 帮我们创建 MimeMessage 对象

@Component
public class SendMailManagerImpl3 implements SendMailManager {

    @Autowired
    private JavaMailSender mailSender;

    public void sendMail(String[] to) {

        MimeMessage message = mailSender.createMimeMessage();
        try {
            // 使用 true 表示要创建一个有多部分的邮件
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8");
            helper.setFrom("827952316@qq.com");
            helper.setTo(to);
            // 使用 true 表示邮件内容为 HTML,在这里引用内联资源 图片
            helper.setText("<html><body><h1>邮件内容</h1><img src='cid:inlineImg'/></body></html>", true);

            // 添加附件
            FileSystemResource file = new FileSystemResource(new File("D:/0.jpeg"));
            helper.addAttachment("CoolImage.jpeg", file);

            // 添加内联资源(在html中引用)
            FileSystemResource res = new FileSystemResource(new File("D:/0.jpeg"));

            helper.addInline("inlineImg", res);

            this.mailSender.send(message);
        } catch (MailException | MessagingException ex) {
            System.err.println(ex.getMessage());
        }
    }
}

使用内联资源的时候要指定 Content-ID,MimeMessage在邮件内容中添加。添加文本和资源的顺序非常重要。要先添加文本,然后再添加资源

3、使用模板创建邮件

通常我们在使用代码创建邮件是都不会是简单的纯文本邮件,在使用Java代码创建基于HTML的电子邮件内容非常繁琐且容易出错,而且更改电子邮件内容的显示结构需要编写Java代码,重新编译,重新部署

使用模板是可以解决这些问题的,使用模板库(例如FreeMarker、Velocity、Thymeleaf)来定义电子邮件内容的显示结构。从 Spring 4.3 之后,Velocity支持已被弃用。这里我们使用 FreeMaker 模板发送邮件做个例子

首先我们添加依赖

<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.28</version>
</dependency>

1)配置 bean

FreeMarker 配置

<!-- web项目中 -->
<!-- <bean id="freeMarkerConfigurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
    <property name="templateLoaderPath" value="/WEB-INF/config/template/" />
    <property name="freemarkerSettings">
        <props>
            <prop key="template_update_delay">1800</prop>模板更新延时
            <prop key="default_encoding">UTF-8</prop>
            <prop key="locale">zh_CN</prop>
        </props>
    </property>
</bean> -->
<!-- 非web -->
<bean id="freeMarkerConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
    <property name="templateLoaderPath" value="classpath:template/ftl/" />
</bean>

2)通过模板获得邮件内容

FreeMarker 模板 user.ftl

<html>
    <body>
        <h3>username: ${user.username}</h3>
        <p>password : ${user.password}</p>
        <span>Sent using FreeMarker Template</span>
    </body>
</html>

使用 FreeMarker 模板获得邮件内容

@Component
public class TemplateManagerImpl implements SendMailManager {

    @Autowired
    private JavaMailSender mailSender;
    @Autowired
    private Configuration freeMarkerConfiguration;

    @Override
    public void sendMail(String[] to,User user) {
        MimeMessage message = mailSender.createMimeMessage();
        try {
            // 使用 true 表示要创建一个有多部分的邮件
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8");
            helper.setFrom("827952316@qq.com");
            helper.setTo(to);
            helper.setSubject("标题");
            
            //获取模板
            Map<String, Object> model = new HashMap<String, Object>();
            model.put("user", user);
            String text = geFreeMarkerTemplateContent(model);
            // 使用 true 表示邮件内容为 HTML
            helper.setText(text, true);

            this.mailSender.send(message);
        } catch (MailException | MessagingException ex) {
            System.err.println(ex.getMessage());
        }
    }

    /**
     * 获得模板内容
     * @param model
     * @return
     */
    private String geFreeMarkerTemplateContent(Map<String, Object> model) {
        String content = null;
        try {
            content = FreeMarkerTemplateUtils.processTemplateIntoString(freeMarkerConfiguration.getTemplate("user.ftl"), model);
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
        return content;
    }
}

邮件如下

© 著作权归作者所有

TurboSanil
粉丝 2
博文 34
码字总数 60261
作品 0
广州
程序员
私信 提问
SpringBoot | 第二十六章:邮件发送

前言 讲解了日志相关的知识点后。今天来点相对简单的,一般上,我们在开发一些注册功能、发送验证码或者订单服务时,都会通过短信或者邮件的方式通知消费者,注册或者订单的相关信息。而且基...

oKong
2018/08/29
0
0
Spring Cloud 2.x系列之springboot发送邮件

虽然现在短信验证已经最流行也是最常用的验证方式;但是邮件验证还是必不可少,依然是网站的必备功能之一。什么注册验证,忘记密码或者是给用户发送营销信息都是可以使用邮件发送功能的。最早...

技术小能手
2018/10/22
0
0
[手记]使用java Mail发送邮件.

因为项目中要用到这个功能,写出来了.所以和大家分享一下.首先,完成javamail发送电子邮件,需要到oracle网站上下载javamail的jar包:地址为:http://www.oracle.com/technetwork/java/javamail...

被风遗忘
2012/05/06
0
0
【ME - Mail】之Java Mail

Java Mail 参考示例 biezhi/oh-my-email(https://github.com/biezhi/oh-my-email) journaldev.com(https://www.journaldev.com/2532/javamail-example-send-mail-in-java-smtp) 从这开始吧 ......

近在咫尺远在天涯
05/14
0
0
Java 发送qq邮件基础和封装

前文摘自 菜鸟教程 :http://www.runoob.com/java/java-sending-email.html 使用Java应用程序发送 E-mail 十分简单,但是首先你应该在你的机器上安装 JavaMail API 和Java Activation Frame...

fantj666
2018/03/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Taro ScrollView 组件的 scrollTop 属性是个坑

官方issue:ScrollView设置scrollTop没效果 同样的,设置 scrollTop=0 并不能实现置顶,官方回复早就修复了,我的 Taro 版本已经是最新的,然而并未修复。 万能的评论区,给出了失效的原因。...

dkvirus
50分钟前
3
0
Qt那些事0.0.21

这次还是关于PRO文件中QMAKE_POST_LINK的故事。 平时都是使用VS2015作为编译器,恰巧想用MinGW编一版程序,结果偏偏出现了错误。话说测试的这个项目可是在Linux下(fodera 20)可以正确编译通...

Ev4n
今天
1
0
OSChina 周六乱弹 —— 抖音外放 亲妈下葬。

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @巴拉迪维 :一直没想明白黎明是怎么混进「四大天王」的,直到最近网易云音乐心动模式开启之后 #今日歌曲推荐# 《那有一天不想你》- 黎明 手机...

小小编辑
今天
508
8
Linux使用源码包安装软件

前言: 最近整理一些以前的学习笔记。 过去都是存储在本地,此次传到网络留待备用。 源码包 Linux软件多数免费、开源,是开发人员编写的,具有很强可读性的一组相关代码文本。 源码包 --> 编...

迷失De挣扎
今天
6
0
IPv4如何转换为IPv6?

ipv6已经逐渐在应用,现在已经有很多的运营商支持ipv6,前天我们也发布了如何让电脑使用ipv6地址?有很多朋友在问?ipv6有什么作用,它的表示方式是什么,今天我们来一起来详细了解下ipv6相关计...

xiangyunyan
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部