分享

java组件开发(21)邮件发送组件mysmtp

 X的世界 2012-04-21
转载注明出处,违者必究

邮件发送组件:mysmtp

在发送电子邮件时,可以通过使用引入JavaMail来达到这个目的,但是JavaMail本身在使用上还是比较复杂,特别是处理TLS、SSL加密以及附件的发送上比较麻烦。故本节通过对其封装,达到简便使用的效果,在日后编程中可以直接使用。
JavaMail不是标准的JDK的一部分,所以需要引入mail.jar到claasPath。另外还使用了commons.logging和log4j.jar作为日志输出,同时还使用了前面我们开发的commons.jar。

组件名: mysmtp
版本: 1.1
依赖包:commons-logging-1.1.1.jar、log4j-1.2.15.jar、mail.jar、commons_2010_10_17.jar
作者:UnclePeng

对象建模:

1、SMTPSetting,发送邮件需要用户名,密码,端口,加密算法,smtp地址等设置,所以集合这些属性,形成SMTP的设置类: SMTPSetting
2、MailMessage,邮件除了正文外,还有标题,收件人,回复人,抄送人,密送人等等属性,集合这些属性,形成邮件消息类: MailMessage
3、Attachment,除了文字外,邮件有时还带有附件,供MailMessage引用,Attachment直接引用本地或者网络路径上的文件路径。
4、MailSender,外部调用入口,该类初台化三个不同的seesion,分别是正常的session、ssl session、tls session,根据不同配置选择不同的session来发送邮件。

源码:

1、SMTPSetting.java

/*
 *@# SMTPSetting.java 2:55:44 PM Jul 17, 2009
 *Copyright 2009 UnclePeng, Inc. All rights reserved.
 */
package com.upeng.mysmtp;

/**
 * <p>SMTP设置</p>
 * @author Lucky
 * 2:55:44 PM Jul 17, 2009 
 */
public class SMTPSetting {
/**加密协议**/
public enum SMTPEncrypt{
NORMAL, SSL ,TLS;
}
//用户名
private String userName = "";
//密码
private String pwd = "";
//SMTP地址
private String smtpHost;
//端口
private int port = 25;
//加密协议
private SMTPEncrypt enc = SMTPEncrypt.NORMAL;
/**
* @param userName 用户名
* @param pwd 密码
* @param smtpHost SMTP地址
* @param port 端口
* @param enc 加密协议
*/
public SMTPSetting(String userName , String pwd , String smtpHost , int port , SMTPEncrypt enc){
this.userName = userName;
this.pwd = pwd;
this.smtpHost = smtpHost;
this.port = port;
this.enc = enc;
}
/**
* @param userName 用户名
* @param pwd 密码
* @param smtpHost SMTP地址
* @param port 端口
*/
public SMTPSetting(String userName , String pwd , String smtpHost , int port){
this.userName = userName;
this.pwd = pwd;
this.smtpHost = smtpHost;
this.port = port;
}
/**
* @param userName 用户名
* @param pwd 密码
* @param smtpHost SMTP地址
* @param enc 加密协议
*/
public SMTPSetting(String userName , String pwd , String smtpHost , SMTPEncrypt enc){
this.userName = userName;
this.pwd = pwd;
this.smtpHost = smtpHost;
this.enc = enc;
}
/**
* @param userName 用户名
* @param pwd 密码
* @param smtpHost SMTP地址
*/
public SMTPSetting(String userName , String pwd , String smtpHost){
this.userName = userName;
this.pwd = pwd;
this.smtpHost = smtpHost;
}
public SMTPSetting(){
}

/**
* @return the userName
*/
public String getUserName() {
return userName;
}

/**
* @param userName the userName to set
*/
public void setUserName(String userName) {
this.userName = userName;
}

/**
* @return the pwd
*/
public String getPwd() {
return pwd;
}

/**
* @param pwd the pwd to set
*/
public void setPwd(String pwd) {
this.pwd = pwd;
}

/**
* @return the smtpHost
*/
public String getSmtpHost() {
return smtpHost;
}

/**
* @param smtpHost the smtpHost to set
*/
public void setSmtpHost(String smtpHost) {
this.smtpHost = smtpHost;
}

/**
* @return the port
*/
public int getPort() {
return port;
}

/**
* @param port the port to set
*/
public void setPort(int port) {
this.port = port;
}

/**
* @return the enc
*/
public SMTPEncrypt getEnc() {
return enc;
}

/**
* @param enc the enc to set
*/
public void setEnc(SMTPEncrypt enc) {
this.enc = enc;
}
}

