使用Spring发送邮件

Spring 提供了对发送邮件的基础服务的支持,所以我尝试使用Spring来重构发送邮件的代码。
   
MailSenderInfo

        对于这个类,职责很简单,用于保存邮件的所有相关信息。这个实体Bean是可以根据实际的业务需求进行动态扩展的,比如涉及带附件的邮件,那么可以指定附件的路劲。
根据 Effective Java 作者的推荐,一个通用的普通类应该覆写三个方法,实现一个接口:@override: hashCode, @override equals, @override toString, implement Comparable.但是由于这个实体类的功能过于简单,甚至用Map 的键值对都可替换,所以我就不做过多的实现,如果将来有实际的业务需要,可以再实现。
package com.spring.mail;

public class MailSenderInfo {
	
	private String serverHost;
	
	private int serverPort;
	
	private boolean validate;
	
	private String userName;
	
	private String password;
	
	private String fromAddress;
	
	private String sendName;
	
	private int timeout;
	
	private String toAddress;
	
	private String subject;
	
	private String text;
	
	private String filepath;

	public String getServerHost() {
		return serverHost;
	}

	public void setServerHost(String serverHost) {
		this.serverHost = serverHost;
	}

	public int getServerPort() {
		return serverPort;
	}

	public void setServerPort(int serverPort) {
		this.serverPort = serverPort;
	}

	public boolean isValidate() {
		return validate;
	}

	public void setValidate(boolean validate) {
		this.validate = validate;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getFromAddress() {
		return fromAddress;
	}

	public void setFromAddress(String fromAddress) {
		this.fromAddress = fromAddress;
	}

	public String getSendName() {
		return sendName;
	}

	public void setSendName(String sendName) {
		this.sendName = sendName;
	}

	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

	public int getTimeout() {
		return timeout;
	}

	public void setToAddress(String toAddress) {
		this.toAddress = toAddress;
	}

	public String getToAddress() {
		return toAddress;
	}

	public void setSubject(String subject) {
		this.subject = subject;
	}

	public String getSubject() {
		return subject;
	}

	public void setText(String text) {
		this.text = text;
	}

	public String getText() {
		return text;
	}

	public void setFilepath(String filepath) {
		this.filepath = filepath;
	}

	public String getFilepath() {
		return filepath;
	}

}



MailSender

        有了邮件的相关配置信息之后,下一步就是如何发送的问题。考虑到发送邮件存在一定的差异性,比如说带附件的邮件,HTML格式的邮件;但同时邮件发送的原理又存在共性,所以我考虑使用一个抽象类来抽象共性,并用一个抽象方法来提供差异性。
        因为代码的重构是依托Spring来进行的,本身不重新发明轮子的思路,我尽量使用spring已经实现的基础服务设施类。
        JavaMailSenderImpl和SimpleMailMessage 都是基础设计服务类,一个用于发送邮件,一个用于组装邮件信息。
        FreeMarkerConfigurer 是用于组装Freemarker 模板邮件而服务的类。
package com.spring.mail;

import org.apache.log4j.Logger;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

public abstract class MailSender {
	
	protected static Logger logger = Logger.getLogger(MailSender.class);
	
	protected JavaMailSenderImpl javaMailSender;

	public void setJavaMailSender(JavaMailSenderImpl javaMailSender) {
		this.javaMailSender = javaMailSender;
	}
	
	protected MailSenderInfo mailSenderInfo;

	public void setMailSenderInfo(MailSenderInfo mailSenderInfo) {
		this.mailSenderInfo = mailSenderInfo;
	}
	
	protected SimpleMailMessage simpleMailMessage;

	public void setSimpleMailMessage(SimpleMailMessage simpleMailMessage) {
		this.simpleMailMessage = simpleMailMessage;
	}
	
	protected FreeMarkerConfigurer freemarkerConfiguration;

	public void setFreemarkerConfiguration(FreeMarkerConfigurer freemarkerConfiguration) {
		this.freemarkerConfiguration = freemarkerConfiguration;
	}

	public abstract void sendMail() throws Exception;

}


SimpleMailSender

