參考資料
1 Spring郵件發送(可帶附件,模板,羣發,異步發送等功能)
http://linqincai.iteye.com/blog/508797
2 Spring mail 使用多個賬號發送帶有附件的HTML郵件
http://wisdombrave.iteye.com/blog/546508
3 spring各種郵件發送
http://blog.csdn.net/lenolong/article/details/3970110
4 spring來發EMAIL
http://www.cnblogs.com/jackyrong/archive/2006/08/17/479812.html
5 使用spring發送郵件例
http://www.blogjava.net/amigoxie/archive/2007/04/28/114310.html
6 Spring Mail中文亂碼問題
http://blog.csdn.net/matrixjava/article/details/3237772
7 國內常用郵箱客戶端POP3和SMTP服務器大全
http://www.hiapk.com/thread-7912-1-1.html
寫在前面的話
網上很多文章都是針對配置文件來說的,本文是對spring各種郵件發送這篇文章作了封裝,使用spring發送Email更加方便
網易和其它很多公司現在都沒有對外開放POP3/SMTP服務,可能你會碰到這樣的錯誤:
org.springframework.mail.MailAuthenticationException: Authentication failed; nested exception is javax.mail.AuthenticationFailedException
我測試時是用的是:新浪的郵箱:smtp.sina.com也是可以的
如下設置:
Exception: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection
參考文章:http://zhidao.baidu.com/question/227409027.html
解答: 配置JavaMail的Properties時,不要指定mail.smtp.socketFactory.class,因爲TLS使用的是普通的Socket。 然後指定屬性mail.smtp.starttls.enable爲true.
介紹
Spring郵件抽象層的主要包爲org.springframework.mail。它包括了發送電子郵件的主要接口MailSender,和值對象SimpleMailMessage,
它封裝了簡單郵件的屬性如from, to,cc, subject,text。 包裏還包含一棵以MailException爲根的checked Exception繼承樹,
它們提供了對底層郵件系統異常的高級別抽象.爲了使用JavaMail中的一些特色, 比如MIME類型的信件, Spring提供了MailSender的一個子接口,
即org.springframework.mail.javamail.JavaMailSender。Spring還提供了一個回調接口org.springframework.mail.javamail.MimeMessagePreparator,
用於準備JavaMail的MIME信件.
工程環境:XP+Myeclipse6.5+JDK1.6
一 實現功能
1 封裝了常用的四種發送Email的方法(文本,html,img,file),用戶只要調用一個工廠類傳遞相應的郵件的屬性如from, to,cc, subject,text,或者是消息對象
2 解決了發送郵件附件中的中文籌碼問題,參見了Spring Mail中文亂碼問題
3 支持鏈式風格
4 可以混合發送多種消息(text,html,img,file)
二 工程圖片
或者你也可以這樣,使用打包好的jar:email.spring.util.jar
,見附件
三 調用說明
1 發送文本消息
//默認空構造爲發送文本類型
MailMessageFactory mms = new MailMessageFactory();
mms.setSubject("使用spring email 測試發送文本消息")
.setText("正文消息了。。。。")
.send();
2 發送Html格式消息
MailMessageFactory mms = new MailMessageFactory(SendMailType.HTML);
mms.setSubject("使用spring email 測試發送Html中文郵件")
.setText("<html><head><meta http-equiv='content-type' content='text/html; charset=GBK'>" +
"</head><body><h1>這裏是咫尺天涯發送的郵件</h1></body></html>").send();
3 發送含有圖片的消息
MailMessageFactory mms = new MailMessageFactory(SendMailType.HTML);
String text = "<html><body>歡迎訪問咫尺天涯博客<br>"
+ "<a href='http://liuzidong.iteye.com/' target='_blank'>"
+ "<img src='cid:belle'></a><br><img src='cid:belle2'></body></html>";
//附件要嵌入到HTML中顯示,則在IMG標籤中用"cid:XXX"標記。
mms.setSubject("使用spring email 測試郵件中嵌套圖片");
mms.setText(text);
File file = new File("c:\\5.jpg");
mms.setImgFile("belle", file);
File file2 = new File("c:\\4.jpg");
mms.setImgFile("belle2", file2);
mms.send();
4 發送含有附件的消息
MailMessageFactory mms = new MailMessageFactory(SendMailType.HTML);
mms.setSubject("使用spring email 測試發送附件");
File file = new File("c:\\1.zip");
mms.setAttachmentFile("jquery學習記錄", file).send();
5 綜合發送(文本,html,img,file)消息
MailMessageFactory mms = new MailMessageFactory(SendMailType.HTML);
mms.setSubject("使用spring email 測試發送郵件<包含html,img,file>等格式");
mms.setText("這是我的文本格式");
mms.setText("<html><head><h1>這裏是咫尺天涯發送的郵件</h1></head><body>" +
"<h1><a href='http://liuzidong.iteye.com/' target='_blank'></h1><br>" +
"<img src='cid:belle'></a><br><img src='cid:belle2'>"+
"</body></html>");
//附件要嵌入到HTML中顯示,則在IMG標籤中用"cid:XXX"標記。
File file = new File("c:\\5.jpg");
mms.setImgFile("belle", file);
File file2 = new File("c:\\4.jpg");
mms.setImgFile("belle2", file2);
File file3 = new File("c:\\1.zip");
mms.setAttachmentFile("附件1", file3);
File file4 = new File("c:\\jquery學習記錄.txt");
mms.setAttachmentFile("jquery學習記錄", file4);
mms.send();
四 代碼如下
1 消息發送類:MailMessageFactory
package net.liuzd.email.spring;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import net.liuzd.email.EmailEntity;
import net.liuzd.email.MailType;
import net.liuzd.email.SendMailType;
import net.liuzd.email.SendMessage;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
/**
* Title: 消息發送類
* Description: Copyright: Copyright (c) 2011
* Company:http://liuzidong.iteye.com/ Makedate:2011-7-4 上午10:11:08
* @author liuzidong
* @version 1.0
* @since 1.0
*
*/
public class MailMessageFactory {
private SimpleMailMessage simpleMailMessage;
private MimeMessageHelper mimeMessageHelper;
private JavaMailSenderImpl senderImpl;
private MimeMessage mimeMessage;
private SendMailType sendMailType;
private SendMessage sendMessage;
private static final String ENCODING = EmailEntity.EMAIL_ENCODING;
/**
* 默認爲發送文本類型
* */
public MailMessageFactory() {
this(SendMailType.TEXT);
}
/**
* 請顯示指明文件類型爲:TEXT,HTML,默認爲文本類型
*
* */
public MailMessageFactory(SendMailType sendMailType){
this.sendMailType = sendMailType;
this.senderImpl = JavaMailFactory.getJavaMail();
this.mimeMessage = senderImpl.createMimeMessage();
sendMessage = new SendMessage();
try {
switch (this.sendMailType) {
case TEXT:
simpleMailMessage = new SimpleMailMessage();
break;
case HTML:
mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, ENCODING);
}
} catch (Exception e) {
e.fillInStackTrace();
}
}
/**
* @param to 接收者人地址
* @return
*/
public MailMessageFactory setTo(String ... to){
sendMessage.setTos(to);
return this;
}
/**發送標題*/
public MailMessageFactory setSubject(String subject){
sendMessage.setSubject(subject);
return this;
}
/**發送內容*/
public MailMessageFactory setText(String text){
sendMessage.addText(text);
return this;
}
/**
* 加入圖片文件
* @param imageName 圖片名稱
* @param file 圖片源
* @return
*/
public MailMessageFactory setImgFile(String imageName,File file){
try {
sendMessage.addFile(MailType.IMG,MimeUtility.encodeWord(imageName), file);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return this;
}
/**
* 加入圖片文件
* @param imageName 圖片名稱
* @param filePath 圖片路徑
* @return
*/
public MailMessageFactory setImgFile(String imageName,String filePath){
setImgFile(imageName, new File(filePath));
return this;
}
/**
* 加入附件
* @param fileName 附件名稱
* @param file 附件路徑
* @return
*/
public MailMessageFactory setAttachmentFile(String fileName,String filePath){
setAttachmentFile(fileName, new File(filePath));
return this;
}
/**
* 加入附件
* @param fileName 附件名稱
* @param file 附件源
* @return
*/
public MailMessageFactory setAttachmentFile(String fileName,File file){
try {
sendMessage.addFile(MailType.FILE,MimeUtility.encodeWord(fileName),file);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return this;
}
/**發送消息,你調用此方法進行Email消息的發送*/
public void send(){
//消息發送前,檢查發送人地址,接收人地址是否爲空,爲空就設置爲配置文件中的地址
sendMessage.setForm(EmailEntity.EMAIL_FROM);
//檢查接收人地址是否爲空
String [] tos = sendMessage.getTos();
if(null == tos || tos.length == 0){
tos = new String[]{EmailEntity.EMAIL_TO};
sendMessage.setTos(tos);
}
long startTime = System.currentTimeMillis();
//發送普通文本
if(sendMailType == SendMailType.TEXT){
sendTextMessage();
}else{
sendHtmlImgFileMessage();
}
long endTime = System.currentTimeMillis();
System.out.println(sendMailType + "成功!,耗費時間: " + (endTime - startTime)+"毫秒!");
}
/**
* 發送html,圖片,附件的消息
*/
private void sendHtmlImgFileMessage() {
try {
mimeMessageHelper.setTo(sendMessage.getTos());
mimeMessageHelper.setFrom(sendMessage.getForm());
String subject = sendMessage.getSubject();
if(null != subject && !"".equals(subject)){
mimeMessageHelper.setSubject(subject);
}
String text = sendMessage.getSendTexts();
if(null != text && !"".equals(text)){
mimeMessageHelper.setText(text,true);
}
//檢查圖片或者文件集合是否爲空
int imgSize = sendMessage.getImages().size();
if(imgSize > 0){
List<SendMessage> lists = sendMessage.getImages();
FileSystemResource fsr = null;
String imgName = null;
for(SendMessage entity : lists){
fsr = new FileSystemResource(entity.getFile());
imgName = entity.getImgName();
//如果爲圖片類型就調用addInline,否則就調用:addAttachment方法^_^
if(entity.getMailType() == MailType.IMG)
mimeMessageHelper.addInline(imgName, fsr);
else
mimeMessageHelper.addAttachment(imgName, fsr);
}
fsr = null;
}
} catch (MessagingException e) {
e.printStackTrace();
}
senderImpl.send(mimeMessage);
}
/**
* 發送文本消息
*/
private void sendTextMessage() {
simpleMailMessage.setTo(sendMessage.getTos());
simpleMailMessage.setFrom(sendMessage.getForm());
String subject = sendMessage.getSubject();
if(null != subject && !"".equals(subject)){
simpleMailMessage.setSubject(subject);
}
String text = sendMessage.getSendTexts();
if(null != text && !"".equals(text)){
simpleMailMessage.setText(text);
}
senderImpl.send(simpleMailMessage);
}
/**
* @param subject 發送標題
* @param text 發送內容
* @param to 接收人地址
*/
public void send(String subject,String text,String ... to){
sendMessage(subject, text, to);
}
private void sendMessage(String subject, String text, String... to) {
setTo(to);
setSubject(subject);
setText(text);
}
public SendMessage getSendMessage() {
return sendMessage;
}
/***
* 接收一個消息對象
* */
public MailMessageFactory setSendMessage(SendMessage sendMessage) {
this.sendMessage = sendMessage;
return this;
}
}
2 郵件發送類型:SendMailType
package net.liuzd.email;
/**
*Title: 郵件發送類型
*Description:
*Copyright: Copyright (c) 2011
*Company:http://liuzidong.iteye.com/
*Makedate:2011-7-4 上午09:59:08
* @author liuzidong
* @version 1.0
* @since 1.0
*
*/
public enum SendMailType {
/**
* 文本類型
* */
TEXT,
/**
* HTML類型,包含圖片與附件內容
* **/
HTML;
@Override
public String toString() {
String message = null;
switch (this) {
case TEXT:
message = "發送文本消息";
break;
case HTML :
message = "發送html消息";
break;
}
return message;
}
}
3 讀取配置文件類:ReadConfigEmail
public class ReadConfigEmail {
private static Properties mailProps = new Properties();
private static final String EMAILPROPERTIES = "mail.properties";
static {
try {
InputStream inStream = ReadConfigEmail.class.getClassLoader()
.getResourceAsStream(EMAILPROPERTIES);
mailProps.load(inStream);
} catch (Exception ex) {
throw new RuntimeException("讀取配置文件出錯了..." + ex.getMessage(), ex);
}
}
public static Properties getProperty() {
return mailProps;
}
public static String getPropertyByKey(String key) {
return mailProps.getProperty(key);
}
}
4 消息對象:SendMessage
public class SendMessage {
private String [] tos;
private String subject;
private String imgName;
private File file;
private MailType mailType;
private String form;
private List<String> texts = new ArrayList<String>();
//圖片集合
private List<SendMessage> images = new ArrayList<SendMessage>();
public MailType getMailType() {
return mailType;
}
public void setMailType(MailType mailType) {
this.mailType = mailType;
}
public void addFile(MailType mailType,String imgName,File file){
images.add(new SendMessage(mailType,imgName,file));
}
public void addText(String text){
texts.add(text);
}
public SendMessage(MailType mailType,String imgName, File file) {
super();
this.mailType = mailType;
this.imgName = imgName;
this.file = file;
}
public List<SendMessage> getImages() {
return images;
}
public void setImages(List<SendMessage> images) {
this.images = images;
}
public String getForm() {
return form;
}
public void setForm(String form) {
this.form = form;
}
public String getImgName() {
return imgName;
}
public void setImgName(String imgName) {
this.imgName = imgName;
}
public String[] getTos() {
return tos;
}
public void setTos(String[] tos) {
this.tos = tos;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public SendMessage() {
}
public SendMessage(String[] tos, String subject, String text) {
super();
this.tos = tos;
this.subject = subject;
addText(text);
}
public String getSendTexts(){
StringBuilder sbr = new StringBuilder();
List<String> texts = getTexts();
for(String text : texts){
sbr.append(text);
}
return sbr.toString();
}
@Override
public String toString() {
StringBuilder sbrTos = new StringBuilder();
for(String to : tos){
sbrTos.append(to).append(",");
}
String sbrText = sbrTos.substring(0,sbrTos.length()-1);
return new StringBuilder()
.append("接收人地址: ").append(sbrText)
.append(",發送人地址: ").append(form)
.append(",發送標題: ").append(subject)
.append(",發送內容: ").append(getSendTexts())
.toString();
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public List<String> getTexts() {
return texts;
}
public void setTexts(List<String> texts) {
this.texts = texts;
}
}
5 郵件發送服務器:JavaMailFactory
public class JavaMailFactory {
/***
* 此處也可修改爲
* private JavaMailSenderImpl javaMailSenderImpl;
* ... 省略set,get,方便使用spring注入
* */
private static JavaMailSenderImpl senderImpl = new JavaMailSenderImpl();
static{
senderImpl.setHost(EmailEntity.EMAIL_HOST);
senderImpl.setUsername(EmailEntity.EMAIL_USERNAME);
senderImpl.setPassword(EmailEntity.EMAIL_PASSWORD);
senderImpl.setJavaMailProperties(EmailEntity.safetyProperties);
}
public static JavaMailSenderImpl getJavaMail(){
return senderImpl;
}
}
6 Email實體:EmailEntity
public class EmailEntity {
/**郵件服務器*/
private static final String EMAIL_HOST_KEY = "mail.host";
public static final String EMAIL_HOST = ReadConfigEmail.getPropertyByKey(EMAIL_HOST_KEY);
/**用戶名*/
private static final String EMAIL_USERNAME_KEY = "mail.username";
public static final String EMAIL_USERNAME = ReadConfigEmail.getPropertyByKey(EMAIL_USERNAME_KEY);
/**用戶密碼*/
private static final String EMAIL_PASSWORD_KEY = "mail.password";
public static final String EMAIL_PASSWORD = ReadConfigEmail.getPropertyByKey(EMAIL_PASSWORD_KEY);
/**接收人*/
private static final String EMAIL_TO_KEY = "mail.to";
public static final String EMAIL_TO = ReadConfigEmail.getPropertyByKey(EMAIL_TO_KEY);
/**發送人*/
private static final String EMAIL_FROM_KEY = "mail.from";
public static final String EMAIL_FROM = ReadConfigEmail.getPropertyByKey(EMAIL_FROM_KEY);
/**服務器進行認證,認證用戶名和密碼是否正確*/
private static final String EMAIL_SMTP_AUTH_KEY = "mail.smtp.auth";
public static final String EMAIL_SMTP_AUTH = ReadConfigEmail.getPropertyByKey(EMAIL_SMTP_AUTH_KEY);
/**超時時間設定*/
private static final String EMAIL_SMTP_TIMEOUT_KEY = "mail.smtp.timeout";
public static final String EMAIL_SMTP_TIMEOUT = ReadConfigEmail.getPropertyByKey(EMAIL_SMTP_TIMEOUT_KEY);
/**編碼設置*/
private static final String EMAIL_ENCODING_KEY = "mail.encoding";
public static final String EMAIL_ENCODING = ReadConfigEmail.getPropertyByKey(EMAIL_ENCODING_KEY);
private static final String EMAIL_SMTP_STARTTLS_KEY = "mail.smtp.starttls.enable";
public static final String EMAIL_SMTP_STARTTLS = ReadConfigEmail.getPropertyByKey(EMAIL_SMTP_STARTTLS_KEY);
//private static final String EMAIL_SMTP_SOCKETFACTORY_CLASS_KEY = "mail.smtp.socketFactory.class";
//public static final String EMAIL_SMTP_SOCKETFACTORY_CLASS = ReadConfigEmail.getPropertyByKey(EMAIL_SMTP_SOCKETFACTORY_CLASS_KEY);
/**安全認證設置*/
public static Properties safetyProperties = new Properties();
static{
//調試信息,可以取消
//System.setProperty( "javax.net.debug", "ssl");
/**
* #配置JavaMail的Properties時,不要指定“mail.smtp.socketFactory.class”,
#因爲TLS使用的是普通的Socket。然後指定屬性“mail.smtp.starttls.enable”爲“true”。
* */
safetyProperties.put(EMAIL_SMTP_AUTH_KEY, EMAIL_SMTP_AUTH);
safetyProperties.put(EMAIL_SMTP_TIMEOUT_KEY, EMAIL_SMTP_TIMEOUT);
safetyProperties.put(EMAIL_SMTP_STARTTLS_KEY, EMAIL_SMTP_STARTTLS);
//safetyProperties.put(EMAIL_SMTP_SOCKETFACTORY_CLASS_KEY, EMAIL_SMTP_SOCKETFACTORY_CLASS);
}
}
7 MailType.java
public enum MailType {
/**
* 圖片類型
* */
IMG,
/**
* 文件類型
* */
FILE;
@Override
public String toString() {
String message = null;
switch (this) {
case IMG :
message = ",包含圖片";
default:
message = ",包含附件";
break;
}
return message;
}
}
8 mail.properties
#新浪郵件服務器
mail.host=smtp.sina.com
mail.smtp.auth=true
mail.smtp.timeout=25000
mail.encoding=utf-8
mail.smtp.starttls.enable=true;
#mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
#Email地址
mail.username=XXX
#Email密碼
mail.password=XXX
#發送人地址
mail.from=XXX@sina.com
#收件人地址
mail.to=XXX@163.com