说明:
SMTPSetting里面定义了三个不同加密类型的枚举,分别是不加密、SSL加密和TLS加密,默认是不加密
SMTP默认发送端口是25,可以更改,用户名和密码在需要的时候根据实际情况设置。

2、Attachment.java

/*
 *@# Attachment.java 11:06:54 AM Jun 24, 2009
 *Copyright 2009 UnclePeng, Inc. All rights reserved.
 */
package com.upeng.mysmtp;

import com.upeng.commons.io.FileUtils;

/**
 * <p>附件</p>
 * @author Lucky
 * 11:06:54 AM Jun 24, 2009 
 */
public class Attachment {

//文件名
private String fileName;
//文件大小
private int fileSize;
//文件路径
private String filePath;
/**
* <p>获取文件名</p>
* @return
*/
public String getFileName() {
if(this.fileName == null){
this.fileName = FileUtils.getFileName(filePath);
}
return fileName;
}
/**
* <p>设置文件名</p>
* @param fileName 文件名
*/
public void setFileName(String fileName) {
this.fileName = fileName;
}
/**
* <p>获取文件大小</p>
* @return
*/
public int getFileSize() {
return fileSize;
}
/**
* <p>设置文件大小</p>
* @param fileSize 文件大小
*/
public void setFileSize(int fileSize) {
this.fileSize = fileSize;
}

/**
* @return the filePath
*/
public String getFilePath() {
return filePath;
}

/**
* @param filePath the filePath to set
*/
public void setFilePath(String filePath) {
this.filePath = filePath;
}

}

3、MailMessage

/*
 *@# MailMessage.java 11:28:41 AM Jun 24, 2009
 *Copyright 2009 UnclePeng, Inc. All rights reserved.
 */
package com.upeng.mysmtp;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Message.RecipientType;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.upeng.commons.lang.StringUtils;

/**
 * <p>邮件消息</p>
 * @author Lucky
 * 11:28:41 AM Jun 24, 2009 
 */
