前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot入门建站全系列(十)邮件发送功能

SpringBoot入门建站全系列(十)邮件发送功能

原创
作者头像
品茗IT
修改2019-08-13 10:57:03
6680
修改2019-08-13 10:57:03
举报
文章被收录于专栏:品茗IT品茗IT

SpringBoot入门建站全系列(十)邮件发送功能

Spring Mail API都在org.springframework.mail及其子包org.springframework.mail.javamail中封装。

JavaMailSenderImpl: 邮件发送器,主要提供了邮件发送接口、透明创建Java Mail的MimeMessage、及邮件发送的配置(如:host/port/username/password...)。

MimeMailMessage、MimeMessageHelper:对MimeMessage进行了封装。Spring还提供了一个回调接口MimeMessagePreparator, 用于准备JavaMail的MIME信件.

SpringBoot对Email做了封装:[https://docs.spring.io/spring-boot/docs/2.0.9.RELEASE/reference/htmlsingle/#boot-features-email

](https://docs.spring.io/spring-boot/docs/2.0.9.RELEASE/reference/htmlsingle/#boot-features-email

)

直接读取配置,然后我们的Service逻辑可以直接注入JavaMailSender进行邮件发送。

一、配置

本文假设你已经引入spring-boot-starter-web。已经是个SpringBoot项目了,如果不会搭建,可以打开这篇文章看一看《SpringBoot入门建站全系列(一)项目建立》

1.1 Maven依赖
代码语言:txt
复制
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>fastjson</artifactId>
</dependency>

配置fastjson是因为我写的示例中用到了,用不到的话就可以去掉。

1.2 配置文件

application.properties 中需要添加下面的配置:

代码语言:txt
复制
spring.mail.host=smtp.qq.com
spring.mail.username=916881512@qq.com
spring.mail.password=xxxxx
spring.mail.port=465
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.ssl.enable=true
spring.mail.properties.mail.smtp.starttls.required=true 

mail.from=916881512@qq.com
mail.fromName=Admin

这里,

  • spring.mail.properties是额外的配置信息。
  • spring.mail.port这个很重要,我用的是465,是smtp的ssl端口,smtp一般是用25端口,但是很多云服务器把25端口禁用了,美其名曰安全。所以可以用465端口也发送邮件。如果想用25端口,后面的spring.mail.properties.*去掉即可。
  • mail.from和mail.fromName是业务逻辑需要的配置,不是SpringBoot自动装配的。
  • 其他配置文件都是见文知意了,不再说了。

SpringBoot官网配置文件说明:

代码语言:txt
复制
# Email (MailProperties)
spring.mail.default-encoding=UTF-8 # Default MimeMessage encoding.
spring.mail.host= # SMTP server host. For instance, `smtp.example.com`.
spring.mail.jndi-name= # Session JNDI name. When set, takes precedence over other Session settings.
spring.mail.password= # Login password of the SMTP server.
spring.mail.port= # SMTP server port.
spring.mail.properties.*= # Additional JavaMail Session properties.
spring.mail.protocol=smtp # Protocol used by the SMTP server.
spring.mail.test-connection=false # Whether to test that the mail server is available on startup.
spring.mail.username= # Login user of the SMTP server.

二、发送邮件业务逻辑

发送邮件时,需要指明发送人邮箱和名称。

代码语言:txt
复制
package com.cff.springbootwork.mail.service;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.cff.springbootwork.mail.type.*;

@Service
public class MailService {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	static final String DELIM_STR = "{}";

	@Autowired
	private JavaMailSender javaMailSender;
	
	@Value("${mail.from}")
	private String from;
	
	@Value("${mail.fromName}")
	private String fromName;
	
	/**
	 * 简单发送html内容
	 * 
	 * @param to
	 *            指定收件人
	 * @param subject
	 *            主题
	 * @param content
	 *            内容
	 * @param isHtml
	 *            是否是html
	 */
	public void sendSimpleMail(String to, String subject, String content, boolean isHtml) {
		MimeMessage message = javaMailSender.createMimeMessage();
		try {
			MimeMessageHelper helper = new MimeMessageHelper(message, true);
			helper.setFrom(from,fromName);
			helper.setTo(to);
			helper.setSubject(subject);
			helper.setText(content, isHtml);
			javaMailSender.send(message);
			logger.info("html邮件发送成功");
		} catch (MessagingException e) {
			logger.error("发送html邮件时发生异常!", e);
		} catch (UnsupportedEncodingException e) {
			logger.error("发送html邮件时发生异常!", e);
		}

	}

