Spring对邮件发送支持的很好,我们只要配置好邮件发送器,写好邮件发送具体操作类的方法,那么实现就不是很难的事,不过这个过程中经常会出现这样或那样的错误,所以待讲完本篇后我会总体总结下spring邮件发送容易发生的错误及解决办法
关于邮件发送,不外乎有这么几种情况,一种是纯文本的发送,一种是HTML形式的发送,一种就是发送时带有附件,一种就是发送时采取的事群发,针对这几个我将一一来讲下,我的代码中将第一中归为一大类,后面三种归为一代类,所以将会出现两种配置文件
第一大类邮件发送【纯文本发送】
必须包:spring.jar,common-logging.jar,mail.jar,servlet.jar,common-collection.jar
首先我们来看spring配置文件applicationContext.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: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-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!--定义邮件发送器,配置好发送者详细信息--> <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.163.com" /> <property name="port" value="25" /> <property name="username" value="emailusername" /> <property name="password" value="emailpassword" /> <property name="defaultEncoding" value="utf-8" /> <property name="javaMailProperties"> <props> <prop key="mail.smtp.auth">true</prop> </props> </property> </bean> <bean id="emailService" class="com.javacrazyer.comon.SendOrderConfirmationEmailAdvice"> <property name="mailSender" ref="mailSender" /> </bean> </beans>
用到的实体类Order.java
package com.javacrazyer.comon; import java.io.Serializable; public class Order implements Serializable { /* Private Fields */ private int orderId; private String username; private String useremail; public int getOrderId() { return orderId; } public void setOrderId(int orderId) { this.orderId = orderId; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getUseremail() { return useremail; } public void setUseremail(String useremail) { this.useremail = useremail; } }
邮件发送类的接口类MailService.java
package com.javacrazyer.comon; /** * 使用Spring发送邮件 * */ public interface MailService { void sendOrderMail(Order order); }
具体实现的邮件发送类SendOrderConfirmationEmailAdvice.java
package com.javacrazyer.comon; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import org.springframework.mail.MailSender; import org.springframework.mail.SimpleMailMessage; public class SendOrderConfirmationEmailAdvice implements MailService{ private String from="[email protected]"; //发送人邮箱地址,必须与spring配置文件中的邮箱地址一样 private String registeTemplateName = "com/javacrazyer/comon/mail_registe.txt"; private MailSender mailSender; public void setMailSender(MailSender mailSender) { this.mailSender = mailSender; } public void sendOrderMail(Order order) { //SimpleMialMessage只能用来发送TEXT格式的邮件 SimpleMailMessage mail = new SimpleMailMessage(); mail.setFrom(this.from); mail.setTo(order.getUseremail()); mail.setSubject("恭喜你成功注册成为SOMEDAY商城的会员!"); mail.setText(loadTemplateContent(registeTemplateName).replaceAll("\\$\\{LOGINNAME\\}", order.getUsername())); this.mailSender.send(mail); } private String loadTemplateContent(String templateName){ StringBuilder sb = new StringBuilder(); BufferedReader br= null; try{ br = new BufferedReader( new InputStreamReader( Thread.currentThread() .getContextClassLoader() .getResourceAsStream(templateName), "UTF-8")); String lineSeparator = System.getProperty("line.separator"); for(String str = null; (str = br.readLine()) != null;){ sb.append(str); sb.append(lineSeparator); } }catch(IOException e){ e.printStackTrace(); }finally{ if(br != null){ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } }
用到的mail_registe.txt
亲爱的${LOGINNAME}:您好! 恭喜你成为SOMEDAY商城的会员! 你的登录用户名为:${LOGINNAME} 你的登录口令为:******(隐藏) 本站网址:http://www.yoursitename.cn 联系邮箱:[email protected]
测试发送
package com.javacrazyer.service.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.javacrazyer.comon.MailService; import com.javacrazyer.comon.Order; public class UserServiceTest { @Test public void test() throws InterruptedException { ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml"); MailService sf = (MailService) context.getBean("emailService"); Order order = new Order(); order.setUsername("cheneywu"); order.setUseremail("[email protected]"); sf.sendOrderMail(order); } }
注意查收邮箱中的信息哦
第二大类邮件发送【HTML格式的发送,群发,附件】
除了上面包外,还需要spring-webmvc.jar,freemarker.jar,为什么需要freemarker呢,因为要发送HTML格式的文件,所以要先写好HTML内容的文件,然后用模板freemarker匹配其中的值,Spring中对freemarker也有很好的支持
spring配置文件applicatonContext-html.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: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-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <bean id="freeMarker" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="templateLoaderPath" value="classpath:mailTemplate" /> <!--指定模板文件目录--> <property name="freemarkerSettings"><!-- 设置FreeMarker环境属性--> <props> <prop key="template_update_delay">1800</prop><!--刷新模板的周期,单位为秒--> <prop key="default_encoding">UTF-8</prop><!--模板的编码格式 --> <prop key="locale">zh_CN</prop><!-- 本地化设置--> </props> </property> </bean> <!-- 注意:这里的参数(如用户名、密码)都是针对邮件发送者的 --> <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.163.com" /> <property name="port" value="25" /> <property name="username" value="emailusername" /> <property name="password" value="emailpassword" /> <property name="defaultEncoding" value="utf-8" /> <property name="javaMailProperties"> <props> <prop key="mail.smtp.auth">true</prop> </props> </property> </bean> <bean id="emailService" class="com.javacrazyer.comon.EmailService"> <property name="mailSender" ref="mailSender"></property> <property name="freeMarkerConfigurer" ref="freeMarker"></property> </bean> </beans>
模板文件目mailTemplate下的模板文件registe.ftl 【这个文件无名字、后缀无所谓,只要内容是HTML内容即可】
<html> <head> <meta http-equiv="content-type" content="text/html;charset=utf8"> </head> <body> 恭喜您成功注册!您的用户名为:<font color=‘red‘ size=‘30‘>${LOGINNAME}</font> </body> </html>
具体邮件发送类EmailService.java
package com.javacrazyer.comon; import java.io.File; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeUtility; import org.springframework.mail.MailSender; 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 freemarker.template.Template; public class EmailService implements MailService { private JavaMailSender mailSender; private FreeMarkerConfigurer freeMarkerConfigurer = null; // FreeMarker的技术类 public void setMailSender(JavaMailSender mailSender) { this.mailSender = mailSender; } public void setFreeMarkerConfigurer( FreeMarkerConfigurer freeMarkerConfigurer) { this.freeMarkerConfigurer = freeMarkerConfigurer; } /** * 发送带模板的单个html格式邮件 */ public void sendOrderMail(Order order) { MimeMessage msg = mailSender.createMimeMessage(); // 设置utf-8或GBK编码,否则邮件会有乱码,true表示为multipart邮件 try { MimeMessageHelper helper = new MimeMessageHelper(msg, true, "utf-8"); helper.setTo(order.getUseremail()); // 邮件接收地址 helper.setFrom("[email protected]"); // 邮件发送地址,这里必须和xml里的邮件地址相同一致 helper.setSubject("你好,恭喜你注册成功"); // 主题 String htmlText; htmlText = getMailText(order.getUsername()); helper.setText(htmlText, true); // 邮件内容,注意加参数true,表示启用html格式 } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } // 使用模板生成html邮件内容 mailSender.send(msg); // 发送邮件 } /** * 批量发送带附件的html格式邮件,带附件 */ public void sendBatchEmail(Order order, List<String> address) { MimeMessage msg = mailSender.createMimeMessage(); try { MimeMessageHelper helper = new MimeMessageHelper(msg, true, "utf-8"); String toList = getMailList(address); InternetAddress[] iaToList = new InternetAddress().parse(toList); msg.setRecipients(Message.RecipientType.TO, iaToList); helper.setFrom("[email protected]"); helper.setSubject("你好,恭喜你注册成功"); String htmlText = getMailText(order.getUsername()); helper.setText(htmlText, true); // 添加内嵌文件,第1个参数为cid标识这个文件,第2个参数为资源 helper.addInline("a", new File("E:/11.jpg")); // 附件内容 helper.addInline("b", new File("E:/12.jpg")); File file = new File("E:/各种框架图介绍.docx"); // 这里的方法调用和插入图片是不同的,使用MimeUtility.encodeWord()来解决附件名称的中文问题 helper.addAttachment(MimeUtility.encodeWord(file.getName()), file); } catch (MessagingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } // 如果主题出现乱码,可以使用该函数,也可以使用下面的函数 // helper.setSubject(MimeUtility.encodeText(String text,String // charset,String encoding)) // 第2个参数表示字符集,第三个为目标编码格式。 // MimeUtility.encodeWord(String word,String charset,String encoding) mailSender.send(msg); } /** * 集合转换字符串 */ public String getMailList(List<String> to) { StringBuffer toList = new StringBuffer(); int length = to.size(); if (to != null && length < 2) { toList.append(to.get(0)); } else { for (int i = 0; i < length; i++) { toList.append(to.get(i)); if (i != (length - 1)) { toList.append(","); } } } return toList.toString(); } // 通过模板构造邮件内容,参数content将替换模板文件中的${content}标签。 private String getMailText(String content) throws Exception { String htmlText = ""; // 通过指定模板名获取FreeMarker模板实例 Template tpl = freeMarkerConfigurer.getConfiguration().getTemplate( "registe.ftl"); Map map = new HashMap(); // FreeMarker通过Map传递动态数据 map.put("LOGINNAME", content); // 注意动态数据的key和模板标签中指定的属性相匹配 // 解析模板并替换动态数据,最终content将替换模板文件中的${content}标签。 htmlText = FreeMarkerTemplateUtils.processTemplateIntoString(tpl, map); return htmlText; } }
单一发送HTML格式的邮件测试
package com.javacrazyer.service.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.javacrazyer.comon.MailService; import com.javacrazyer.comon.Order; public class UserServiceTest { @Test public void test() throws InterruptedException { ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext-html.xml"); MailService sf = (MailService) context.getBean("emailService"); Order order = new Order(); order.setUsername("cheneywu"); order.setUseremail("[email protected]"); sf.sendOrderMail(order); } }
收到邮件了
群发,带附件的测试
package com.javacrazyer.service.test; import java.util.ArrayList; import java.util.List; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.javacrazyer.comon.EmailService; import com.javacrazyer.comon.Order; public class UserServiceTest { @Test public void test() throws InterruptedException { ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext-html.xml"); EmailService sf = (EmailService) context.getBean("emailService"); Order order = new Order(); order.setUsername("cheneywu"); List<String> maillist = new ArrayList<String>(); maillist.add("[email protected]"); maillist.add("[email protected]"); sf.sendBatchEmail(order, maillist); } }
收到邮件了哦
看到了没有,这个上边有两个接收人,下边的是附件