android javamail获取邮件太多太慢_结合 Spring 发送邮件的4种正确姿势,你知道几种?...

9403e659e802a05bf6969ef5c5c48e79.png
Java程序猿阿谷:面试字节跳动三轮凉凉,内推4面终拿下抖音offer(Java后台研发)​zhuanlan.zhihu.com
3013ce4402373df2a7b7e3d5cedfd9cb.png

一、前言

测试所使用的环境

测试使用的环境是企业主流的SSM 框架即 SpringMVC+Spring+Mybatis。为了节省时间,我直接使用的是我上次的“SSM项目中整合Echarts开发”该项目已经搭建完成的SSM环境。

标题说的四种姿势指的是哪四种姿势?

  1. 发送text格式的邮件
  2. 发送HTML格式的邮件
  3. 基于FreeMarker模板引擎发送邮件
  4. 基于Velocity模板引擎发送邮件

如何获取以及运行我的Demo

Github地址:http://github.com/Snailclimb/…。

你可以选择直接下载或者直接在DOS窗口运行:git clone https://github.com/Snailclimb/J2ee-Advanced.git命令,这样项目就被拷贝到你的电脑了。

bcad67b178e7be6d92c4b0f28ac95d32.png

然后选择导入Maven项目即可(不懂Maven的可以自行百度学习).

二、准备工作

既然要发送邮件,那么你首先要提供一个能在第三方软件上发送邮件功能的账号。在这里,我选择的网易邮箱账号。

我拿网易邮箱账号举例子,那么我们如何才能让你的邮箱账号可以利用第三方发送邮件(这里的第三方就是我们即将编写的程序)。

大家应该清楚:客户端和后台交互数据的时候用到了Http协议,那么相应的,邮箱传输也有自己的一套协议,如SMTP,POP3,IMAP。

开启POP3/SMTP/IMAP服务

所以,我们第一步首先要去开启这些服务,如下图所示:

bfa2a41ed35ffaa88b8d9a20254835f9.png

如果你未开启该服务的话,运行程序会报如下错误(配置文件中配置的密码是你的授权码而不是你登录邮箱的密码,授权码是你第三方登录的凭证):

HTTP Status 500 - Request processing failed; nested exception is org.springframework.mail.MailAuthenticationException: Authentication failed; nested exception is javax.mail.AuthenticationFailedException: 550 User has no permission

JavaMail介绍

我们需要用到的发邮件的核心jar包,所以这里好好介绍一下。

JavaMail是由Sun定义的一套收发电子邮件的API,不同的厂商可以提供自己的实现类。但它并没有包含在JDK中,而是作为JavaEE的一部分。厂商所提供的JavaMail服务程序可以有选择地实现某些邮件协议,常见的邮件协议包括:

  • SMTP:简单邮件传输协议,用于发送电子邮件的传输协议;
  • POP3:用于接收电子邮件的标准协议;
  • IMAP:互联网消息协议,是POP3的替代协议。

这三种协议都有对应SSL加密传输的协议,分别是SMTPS,POP3S和IMAPS。

我们如果要使用JavaMail的话,需要自己引用相应的jar包,如下图所示:

<dependency>
			<groupId>javax.mail</groupId>
			<artifactId>mail</artifactId>
			<version>1.4.7</version>
		</dependency>

相关配置文件

下图是除了pom.xml之外用到的其他所有配置文件

1cac0c170db42deccd26d888630bfb5c.png

pom.xml

需要用到的jar包。

<!--spring支持-->
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context-support</artifactId>
 <version>5.0.0.RELEASE</version>
 </dependency>
		<!-- 发送邮件 -->
		<dependency>
			<groupId>javax.mail</groupId>
			<artifactId>mail</artifactId>
			<version>1.4.7</version>
		</dependency>
		<!-- Freemarker -->
		<dependency>
			<groupId>org.freemarker</groupId>
			<artifactId>freemarker</artifactId>
			<version>2.3.23</version>
		</dependency>
		<!-- velocity模板引擎 -->
		<dependency>
			<groupId>org.apache.velocity</groupId>
			<artifactId>velocity</artifactId>
			<version>1.7</version>
		</dependency>
		<dependency>
			<groupId>org.apache.velocity</groupId>
			<artifactId>velocity-tools</artifactId>
			<version>2.0</version>
		</dependency>

mail.properties