        首先看一种最简单的实现,文本邮件。通过实现父类的抽象方法 sendMail, 从而把子类的逻辑放进去。同时也使用了从父类继承而来的基础服务设施类,使得子类的代码显得目的明确而且很简洁。
package com.spring.mail.impl;

import java.util.Properties;

import com.spring.mail.MailSender;

public class SimpleMailSender extends MailSender{
	
	@Override
	public void sendMail() {
		javaMailSender.setHost(mailSenderInfo.getServerHost());
		javaMailSender.setPort(mailSenderInfo.getServerPort());
		javaMailSender.setUsername(mailSenderInfo.getUserName());
		javaMailSender.setPassword(mailSenderInfo.getPassword());

		simpleMailMessage.setTo(mailSenderInfo.getToAddress());
		simpleMailMessage.setFrom(mailSenderInfo.getFromAddress());
		simpleMailMessage.setSubject(mailSenderInfo.getSubject());
		simpleMailMessage.setText(mailSenderInfo.getText());

		Properties prop = new Properties();
		prop.put("mail.smtp.auth", mailSenderInfo.isValidate());
		prop.put("mail.smtp.timeout", mailSenderInfo.getTimeout());

		javaMailSender.setJavaMailProperties(prop);
		
		javaMailSender.send(simpleMailMessage);
	}

}


HTMLMailSender

        这是发送HTML格式的邮件,思路一致。
package com.spring.mail.impl;

import java.io.File;

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

import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.MimeMessageHelper;

import com.spring.mail.MailSender;

public class HTMLMailSender extends MailSender{
	
	@Override
	public void sendMail() throws Exception {
		javaMailSender.setHost(mailSenderInfo.getServerHost());
		javaMailSender.setPort(mailSenderInfo.getServerPort());
		javaMailSender.setUsername(mailSenderInfo.getUserName());
		javaMailSender.setPassword(mailSenderInfo.getPassword());

		/**
		 * Create Mime mail(contains attach, html format)
		 */
		MimeMessage mailMessage = javaMailSender.createMimeMessage();
		MimeMessageHelper messageHelper = new MimeMessageHelper(mailMessage, true, "utf-8");

		messageHelper.setFrom(mailSenderInfo.getFromAddress());
		messageHelper.setTo(mailSenderInfo.getToAddress());
		messageHelper.setSubject(mailSenderInfo.getSubject());
		/**
		 * true means html format
		 */
		messageHelper.setText("<html><head></head><body><h1>hello!</h1></body></html>", true);

		File file = new File(mailSenderInfo.getFilepath());
		if (file.exists()) {
			FileSystemResource fileAdd = new FileSystemResource(file);
			messageHelper.addAttachment(MimeUtility.encodeWord(fileAdd.getFilename()), fileAdd);
		}
		
		javaMailSender.send(mailMessage);
	}
	
	

}


TemplateMailSender

        这是发送模板邮件。
package com.spring.mail.impl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

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

import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import com.spring.mail.MailSender;

import freemarker.template.Template;
import freemarker.template.TemplateException;

public class TemplateMailSender extends MailSender{
	
	@Override
	public void sendMail() throws Exception{
		javaMailSender.setHost(mailSenderInfo.getServerHost());
		javaMailSender.setPort(mailSenderInfo.getServerPort());
		javaMailSender.setUsername(mailSenderInfo.getUserName());
		javaMailSender.setPassword(mailSenderInfo.getPassword());

		/**
		 * Create Mime mail(contains attach, html format)
		 */
		MimeMessage mailMessage = javaMailSender.createMimeMessage();
		MimeMessageHelper messageHelper = new MimeMessageHelper(mailMessage, true, "utf-8");

		messageHelper.setFrom(mailSenderInfo.getFromAddress());
		messageHelper.setTo(mailSenderInfo.getToAddress());
		messageHelper.setSubject(mailSenderInfo.getSubject());
		/**
		 * true means html format
		 */
		messageHelper.setText(getEmailContent(), true);

		File file = new File(mailSenderInfo.getFilepath());
		if (file.exists()) {
			FileSystemResource fileAdd = new FileSystemResource(file);
			messageHelper.addAttachment(MimeUtility.encodeWord(fileAdd.getFilename()), fileAdd);
		}

		javaMailSender.send(mailMessage);
	}
	