	/**
	 * 简单发送内嵌文件方法
	 * 
	 * @param to
	 *            指定收件人
	 * @param subject
	 *            主题
	 * @param content
	 *            内容
	 * @param rscPath
	 *            资源路径(文件路径)
	 * @param rscId
	 *            资源标识
	 */
	public void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId) {
		MimeMessage message = javaMailSender.createMimeMessage();

		try {
			MimeMessageHelper helper = new MimeMessageHelper(message, true);
			helper.setFrom(from,fromName);
			helper.setTo(to);
			helper.setSubject(subject);
			helper.setText(content, true);

			FileSystemResource res = new FileSystemResource(new File(rscPath));
			helper.addInline(rscId, res);

			javaMailSender.send(message);
			logger.info("嵌入静态资源的邮件已经发送。");
		} catch (MessagingException e) {
			logger.error("发送嵌入静态资源的邮件时发生异常!", e);
		} catch (UnsupportedEncodingException e) {
			logger.error("发送嵌入静态资源的邮件时发生异常!", e);
		}
	}

	/**
	 * 简单发送附件方法
	 * 
	 * @param to
	 *            指定收件人
	 * @param subject
	 *            主题
	 * @param content
	 *            内容
	 * @param filePath
	 *            附件地址,可传递多个
	 */
	public void sendAttachmentsMail(String to, String subject, String content, String[] filePaths) {
		System.getProperties().setProperty("mail.mime.splitlongparameters", "false");

		MimeMessage message = javaMailSender.createMimeMessage();
		try {
			MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8");
			helper.setFrom(from,fromName);
			helper.setTo(to);
			helper.setSubject(subject);
			helper.setText(content, true);

			for (String filePath : filePaths) {
				FileSystemResource file = new FileSystemResource(new File(filePath));
				String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
				helper.addAttachment(MimeUtility.encodeText(fileName), file);
			}

			javaMailSender.send(message);
			logger.info("带附件的邮件已经发送。");
		} catch (MessagingException e) {
			logger.error("发送带附件的邮件时发生异常!", e);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 完整发送邮件方法,需要调用setMailMessage方法配置邮件 {@link #setMailMessage(MailMessage)}
	 * <p>占位符使用{},内容中如果要使用{},就修改代码吧,这里不支持。
	 * @param content
	 *            带占位符正文
	 * @param mailTypes
	 *            可变参数,填充占位符
	 * @throws Exception 
	 */
	public void sendCompleteHtml(String content, List<MailType> mailTypes, MailMessage mailMessage) throws Exception {
		System.getProperties().setProperty("mail.mime.splitlongparameters", "false");
		if (mailMessage.getFrom() == null || "".equals(mailMessage.getFrom())) {
			mailMessage.setFrom(from);
			mailMessage.setFromName(fromName);
		}
		MimeMessage message = javaMailSender.createMimeMessage();
		MimeMessageHelper helper = new MimeMessageHelper(message, true);
		helper.setFrom(mailMessage.getFrom());
		helper.setTo(mailMessage.getTo());
		if (mailMessage.getCc() != null && mailMessage.getCc().length > 0)
			helper.setCc(mailMessage.getCc());
		helper.setSubject(mailMessage.getSubject());
		String msg = getContent(content, mailTypes);
		helper.setText(msg, true);
		for (MailType item : mailTypes) {
			switch (item.getType()) {
			case MailType.TYPE_FILE:
				if (item != null) {
					InlineFile inlineFile = (InlineFile) item;
					helper.addInline(inlineFile.getCid(), new File(inlineFile.getFilePath()));
				}
				break;
			case MailType.TYPE_ATTACH:
				if (item != null) {
					AttachFile attachFile = (AttachFile) item;
					helper.addAttachment(MimeUtility.encodeText(attachFile.getFileName()),
							new File(attachFile.getFilePath()));
				}
				break;
			}
		}
		try{
			javaMailSender.send(message);
		}catch(MailException e){
			logger.error("邮件发送过程出错,重发一次。",e);
			javaMailSender.send(message);
		}
		logger.info("完整的邮件已经发送。");

	}

	/**
	 * 解析占位符
	 *
	 * @param content
	 *            字符串,带占位符{},有多少个{},就要有多少个MailType
	 * @param mailTypes
	 *            MailType填充参数, 注:换行需主动添加
	 * @return 解析后的正文
	 * @throws MessagingException
	 * @throws IOException
	 */
	private String getContent(String content, List<MailType> mailTypes) throws MessagingException, IOException {
		String bodyPrefix = "<html><body>";
		String bodySuffix = "</body></html>";
		StringBuffer sb = new StringBuffer();
		sb.append(bodyPrefix);
		for (MailType item : mailTypes) {
			if (content.length() < 1)
				break;

			int index = content.indexOf(DELIM_STR);
			if (index == -1)
				break;
			sb.append(content.substring(0, index));
			switch (item.getType()) {
			case MailType.TYPE_FILE:
				if (item != null) {
					InlineFile inlineFile = (InlineFile) item;
					sb.append("<img src=\'cid:" + inlineFile.getCid() + "\' />");
				}
				break;
			case MailType.TYPE_TEXT:
				TextString textString = (TextString) item;
				sb.append(textString.getText());
				break;
			case MailType.TYPE_JSON:
				JsonTable json = (JsonTable) item;
				sb.append(genReportData(json));
				
				break;
			}
			content = content.substring(index + 2);
		}
		sb.append(content);
		sb.append(bodySuffix);
		return sb.toString();
	}

	/**
	 * 根据Json字符串,生成有序的表格
	 *
	 * @param jsonTable
	 *            json转table实体
	 * @return 表格字符串
	 * @throws IOException
	 */
	private String genReportData(JsonTable jsonTable) throws IOException {
		JSONArray ja = (JSONArray) JSON.parse(jsonTable.getData(), Feature.OrderedField);
		StringBuilder sb = new StringBuilder();
		try {
			sb.append("<table border=\"1\" style=\"border-collapse:collapse;font-size:14px\">\n");
			sb.append("<caption align = \"left\">");
			sb.append(jsonTable.getTitle());
			sb.append("</caption>\n");
			JSONObject jsonFirst = (JSONObject) ja.get(0);
			sb.append("<tr>\n");
			for (String key : jsonFirst.keySet()) {
				sb.append("<td>");
				sb.append(jsonFirst.get(key));
				sb.append("</td>\n");
			}

			sb.append("</tr>\n");
			ja.remove(0);
			for (Object column : ja) {
				sb.append("<tr>\n");
				JSONObject json = (JSONObject) column;
				for (String key : jsonFirst.keySet()) {
					sb.append("<td>");
					sb.append(json.get(key));
					sb.append("</td>\n");
				}

				sb.append("</tr>\n");
			}

			sb.append("</table>\n");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sb.toString();
	}

	public String getFrom() {
		return from;
	}

	public void setFrom(String from) {
		this.from = from;
	}

	public JavaMailSender getJavaMailSender() {
		return javaMailSender;
	}

	public void setJavaMailSender(JavaMailSender javaMailSender) {
		this.javaMailSender = javaMailSender;
	}

	public String getFromName() {
		return fromName;
	}

	public void setFromName(String fromName) {
		this.fromName = fromName;
	}
}

这里的MailService定义了多种邮件发送方式,包含普通文本、html、内嵌图片、附件、表格等。因此需要我们定义多种实体。

三、测试

新建一个MailRest,用来测试邮件发送:

代码语言:txt
复制
package com.cff.springbootwork.mail.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.cff.springbootwork.mail.service.MailService;


@RestController
@RequestMapping("/mail")
public class MailRest {
	@Autowired
	MailService mailService;
	
	@RequestMapping(value = "/mail/{to}", method = { RequestMethod.GET })
	public String mail(@PathVariable("to") String to) {
		String content = "直接登录网页  看发邮件吗,不能发的话 asdasd";
		mailService.sendSimpleMail(to, content, content, true);
		return "hello,world";
	}
	
}

四、过程中用到的邮件类型实体

MailMessage邮件实体:

代码语言:txt
复制
package com.cff.springbootwork.mail.type;

import java.util.ArrayList;
import java.util.List;

/**
 * mail实体,使用Builder生成   例: new MailMessage.Builder().to(to).build();
 * @author fufei
 *	
 */
public class MailMessage {
	private String from;
	private String fromName;
	private List<String> to;
	private List<String> cc;
	private String subject;

	MailMessage(Builder builder) {
		this.from = builder.from;
		this.to = builder.to;
		this.cc = builder.cc;
		this.subject = builder.subject;
		this.fromName = builder.fromName;
	}

	public static class Builder {
		private String from;
		private String fromName;
		private List<String> to = new ArrayList<String>();
		private List<String> cc = new ArrayList<String>();
		private String subject;

		public Builder() {

		}

		/**
		 * 添加发送人信息,为空则需要调用方主动设置
		 * @param from 发送人邮件字符串
		 * @return
		 */
		public Builder from(String from) {
			this.from = from;
			return this;
		}
		
		/**
		 * 添加发送人信息,为空则需要调用方主动设置
		 * @param from 发送人邮件字符串
		 * @return
		 */
		public Builder fromName(String fromName) {
			this.fromName = fromName;
			return this;
		}

		/**
		 * 添加收件人
		 * @param toAddr String
		 * @return
		 */
		public Builder addTo(String toAddr) {
			to.add(toAddr);
			return this;
		}
		
		/**
		 * 添加收件人列表
		 * @param toAddr String
		 * @return
		 */
		public Builder addTo(List<String> toAddr) {
			to.addAll(toAddr);
			return this;
		}

		/**
		 * 设置收件人列表
		 * @param to 收件人数组
		 * @return
		 */
		public Builder to(List<String> to) {
			this.to = to;
			return this;
		}

		/**
		 * 添加抄送人
		 * @param ccAddr
		 * @return
		 */
		public Builder addCc(String ccAddr) {
			cc.add(ccAddr);
			return this;
		}
		
		/**
		 * 添加抄送人列表
		 * @param ccAddr
		 * @return
		 */
		public Builder addCc(List<String> ccAddr) {
			cc.addAll(ccAddr);
			return this;
		}

		/**
		 * 设置抄送人列表
		 * @param cc
		 * @return
		 */
		public Builder cc(List<String> cc) {
			this.cc = cc;
			return this;
		}

		/**
		 * 设置主题
		 * @param subject
		 * @return
		 */
		public Builder subject(String subject) {
			this.subject = subject;
			return this;
		}
		
		/**
		 * 生成MailMessage
		 * @return MailMessage
		 */
		public MailMessage build() {
			if (to.size() < 1)
				throw new IllegalStateException("邮件接收人为空!");
			return new MailMessage(this);
		}
	}

	public String getFrom() {
		return from;
	}

	public void setFrom(String from) {
		this.from = from;
	}

	public String getFromName() {
		return fromName;
	}

	public void setFromName(String fromName) {
		this.fromName = fromName;
	}

	public String[] getTo() {
		String[] array = new String[to.size()];
		String[] s = to.toArray(array);
		return s;
	}

	public String[] getCc() {
		if (cc.size() < 1)
			return null;
		String[] array = new String[cc.size()];
		String[] s = cc.toArray(array);
		return s;
	}

	public String getSubject() {
		return subject;
	}
}

MailType邮件类型接口:

代码语言:txt
复制
package com.cff.springbootwork.mail.type;

/**
 * 邮件类型
 * @author fufei
 *
 */
public abstract class MailType {
	public final static char TYPE_FILE = 'F';
	public final static char TYPE_ATTACH = 'A';
	public final static char TYPE_TEXT = 'T';
	public final static char TYPE_JSON = 'J';

	public abstract char getType();
}

详细完整的邮件类型,可以访问品茗IT-博客《SpringBoot入门建站全系列(十)邮件发送功能》进行查看

快速构建项目

Spring组件化构建

SpringBoot组件化构建

SpringCloud服务化构建

喜欢这篇文章么,喜欢就加入我们一起讨论SpringBoot技术吧!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SpringBoot入门建站全系列(十)邮件发送功能
    • 一、配置
      • 1.1 Maven依赖
      • 1.2 配置文件
    • 二、发送邮件业务逻辑
      • 三、测试
        • 四、过程中用到的邮件类型实体
          • 快速构建项目
          相关产品与服务
          网站建设
          网站建设(Website Design Service,WDS),是帮助您快速搭建企业网站的服务。通过自助模板建站工具及专业设计服务,无需了解代码技术,即可自由拖拽模块,可视化完成网站管理。全功能管理后台操作方便,一次更新,数据多端同步,省时省心。使用网站建设服务,您无需维持技术和设计师团队,即可快速实现网站上线,达到企业数字化转型的目的。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档