<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
spring:
mail:
host: smtp.163.com
port: 25
username: your_email@163.com
password: your_auth_code # 授權碼,非登錄密碼
protocol: smtp
default-encoding: UTF-8
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
ssl:
enable: false
# 自定義發件人
mail.from: your_email@163.com
@Service
public class MailService {
@Autowired private JavaMailSender mailSender;
@Value("${spring.mail.from}") private String from;
/** 發送純文本郵件 */
public void sendSimpleMail(String to, String subject, String content) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(to);
message.setSubject(subject);
message.setText(content);
mailSender.send(message);
}
/** 發送 HTML 富文本郵件 */
public void sendHtmlMail(String to, String subject, String htmlContent) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(htmlContent, true); // true = HTML
mailSender.send(message);
}
/** 發送帶附件郵件 */
public void sendWithAttachment(String to, String subject, String text,
String filePath, String fileName) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text);
FileSystemResource file = new FileSystemResource(new File(filePath));
helper.addAttachment(MimeUtility.encodeText(fileName), file);
mailSender.send(message);
}
/** 發送帶內嵌圖片的 HTML 郵件 */
public void sendWithInlineImage(String to, String subject, String html,
String imgPath, String contentId) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(html, true);
FileSystemResource res = new FileSystemResource(new File(imgPath));
helper.addInline(contentId, res); // HTML 中用 <img src="cid:contentId">
mailSender.send(message);
}
}
@RestController
@RequestMapping("/api/mail")
public class MailController {
@Autowired private MailService mailService;
@PostMapping("/simple")
public Result sendSimple(@RequestParam String to, @RequestParam String subject, @RequestParam String content) {
mailService.sendSimpleMail(to, subject, content);
return Result.success();
}
@PostMapping("/attachment")
public Result sendAttach(@RequestParam String to, @RequestParam String subject,
@RequestParam String text, @RequestParam MultipartFile file) throws Exception {
// 保存臨時文件或直接用 InputStreamResource
File temp = File.createTempFile("mail_", "_" + file.getOriginalFilename());
file.transferTo(temp);
mailService.sendWithAttachment(to, subject, text, temp.getAbsolutePath(), file.getOriginalFilename());
return Result.success();
}
}
| 問題 | 原因與解決 |
|---|---|
| 535 Error: Authentication failed | 使用授權碼而非登錄密碼;確認 SMTP 服務已在郵箱開啟 |
| Could not connect to SMTP host | 端口錯誤(25/465/587),防火牆攔截,或需 SSL/TLS |
| 附件中文名亂碼 | 使用 MimeUtility.encodeText() 編碼文件名 |
| 大附件發送失敗 | 調整 spring.mail.properties.mail.smtp.maxsize 或分卷壓縮 |
@Async("mailExecutor")
public void sendAsync(...) { ... }
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean("mailExecutor")
public Executor mailExecutor() {
ThreadPoolTaskExecutor ex = new ThreadPoolTaskExecutor();
ex.setCorePoolSize(5);
ex.setMaxPoolSize(20);
ex.setQueueCapacity(100);
ex.setThreadNamePrefix("mail-");
ex.initialize();
return ex;
}
}
結合 @Async 實現非阻塞發送,提升 API 響應速度。