	private String getEmailContent() {
		try {
			Template template = freemarkerConfiguration.getConfiguration().getTemplate("mail.ftl");

			Map<String, String> map = new HashMap<String, String>();
			map.put("user", "Andy");
			map.put("currentDate", new Date().toString());

			String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
			return content;

		} catch (TemplateException e) {
			logger.error("Error while processing FreeMarker template ", e);
		} catch (FileNotFoundException e) {
			logger.error("Error while open template file ", e);
		} catch (IOException e) {
			logger.error("Error while generate Email Content ", e);
		}
		return "";
	}

}


ApplicationContext-mail.xml

        对于邮件来说,有很多属性需要配置,所以采用xml文件的方式应该会更合适,同时Spring提供的扫描注入方式也使得对原生代码的侵入性更低,所以我没有采用注解来实现注入依赖。
<?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:context="http://www.springframework.org/schema/context"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans 
						   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
						   http://www.springframework.org/schema/context
						   http://www.springframework.org/schema/context/spring-context-3.0.xsd" default-autowire="byType">
	
	<context:component-scan base-package="com.spring.mail">
		<context:include-filter type="regex" expression="com\.spring\.mail\.impl\..*Sender.*" /> 
	</context:component-scan>
	
	<bean id="mailSenderInfo" class="com.spring.mail.MailSenderInfo" >
		<property name="serverHost" value="smtp.**.com"/>
		<property name="serverPort" value="25"/>
		<property name="validate" value="true"/>
		<property name="userName" value="*************"/>
		<property name="password" value="*************"/>
		<property name="fromAddress" value="*************"/>
		<property name="toAddress" value="*************"/>
		<property name="timeout" value="25000"/>
		<property name="subject" value="this is a test mail"/>
		<property name="text" value="this is a test mail"/>
		<property name="filepath" value="E:\\Document\\LIR\\LIR_Tech_refresh.docx"/>
	</bean>
	
	<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl" />
	
	<bean id="simpleMailMessage" class="org.springframework.mail.SimpleMailMessage" />
	
	<bean id="freemarkerConfiguration" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
		<property name="templateLoaderPaths">
			<list>			
				<value>/mail/</value>
			</list>
		</property>
		<property name="freemarkerSettings">
			<props>
				<prop key="default_encoding">UTF-8</prop> 
				<prop key="output_encoding">UTF-8</prop>
				<prop key="locale">en_US</prop> 
				<prop key="number_format">#</prop>
				<prop key="whitespace_stripping">true</prop>
				<prop key="classic_compatible">true</prop>
			</props>
		</property>
	</bean>
	
</beans>


Mail.ftl

        对于使用模板发送邮件的例子,这里给出一个模板案例。
<html>   
   <head>   
      <meta http-equiv="content-type" content="text/html;charset=utf8">   
   </head>   
   <body>   
 	  ${user} Welcome to Java world!!!<br/>

       <br/><br/>
       ---------------------------------
       <br/>
       ${currentDate}<br/> 
       connector: Andy<br/>
       phone: 18688886666<br/>
       mail: [email protected]<br/>
   </body>   
</html>  


Junit

        最后,给出junit单元测试的例子。

package com.spring.mail;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MailTester {
	
	ApplicationContext context;
	MailSender sender;
	
	@Before
	public void setUp(){
		context = new ClassPathXmlApplicationContext("/mail/applicationContext-*.xml");
	}
	
	@Test
	public void sendSimpleMail() throws Exception{
		sender = (MailSender) context.getBean("simpleMailSender");
		sender.sendMail();
	}
	
	@Test
	public void sendHTMLMail() throws Exception{
		sender = (MailSender) context.getBean("HTMLMailSender");
		sender.sendMail();
	}
	
	@Test
	public void setTemplateMail() throws Exception{
		sender = (MailSender) context.getBean("templateMailSender");
		sender.sendMail();
	}
}


说明

        本例子是采用Spring 3.1.12Release版本实现的,对于xml文件中的星号,是需要读者自己定义的邮箱信息,项目的构建使用maven,推荐!


附件
  
        附件中提供了word文档。

猜你喜欢

转载自delinghayiye-163-com.iteye.com/blog/1683812