public class MailMessage {
private static final Log logger = LogFactory.getLog(MailMessage.class);
//分隔符
private static final String SEPARATOR = ":";
//常见错误分隔符
private static final String USUALLY_ERROR_SEPARATOR = ":";
//发件人Email地址
private String from;
//收件人列表
private List<String> to = new ArrayList<String>();
//抄送人列表
private List<String> cc = new ArrayList<String>();
//密送人列表
private List<String> bcc = new ArrayList<String>();
//日期
private Date date;

//邮件标题
private String subject;
//邮件正文
private String body;
//附件列表
private List<Attachment> attachments = new ArrayList<Attachment>();
//邮件大小
private int size;
//邮件优先级,默认为3
private int priority = 3;
private List<String> replyList = new ArrayList<String>();

/**
* <p>获取发件人信息</p>
* @return the 发件人信息
*/
public String getForm() {
return from;
}

/**
* <p>设置发件人信息</p>
* @param form 发件人信息
*/
public void setForm(String from) {
this.from = from;
}

/**
* <p>获取收件人列表</p>
* @return 收件人列表
*/
public List<String> getTo() {
return to;
}

/**
* <p>设置收件人列表</p>
* @param to 收件人列表
*/
public void setTo(List<String> to) {
this.to = to;
}

/**
* <p>获取抄送人列表</p>
* @return 抄送人列表
*/
public List<String> getCc() {
return cc;
}

/**
* <p>设置抄送人列表</p>
* @param cc 抄送人列表
*/
public void setCc(List<String> cc) {
this.cc = cc;
}

/**
* <p>获取密送人列表</p>
* @return 密送人列表
*/
public List<String> getBcc() {
return bcc;
}

/**
* <p>设置密送人列表</p>
* @param bcc 密送人列表
*/
public void setBcc(List<String> bcc) {
this.bcc = bcc;
}

/**
* </p>获取日期</p>
* @return 日期
*/
public Date getDate() {
return date;
}

/**
* <p>设置日期</p>
* @param date 日期
*/
public void setDate(Date date) {
this.date = date;
}

/**
* <p>获取邮件主题</p>
* @return 邮件主题
*/
public String getSubject() {
return subject;
}

/**
* <p>设置邮件主题</p>
* @param subject 邮件主题t
*/
public void setSubject(String subject) {
this.subject = subject;
}

/**
* <p>获取邮件正文</p>
* @return 邮件正文
*/
public String getBody() {
return body;
}

/**
* <p>设置邮件正文</p>
* @param body 邮件正文
*/
public void setBody(String body) {
this.body = body;
}

/**
* <p>获取附件列表</p>
* @return 附件列表
*/
public List<Attachment> getAttachments() {
return attachments;
}
/**
* <p>Add attachment</p>
* @param att
*/
public void addAttachment(Attachment att){
this.attachments.add(att);
}

/**
* <p>设置附件列表</p>
* @param attachments 附件列表
*/
public void setAttachments(List<Attachment> attachments) {
this.attachments = attachments;
}

/**
* <p>获取邮件大小</p>
* @return the 邮件大小
*/
public int getSize() {
return size;
}

/**
* <p>设置邮件大小</p>
* @param size 邮件大小
*/
public void setSize(int size) {
this.size = size;
}
/**
* <p>获取邮件优先级</p>
* @return 邮件优先级
*/
public int getPriority() {
return priority;
}
/**
* <p>设置邮件优先级</p>
* @param priority 邮件优先级
*/
public void setPriority(int priority) {
this.priority = priority;
}
/**
* <p>获取邮件答复人列表</p>
* @return ArrayList
*/
public List<String> getReplyList() {
return replyList;
}

/**
* <p>设置邮件优先级</p>
* @param list 答复人列表
*/
public void setReplyList(List<String> list) {
this.replyList = list;
}
/**
* <p>自定义的MailMessage转换成JavaMail的Message</p>
* @return JavaMail的Message
* @throws MessagingException 
*/
protected Message toJavaMailMessage() throws Exception{
//设置邮件头信息
Message message = new MimeMessage(MailSender.getNormalSMTPSession());
message.setSubject(this.subject);
message.setSentDate(new Date());
message.setHeader("X-Priority", this.priority + "");
//FROM
message.setFrom(MailMessage.toAddress(this.from));
//REPLAY TO
message.setReplyTo(MailMessage.toAddressArray(this.replyList));
//TO
for(String str : this.to){
message.setRecipient(RecipientType.TO, MailMessage.toAddress(str));
}
//CC
for(String str : this.cc){
message.setRecipient(RecipientType.CC, MailMessage.toAddress(str));
}
//BCC
for(String str : this.bcc){
message.setRecipient(RecipientType.BCC, MailMessage.toAddress(str));
}
MimeMultipart mmp = null;
//以下为邮件体部分
if(this.attachments.size() == 0){
logger.trace("no attachmennts");
mmp = new MimeMultipart("alternative");
}else{
logger.trace("has attachmennts");
mmp = new MimeMultipart();
}
//正文
message.setContent(mmp);
MimeBodyPart part = new MimeBodyPart();
part.setText(this.body, "UTF-8");
mmp.addBodyPart(part);
//有附件则需要加上附件
if(this.attachments != null){
for(Attachment att : this.attachments){
DataSource source = null;
try{
source = new FileDataSource(att.getFilePath());
}catch(Exception e){
logger.error(e);
}
if(source == null){
logger.trace("cannot get file");
continue;
}
MimeBodyPart fileBodyPart = new MimeBodyPart();
fileBodyPart.setDataHandler(new DataHandler(source));
fileBodyPart.setFileName(MimeUtility.encodeText(att.getFileName(), "UTF-8", null));
mmp.addBodyPart(fileBodyPart);
}
}
return message;
}
/**
* <p>将自定义地址格式转换成javaMail中的Address</p>
* @param addressStr
* @return
* @throws Exception
*/
private static Address toAddress(String addressStr) throws Exception{
if(StringUtils.isBlank(addressStr)){
return null;
}
//将全角的:替换成半角的:
addressStr = addressStr.replace(MailMessage.USUALLY_ERROR_SEPARATOR, MailMessage.SEPARATOR);
String personal = StringUtils.substringBefore(addressStr, MailMessage.SEPARATOR);
String address = StringUtils.substringAfter(addressStr, MailMessage.SEPARATOR);
if(StringUtils.isBlank(address)){
address = addressStr;
}
Address javaMailAddress = new InternetAddress(address , personal);
return javaMailAddress;
}
/**
* <p>将List中的地址列表转换成JavaMail Address数组</p>
* @param list 地址列表
* @return
* @throws Exception
*/
private static Address[] toAddressArray(List<String> list) throws Exception {
List<Address> addressList = new ArrayList<Address>();
if(list == null){
return null;
}
for(String str : list){
addressList.add(MailMessage.toAddress(str));
}
return addressList.toArray(new Address[]{});
}
}