#服务器主机名
mail.smtp.host=smtp.163.com
#你的邮箱地址
mail.smtp.username=koushuangbwcx@163.com
#你的授权码
mail.smtp.password=cSdN153963000
#编码格式
mail.smtp.defaultEncoding=utf-8
#是否进行用户名密码校验
mail.smtp.auth=true
#设置超时时间
mail.smtp.timeout=20000

如果你的授权码填写错误的话,会报如下错误:

TTP Status 500 - Request processing failed; nested exception is org.springframework.mail.MailAuthenticationException: Authentication failed; nested exception is javax.mail.AuthenticationFailedException: 535 Error: authentication failed

velocity.properties

input.encoding=UTF-8 
output.encoding=UTF-8 
contentType=ext/html;charset=UTF-8
directive.foreach.counter.name=loopCounter 
directive.foreach.counter.initial.value=0

applicationContext-email.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
 http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-4.0.xsd
 http://www.springframework.org/schema/tx 
 http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
 http://www.springframework.org/schema/aop 
 http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
	<!--邮件配置 -->
	<context:property-placeholder location="classpath:mail.properties"
		ignore-unresolvable="true" />
	<!--配置邮件接口 -->
	<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
		<property name="host" value="${mail.smtp.host}" />
		<property name="username" value="${mail.smtp.username}" />
		<property name="password" value="${mail.smtp.password}" />
		<property name="defaultEncoding" value="${mail.smtp.defaultEncoding}" />
		<property name="javaMailProperties">
			<props>
				<prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
				<prop key="mail.smtp.timeout">${mail.smtp.timeout}</prop>
			</props>
		</property>
	</bean>
	<!-- freemarker -->
	<bean id="configuration"
		class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
		<property name="templateLoaderPath" value="/WEB-INF/freemarker/" />
		<!-- 设置FreeMarker环境变量 -->
		<property name="freemarkerSettings">
			<props>
				<prop key="default_encoding">UTF-8</prop>
			</props>
		</property>
	</bean>
	<!-- velocity -->
	<bean id="velocityEngine"
		class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
		<property name="resourceLoaderPath" value="/WEB-INF/velocity/" /><!-- 
			模板存放的路径 -->
		<property name="configLocation" value="classpath:velocity.properties" /><!-- 
			Velocity的配置文件 -->
	</bean>
</beans>

三、开始编写工具类

我这里说是工具类,其实只是我自己做了简单的封装,实际项目使用的话,可能会需要根据需要简单修改一下。

所有用到的类如下图所示:

34ebfb2186e7ba664b257b915981ac3e.png

发送Text或者HTML格式的邮件的方法

