邮件群发软件很多,就是没有一版本是java的,今天特上传一个java群发代码,和可运行的工程,分享于大家相互学习和进步,部分代码出自网络,另部分出自自己,
/**
*
*/
package com.hzsuwang.email;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.commons.mail.EmailAttachment;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
import org.apache.log4j.Logger;
import org.htmlparser.util.ParserException;
import org.jdom.JDOMException;
/**
* @Site:http://www.hzsuwang.com
* @Email:hzsuwang@163.com
* @@blog:http://www.hzqvod.com
* @author tony.yan
*
*/
public class MailStart implements Runnable {
protected Logger logger = Logger.getLogger(MailStart.class);
private MailInfo mailInfo = null;
private final String tipInfoFormat = "一共需要发送{0}封邮件,成功发送{1}封,失败发送{2}封。\n\r失败邮件列表地址:{3}";
public MailStart() {
try {
mailInfo = MailUtil.getMailInfo();
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Runnable run = new MailStart();
run.run();
}
public void run() {
List<String> list = MailUtil.getMailToList(mailInfo.getAddressPath());
try {
this.sendHtmlEmail(mailInfo, list);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String getResultInfo(int sum, int success, int fail, List<String> failList) {
return MessageFormat.format(this.tipInfoFormat, sum, success, fail, failList.toString());
}
/**
* 发送邮件
*
* @param info
* 配置文件信息
* @param emailAddresslist
* 已经加载到内存的电邮List
* @throws Exception
*/
private void sendHtmlEmail(MailInfo info, List<String> emailAddresslist) throws Exception {
List<String> fialAddressList = new ArrayList<String>();
// 读取已经发送的邮件
ArrayList<String> sendedEmail = MailUtil.getSendedEmail(info.getSendedAddressPath());
// 获取不需要发送的邮件服务器
List donNotSendEmailType = MailUtil.getDonNotSendEmailType(info.getDonNotSendEmailType());
String saveSuccEmailFile = info.getSaveMailSendedSuccFile();
String saveFailEmailFile = info.getSaveMailSendedFailFile();
String htmlContentDealHandler = info.getHandler();
htmlContentDealHandler = htmlContentDealHandler == null ? "" : htmlContentDealHandler.trim();
if (saveSuccEmailFile == null) {
saveSuccEmailFile = "";
}
saveSuccEmailFile = saveSuccEmailFile.trim();
if (saveFailEmailFile == null) {
saveFailEmailFile = "";
}
saveFailEmailFile = saveFailEmailFile.trim();
// 收件人邮件地址list集合
int failCount = 0;
int successCount = 0;
// 每封邮件发送的间隔时间
int sendInterval = 0;
try {
sendInterval = Integer.parseInt(info.getSendInterval()) * Constants.second;
} catch (NumberFormatException f) {
sendInterval = Constants.defaultSendInterval * Constants.second;
}
try {
System.out.println(info.getHtmlPath());
String htmlPath = info.getHtmlPath();
String urlPath = "";
if (!htmlPath.startsWith("http")) {
if (htmlPath.indexOf(":") < 0) {// 根据传入的路径中是否带":"确认传入的是相对路径还是绝对路径,相对路径则做路径补充,绝对路径直接使用
htmlPath = new File("").getAbsolutePath() + File.separator + htmlPath;
}
if (!htmlPath.startsWith("file:///")) {
urlPath = "file:///" + htmlPath;
}
} else {
urlPath = htmlPath;
}
String context = UrlUtil.getContentByURL(urlPath);
String email = "";
Handler handler = null;
if (!htmlContentDealHandler.equals("")) {
handler = (Handler) Class.forName(htmlContentDealHandler).newInstance();
}
for (int i = 0; i < emailAddresslist.size(); i++) {
boolean flag = false;
try {
email = emailAddresslist.get(i);
if (email.indexOf("@") <= 0 || email.endsWith("@") || email.endsWith(".") || email.indexOf(".") <= 0) {
System.out.println("email地址:" + email + " 无效");
continue;
}
// 未发送过的邮件才允许发送
if (sendedEmail.contains(email)) {
System.out.println("email " + email + "已经发送过了");
continue;
}
if (!donNotSendEmailType.contains(MailUtil.getEmailHost(email))) {
sendedEmail.add(email);
String sendContext = context;
if (handler != null) {
sendContext = handler.dealContent(email, sendContext);
}
flag = sendSingleHtmlEmail(info, email, sendContext);
} else {
continue;
}
} catch (Exception e) {
System.out.println("发送邮件到email地址:" + email + " 时发生异常:");
e.printStackTrace();
}
if (flag) {
if (!saveSuccEmailFile.equals("")) {
MailUtil.saveSuccEmail(email, saveSuccEmailFile);
}
System.out.println("邮件" + email + "发送成功!");
successCount++;
} else {
if (!saveFailEmailFile.equals("")) {
MailUtil.saveSuccEmail(email, saveFailEmailFile);
}
System.out.println("邮件" + email + "发送失败!");
fialAddressList.add(email);
failCount++;
}
// 发送一封邮件休息指定的时间再发下一封
Thread.sleep(sendInterval);
}
} catch (Exception ex) {
ex.printStackTrace();
}
logger.info(getResultInfo(emailAddresslist.size(), successCount, failCount, fialAddressList));
}
/**
* 发送单个Html文本邮件
*
* @param info
* @param to
* @param context
* @return
* @throws Exception
*/
private boolean sendSingleHtmlEmail(MailInfo info, String to, String context) throws Exception {
String username = info.getUsername();
String password = info.getPassword();
String host = info.getHostName();
String from = info.getFrom();
String title = info.getTitle();
Date sendDate = new Date();
System.out.println(new Date().toString() + ": 开始向" + to + "邮箱发送邮件....");
boolean flag = false;
HtmlEmail email = new HtmlEmail();
email.setAuthentication(username, password);
email.setHostName(host);
email.setCharset(info.getCharset());
// 设置邮件标题
email.setSubject(title);
context = linkPicture2HTML(info, email, context);
addAttachment(info, email);
try {
// 设置发件人
email.setFrom(from);
// 设置收件人
email.addTo(to);
// Html邮件上下文,邮件内容
email.setHtmlMsg(context);
// 设置邮件发送时间
email.setSentDate(sendDate);
email.send();
flag = true;
logger.info(new Date().toString() + ":成功发送邮件");
} catch (Exception ex) {
logger.error("发送邮件出现异常!");
throw ex;
}
return flag;
}
/**
* 将图片附加于发送的邮件中
*
* @param info
* @param email
* @param context
* @return
* @throws EmailException
* @throws IOException
* @throws ParserException
*/
private static String linkPicture2HTML(MailInfo info, HtmlEmail email, String context) throws EmailException, IOException, ParserException {
String htmlPath = info.getHtmlPath();// 发送的HTML的地址
String htmlFile = "";// 网络HTML的地址
boolean localFile = true;// 是否本地文件
if (htmlPath.startsWith("http")) {
localFile = false;
}
if (localFile) {
File file = new File(htmlPath);
String name = file.getName();
/* 获取到发送的文件所在路径 */
htmlPath = htmlPath.replace(name, "");
} else {
// 如htmlPath为"http://www.2345.com/a/b.htm"
URL u = new URL(htmlPath);
/* 带"/"的路径,如"/a/b.htm" */
htmlFile = u.getFile();
/* 网站的地址"http://www.2345.com" */
htmlPath = htmlPath.replace(htmlFile, "");
}
ArrayList<ImageElement> imageElements = ImageParser.imageParser(context);
for (ImageElement image : imageElements) {
String imagePath = image.getSrc();
String cid = "";
/************************* 获取本地图片及来自网络的图片都附加于发送的邮件中,但是附加网络图片时有问题(开始) ****************************/
// if(localFile){
// if(imagePath.startsWith("http")){//本地文件从网站服务器获取图片
// URL u = new URL(imagePath);
// cid = email.embed(u, u.getFile());
// cid = "cid:"+cid;
// }else if(imagePath.startsWith("file:///")){//本地文件中的图片采用的是绝对地址
// File file = new File(imagePath.replace("file:///", ""));
// cid = email.embed(file);
// cid = "cid:"+cid;
// }else{//本地文件的图片采用的相对地址
// File file = new File(htmlPath+imagePath);
// cid = email.embed(file);
// cid = "cid:"+cid;
// }
// }else{
// if(imagePath.startsWith("http")){//网络文件从其它网站服务器获取图片
// URL u = new URL(imagePath);
// cid = email.embed(u, u.getFile());
// cid = "cid:"+cid;
//
// }else{//网络文件的图片采用的相对地址
// URL u = new URL(htmlPath+imagePath);
// cid = email.embed(htmlPath+imagePath,u.getFile());
// cid = "cid:"+cid;
// }
// }
// context = context.replace("\""+imagePath, "\""+cid);
// context = context.replace("="+imagePath, "="+cid);
/************************* 获取本地图片及来自网络的图片都附加于发送的邮件中,但是附加网络图片时有问题(结束) ****************************/
/************* 仅对本地的图片于发送的邮件中,对来自网络文件的中的图片采用相对地址图片进行地址处理,但不附加于发送的邮件中(开始) **************/
if (localFile) {
if (!imagePath.startsWith("http")) {
if (imagePath.startsWith("file:///")) {// 本地文件中的图片采用的是绝对地址
File file = new File(imagePath.replace("file:///", ""));
cid = email.embed(file);
cid = "cid:" + cid;
} else {// 本地文件的图片采用的相对地址
File file = new File(htmlPath + imagePath);
cid = email.embed(file);
cid = "cid:" + cid;
}
/**
* 这里不直接采用:context = context.replace(imagePath,cid);
* 是因为有可能图片名称的后几位相同,如邮件中包括male.jpg,及female.jpg时,在如上替换时就会出错;
* 考虑到img的src的写法可能有这样两种:src=male.jpg、src="male.jpg"两种,
* 因此采用这样的替换方式可以保证替换掉,并且不会影响到其它的图片
*/
context = context.replace("\"" + imagePath, "\"" + cid);
context = context.replace("=" + imagePath, "=" + cid);
}
} else {
if (!imagePath.startsWith("http")) {// 网络文件的图片采用的相对地址
String imageUrlPath = "";
/* 将来自于网络中的图片地址,处理为绝对地址 */
if (!imagePath.startsWith("/")) {
imageUrlPath = htmlPath + "/" + imagePath;
} else {
imageUrlPath = htmlPath + imagePath;
}
context = context.replace("\"" + imagePath, "\"" + imageUrlPath);
context = context.replace("=" + imagePath, "=" + imageUrlPath);
}
}
/************* 仅对本地的图片于发送的邮件中,对来自网络文件的中的图片采用相对地址图片进行地址处理,但不附加于发送的邮件中(结束) **************/
}
return context;
}
/**
* 增加附件到邮件中,包括指定目录下面的所有子目录
*
* @param info
* @param email
* @throws EmailException
*/
private static void addAttachment(MailInfo info, HtmlEmail email) throws EmailException {
String attachmentPath = info.getAttachmentPath();
if (attachmentPath != null && !attachmentPath.equals("")) {
File path = new File(attachmentPath);
if (path.exists()) {
if (path.isFile()) {/* 文件就直接增加 */
EmailAttachment oneAttachment = new EmailAttachment();
oneAttachment.setPath(attachmentPath);
email.attach(oneAttachment);
} else if (path.isDirectory()) {
File[] files = path.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
info.setAttachmentPath(files[i].getAbsolutePath());
addAttachment(info, email);
} else {
EmailAttachment oneAttachment = new EmailAttachment();
oneAttachment.setPath(files[i].getAbsolutePath());
email.attach(oneAttachment);
}
}
}
}
}
}
}
/**
*
*/
package com.hzsuwang.email;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
/**
* @Site:http://www.hzsuwang.com
* @Email:hzsuwang@163.com
* @@blog:http://www.hzqvod.com
* @author tony.yan
*
*/
public class EmailHandler implements Handler {
private static Map<String, String> emailName;
static {
String email_name = "email_name.txt";
try {
if (emailName == null) {
emailName = getSendedEmail(email_name);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public String dealContent(String email, String htmlContent) throws Exception {
String name = emailName.get(email);
htmlContent = htmlContent.replace("{1}", name);
return htmlContent;
}
/**
* 将邮件、名称放入HashMap中
*
* @param email_name
* 存放email与名称对应关系的文件
* @return 全部对应的HashMap
* @throws Exception
*/
private static Map<String, String> getSendedEmail(String email_name) throws Exception {
Map<String, String> sendedEmail = new HashMap<String, String>();
FileReader read = null;
BufferedReader br = null;
try {
if (email_name.indexOf(":") < 0) {// 根据传入的路径中是否带":"确认传入的是相对路径还是绝对路径,相对路径则做路径补充,绝对路径直接使用
email_name = new File("").getAbsolutePath() + File.separator + email_name;
}
read = new FileReader(email_name);
br = new BufferedReader(read);
String line = null;
while ((line = br.readLine()) != null) {
if (!line.trim().equals("")) {
if (line.indexOf(",") > 0) {
String[] info = line.split(",");
if (info.length > 1) {
String email = info[0];
// 只加载有效的email地址
if (!(email.indexOf("@") <= 0 || email.endsWith("@") || email.endsWith(".") || email.indexOf(".") <= 0)) {
String name = info[1];
sendedEmail.put(email, name);
}
}
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
throw new Exception(ex);
} finally {
try {
br.close();
read.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
return sendedEmail;
}
}
以下工程可运行,运行之前请配置好 mail-config.xml 文件中的发件人信息(邮件地扯:密码,mailHost),包括邮件的POP/IMAP和Exchange服务的设置方法,可以参考qq的:
http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=14&&no=1000898