说明:
toJavaMailMessage方法将自定义的MailMessage转化为JavaMessage对象
toAddress方法将自定义的address(即String)转换为JavaMail的Address对象
以上两个方法作为对JavaMail依赖的解耦,让应用程序不需要直接依赖于javaMail。
自定义分隔符":"的作用是因为可以支持类似"UnclePeng:itworker@126.com"的方式,前者可以代表发件人,后者可以代表发件人地址。由于全角和半角的:区分并不显示,所以在调用的时候也要求能兼容这两个方式的写法。

3、MailSender.java

/*
 *@# MailSender.java 4:33:54 PM Jul 17, 2009
 *Copyright 2009 mozat, Inc. All rights reserved.
 */
package com.upeng.mysmtp;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.upeng.commons.lang.StringUtils;

/**
 * <p>邮件发送类</p>
 * @author Lucky
 * 4:33:54 PM Jul 17, 2009 
 */
public class MailSender {

private static final Log logger = LogFactory.getLog(MailSender.class);
//普通邮件发送session
private static final Session normalSMTPSession = Session.getInstance(new Properties());;
//SSL加密方式的邮件发送session
private static final Session sslSMTPSession = Session.getInstance(new Properties());
//TLS加密方式的邮件发送session
private static final Session tlsSMTPSession = Session.getInstance(new Properties());
static {
normalSMTPSession.getProperties().setProperty("mail.smtp.auth", "true");
normalSMTPSession.getProperties().setProperty("mail.smtps.auth", "true");
sslSMTPSession.getProperties().setProperty("mail.smtp.auth", "true");
sslSMTPSession.getProperties().setProperty("mail.smtps.auth", "true");
tlsSMTPSession.getProperties().setProperty("mail.smtp.auth", "true");
tlsSMTPSession.getProperties().setProperty("mail.smtps.auth", "true");
tlsSMTPSession.getProperties().setProperty("mail.smtp.starttls.enable", "true");
}
/**
* <p>发送邮件</p>
* @param setting SMTP设置
* @param message 邮件
* @throws Exception
*/
public static void sendMail(SMTPSetting setting , MailMessage message) throws Exception{
if(StringUtils.isBlank(setting.getSmtpHost())){
throw new java.lang.IllegalArgumentException("SMTP host can't be blank!");
}
//默认用普通的session
Session mailSenderSession = normalSMTPSession;
//协议名
String protocolName = "smtp";
if(setting.getEnc().equals(SMTPSetting.SMTPEncrypt.SSL)){//SSL
mailSenderSession = sslSMTPSession;
protocolName = "smtps";
logger.trace("use SSL session");
}else if(setting.getEnc().equals(SMTPSetting.SMTPEncrypt.TLS)){//TLS
mailSenderSession = tlsSMTPSession;
logger.trace("user TLS session");
}else{
logger.trace("user NORMAL session");
}
logger.trace(String.format("protocol name is %s", protocolName));
//将MailMessage对象转换成JavaMail的Message对象
Message javaMailMessage = message.toJavaMailMessage();
long starttime = System.currentTimeMillis();
//连接服务器并发送邮件
Transport transport = mailSenderSession.getTransport(protocolName);
transport.connect(setting.getSmtpHost(), setting.getPort(), setting.getUserName() , setting.getPwd());
transport.sendMessage(javaMailMessage, javaMailMessage.getAllRecipients());
transport.close();
long endTime = System.currentTimeMillis();
logger.trace(String.format("send mail from %s to %s successfuly [%d milliseconds]", message.getForm(), message.getTo().get(0), endTime - (starttime)));
}

/**
* @return the normalSMTPSession
*/
public static Session getNormalSMTPSession() {
return normalSMTPSession;
}

/**
* @return the sslSMTPSession
*/
public static Session getSslSMTPSession() {
return sslSMTPSession;
}

/**
* @return the tlsSMTPSession
*/
public static Session getTlsSMTPSession() {
return tlsSMTPSession;
}

}