/**
	 * 
	 * Text或者HTML格式邮件的方法
	 * 
	 * @param text
	 * 要发送的内容
	 * @param subject
	 * 邮件的主题也就是邮件的标题
	 * @param location
	 * 文件的地址
	 * @param emailAdress
	 * 目的地
	 * @param javaMailSender
	 * 发送邮件的核心类(在xml文件中已经配置好了)
	 * @param type
	 * 如果为true则代表发送HTML格式的文本
	 * @return
	 * @throws TemplateException
	 */
	public String sendMail(String text, String subject, String location, String emailAdress,
			JavaMailSender javaMailSender, Boolean type) {
		MimeMessage mMessage = javaMailSender.createMimeMessage();// 创建邮件对象
		MimeMessageHelper mMessageHelper;
		Properties prop = new Properties();
		try {
			// 从配置文件中拿到发件人邮箱地址
			prop.load(this.getClass().getResourceAsStream("/mail.properties"));
			String from = prop.get("mail.smtp.username") + "";
			mMessageHelper = new MimeMessageHelper(mMessage, true, "UTF-8");
			// 发件人邮箱
			mMessageHelper.setFrom(from);
			// 收件人邮箱
			mMessageHelper.setTo(emailAdress);
			// 邮件的主题也就是邮件的标题
			mMessageHelper.setSubject(subject);
			// 邮件的文本内容,true表示文本以html格式打开
			if (type) {
				mMessageHelper.setText(text, true);
			} else {
				mMessageHelper.setText(text, false);
			}
			// 通过文件路径获取文件名字
			String filename = StringUtils.getFileName(location);
			// 定义要发送的资源位置
			File file = new File(location);
			FileSystemResource resource = new FileSystemResource(file);
			FileSystemResource resource2 = new FileSystemResource("D:/email.txt");
			mMessageHelper.addAttachment(filename, resource);// 在邮件中添加一个附件
			mMessageHelper.addAttachment("JavaApiRename.txt", resource2);//
			// 在邮件中添加一个附件
			javaMailSender.send(mMessage);// 发送邮件
		} catch (MessagingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "发送成功";
	}

我在sendMail()方法中添加了一个boolean类型的变量type作为标志,如果为ture就表示发送html格式的邮件否则直接发送text格式的邮件。实现起来很简单,我们通过下面的判断语句就可以实现了

if (type) {
		 //表示文本以html格式打开
				mMessageHelper.setText(text, true);
			} else {
				mMessageHelper.setText(text, false);
			}

效果:

fb3589249d9a5c29e6d20246c9629fd9.png

基于FreeMarker模板引擎发送邮件

下图是我们用到的FreeMarker模板文件以及Velocity模板文件的位置。

6f85cd02db7220feaaa8842c37e815e0.png
/**
	 * FreeMarker模板格式的邮件的方法
	 * 
	 * @param subject
	 * 邮件的主题也就是邮件的标题
	 * @param location
	 * 文件的地址
	 * @param emailAdress
	 * 目的地
	 * @param javaMailSender
	 * 发送邮件的核心类(在xml文件中已经配置好了)
	 * @param freeMarkerConfiguration
	 * freemarker配置管理类
	 * @return
	 * @throws TemplateException
	 */
	public String sendMailFreeMarker(String subject, String location, String emailAdress, JavaMailSender javaMailSender,
			Configuration freeMarkerConfiguration) {
		MimeMessage mMessage = javaMailSender.createMimeMessage();// 创建邮件对象
		MimeMessageHelper mMessageHelper;
		Properties prop = new Properties();
		try {
			// 从配置文件中拿到发件人邮箱地址
			prop.load(this.getClass().getResourceAsStream("/mail.properties"));
			String from = prop.get("mail.smtp.username") + "";
			mMessageHelper = new MimeMessageHelper(mMessage, true);
			// 发件人邮箱
			mMessageHelper.setFrom(from);
			// 收件人邮箱
			mMessageHelper.setTo(emailAdress);
			// 邮件的主题也就是邮件的标题
			mMessageHelper.setSubject(subject);
			// 解析模板文件
			mMessageHelper.setText(getText(freeMarkerConfiguration), true);
			// 通过文件路径获取文件名字
			String filename = StringUtils.getFileName(location);
			// 定义要发送的资源位置
			File file = new File(location);
			FileSystemResource resource = new FileSystemResource(file);
			mMessageHelper.addAttachment(filename, resource);// 在邮件中添加一个附件
			javaMailSender.send(mMessage);// 发送邮件
		} catch (MessagingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "发送成功";
	}
	
 	/**
	 * 读取freemarker模板的方法
	 */
	private String getText(Configuration freeMarkerConfiguration) {
		String txt = "";
		try {
			Template template = freeMarkerConfiguration.getTemplate("email.ftl");
			// 通过map传递动态数据
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("user", "Snailclimb");
			// 解析模板文件
			txt = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
			System.out.println("getText()->>>>>>>>>");// 输出的是HTML格式的文档
			System.out.println(txt);
		} catch (IOException e) {
			// TODO 异常执行块!
			e.printStackTrace();
		} catch (TemplateException e) {
			// TODO 异常执行块!
			e.printStackTrace();
		}
		return txt;
	}

我们通过getText(Configuration freeMarkerConfiguration)方法读取freemarker模板,返回的格式如下图所示:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试</title>
</head>
<body>
<h1>你好Snailclimb</h1>
</body>
</html>

其实就是HTML,然后我们就可以像前面发送HTML格式邮件的方式发送这端消息了。

email.ftl

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试</title>
</head>
<body>
<h1>你好${user}</h1>
</body>
</html>

效果:

不知道为啥,腾讯每次把我使用模板引擎发的邮件直接放到垃圾箱。大家如果遇到接收不到邮件,但是又没报错的情况,可以看看是不是到了自己邮箱的垃圾箱。

ed8deb3fac5308f61fc76a250c253210.png

基于Velocity模板引擎发送邮件

/**
	 * 
	 * @param subject
	 * 邮件主题
	 * @param location
	 * 收件人地址
	 * @param emailAdress
	 * 目的地
	 * @param javaMailSender
	 * 发送邮件的核心类(在xml文件中已经配置好了)
	 * @param velocityEngine
	 * Velocity模板引擎
	 * @return
	 */
	public String sendMailVelocity(String subject, String location, String emailAdress, JavaMailSender javaMailSender,
			VelocityEngine velocityEngine) {
		MimeMessage mMessage = javaMailSender.createMimeMessage();// 创建邮件对象
		MimeMessageHelper mMessageHelper;
		Properties prop = new Properties();
		try {
			// 从配置文件中拿到发件人邮箱地址
			prop.load(this.getClass().getResourceAsStream("/mail.properties"));
			System.out.println(this.getClass().getResourceAsStream("/mail.properties"));
			String from = prop.get("mail.smtp.username") + "";
			mMessageHelper = new MimeMessageHelper(mMessage, true, "UTF-8");
			// 发件人邮箱
			mMessageHelper.setFrom(from);
			// 收件人邮箱
			mMessageHelper.setTo(emailAdress);
			// 邮件的主题也就是邮件的标题
			mMessageHelper.setSubject(subject);
			Map<String, Object> map = new HashMap<>();
			// 获取日期并格式化
			Date date = new Date();
			DateFormat bf = new SimpleDateFormat("yyyy-MM-dd E a HH:mm:ss");
			String str = bf.format(date);
			map.put("date", str);
			String content = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, "email.vm", "UTF-8", map);
			mMessageHelper.setText(content, true);
			// 通过文件路径获取文件名字
			String filename = StringUtils.getFileName(location);
			// 定义要发送的资源位置
			File file = new File(location);
			FileSystemResource resource = new FileSystemResource(file);
			mMessageHelper.addAttachment(filename, resource);// 在邮件中添加一个附件
			// mMessageHelper.addAttachment("JavaApiRename.txt", resource2);//
			// 在邮件中添加一个附件
			javaMailSender.send(mMessage);// 发送邮件
		} catch (MessagingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "发送成功";
	}

email.vm

<!DOCTYPE html>
<html>
<head lang="en">
 <meta charset="UTF-8">
 <title></title>
 
<body>
<h3>今天的日期是:${date}</h3>
</body>
</html>

效果:

4e7024b8a47e0ca3555917fa3cc5f84c.png

controller层

/**
 * 测试邮件发送controller
 * @author Snailclimb
 */
@RestController
@RequestMapping("mail")
public class SendMailController {
	@Autowired
	private JavaMailSender javaMailSender;// 在spring中配置的邮件发送的bean
	@Autowired
	private Configuration configuration;
	@Autowired
	private VelocityEngine velocityEngine;
	// text
	@RequestMapping("send")
	public String sendEmail() {
		EmailUtils emailUtils = new EmailUtils();
		return emailUtils.sendMail("大傻子大傻子大傻子,你好!!!", "发送给我家大傻子的~", "D:/picture/meizi.jpg", "1361583339@qq.com",
				javaMailSender, false);
	}
	// html
	@RequestMapping("send2")
	public String sendEmail2() {
		EmailUtils emailUtils = new EmailUtils();
		return emailUtils.sendMail(
				"<p>大傻子大傻子大傻子,你好!!!</p><br/>" + "<a href='https://github.com/Snailclimb'>点击打开我的Github!</a><br/>",
				"发送给我家大傻子的~", "D:/picture/meizi.jpg", "1361583339@qq.com", javaMailSender, true);
	}
	// freemarker
	@RequestMapping("send3")
	public String sendEmail3() {
		EmailUtils emailUtils = new EmailUtils();
		return emailUtils.sendMailFreeMarker("发送给我家大傻子的~", "D:/picture/meizi.jpg", "1361583339@qq.com", javaMailSender,
				configuration);
	}
	// velocity
	@RequestMapping("send4")
	public String sendEmail4() {
		EmailUtils emailUtils = new EmailUtils();
		return emailUtils.sendMailVelocity("发送给我家大傻子的~", "D:/picture/meizi.jpg", "1361583339@qq.com", javaMailSender,
				velocityEngine);
	}
}

四、总结

上面我们总结了Spring发送邮件的四种正确姿势,并且将核心代码提供给了大家。代码中有我很详细的注释,所以我对于代码以及相关类的讲解很少,感兴趣的同学可以自行学习。最后,本项目Github地址:http://github.com/Snailclimb/…。

作者:SnailClimb
链接: https:// juejin.im/post/5b6cdd0b 5188251b1b44be66
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值