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

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", "xxxxxxxxxxxxxxx");  //密码或者授权码
        
        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;
    }
}

邮件如下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值