1. spring mvc工程中引入相关freemarker\mail的包
如:pom.xml中加入类似
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.5.0-b01</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.21</version>
</dependency>


2.编写邮件发送接口TemplateEmailService.java与实现类TemplateEmailServiceImpl.java:


import java.util.Map;

public interface TemplateEmailService
{
/**
* 发送邮件
*
* @param root 存储动态数据的map
* @param toEmail 邮件地址
* @param subject 邮件主题
* @return
*/
public boolean sendTemplateMail(Map rootMap, String from, String[] toEmail, String[] cc, String subject,
String templateName);
}

 

 

import java.io.File;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

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

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.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import com.vipshop.service.TemplateEmailService;

import freemarker.template.Template;

/**
* 发送邮件 可以自己编写freemarker模板
*
* @author sea.zeng
* @email sea.zeng@vipshop.com 2014-11-20
*/
public class TemplateEmailServiceImpl implements TemplateEmailService
{

private JavaMailSender sender;

private FreeMarkerConfigurer freeMarkerConfigurer = null;// FreeMarker的技术类

public void setFreeMarkerConfigurer(FreeMarkerConfigurer freeMarkerConfigurer)
{
this.freeMarkerConfigurer = freeMarkerConfigurer;
}

public void setSender(JavaMailSender sender)
{
this.sender = sender;
}

/**
* 生成html模板字符串
*
* @param root 存储动态数据的map
* @return
*/
private String getMailText(Map<String, Object> rootMap, String templateName)
{
String htmlText = "";
try
{
// 通过指定模板名获取FreeMarker模板实例
Template tpl = freeMarkerConfigurer.getConfiguration().getTemplate(templateName);
htmlText = FreeMarkerTemplateUtils.processTemplateIntoString(tpl, rootMap);
}
catch (Exception e)
{
e.printStackTrace();
}

return htmlText;
}

/**
* 发送邮件
*
* @param root 存储动态数据的map
* @param toEmail 邮件地址
* @param subject 邮件主题
* @return
*/
public boolean sendTemplateMail(Map rootMap, String from, String[] toEmail, String[] cc, String subject,
String templateName)
{
try
{

MimeMessage msg = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(msg, false, "UTF-8");
helper.setFrom(from);
helper.setTo(toEmail);
if (null != cc)
{
helper.setCc(cc);
}

helper.setSubject(subject);

Map map = new HashMap();
map.put("rootMap", rootMap);

String htmlText = getMailText(map, templateName);// 使用模板生成html邮件内容
helper.setText(htmlText, true);

// 以下仅做示范(如何增加本地文件、远程URI图片),sea.zeng 2014-11-27
// helper.addAttachment("唯品会.png", new FileSystemResource(new
// File("E:\\svn\\Testing\\Automation\\Tools\\TestPlatformApi\\Trank\\mobilet\\target\\vips-mobile\\images\\vip_logo.png")));
// helper.addAttachment("明细.jpg", new UrlResource("http://192.168.32.219:8080/mobilet/images/demo.jpg"));
// System.out.println(htmlText);
sender.send(msg);
System.out.println("成功发送模板邮件----" + templateName);
return true;
}
catch (MailException e)
{
System.out.println("失败发送模板邮件----" + templateName);
e.printStackTrace();
return false;
}
catch (MessagingException e)
{
System.out.println("失败发送模板邮件----" + templateName);
e.printStackTrace();
return false;

}

}

/**
* 发送邮件
*
* @param root 存储动态数据的map
* @param toEmail 邮件地址
* @param subject 邮件主题
* @return
*/
public boolean sendTemplateMailWithAttachment(Map rootMap, String from, String[] toEmail, String[] cc,
String subject, String templateName)
{
try
{

MimeMessage msg = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(msg, true, "UTF-8");
helper.setFrom(from);
helper.setTo(toEmail);
if (null != cc)
{
helper.setCc(cc);
}

helper.setSubject(subject);

Map map = new HashMap();
map.put("rootMap", rootMap);

String htmlText = getMailText(map, templateName);// 使用模板生成html邮件内容
helper.setText(htmlText, true);

File fp = new File("/趋势图分析.html");
PrintWriter pfp = new PrintWriter(fp);
pfp.print(htmlText);
pfp.close();
helper.addAttachment("趋势图分析.html", new FileSystemResource(fp));

// 以下仅做示范(如何增加本地文件、远程URI图片),sea.zeng 2014-11-27
// helper.addAttachment("XXXpng", new FileSystemResource(new
// File("E:\\FILEURL\\images\\vip_logo.png")));
// helper.addAttachment("明细.jpg", new UrlResource("http://URL/images/demo.jpg"));

sender.send(msg);
System.out.println("成功发送模板邮件----" + templateName);
return true;
}
catch (Exception e)
{
System.out.println("失败发送模板邮件----" + templateName);
e.printStackTrace();
return false;
}

}
}

 

