赞
踩
发送邮件常用的有163邮箱,qq邮箱,其中发送邮件的协议叫SMTP,接收邮件的协议叫POP3/IMAP,IMAP协议比POP3更强大,不过我们不需要要关注,因为服务器集成邮件只会涉及到发送邮件,一般不涉及接收邮件。
我们已163邮箱为例来讲解,首先要开通允许客户端发送邮件的功能
登录进163邮箱后,点击设置
选择开启服务,下面两个随便哪个都可以,点击开启后会提示扫码发送短信,发完短信会显示授权码, 这个授权码只会显示一次,要记录下来,后面会用到
接下来就是代码阶段了
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-mail</artifactId>
- </dependency>
- spring:
- mail:
- #smtp服务主机 qq邮箱则为smtp.qq.com
- host: smtp.163.com
- port: 465 #端口不要使用默认的25,阿里云无法开通这个端口,使用465
- protocol: smtps
- # 编码集
- default-encoding: UTF-8
- #发送邮件的账户
- username: xxxxxxx@163.com
- #授权码
- password: xxxxxx
- test-connection: true
- properties:
- mail:
- smtp:
- auth: true
- starttls:
- enable: true
- required: true
- @Service
- public class EmailService {
- @Value("${spring.mail.username}")
- private String from;
- @Autowired
- private JavaMailSender mailSender;
-
- /**
- * 发送纯文本邮件
- *
- * @param tos 接收方
- * @param subject 主题
- * @param content 邮件内容
- * @return
- */
- public void sendTxtMail(String[] tos, String subject, String content) {
- //创建简单邮件消息
- SimpleMailMessage message = new SimpleMailMessage();
- message.setFrom(from);
- message.setTo(tos);
- message.setSubject(subject);
- message.setText(content);
- try {
- mailSender.send(message);
- } catch (MailException e) {
- e.printStackTrace();
- throw new ServiceFailException("发送邮件失败", e);
- }
- }
- }
- public void sendHtmlEmail(String[] tos, String subject, String html) {
- try {
- //创建一个MINE消息
- MimeMessage message = mailSender.createMimeMessage();
- MimeMessageHelper minehelper = new MimeMessageHelper(message, true);
- minehelper.setFrom(from);
- minehelper.setTo(tos);
- minehelper.setSubject(subject);
- //邮件内容 true 表示带有附件或html
- minehelper.setText(html, true);
- mailSender.send(message);
- } catch (Exception e) {
- throw new ServiceFailException("发送邮件失败", e);
- }
- }
由于发送附件的时间较长,所有我们用@Async注解做成异步的,SpringBoot的异步线程只有一个,所以并发量大的话会有延迟,有条件的话可以把发送邮件的任务放入MQ,然后从MQ中取出再执行。需要注意的是发送Multipart不能异步,因为Multipart文件在上传时会创建一个临时文件,一旦请求结束这个文件就会被删除
- /**
- * 发送带附件的邮件,附件格式为Multipart
- *
- * @param tos
- * @param subject
- * @param html
- * @param files
- */
- public void sendMultipartEmail(String[] tos, String subject, String html, List<MultipartFile> files) {
- List<File> list = new ArrayList<>();
- List<ResourceBean> resourceBeans = new ArrayList<>();
- if (CollectionUtils.isNotEmpty(files)) {
- for (MultipartFile multipartFile : files) {
- //把multipart转成file
- Optional<File> optionalFile = FileUtils.multipartFileToFile(multipartFile);
- //存在则放入list
- optionalFile.ifPresent(file -> {
- list.add(file);
- resourceBeans.add(new ResourceBean(new FileSystemResource(file), multipartFile.getOriginalFilename()));
- });
- }
- }
- sendResourceEmail(tos, subject, html, resourceBeans);
- //发送完删除临时文件
- for (File file : list) {
- file.delete();
- }
- }
-
- /**
- * 发送带附件的邮件,File格式
- *
- * @param tos
- * @param subject
- * @param html
- * @param files
- */
- @Async
- public void sendHtmlEmail(String[] tos, String subject, String html, List<File> files) {
- List<ResourceBean> resourceBeans = files.stream().map(file -> new ResourceBean(new FileSystemResource(file), file.getName())).collect(Collectors.toList());
- sendResourceEmail(tos, subject, html, resourceBeans);
- }
-
- private void sendResourceEmail(String[] tos, String subject, String html, List<ResourceBean> resourceBeans) {
- //创建一个MINE消息
- MimeMessage message = mailSender.createMimeMessage();
- try {
- MimeMessageHelper helper = new MimeMessageHelper(message, true);
- helper.setFrom(from);
- helper.setTo(tos);
- helper.setSubject(subject);
- //邮件内容 true 表示带有附件或html
- helper.setText(html, true);
- if (CollectionUtils.isNotEmpty(resourceBeans)) {
- for (ResourceBean resourceBean : resourceBeans) {
- //添加附件
- helper.addAttachment(resourceBean.getFilename(), resourceBean.getResource());
- }
- }
- mailSender.send(message);
- } catch (Exception e) {
- throw new ServiceFailException("发送邮件失败", e);
- }
- }
-
- @Getter
- @Setter
- @AllArgsConstructor
- static class ResourceBean {
- FileSystemResource resource;
- String filename;
- }
下面是MultipartFile转File的方法
- /**
- * multiFile转成file,在本地生成一个文件,文件名随机,使用完需删除
- *
- * @param multiFile 要转换的文件
- * @return
- */
- public static Optional<File> multipartFileToFile(MultipartFile multiFile) {
- // 获取文件名
- String fileName = multiFile.getOriginalFilename();
- // 获取文件后缀
- String prefix = getExtention(fileName);
- try {
- File file = File.createTempFile(UUIDUtils.getUUID(), prefix);
- file.deleteOnExit();
- multiFile.transferTo(file);
- return Optional.of(file);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return Optional.empty();
- }
我们使用thymeleaf作为模板来发送邮件,首先引入依赖
- <!-- thymeleaf模板 -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-thymeleaf</artifactId>
- </dependency>
加入配置项,所有模板放在类路径的templates下面并且以html结尾
- spring:
- thymeleaf:
- cache: false
- mode: LEGACYHTML5
- prefix: classpath:/templates/
- suffix: .html
然后在建一个mail.html
- <!DOCTYPE html>
- <html lang="en" xmlns:th="http://www.thymeleaf.org">
- <head>
- <meta charset="UTF-8">
- <title>邮件模板</title>
- </head>
- <body>
- <p>您好,感谢您的注册,这时一封验证邮件,请点击下面的链接完成注册!</p>
- <a href="#" th:href="@{http://www.baidu.com(id=${id})}">点我完成注册</a>
- </body>
- </html>
使用templateEngine拿到模板和参数,渲染成html, 之后就跟发送html邮件一样了
- @Async
- public void sendTemplateEmail(String[] tos, String subject, String templateName, Map<String, Object> params) {
- Context context = new Context();
- //设置参数
- if (params != null) {
- Set<Map.Entry<String, Object>> entrySet = params.entrySet();
- entrySet.stream().forEach(entry -> context.setVariable(entry.getKey(), entry.getValue()));
- }
- //渲染模板,获得html内容
- String html = templateEngine.process("email/" + templateName, context);
- sendHtmlEmail(tos, subject, html);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。