说明:在static块中初始化了3个session,根据SMTPSetting对象具体设置的是哪种加密方式调用不同的session来发送邮件
sendMail方法调用了JavaMail来发送邮件,是外部调用者与JavaMail彻底解耦。

测试:

126的邮箱,没有使用加密
public class Send126MailTest {

public static void main(String[] args) {

//SMTP设置,包括登录用户名、密码、SMTP主机地址和端口等信息
SMTPSetting setting = new SMTPSetting();
setting.setSmtpHost("smtp.126.com");
//setting.setSmtpHost("192.168.1.181");
setting.setUserName("itworker");
setting.setPwd("******");//换成你的密码
//邮件内容
MailMessage message = new MailMessage();
message.setForm("UnclePeng:itworker@126.com");//发件人
message.getTo().add("lucky.peng@mozat.com");//收件人
message.setSubject("this mail send by mysmtp");//主题
message.setBody("<html>试试发送中文邮件能过mysmtp的哟,哈哈!!!</html>");//正文
message.setPriority(1);//邮件优先级1为高,3为中,5为低
message.getReplyList().add("lucky.peng@mozat.com");
//附件
//Attachment att = new Attachment();
//att.setFileName("xxx.java");//附件名
//att.setFilePath("C:\\TestCase.java");//设置附件的路径
//message.addAttachment(att);
//发送邮件
try {
MailSender.sendMail(setting, message);
} catch (Exception e) {
e.printStackTrace();
}

}

}

gmail邮箱,使用ssl加密
public class SendGMailTest {

public static void main(String[] args) {

//SMTP设置,包括登录用户名、密码、SMTP主机地址和端口等信息
SMTPSetting setting = new SMTPSetting();
setting.setSmtpHost("smtp.gmail.com");
setting.setUserName("pengzhoushuo");
setting.setPwd("******");//换成你的密码
setting.setPort(465);
setting.setEnc(SMTPEncrypt.SSL);
//邮件内容
MailMessage message = new MailMessage();
message.setForm("pengzhoushuo:pengzhoushuo@gmail.com");//发件人
List<String> toList = new ArrayList<String>();//收件人列表
toList.add("lucky.peng@mozat.com.cn");
message.setTo(toList);
message.setSubject("this mail send by mysmtp");//主题
message.setBody("hello world!");//正文
message.setPriority(3);//邮件优先级1为高,3为中,5为低,默认为中

//发送邮件
try {
MailSender.sendMail(setting, message);
} catch (Exception e) {
e.printStackTrace();
}

}
}

HotMail邮箱,使用tls加密

public class SendHotMailTest {

public static void main(String[] args) {

//SMTP设置,包括登录用户名、密码、SMTP主机地址和端口等信息
SMTPSetting setting = new SMTPSetting();
setting.setSmtpHost("smtp.live.com");
setting.setUserName("pengzhoushuo@hotmail.com");//注意用户名必须是全称
setting.setPwd("******");//换成你的密码
setting.setEnc(SMTPEncrypt.TLS);//需要TLS支持
//邮件内容
MailMessage message = new MailMessage();
message.setForm("pengzhoushuo@yahoo.com");//发件人,原来HotMail还可以伪造发件人
List<String> toList = new ArrayList<String>();//收件人列表
toList.add("lucky.peng@mozat.com.cn");
message.setTo(toList);
message.setSubject("this mail send by mysmtp");//主题
message.setBody("hello world!");//正文
message.setPriority(3);//邮件优先级1为高,3为中,5为低,默认为中

//发送邮件
try {
MailSender.sendMail(setting, message);
} catch (Exception e) {
e.printStackTrace();
}

}
}

本节总结:
通过对JavaMail的封装,将调用者从具体的javaMail api中解耦出来,用简洁直观的代码来发送邮件,new一个SMTPSetting,再new一个Mailmessage,再调用MailSender的方法将前两个对象作为参数实现发送邮件。
另外这一系列的过程还可以通过log打印出执行步骤,方便开发调试。同时还支持简洁的方式发送附件,直接设置好附件的file path即可。另外本组件己经开源,svn地址是:http://mysmtp./svn/trunk/




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多