3. 新增加applicationContext-mail.xml,并包含加入到主applicationContext.xml中( <import resource="classpath:applicationContext-mail.xml" /> ):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

<bean id="freeMarker" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="classpath:mailtemplates"/><!--指定模板文件目录-->
<property name="freemarkerSettings"><!-- 设置FreeMarker环境属性-->
<props>
<prop key="template_update_delay">60</prop><!--刷新模板的周期,单位为秒-->
<prop key="default_encoding">UTF-8</prop><!--模板的编码格式 -->
<prop key="locale">zh_CN</prop><!-- 本地化设置-->
</props>
</property>
</bean>

<bean id="templateEmailService" class="com.xxx.service.impl.TemplateEmailServiceImpl">
<property name="sender" ref="mailsender"></property>
<property name="freeMarkerConfigurer" ref="freeMarker"></property>
</bean>

<bean id="mailsender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host">
<value>smtp.163.com</value>
</property>
<property name="port">
<value>465</value>
</property>
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.timeout">25000</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop> //ssl邮箱
<prop key="mail.smtp.socketFactory.fallback">false</prop>
</props>
</property>
<property name="username">
<value>邮箱账号</value>
</property>
<property name="password">
<value>密码</value>
</property>
</bean>

</beans>

 

4. 配置邮件freemarker模板functionFail.ftl
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>重要功能检查异常预警</title>

 

