package com.reagle.bean;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Part;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.URLName;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
public class MailBean {
private Logger log = LogManager.getLogger(MailBean.class);
/**
* 主题
*/
private String subject;
/**
* 发送邮箱地址
*/
private String sendMail;
/**
* 发送邮箱密码
*/
private String sendMailPassword;
/**
* 收件人
*/
private List tos;
/**
* 抄送
*/
private List ccs;
/**
* 发送内容
*/
private String content;
/**
* 内容编码
*/
private String character;
/**
* 发送服务器地址
*/
private String mailHost;
/**
* 附件
*/
private List accessories;
/**
* 发送是否需要校验
*/
private String isCheckSend;
/**
*
* @param subject 主题
* @param sendMail 发件人
* @param sendMailPassword 密码
* @param tos 收件人
* @param content 内容
* @param character 内容字符集
* @param mailHost SMTP主机
* @param isCheckSend 是否需要验证
*/
public MailBean(String subject, String sendMail, String sendMailPassword,
List tos, String content, String character,
String mailHost, String isCheckSend) {
this.subject = subject;
this.sendMail = sendMail;
this.sendMailPassword = sendMailPassword;
this.tos = tos;
this.content = content;
this.character = character;
this.mailHost = mailHost;
this.isCheckSend = isCheckSend;
}
/**
*
* @param subject 主题
* @param sendMail 发件人
* @param sendMailPassword 密码
* @param tos 收件人
* @param content 内容
* @param character 内容字符集
* @param mailHost SMTP主机
* @param isCheckSend 是否需要验证
* @param accessories 附件
*/
public MailBean(String subject, String sendMail, String sendMailPassword,
List tos, String content, String character,
String mailHost, List accessories, String isCheckSend) {
this.subject = subject;
this.sendMail = sendMail;
this.sendMailPassword = sendMailPassword;
this.tos = tos;
this.content = content;
this.character = character;
this.mailHost = mailHost;
this.accessories = accessories;
this.isCheckSend = isCheckSend;
}
/**
*
* @param subject 主题
* @param sendMail 发件人
* @param sendMailPassword 密码
* @param tos 收件人
* @param content 内容
* @param character 内容字符集
* @param mailHost SMTP主机
* @param isCheckSend 是否需要验证
* @param accessories 附件
* @param cc 抄送
*/
public MailBean(String subject, String sendMail, String sendMailPassword,
List takeMail, String content, String character,
String mailHost, List accessories, String isCheckSend, List cc) {
this.subject = subject;
this.sendMail = sendMail;
this.sendMailPassword = sendMailPassword;
this.tos = takeMail;
this.content = content;
this.character = character;
this.mailHost = mailHost;
this.accessories = accessories;
this.isCheckSend = isCheckSend;
this.ccs = cc;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getSendMail() {
return sendMail;
}
public void setSendMail(String sendMail) {
this.sendMail = sendMail;
}
public String getSendMailPassword() {
return sendMailPassword;
}
public void setSendMailPassword(String sendMailPassword) {
this.sendMailPassword = sendMailPassword;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getCharacter() {
return character;
}
public void setCharacter(String character) {
this.character = character;
}
public String getMailHost() {
return mailHost;
}
public void setMailHost(String mailHost) {
this.mailHost = mailHost;
}
public List getAccessories() {
return accessories;
}
public void setAccessories(List accessories) {
this.accessories = accessories;
}
public String getCheckSend() {
return isCheckSend;
}
public void setCheckSend(String isCheckSend) {
this.isCheckSend = isCheckSend;
}
public List getTos() {
return tos;
}
public void setTos(List tos) {
this.tos = tos;
}
public List getCcs() {
return ccs;
}
public void setCcs(List ccs) {
this.ccs = ccs;
}
public String getIsCheckSend() {
return isCheckSend;
}
public void setIsCheckSend(String isCheckSend) {
this.isCheckSend = isCheckSend;
}
// 获得所有收件人
private Address[] getAllTake() throws ArrayIndexOutOfBoundsException, AddressException{
return valueOfAddress(tos);
}
private Address[] valueOfAddress(List list) throws ArrayIndexOutOfBoundsException, AddressException{
Address[] takes = new Address[0];
if(null == list || list.size() == 0)
throw new ArrayIndexOutOfBoundsException("list is null");
takes = new Address[list.size()];
for(int i = 0; i < list.size(); ++ i) {
takes[i] = InternetAddress.parse(list.get(i))[0];
}
return takes;
}
private Address[] getAllOtherTake() throws ArrayIndexOutOfBoundsException, AddressException {
if (null == ccs || ccs.size() == 0)
return new Address[0];
else
return valueOfAddress(getCcs());
}
// 添加所有附件
private void addBodyPartByMimeMultipart(MimeMultipart mm,
List filePaths) throws MessagingException,
ArrayIndexOutOfBoundsException, NullPointerException {
if (null == filePaths || filePaths.size() == 0)
return;
if(null == mm)
throw new NullPointerException("MimeMultipart is null");
for (int i = 0; i < filePaths.size(); i++) {
MimeBodyPart bp = new MimeBodyPart();
FileDataSource fileds = new FileDataSource(filePaths.get(i));
DataHandler dh = new DataHandler(fileds);
bp.setDisposition(Part.ATTACHMENT);
bp.setFileName(fileds.getName());
bp.setDataHandler(dh);
mm.addBodyPart(bp);
}
}
public boolean send() throws Exception {
boolean isSend = false;
// 设置SMTP发送服务器
Properties props = System.getProperties();
// 设置SMTP的主机
props.put("mail.smtp.host", mailHost);
// 需要经过验证
props.put("mail.smtp.auth", isCheckSend);
//Authenticator auth = Authenticator
// 获得邮件会话对象
Session session = Session.getDefaultInstance(props,null);
URLName url = new URLName(this.sendMail);
PasswordAuthentication pw = new PasswordAuthentication(this.sendMail, this.sendMailPassword);
session.setPasswordAuthentication(url, pw);
// 邮件对象
MimeMessage mimeMsg = new MimeMessage(session);
MimeMultipart multipart = new MimeMultipart();
// 发送邮件地址
mimeMsg.setFrom(new InternetAddress(sendMail));
// 收件人
mimeMsg.setRecipients(Message.RecipientType.TO, getAllTake());
mimeMsg.setSentDate(new Date());
// 抄送人
mimeMsg.setRecipients(Message.RecipientType.CC, getAllOtherTake());
// 主题 与字符编码
mimeMsg.setSubject(getSubject(), getCharacter());
// 设置邮件体格式
BodyPart bp = new MimeBodyPart();
//bp.setContent(""
// + content, "text/html;charset="+getCharacter());
bp.setText(content);
log.info(bp.getContent().toString());
multipart.addBodyPart(bp);
// 添加附件
addBodyPartByMimeMultipart(multipart, getAccessories());
isSend = process(session, mimeMsg, multipart, props);
return isSend;
}
private boolean process(Session session, MimeMessage mimeMsg, MimeMultipart multipart, Properties props) throws MessagingException {
boolean isSuccessfully = false;
mimeMsg.setContent(multipart);
mimeMsg.saveChanges();
Session mailSession = Session.getInstance(props, null);
Transport transport = mailSession.getTransport("smtp");
transport.connect((String) props.get("mail.smtp.host"), getSendMail(),
getSendMailPassword());
transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients());
log.info("Mail Successfully Sended!");
transport.close();
isSuccessfully = true;
return isSuccessfully;
}
}
邮件工具类
/**
*
*/
package com.reagle.util.others;
import java.io.IOException;
import java.util.Properties;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
/**
* @Program Name : reaglews.com.reagle.util.others.MailUtil.java
* @Written by : kzw
* @version : v1.00
* @Creation Date : 2012-7-17 上午10:40:40
* @Description :
* 邮件操作工具类
* @ModificationHistory
* Who When What
* ------- ------------- -----------------
* kzw 2012-7-17 上午10:40:40 create
*
**/
public class MailUtil {
private static Logger log = LogManager.getLogger(MailUtil.class);
private static final String CONFIGPATH = "mail.properties";
private static final String SMTP = "smtp";
private static final String EMAILREGEX = "emailRegex";
private static Properties mailConfig;
static {
reloadPro();
}
/**
* 获取邮箱对应SMTP服务器
* 通过邮件来判断需要的SMTP主机,这里默认了使用了QQ的SMTP服务器
* @Eclosing_Method : getMail2SMTP
* @author by : kzw
* @creation Date : 2012-7-17上午11:02:33
* @param mail
* @return
*
*/
public static String getMail2SMTP(String mail) {
return (String)getConfigValue(SMTP);
}
public static String getConfigValue(String key) {
if(null == mailConfig)
reloadPro();
return (String)mailConfig.get(key);
}
/**
* 重新加载配置文件
* @Eclosing_Method : reloadPro
* @author by : kzw
* @creation Date : 2012-7-17上午11:57:19
*
*/
public static void reloadPro(){
mailConfig = new Properties();
try {
mailConfig.load(MailUtil.class.getClassLoader().getResourceAsStream(CONFIGPATH));
} catch (IOException e) {
log.error("加载邮件配置错误! e=" + e.getMessage());
}
}
/**
* 邮箱地址是否正确
* @Eclosing_Method : isEmail
* @author by : kzw
* @creation Date : 2012-7-17下午12:17:28
* @param email
* @return
*
*/
public static boolean isEmail(String email) {
if(StringUtils.isNotBlank(email))
return email.matches(getConfigValue(EMAILREGEX));
return false;
}
}
邮件配置文件mail.properties
#
# 邮件发送配置文件
#
# kzw create 2012-07-17
#
#
#
#邮件内容字符集
character=UTF-8
#SMTP
smtp=smtp.exmail.qq.com
#默认发送者
defaultSend=XXXXX
#密码
password=XXXXXX
#是否需要发送验证
checkSend=true
#邮箱校验正则
emailRegex=^([a-z0-9A-Z]+[_|.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?.)+[a-zA-Z]{2,}$
邮件接口
package com.reagle.server;
import java.util.List;
/**
* @Program Name : reaglews.com.reagle.server.IMailService.java
* @Written by : kzw
* @version : v1.00
* @Creation Date : 2012-7-17 上午09:29:30
* @Description :
* 邮件接口
* @ModificationHistory
* Who When What
* ------- ------------- -----------------
* kzw 2012-7-17 上午09:29:30 create
*
**/
public interface IMailService {
/**
* 字符集配置key,这里有点怪怪的, 以后优化//TODO....
*/
public final String CHARACTERCONFIG = "character";
public final String SMTPCONFIG = "smtp";
public final String CHECKSEND = "checkSend";
public final String DEFAULT_SEND = "defaultSend";
public final String DEFAULT_SEND_PWD = "password";
/**
* 发送邮件
* @Eclosing_Method : sendMail
* @author by : kzw
* @creation Date : 2012-7-17上午10:08:50
* @param sendMailAddr 发送人邮箱
* @param sendMailPwd 发送人密码
* @param cc 抄送人
* @param to 收件人
* @param subject 邮件主题
* @param content 邮件内容
* @param accessories 附件
* @param mailType 邮件类型
* @param operMan 操作员
* @param memo 备注
*
*/
void sendMail(String sendMailAddr, String sendMailPwd, List cc,
List to, String subject, String content, List accessories,
String mailType, String operMan, String memo);
}
邮件接口实现类
/**
*
*/
package com.reagle.server.impl;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import com.reagle.bean.MailBean;
import com.reagle.common.db.DbUtilsTemplate;
import com.reagle.server.IMailService;
import com.reagle.util.others.MailUtil;
/**
* @Program Name : reaglews.com.reagle.server.impl.MailServiceImpl.java
* @Written by : kzw
* @version : v1.00
* @Creation Date : 2012-7-17 上午10:10:32
* @Description : 邮件接口实现
* @ModificationHistory Who When What ------- ------------- -----------------
* kzw 2012-7-17 上午10:10:32 create
*
**/
public class MailServiceImpl implements IMailService {
private static Logger log = LogManager.getLogger(MailServiceImpl.class);
/* pool config */
private static final int COREPOOLSIZE = 10;
private static final int MAXIMUMPOOLSIZE = 20; //最大连接数
private static ThreadPoolExecutor pool;
private static BlockingQueue queue = new LinkedBlockingQueue();
static {
/**
* 使用JDK中的线程池,线程执行采用无边界策略
*/
pool = new ThreadPoolExecutor(COREPOOLSIZE, MAXIMUMPOOLSIZE, 2, TimeUnit.MINUTES, queue);
}
@Override
public void sendMail(String sendMailAddr, String sendMailPwd,
List ccs, List tos, String subject,
String content, List accessories, String mailType, String operMan, String memo) {
MailThread mail = new MailThread();
mail.init(sendMailAddr, sendMailPwd, ccs, tos, subject, content, accessories, mailType, operMan, memo);
pool.execute(mail);
}
/**
*
* @Program Name : reaglews.com.reagle.server.impl.MailServiceImpl.java
* @Written by : kzw
* @version : v1.00
* @Creation Date : 2012-7-18 下午04:14:23
* @Description :
* 发送邮件线程
* @ModificationHistory
* Who When What
* ------- ------------- -----------------
* kzw 2012-7-18 下午04:14:23 create
*
*
*/
class MailThread implements Runnable {
private Logger logger = LogManager.getLogger(MailThread.class);
private List ccs;
private List tos;
private List accessories;
private String sendMailAddr;
private String sendMailPwd;
private String subject;
private String content;
private String mailType;
private String operMan;
private String memo;
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* 初始化线程数据
* @Eclosing_Method : init
* @author by : kzw
* @creation Date : 2012-7-17下午05:25:48
* @param sendMailAddr
* @param sendMailPwd
* @param ccs 抄送号码
* @param tos 收件人
* @param subject 主题
* @param content 内容
* @param accessories 附件
*
*/
public void init(String sendMailAddr, String sendMailPwd,
List ccs, List tos, String subject,
String content, List accessories, String mailType, String operMan, String memo){
this.sendMailAddr = sendMailAddr;
this.sendMailPwd = sendMailPwd;
this.ccs = ccs;
this.tos = tos;
this.subject = subject;
this.content = content;
this.accessories = accessories;
this.mailType = mailType;
this.operMan = operMan;
this.memo = memo;
}
@Override
public void run() {
logger.info("发送邮件开始" + sdf.format(new Date()));
int id = 0;
String flag = "0"; //待发送
String msg = ""; //发送信息
boolean res = false;// 发送结果
try {
id = getSeqNo();
ccs.addAll(queryCCsByMailType(mailType)); // 添加需要抄送的邮箱地址
// 使用默认的邮箱
if(StringUtils.isBlank(sendMailAddr)) {
sendMailAddr = MailUtil.getConfigValue(DEFAULT_SEND);
sendMailPwd = MailUtil.getConfigValue(DEFAULT_SEND_PWD);
}
// 插入待发送邮件日志
saveLog(sendMailAddr, ccs, tos, subject, content, accessories, mailType, operMan, memo, id);
// 校验数据, 去掉错误邮箱地址
if(!validate(sendMailAddr, sendMailPwd, ccs, tos, subject, content, accessories)) {
logger.error("校验邮件数据失败");
return;
}
// 获取邮件对象
MailBean mail = getMailInstance(sendMailAddr, sendMailPwd, ccs, tos, subject, content, accessories);
// 发送邮件
res = mail.send();
flag = res ? "1" : "2";
if(!res) msg = "未知错误,发送失败";
// 更新发送记录
modifyLog(msg, flag, id);
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage(), e);
modifyLog(e.getMessage(), "2", id);
}
logger.info("发送邮件结束" + sdf.format(new Date()));
}
/**
* 获取邮件对象实体
* @Eclosing_Method : getInstance
* @author by : kzw
* @creation Date : 2012-7-17下午03:16:02
* @param sendMailAddr 发件人
* @param sendMailPwd 发件人密码
* @param ccs 抄送
* @param tos 收件人
* @param subject 主题
* @param content 内容
* @param accessories 附件
* @return
*
*/
private MailBean getMailInstance(String sendMailAddr, String sendMailPwd,
List ccs, List tos, String subject,
String content, List accessories){
// 获取SMTP地址
String mailHost = MailUtil.getMail2SMTP(sendMailAddr);
// 创建邮件
MailBean mail = new MailBean(subject,
sendMailAddr,
sendMailPwd,
tos, // 收件人
content,
MailUtil.getConfigValue(CHARACTERCONFIG),
mailHost,
accessories, // 附件
MailUtil.getConfigValue(CHECKSEND),
ccs //抄送
);
return mail;
}
private boolean validate(String sendMailAddr, String sendMailPwd,
List transmitMails, List takeMail, String subject,
String content, List multiparts){
boolean res = true;
if(!MailUtil.isEmail(sendMailAddr)) res = false;
// 清除错误号码
cancelErrorMailAddr(transmitMails);
cancelErrorMailAddr(takeMail);
return res;
}
private void cancelErrorMailAddr(List list) {
if(null == list || list.isEmpty()) return;
List back = new ArrayList(list);
for (String email : back) {
if(!MailUtil.isEmail(email)) {
list.remove(email);
log.info("移除错误邮件:" + email);
}
}
}
private int getSeqNo() {
String seqSql = "select seq_mail.nextval from dual";
BigDecimal b = (BigDecimal) new DbUtilsTemplate().findBy(seqSql, 1);
return b.intValue();
}
private boolean saveLog(String sendMail, List ccs, List tos, String subject,
String content, List accessories, String mailType, String operman, String memo, int id) {
StringBuffer sql = new StringBuffer();
sql.append(" INSERT INTO mail_send_detail ");
sql.append(" (ID, sendmail, senddate, tos, ccs, subject, CONTEXT, status, ");
sql.append(" mailtype, accessories, operman, operdate,opermemo) values(?, ?, sysdate, ?, ?, ?, ?, '0', ?, ?, ?, sysdate, ?)");
String[] params = {
String.valueOf(id),
sendMail,
Arrays.toString(ccs.toArray()).replace("[", "").replace("]", ""),
Arrays.toString(tos.toArray()).replace("[", "").replace("]", ""),
subject,
content,
mailType,
Arrays.toString(accessories.toArray()).replace("[", "").replace("]", ""),
operman,
memo
};
return (1 == new DbUtilsTemplate().update(sql.toString(), params));
}
private boolean modifyLog(String memo, String flag, int id){
String sql ="update mail_send_detail set status=?, memo = ? where id = ?";
return (1 == new DbUtilsTemplate().update(sql,
new String[]{flag, memo, String.valueOf(id)}));
}
// 查询邮件类型下, 需要抄送的
private List queryCCsByMailType(String mailType) {
List list = new ArrayList();
String sql = "select ccs from dm_mail_type where dm01=?";
String emails = (String) new DbUtilsTemplate().findBy(sql, 1, mailType);
if(StringUtils.isNotBlank(emails)) {
list = Arrays.asList(emails.split(";"));
}
return list;
}
}
}
单元测试
/**
*
*/
package com.reagle.IMailService;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import com.reagle.server.IMailService;
import com.reagle.server.impl.MailServiceImpl;
/**
* @Program Name : reaglews.com.reagle.IMailService.TestMailService.java
* @Written by : kzw
* @version : v1.00
* @Creation Date : 2012-7-18 上午09:07:25
* @Description :
*
* @ModificationHistory
* Who When What
* ------- ------------- -----------------
* kzw 2012-7-18 上午09:07:25 create
*
**/
public class TestMailService {
IMailService service;
List transmitMails;
List takeMail;
List multiparts;
@Before
public void init(){
service = new MailServiceImpl();
transmitMails = new ArrayList();
takeMail = new ArrayList();
multiparts = new ArrayList();
takeMail.add("[email protected]");
}
@Test
public void testThreadPool() throws InterruptedException{
// 策略 1 同时提交1000份请求
int size = 1000;
long start = System.currentTimeMillis();
for (int i = 0; i < size; i++)
service.sendMail(null, null, transmitMails, takeMail, "sub"+ System.currentTimeMillis(),
"content"+System.currentTimeMillis(), multiparts, "预订取消","1872", "测试");
long end = System.currentTimeMillis();
Thread.sleep(5000000);
System.out.println("邮件数量:" + size +", 总耗时:" + (end - start));
}
@Test
public void testMailSend() throws InterruptedException{
String sendMailAddr = "[email protected]";
String sendMailPwd = "XXX";
List transmitMails = new ArrayList();
//transmitMails.add("[email protected]");
List takeMail = new ArrayList();
takeMail.add("[email protected]");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String subject = sdf.format(new Date()) + " subject";
String content = sdf.format(new Date()) + "content 中文内容";
// HTML代码 注意编码
/*File f = new File("G:a.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
System.out.println(new InputStreamReader(new FileInputStream(f)).getEncoding());
String fileContent = null;
while(null != (fileContent = in.readLine())) {
content += fileContent;
}
in.close();
*/
List multiparts = new ArrayList();
//multiparts.add("G:/a.txt");
new MailServiceImpl().sendMail(sendMailAddr, sendMailPwd, transmitMails, takeMail, subject, content, multiparts, "02","1872", "测试");
Thread.sleep(200000);
}
}
webservices配置
mail
http://com.reagle
com.reagle.server.IMailServ
|