更多SpringBoot3内容请关注我的专栏:《SpringBoot3》
期待您的点赞👍收藏⭐评论✍
重学SpringBoot3-如何发送 Email
在企业应用开发中,发送邮件是一个非常常见的需求,比如用户注册验证、密码重置、系统通知等场景。SpringBoot 3提供了完善的邮件发送支持,本文将详细介绍如何在SpringBoot 3中实现邮件发送功能,并提供最佳实践建议。
1. 环境准备
- JDK 17+
- SpringBoot 3.0+
- Maven/Gradle
2. 项目配置
2.1 添加依赖
在
pom.xml
中添加以下依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
2.2 配置邮件服务器
在
application.yml
中添加邮件服务器配置:
spring:mail:host: smtp.qq.com # QQ邮件服务器地址port:587# 端口号username: ${username}password: ${password}# 需要去QQ邮箱开通开通POP3/IMAP服务,并设置专用密码properties:mail:smtp:auth:truestarttls:enable:truerequired:truethymeleaf:cache:truecheck-template:truecheck-template-location:truecontent-type: text/html
enabled:trueencoding: UTF-8excluded-view-names:''mode: HTML
prefix: classpath:/templates/
suffix: .html
3. 代码实现
3.1 创建邮件服务接口
packagecom.example.springboot3email.service;importorg.springframework.web.multipart.MultipartFile;/**
* @author CoderJia
* @create 2024/11/21 10:22
* @Description
**/publicinterfaceIEmailService{voidsendSimpleEmail(Stringto,String subject,String text);voidsendHtmlEmail(Stringto,String subject,String htmlContent);voidsendEmailWithAttachment(Stringto,String subject,String text,MultipartFile attachment);}
3.2 实现邮件服务
packagecom.example.springboot3email.service;importjakarta.annotation.Resource;importjakarta.mail.internet.MimeMessage;importlombok.extern.slf4j.Slf4j;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.core.io.FileSystemResource;importorg.springframework.mail.SimpleMailMessage;importorg.springframework.mail.javamail.JavaMailSender;importorg.springframework.mail.javamail.MimeMessageHelper;importorg.springframework.stereotype.Service;importorg.springframework.web.multipart.MultipartFile;importjava.io.File;/**
* @author CoderJia
* @create 2024/11/21 10:23
* @Description
**/@Service@Slf4jpublicclassEmailServiceImplimplementsIEmailService{@ResourceprivateJavaMailSender mailSender;@Value("${spring.mail.username}")privateString from;/**
* 发送简单文本邮件
*
* @param to
* @param subject
* @param text
*/@OverridepublicvoidsendSimpleEmail(Stringto,String subject,String text){try{SimpleMailMessage message =newSimpleMailMessage();
message.setFrom(from);
message.setTo(to);
message.setSubject(subject);
message.setText(text);
mailSender.send(message);
log.info("Simple email sent successfully to: {}",to);}catch(Exception e){
log.error("Failed to send simple email", e);thrownewRuntimeException("Failed to send email", e);}}/**
* 发送HTML格式的邮件
*
* @param to
* @param subject
* @param htmlContent
*/@OverridepublicvoidsendHtmlEmail(Stringto,String subject,String htmlContent){try{MimeMessage message = mailSender.createMimeMessage();MimeMessageHelper helper =newMimeMessageHelper(message,true,"UTF-8");
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(htmlContent,true);
mailSender.send(message);
log.info("HTML email sent successfully to: {}",to);}catch(Exception e){
log.error("Failed to send HTML email", e);thrownewRuntimeException("Failed to send email", e);}}/**
* 发送带附件的邮件
*
* @param to
* @param subject
* @param text
* @param attachment
*/@OverridepublicvoidsendEmailWithAttachment(Stringto,String subject,String text,MultipartFile attachment){try{MimeMessage message = mailSender.createMimeMessage();MimeMessageHelper helper =newMimeMessageHelper(message,true,"UTF-8");
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text);// 创建临时文件File tempFile =File.createTempFile("upload_", attachment.getOriginalFilename());
attachment.transferTo(tempFile);// 使用 FileSystemResource 包装临时文件FileSystemResource file =newFileSystemResource(tempFile);
helper.addAttachment(attachment.getOriginalFilename(), file);
mailSender.send(message);
log.info("Email with attachment sent successfully to: {}",to);// 删除临时文件
tempFile.delete();}catch(Exception e){
log.error("Failed to send email with attachment", e);thrownewRuntimeException("Failed to send email", e);}}}
3.3 创建邮件模板
在
resources/templates
目录下创建HTML模板
EmailTemplate.html
(使用Thymeleaf):
<!DOCTYPEhtml><htmlxmlns:th="http://www.thymeleaf.org"><head><title>Email Template</title></head><body><h1>Welcome, <spanth:text="${name}">User</span>!</h1><p>This is a sample email template using Thymeleaf.</p><p>Your verification code is: <strongth:text="${code}">123456</strong></p></body></html>
3.4 使用模板发送邮件
@ServicepublicclassTemplateEmailService{@AutowiredprivateEmailService emailService;@AutowiredprivateTemplateEngine templateEngine;publicvoidsendTemplateEmail(Stringto,String subject,String templateName,Map<String,Object> variables){Context context =newContext();
variables.forEach(context::setVariable);String htmlContent = templateEngine.process(templateName, context);
emailService.sendHtmlEmail(to, subject, htmlContent);}}
4. 最佳实践建议
4.1 异步发送
为避免邮件发送影响主业务流程,建议使用异步方式发送邮件:
@Configuration@EnableAsyncpublicclassAsyncConfigimplementsAsyncConfigurer{@OverridepublicExecutorgetAsyncExecutor(){ThreadPoolTaskExecutor executor =newThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("EmailAsync-");
executor.initialize();return executor;}}@ServicepublicclassAsyncEmailService{@AsyncpublicCompletableFuture<Void>sendEmailAsync(Stringto,String subject,String content){// 邮件发送逻辑returnCompletableFuture.completedFuture(null);}}
4.2 重试机制
实现邮件发送重试机制:
@ServicepublicclassRetryableEmailService{@Retryable(value ={MessagingException.class},
maxAttempts =3,
backoff =@Backoff(delay =1000))publicvoidsendEmailWithRetry(Stringto,String subject,String content){// 邮件发送逻辑}@Recoverpublicvoidrecover(MessagingException e,Stringto){// 处理最终失败的情况
log.error("Failed to send email after retries", e);}}
4.3 邮件发送限流
使用令牌桶算法实现邮件发送限流:
@ServicepublicclassRateLimitedEmailService{privatefinalRateLimiter rateLimiter =RateLimiter.create(10.0);// 每秒10封邮件publicvoidsendEmailWithRateLimit(Stringto,String subject,String content){if(rateLimiter.tryAcquire()){// 发送邮件}else{thrownewRuntimeException("Rate limit exceeded");}}}
4.4 邮件发送记录
记录邮件发送历史:
@Entity@Table(name ="email_log")publicclassEmailLog{@Id@GeneratedValue(strategy =GenerationType.IDENTITY)privateLong id;privateStringto;privateString subject;privateLocalDateTime sendTime;privateEmailStatus status;privateString errorMessage;// getters and setters}
5. 安全性建议
- 不要在代码中硬编码邮件服务器凭证
- 使用环境变量或配置中心存储敏感信息
- 实现邮件发送频率限制,防止滥用
- 记录邮件发送日志,便于问题排查
- 使用TLS/SSL加密传输
- 定期轮换邮件服务器密码
6. 测试示例
packagecom.example.springboot3email.controller;importcom.example.springboot3email.service.IEmailService;importcom.example.springboot3email.service.TemplateEmailService;importjakarta.annotation.Resource;importlombok.extern.slf4j.Slf4j;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;importorg.springframework.web.multipart.MultipartFile;importjava.util.HashMap;importjava.util.Map;/**
* @author CoderJia
* @create 2024/11/21 10:32
* @Description
**/@Slf4j@RestControllerpublicclassEmailController{@ResourceprivateIEmailService emailService;@ResourceprivateTemplateEmailService templateEmailService;// 发送简单文本邮件接口@PostMapping("/sendSimpleEmail")publicStringsendSimpleEmail(@RequestParam("to")Stringto,@RequestParam("subject")String subject,@RequestParam("text")String text){
emailService.sendSimpleEmail(to, subject, text);return"success";}// 发送HTML邮件接口@PostMapping("/sendHtmlEmail")publicStringsendHtmlEmail(@RequestParam("to")Stringto,@RequestParam("subject")String subject,@RequestParam("htmlContent")String htmlContent){
emailService.sendHtmlEmail(to, subject, htmlContent);return"success";}// 发送带附件的邮件接口@PostMapping("/sendEmailWithAttachment")publicStringsendEmailWithAttachment(@RequestParam("to")Stringto,@RequestParam("subject")String subject,@RequestParam("text")String text,@RequestParam("attachment")MultipartFile attachment){
emailService.sendEmailWithAttachment(to, subject, text, attachment);return"success";}// 发送模板邮件接口@PostMapping("/sendTemplateEmail")publicStringsendTemplateEmail(@RequestParam("to")Stringto,@RequestParam("subject")String subject,@RequestParam("templateName")String templateName){Map<String,Object> variables =newHashMap<>();
variables.put("name","CoderJia");
variables.put("code",12530);
templateEmailService.sendTemplateEmail(to, subject, templateName, variables);return"success";}}
发送效果
普通邮件
HTML邮件
带附件邮件
模板邮件
7. 常见问题解决
7.1 连接超时
spring:mail:properties:mail:smtp:connectiontimeout:5000timeout:5000writetimeout:5000
7.2 SSL证书问题
spring:mail:properties:mail:smtp:ssl:trust:"*"
7.3 中文乱码
helper.setFrom(newInternetAddress(from,"发件人名称","UTF-8"));
8. 总结
本文详细介绍了在SpringBoot 3中实现邮件发送功能的完整解决方案,包括基本配置、代码实现、最佳实践、安全建议等内容。通过采用异步发送、重试机制、限流等最佳实践,可以构建一个健壮的邮件发送系统。在实际应用中,要根据具体需求选择合适的实现方式,同时注意安全性和性能的平衡。
版权归原作者 CoderJia_ 所有, 如有侵权,请联系我们删除。