java 发送邮件
新建sprigboot项目的pom.xml引入以下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
<!--swagger3-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<!--发送邮件依赖 二选一-->
<!--<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.6.4</version>
</dependency>
配置 application.yml
server:
port: 8089
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
email_info:
emailAccount: 发件人邮箱
emailPassword: 发件人邮箱密码
emailHost: SMTP服务器地址 #smtp.163.com
authCode: 授权密码
# swagger开关
springfox:
documentation:
swagger-ui:
enabled: true
编写swagger配置类 Swagger3Config
package com.gremlin.config;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
/**
* Description: Swagger3配置
* @author: gremlin
* Date: 2022/3/4 11:13
* @version: 1.0.0
*/
@Configuration
@EnableOpenApi
public class Swagger3Config {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
// 带方法注释
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("个人项目接口文档")
.description("更多请咨询服务开发者fantasy_starry")
.contact(new Contact("fantasy_starry", "https://www.xxx", "163.com"))
.version("1.0")
.build();
}
}
启动类 添加 @Import({Swagger3Config.class}) 注解 引入swagger
编写发件人信息配置工具类 SenderInfoUtils
package com.gremlin.utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* Description: 发件人信息配置
* @Author: gremlin
* Date: 2022/3/4 10:00
* @Version: 1.0
*/
@Component
public class SenderInfoUtils implements InitializingBean {
@Value("${email_info.emailAccount}")
private String sendEmailAccount;
/**
* 发件人邮箱密码: 有些邮箱服务器为了增加邮箱本身密码的安全性,
* 给SMTP 客户端设置了独立密码(有的邮箱称为“授权码”),
* 对于开启了独立密码的邮箱, 这里的邮箱密码必需使用这个独立密码(授权码)。
*/
@Value("${email_info.emailPassword}")
private String sendEmailPassword;
@Value("${email_info.authCode}")
private String authCode;
@Value("${email_info.emailHost}")
private String sendEmailHost;
public static String EMAIL_ACCOUNT;
public static String EMAIL_PASSWORD;
public static String EMAIL_HOST;
public static String EMAIL_AUTH_CODE;
@Override
public void afterPropertiesSet() {
EMAIL_ACCOUNT = sendEmailAccount;
EMAIL_PASSWORD = sendEmailPassword;
EMAIL_HOST = sendEmailHost;
EMAIL_AUTH_CODE = authCode;
}
}
编写邮件发送工具类 SendEmailUtils
package com.gremlin.utils;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Properties;
/**
* Description: 邮件发送工具类
* @author: gremlin
* Date: 2022/3/4 10:06
* @version: 1.0.0
*/
public class SendEmailUtils {
/**
* 发送邮件
*/
public static void sendEmailConfig() throws MessagingException, UnsupportedEncodingException {
// 1. 创建参数配置, 用于连接邮件服务器的参数配置
Properties properties = new Properties();
// 使用的协议(JavaMail规范要求)
properties.setProperty("mail.transport.protocol", "smtp");
// 发件人的邮箱的SMTP服务器地址
properties.setProperty("mail.smtp.host", SenderInfoUtils.EMAIL_HOST);
// 是否需要请求认证
properties.setProperty("mail.smtp.auth", "true");
properties.setProperty("mail.smtp.starttls.enable","true");
/**
* PS: 某些邮箱服务器要求 SMTP 连接需要使用 SSL
* 安全认证 (为了提高安全性, 邮箱支持SSL连接, 也可以自己开启),
* 如果无法连接邮件服务器, 仔细查看控制台打印的 log,
* 如果有有类似 “连接失败, 要求 SSL 安全连接” 等错误,
* 开启 SSL 安全连接。
*
* SMTP 服务器的端口 (非 SSL 连接的端口一般默认为 25, 可以不添加, 如果开启了 SSL 连接,
* 需要改为对应邮箱的 SMTP 服务器的端口, 具体可查看对应邮箱服务的帮助,
* QQ邮箱的SMTP(SLL)端口为465或587, 其他邮箱自行去查看)
*/
final String smtpPort = "465";
properties.setProperty("mail.smtp.port", smtpPort);
properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.smtp.socketFactory.fallback", "false");
properties.setProperty("mail.smtp.socketFactory.port", smtpPort);
// 2. 根据配置创建会话对象, 用于和邮件服务器交互
Session session = Session.getInstance(properties
, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(SenderInfoUtils.EMAIL_ACCOUNT,SenderInfoUtils.EMAIL_PASSWORD);
}
}
);
// 设置为debug模式, 可以查看详细的发送 log
session.setDebug(true);
// 收件人邮箱地址 可以有多个
String recipientEmailAddress = "XXXXXXX@163.com";
// 3. 调用私有方法创建一封邮件
// MimeMessage message = createMimeMessage(session,SenderInfoUtils.EMAIL_ACCOUNT, recipientEmailAddress);
MimeMessage message = complexEmail(session,SenderInfoUtils.EMAIL_ACCOUNT,recipientEmailAddress);
// 4. 根据 Session 获取邮件传输对象
Transport transport = session.getTransport();
/**
* 使用 邮箱账号 和 密码 连接邮件服务器, 这里认证的邮箱必须与 message 中的发件人邮箱一致, 否则报错
*
* PS_01: 如果连接服务器失败, 都会在控制台输出相应失败原因的log。
* 仔细查看失败原因, 有些邮箱服务器会返回错误码或查看错误类型的链接,
* 根据给出的错误类型到对应邮件服务器的帮助网站上查看具体失败原因。
*
* PS_02: 连接失败的原因通常为以下几点, 仔细检查代码:
* (1) 邮箱没有开启 SMTP 服务;
* (2) 邮箱密码错误, 例如某些邮箱开启了独立密码;
* (3) 邮箱服务器要求必须要使用 SSL 安全连接;
* (4) 请求过于频繁或其他原因, 被邮件服务器拒绝服务;
* (5) 如果以上几点都确定无误, 到邮件服务器网站查找帮助。
*/
transport.connect(SenderInfoUtils.EMAIL_ACCOUNT, SenderInfoUtils.EMAIL_AUTH_CODE);
// 6. 发送邮件, 发到所有的收件地址,
// message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
transport.sendMessage(message, message.getAllRecipients());
// 7. 关闭连接
transport.close();
}
/**
* 简单邮件信息
*/
private static MimeMessage createMimeMessage(Session session, String emailAccount,String recipientEmailAddress) throws UnsupportedEncodingException, MessagingException {
// 1. 创建一封邮件
MimeMessage message = new MimeMessage(session);
// 2. From: 发件人(标题处显示)
message.setFrom(new InternetAddress(emailAccount, "gremlin", "UTF-8"));
/**
//设置收件人,多个
final int num = recipientEmailAddress.size();
InternetAddress[] address = new InternetAddress[num];
for (int i = 0; i < recipientEmailAddress.size(); i++) {
int index = recipientEmailAddress.get(i).lastIndexOf("@");
//不含"@",这叫含头不含尾
String recipientNickName = recipientEmailAddress.get(i).substring(0,index);
address[i] = new InternetAddress(recipientEmailAddress.get(i),recipientNickName,"UTF-8");
}
message.setRecipients(Message.RecipientType.TO, address);*/
/**
* 3. To: 收件人(可以增加多个收件人、抄送、密送)
* Message.RecipientType.TO:消息接受者 展示接收者
* Message.RecipientType.CC:消息抄送者 展示抄送人
* Message.RecipientType.BCC:匿名抄送接收者(其他接受者看不到这个接受者的姓名和地址) 不展示接收者和抄送人
*/
// 设置收件人,单个
//获取最后一个"@"的位置
int index = recipientEmailAddress.lastIndexOf("@");
//不含"@",这叫含头不含尾
String recipientNickName = recipientEmailAddress.substring(0,index);
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(recipientEmailAddress,recipientNickName,"UTF-8"));
// 4. Subject: 邮件主题
message.setSubject("验证码", "UTF-8");
// 可选 设置发送邮件已读回执
message.addHeader("Disposition-Notification-To",emailAccount);
// 5. Content: 邮件正文(可以使用html标签)
int code = (int)(Math.random()*(9999-1000+1))+1000;
String emailContent = "您的验证码为:"+ code;
message.setText(emailContent, "UTF-8");
// 6. 设置发件时间
message.setSentDate(new Date());
// 7. 保存设置
message.saveChanges();
return message;
}
/**
* Java实现文本图片附件复杂的邮件发送
*/
private static MimeMessage complexEmail(Session session,String emailAccount,String recipientEmailAddress) throws UnsupportedEncodingException, MessagingException {
// 1. 创建一封邮件
MimeMessage message = new MimeMessage(session);
// 2. From: 发件人(标题处显示)
message.setFrom(new InternetAddress(emailAccount, "gremlin", "UTF-8"));
// 3. To: 收件人(可以增加多个收件人、抄送、密送)
/**
* Message.RecipientType.TO:消息接受者 展示接受者
* Message.RecipientType.CC:消息抄送者 展示抄送人
* Message.RecipientType.BCC:匿名抄送接收者(其他接受者看不到这个接受者的姓名和地址) 不展示接收者和抄送人
*/
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(recipientEmailAddress,recipientEmailAddress.substring(0,recipientEmailAddress.lastIndexOf("@")),"UTF-8"));
// 4. Subject: 邮件主题
message.setSubject("复杂的邮件带有附件", "UTF-8");
// 可选 设置发送邮件已读回执
message.addHeader("Disposition-Notification-To",emailAccount);
// 5. Content: 邮件正文
//准备图片数据
MimeBodyPart image = new MimeBodyPart();
DataHandler handler = new DataHandler(
new FileDataSource("D:/image/d932ca3f9b9e3e5c2c08e87a564b3e87.jpeg"));
image.setDataHandler(handler);
//设置图片id
image.setContentID("test.png");
//准备文本
MimeBodyPart text = new MimeBodyPart();
text.setContent("这是一段文本
<img src='cid:test.png'>","text/html;charset=utf-8");
//拼装邮件正文
MimeMultipart mimeMultipart = new MimeMultipart();
mimeMultipart.addBodyPart(image);
mimeMultipart.addBodyPart(text);
//文本和图片内嵌成功
mimeMultipart.setSubType("related");
//将拼装好的正文内容设置为主体
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(mimeMultipart);
//附件
MimeBodyPart appendix = new MimeBodyPart();
appendix.setDataHandler(
new DataHandler(
new FileDataSource(
"D:/image/earth.mp4")));
appendix.setFileName("earth.mp4");
//拼接附件
MimeMultipart allFile = new MimeMultipart();
//附件
allFile.addBodyPart(appendix);
//正文
allFile.addBodyPart(contentText);
//正文和附件都存在邮件中,所有类型设置为mixed
allFile.setSubType("mixed");
//放到Message消息中
message.setContent(allFile);
// 6. 设置发件时间
message.setSentDate(new Date());
// 7. 保存设置
message.saveChanges();
return message;
}
}
编写SendEmailController调用发送邮件
package com.gremlin.controller;
import com.gremlin.utils.SendEmailUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Description: 邮件接口
* @author: gremlin
* Date: 2022/3/4 10:54
* @version: 1.0.0
*/
@Slf4j
@Controller
@RequestMapping("email")
@Api(value = "邮件",tags = "邮件")
public class SendEmailController {
@PostMapping("sendEmail")
@ApiOperation(value = "邮件-发送邮件", notes = "邮件-发送邮件")
public void sendEmail(){
try {
SendEmailUtils.sendEmailConfig();
log.info("发送成功!");
}catch (Exception e){
log.info("发送异常!");
e.fillInStackTrace();
}
}
}