发送邮件
在日常工作和生活中经常会用到电子邮件。例如,当注册一个新账户时,系统会自动给注册邮箱发送一封激活邮件,通过邮件找回密码,自动批量发送活动信息等。邮箱的使用基本包括这几步:先打开浏览器并登录邮箱,然后创建邮件再发送邮件。在这个过程中有大量的重复性工作且不能批量发送邮件,说明手动的方式效率太低。本节就介绍如何通过代码完成发送邮件的功能。
SMTP与发送一封邮件的步骤
电子邮件在网络中传输时需要遵从协议,常用的电子邮件协议包括SMTP、POP3、IMAP。其中,邮件的创建和发送只需要使用SMTP(Simple MailTransfer Protocol,简单邮件传输协议)。
如果需要给客户发送邮件,可以直接使用Java代码发送。发送邮件的过程是先登录指定的邮箱,然后再给用户发送邮件,因此需要配置邮箱的权限或者SMTP。本小节以QQ邮箱作为收件人,介绍怎么配置163邮箱发送邮件。首先登录163邮箱,选择"设置"标签,就会看到设置页面如图6.14所示。

必须开启IMAP/SMTP服务和POP3/SMTP服务,开启后可以看到服务器的地址,然后就可以使用Java配置163邮箱发送邮件了,这个很重要。
在网页上创建并发送一封电子邮件的步骤如下:
(1)创建一个邮件对象(MimeMessage)。
(2)设置发件人、收件人,可以增加多个收件人、抄送人。
(3)设置邮件的主题(标题)。
(4)设置邮件的正文(内容)。
(5)设置邮件的发送时间。
(6)发送邮件。
同理,在Java中发送邮件的步骤和上面相似,完成上述步骤就能成功发送邮件,具体的代码实现后面会详细介绍。
实战:使用Java Mail发送邮件
前面简述了邮件的发送过程,下面使用Java的API完成邮件的发送。
(1)在pom.xml中添加E-mail的依赖坐标:
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
(2)编写发送邮件的代码:
package com.example.springextenddemo.email;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.Properties;
/**
* Java 发送邮件
*/
public class JavaSendMailDemo {
/**
* 邮箱账户
*/
public static String emailAddress = "[email protected]";
/**
* 授权码 */
public static String emailPassword = "OTLXYXXOELTJRMSO";
// 发件人邮箱的SMTP服务器地址
public static String smtpHost = "smtp.163.com";
public static void main(String[] args) throws Exception {
// 1. 创建参数配置,用于连接邮件服务器的参数配置
Properties props = new Properties();
// 使用的协议(JavaMail规范要求)
props.setProperty("mail.transport.protocol", "smtp");
// 发件人邮箱的SMTP服务器地址
props.setProperty("mail.smtp.host", smtpHost);
// 是否需要请求认证
props.setProperty("mail.smtp.auth", "true");
// 2. 根据配置创建会话对象,用于和邮件服务器进行交互
Session session = Session.getInstance(props);
// 设置为debug模式,观察详细的发送日志
session.setDebug(true);
// 3. 创建一封邮件
MimeMessage message = createMimeMessage(session,
emailAddress,"[email protected]");
// 4. 根据 Session 获取邮件传输对象
Transport transport = session.getTransport();
//5. 输入邮箱账号和密码连接邮件服务器,这里认证的邮箱必须与message中的发
件人邮箱一致,否则会报错
transport.connect(emailAddress, emailPassword);
// 6.给所有的收件地址发送邮件,message.getAllRecipients() 获取的是在
创建邮件对象时添加的所有收件人、抄送人、密送人
transport.sendMessage(message, message.getAllRecipients());
// 7. 关闭连接
transport.close();
System.out.println("完成邮件的发送");
}
/**
* 创建一封只包含文本的简单邮件
* @param session 和服务器交互的会话
* @param sendMailAddress 发件人邮箱
* @param receiveMailAddress 收件人邮箱
* @return * @throws Exception
*/
public static MimeMessage createMimeMessage(Session session,
String sendMailAddress,
String receiveMailAddress) throws Exception {
// 1. 创建一封邮件
MimeMessage message = new MimeMessage(session);
// 2. From: 发件人
message.setFrom(new InternetAddress(sendMailAddress, "紫龙
神","UTF-8"));
// 3. To: 收件人(可以增加多个收件人、抄送和密送)
message.setRecipient(MimeMessage.RecipientType.TO, new
Internet Address(receiveMailAddress, "你好", "UTF-8"));
// 4. Subject: 邮件主题
message.setSubject("你好,请问你吃饭了没有啊", "UTF-8");
// 5. Content: 邮件正文(可以使用HTML标签)
message.setContent("你好,许久不见,想问问你吃饭了没有啊",
"text/html; charset=UTF-8");
// 6. 设置发件时间
message.setSentDate(new Date());
// 7. 保存设置
message.saveChanges();
return message;
}
}
上述代码演示了邮件从创建到发送的过程。运行代码,控制台上打印的发送邮件的日志如图6.15所示,发件箱的发送记录如图6.16所示,收件箱的收件记录如图6.17所示。可以看到,已经成功发送邮件。



说明:在实际开发中,一般会把邮件发送封装成一个工具类,然后再配置一个只发送邮件的邮箱,最后直接调用工具类完成邮件的发送。
实战:Spring Boot集成邮件发送
Spring Boot为邮件发送功能提供了自动配置类,开发者只需要加入相关依赖,然后再配置邮箱的基本信息就可以发送邮件了,相较于邮件发送工具,类更加简便。
下面介绍在Spring Boot项目中如何实现邮件发送的功能。
(1)在application.properties中添加E-mail配置文件,内容如下:
#email config
spring.mail.port=25
spring.mail.password=OTLXYXXOELTJRMSO
spring.mail.default-encoding=UTF-8
spring.mail.properties.mail.debug=true
(2)编写邮件发送的服务类和具体方法:
package com.example.springextenddemo.email;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service
public class SpringEmailService {
@Autowired
private JavaMailSender javaMailSender;
/**
* 输入发件人的邮箱地址
*/
@Value("${spring.mail.username}")
private String from;
public void sendSimpleMail() {
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject("Spring 邮件发送");
message.setFrom(from);
message.setTo("[email protected]");
message.setSentDate(new Date());
message.setText("这是使用Spring发送邮件");
javaMailSender.send(message);
}
}
(3)新建一个邮件发送的Controller作为Web入口,其中包括发送邮件的方法:
package com.example.springextenddemo.controller;
import com.example.springextenddemo.email.SpringEmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EmailController {
@Autowired
private SpringEmailService springEmailService;
@GetMapping("/sendEamil")
public String sendEmail(){
springEmailService.sendSimpleMail();
return "send success";
}
}
(4)启动当前项目,访问localhost:8080/sendE mail,在控制台能看到邮件发送成功的提示。查看控制台打印的日志,如图6.18所示,收件箱收到的邮件如图6.19所示。


在Spring Boot中添加完E-mail的依赖和E-mail的配置文件后,SpringBoot会自动把E-mail的配置注入邮件的发送配置类中,不需要再手动配置。
使用的配置类是MailSender- AutoConfiguration,其中的部分源码如下:
package org.springframework.boot.autoconfigure.mail;
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({MimeMessage.class, MimeType.class,
MailSender.class})
@ConditionalOnMissingBean({MailSender.class})
@Conditional({MailSenderAutoConfiguration.MailSenderCondition.class})
@EnableConfigurationProperties({MailProperties.class})
@Import({MailSenderJndiConfiguration.class, MailSenderProperties
Configuration.class})
public class MailSenderAutoConfiguration {
static class MailSenderCondition extends AnyNestedCondition {
MailSenderCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}
@ConditionalOnProperty(
prefix = "spring.mail",
name = {"jndi-name"}
)
static class JndiNameProperty {
JndiNameProperty() {
}
}
@ConditionalOnProperty(
prefix = "spring.mail",
name = {"host"}
)
static class HostProperty {
HostProperty() {
}
}
}
}
在
MailSenderAutoConfiguration类中可以看到还导入了另外一个配置类,即Mail- SenderPropertiesConfiguration类,其部分源码如下:
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnProperty(
prefix = "spring.mail",
name = {"host"}
)
MailSenderPropertiesConfiguration类获取application.properties中E-mail的配置文件,把application.properties中E-mail的相关配置组装成E-mail的配置对象,然后注入Spring容器中,这样用户就可以方便地发送Email,不需要再手动配置E-mail信息了。
扩展知识------邮件格式
电子邮件因为其传播的广泛性,所以必须具备公共认同的格式,以便于客户端邮箱软件识别、拆解相应的信息。
电子邮件本身是由ASCII字符构成,总体上分为邮件头和邮件体两部分,允许字符编码、附件和压缩等多样化的格式。邮件体实际上是由一行行的字符构成的简单序列,它和邮件头是靠一个空行(该行只有一个回车换行符CRLF)来区分的。