仔细的查核相关代码,发现原来的开发者其实功能相当简单,连最简单的mail格式查核都没做,并且执行邮件发送程序后只给个不痛不痒的提示,连发送成功,失败都不知道.虽然如此,现在轮到我负责,也只有改了.
Jsp端相当简单:
<%
String[] receiver = {request.getParameter("receiver")};
String mail_subject = "Itmanager Mail Test.";
String mail_content = "Itmanager Mail Test";
Session mailSession = MailUtil.getSession(RptTaskMailConfig.SMTPServer,true,RptTaskMailConfig.Sender,RptTaskMailConfig.EmailPwd);
try
{
MailUtil.sendTextMessage(mailSession,RptTaskMailConfig.Sender,
receiver,null,
mail_subject,mail_content,
"GB2312",null);
}
catch (Exception e)
{
e.printStackTrace();
}
%>
后台:
/**
* 获得指定SMTP服务器的的Session实例
* @param host
* @param isAuth
* @param user
* @param password
* @return
*/
public static Session getSession(String host, boolean isAuth, String user, String password) {
Properties props = new Properties();
props.put("mail.smtp.host", host);
props.put("mail.smtp.auth", String.valueOf(isAuth));
Session session;
if (user != null && user.length() > 0) {
Authentic authentic = new Authentic(user, password);
session = Session.getDefaultInstance(props, authentic);
} else {
session = Session.getDefaultInstance(props, null);
}
return session;
}
/**
* 发送text格式的邮件
* @param session
* @param from
* @param to
* @param cc
* @param subject
* @param content
* @param attachfile
*/
public static void sendTextMessage(Session session, String from, String[] to, String[] cc, String subject,
String content, Vector<File> attachfile) throws MessagingException {
sendMessage(session, from, to, cc, subject, content, MIMETYPE_Default_TEXT, attachfile);
}
/**
* 发送邮件
* @param session
* @param from 发件人
* @param to 收件人
* @param cc 抄送人
* @param subject 主题
* @param content 内容
* @param mimeType
* @param attachfile 附件文件名列表
*/
public static void sendMessage(Session session, String from, String[] to, String[] cc, String subject,
String content, String mimeType, Vector<File> attachfile) throws MessagingException {
// 较验发件人
if (!isValidMailAddress(from)) {
return;
}
try {
Message message = new MimeMessage(session);
InternetAddress sendFrom = new InternetAddress(from);
message.setFrom(sendFrom);
message.setHeader("X-Mailer", "ITManager Mailer");
message.setHeader("From", "<" + from + ">");
// 设置收件人
InternetAddress[] sendTo = new InternetAddress[to.length];
for (int i = 0; i < to.length; i++) {
sendTo[i] = new InternetAddress(to[i]);
}
message.setRecipients(Message.RecipientType.TO, sendTo);
// 设置抄送人
if (cc != null) {
InternetAddress[] copyTo = new InternetAddress[cc.length];
for (int i = 0; i < cc.length; i++) {
copyTo[i] = new InternetAddress(cc[i]);
}
message.setRecipients(Message.RecipientType.CC, copyTo);
}
// 设置主题
message.setSubject((subject == null || subject.length() == 0) ? "No subject" : MimeUtility
.encodeText(subject));
// 设置正文
MimeMultipart mp = new MimeMultipart();
MimeBodyPart mbp = new MimeBodyPart();
mbp.setContent(content, mimeType);
mp.addBodyPart(mbp);
// 添加附件
if (attachfile != null) {
Enumeration<File> efile = attachfile.elements();
while (efile.hasMoreElements()) {
File ele = efile.nextElement();
mbp = new MimeBodyPart();
FileDataSource fds = new FileDataSource(ele);
mbp.setDataHandler(new DataHandler(fds));
sun.misc.BASE64Encoder enc = new sun.misc.BASE64Encoder();
mbp.setFileName("=?GBK?B?" + enc.encode(fds.getName().getBytes()) + "?=");
// mbp.attachFile(ele);
mp.addBodyPart(mbp);
}
}
message.setContent(mp);
// 设置发送日期
message.setSentDate(new Date());
message.saveChanges();
long start = System.currentTimeMillis();
System.out.println("Start time:" + start);
Transport.send(message);
long end = System.currentTimeMillis();
System.out.println("End time:" + end);
System.out.println("Send time:" + (end - start) + "ms");
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (NoSuchProviderException nspe) {
nspe.printStackTrace();
} catch (MessagingException me) {
throw me;
}
}
程 序的整个逻辑都比较清晰,调javax.mail包,直接使用天的Transport.send(message)发送邮件功能.但是却出现了当第一次进 入系统时,可以正常发送邮件,但是如果更改邮件用户名,密码等资料后再发送就报异常.初步判断是jsp页面传入资料时出错,进入debug状态进行调试, 发现 MailUtil.getSession(RptTaskMailConfig.SMTPServer,true,RptTaskMailConfig.Sender,RptTaskMailConfig.EmailPwd) 里的值是保存后新改的值.就陷入迷茫中,既然是新的值为什么会报帐号和密码不匹配.继续调试,估计是Session的问题,应该是第一次的session 没被清除,但是上网查了资料也没有说java邮件发送后需要特别清除session的,并且程序中每次都会调用MailUtil.getSession, 即会产生不同的session,似乎也不存在这个问题.最后发现在session建立时Session.getDefaultInstance(props, authentic);相当可疑.查了一下:
何谓getDefaultInstance?
从处理流程中可以看出,首先是从缓存中查找是否有properties存在
如果存在,则加载默认的properties
如果不存在才加载用户自己定义的properties,
所以当一个应用为每个用户独立创建properties的时候,还是应该调用getInstance,
除非你希望有一个默认的properties让用户使用
问 题找到了,因为它会首先去内存和系统文件中去找properties,所以不管我在页面改几次数据,其实在后台中生成session时都和系统启动时的一 样,所以在MailUtil.sendTextMessage(mailSession,RptTaskMailConfig.Sender,
receiver,null,mail_subject,mail_content,"GB2312",null);时session里的sender和传入的sender不一致,因此出错,修改Session.getDefaultInstance(props, authentic);为Session.getInstance(props, authentic);后,可以正确发送修改帐号,密码等资料后的邮件.OK
最后再补充一下,session.getdefaultinstance和getinstance的区别 :
如果想要同时使用两个帐号发送javamail,比如使用[email protected]发送1#邮件,使用[email protected]发送2#邮件,这时候,你就需要同时创建两个java.mail.Session对象。但是如果你仍然使用Session.getDefaultInstance创建session对象的话,你会发现,第二个username:[email protected]创建的session永远都和第一个一样,这是为什么呢?因为,getDefaultInstance是真正单例模式,而且,里面的username和password属性是final型的,无法更改。所以,你会发现两封email都是由[email protected]发出来的。所以这个时候你要使用javax.mail.Session.getInstance()方法来创建session对象。