<style type="text/css">
body { font-family: 'trebuchet MS', 'Lucida sans', Arial; font-size: 12px;}
table { *border-collapse: collapse; border-spacing: 0; width: 100%; font-size: 12px; }
.bordered { border: solid #ccc 1px; -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; -webkit-box-shadow: 0 1px 1px #ccc; -moz-box-shadow: 0 1px 1px #ccc; box-shadow: 0 1px 1px #ccc;}
.bordered tr:hover { background: #fbf8e9; -o-transition: all 0.1s ease-in-out; -webkit-transition: all 0.1s ease-in-out; -moz-transition: all 0.1s ease-in-out; -ms-transition: all 0.1s ease-in-out; transition: all 0.1s ease-in-out; } .bordered td, .bordered th { border-left: 1px solid #ccc; border-top: 1px solid #ccc; padding: 5px; text-align: left; }
.bordered th { background-color: #dce9f9; background-image: -webkit-gradient(linear, left top, left bottom, from(#ebf3fc), to(#dce9f9)); background-image: -webkit-linear-gradient(top, #ebf3fc, #dce9f9); background-image: -moz-linear-gradient(top, #ebf3fc, #dce9f9); background-image: -ms-linear-gradient(top, #ebf3fc, #dce9f9); background-image: -o-linear-gradient(top, #ebf3fc, #dce9f9); background-image: linear-gradient(top, #ebf3fc, #dce9f9); -webkit-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; -moz-box-shadow:0 1px 0 rgba(255,255,255,.8) inset; box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; border-top: none; text-shadow: 0 1px 0 rgba(255,255,255,.5); }
.bordered td:first-child, .bordered th:first-child { border-left: none;}
.bordered th:first-child { -moz-border-radius: 6px 0 0 0; -webkit-border-radius: 6px 0 0 0; border-radius: 6px 0 0 0;}
.bordered th:last-child { -moz-border-radius: 0 6px 0 0; -webkit-border-radius: 0 6px 0 0; border-radius: 0 6px 0 0;}
.bordered th:only-child{ -moz-border-radius: 6px 6px 0 0; -webkit-border-radius: 6px 6px 0 0; border-radius: 6px 6px 0 0;}
.bordered tr:last-child td:first-child { -moz-border-radius: 0 0 0 6px; -webkit-border-radius: 0 0 0 6px; border-radius: 0 0 0 6px;}
.bordered tr:last-child td:last-child { -moz-border-radius: 0 0 6px 0; -webkit-border-radius: 0 0 6px 0; border-radius: 0 0 6px 0;}
.unusual{font-weight:700; background-color:#FF0000}
</style>

 

</head>


<body>

<p align="center" ><h2>重要功能检查异常提醒</h2> </p>



<br /><br />



<h3><strong>详情:</strong></h3>

<table width='898' class='bordered'>



<tr>
<th width='138' >产品</th>
<th width='131' >设备</th>
<th width='108' >版本</th>
<th width='151' >功能</th>
<th width='103' >时间</th>
<th width='103' >结果</th>
<th width='142' >备注</th>
</tr>




<#if rootMap.failList?? && (rootMap.failList?size > 0) >


<#list rootMap.failList as failResult>
<tr>
<td>${failResult.product?default("")}</td>
<td>${failResult.device?default("")}</td>
<td>${failResult.version?default("")}</td>
<td>${failResult.testFeature?default("")}</td>
<td>${failResult.createTime[0..18]?default("")} </td>
<td>${failResult.result?default("")}</td>
<td>${failResult.remark?default("")}</td>
</#list>

</table>

</#if>


</body>


</html>

 

5. 调用如创建job,FunctionFailCheckJob.java

 

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import xxx.dao.vo.TestReport;
import xxx.service.TestReportService;

public class FunctionFailCheckJob
{

private TestReportService testReportService;

public void setTestReportService(TestReportService testReportService)
{
this.testReportService = testReportService;
}

@SuppressWarnings({"unused", "unchecked"})
public void sendMail()
{

SimpleDateFormat df3 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
boolean result = false;
boolean resultEmpty = false;
try
{

String subject = df3.format(new Date()) + "----重要功能异常提醒";
String templateName = "functionFail.ftl";

String from = "xxx@xxx.com";
String[] toEmail =
{"sea@xxx.com"};
String[] cc = {"xx@xxx.com"};

@SuppressWarnings("rawtypes")
Map rootMap = new HashMap<>();
// 初始化模板数据----重要功能检查部分 半小时内失败记录
List<TestReport> failList = testReportService.queryFailFunctionAgo30Minute();

if (null != failList && 0 < failList.size())
{
rootMap.put("failList", failList);
result = testReportService.sendTemplateMail(rootMap, from, toEmail, cc, subject, templateName);
}
else
{
resultEmpty = true;
}

}
catch (Exception e)
{
e.printStackTrace();
}

}

}

 

6.testReportService实现类TestReportServiceImpl.java中实现

public class TestReportServiceImpl implements TestReportService
{


.....
private TemplateEmailService templateEmailService;

public void setTestReportDao(TestReportDao testReportDao)
{
this.testReportDao = testReportDao;
}

public void setTemplateEmailService(TemplateEmailService templateEmailService)
{
this.templateEmailService = templateEmailService;
}

/**
* 发送邮件
*
* @param root 存储动态数据的map
* @param toEmail 邮件地址
* @param subject 邮件主题
* @return boolean
*/
public boolean sendTemplateMail(Map rootMap, String from, String[] toEmail, String[] cc, String subject,
String templateName)
{

return templateEmailService.sendTemplateMail(rootMap, from, toEmail, cc, subject, templateName);
}
...

}


7. 整个邮件配置和调用完成,配置个spring中的定时job与业务bean这些就省略了,不是我要讲的重点

 

 

本着资源共享的原则,欢迎各位朋友在此基础上完善,并进一步分享,让我们的实现更加优雅。如果有任何疑问和需要进一步交流可以加我QQ 1922003019或者直接发送QQ邮件给我沟通

 

sea 20150610  中国:广州: VIP