原文:http://javaarm.com/faces/display.xhtml?tid=2383
英文:https://community.jboss.org/wiki/JBossAS720EmailSessionConfigurtion-EnglishVersion
JBoss AS 7.2.0 配置Email Session
本文以gamil smtp为例,描述如何配为JBoss AS 7.2.0配置Mail Session,以及如何在Java代码中使用该Mail Session。本文内容根据JBoss论坛和其它论坛相关文章归纳而成,我们同时纠正了一些常规编码错误,并且为一些可能发生的异常的情景给出了建议解 决方案。
本文参考了下列文章:
我们参考了 "1. Jan 5, 2012 5:10 PM" 处的配置代码片段。根据“Jan 11, 2012 12:08 PM”、“ Dec 5, 2011 3:24 AM”和“ Dec 12, 2011 6:07 AM”这些回复,我们还能得知:JBoss AS 7.1.x中为Email Session指定TLS可能有些问题,需要另外打补丁。
我们参考了本文“Dec 15, 2012 4:13 PM”这个回复的资源注射:
@Resource(name = "java:/Mail")
private Session mailSession;
注意:本文主贴“Dec 15, 2012 9:28 AM”的配置内容和Java演示代码都是(我想应该是针对JBoss AS 7.0的)陈旧做法,在JBoss AS 7.1.x以后版本不需这么做。
其中“ Dec 16, 2012 8:01 AM ”这个回复也很有用。
这篇文章中“Step3)”为我们写Java代码提供了一些指导。
这篇文章中的各种配置和前面的几篇文章的配置差不多。
最后,我们在这里询问了一些异常场景如何处理。
注意:一切配置信息其实可以从 jboss-as-7.2.0.Final\docs\schema\jboss-as-mail_1_1.xsd 中获取!!!
1. standalone.xml中配置mail session和smtp
1.1 mail session
找到 <subsystem xmlns="urn:jboss:domain:mail:1.1"> 这个元素,然后将其替换为:
<subsystem xmlns="urn:jboss:domain:mail:1.1">
<mail-session jndi-name="java:/Mail" from="javaarm@gmail.com">
<smtp-server ssl="true" outbound-socket-binding-ref="mail-smtp-gmail">
<login name="javaarm@gmail.com" password="your_password"/>
</smtp-server>
</mail-session>
</subsystem>
1.2 smtp
找到 <outbound-socket-binding name="mail-smtp"> 这个元素,将其替换为:
<outbound-socket-binding name="mail-smtp-gmail">
<remote-destination host="smtp.gmail.com" port="465"/>
</outbound-socket-binding>
注意:SMTP协议里面定义的默认端口为25;而gmail 的 smtp的端口是 465。
2. Java代码获取Mail Session并发送email
2.1 第一种方法:资源注射
在你的EJB/JMX MBean/JSF MBean/Servlet中,可以添加下面的变量将mail session注入:
@Resource(name = "java:/Mail")
private Session mailSession;
EJB中注入mail session的完整代码:
@Local(IEmailService.class)
@Singleton
@Startup
public class EmailService implements IEmailService{
public static final Logger log = Logger.getLogger(EmailService.class.getName());
public static final String EMAIL_SESSION_JNDI_PATH = "java:/Mail";
@PersistenceContext
private EntityManager em;
@Resource(name = "java:/Mail")
private Session mailSession;
@PostConstruct
public void start() throws Exception {
}@PreDestroy
public void destroy(){
}
//*****************[interface methods]***************//
@Override
@PermitAll()
public boolean sendMail(Email email){
try{
MimeMessage m = new MimeMessage(getEmailSession());
InternetAddress[] to = new InternetAddress[] {
new InternetAddress(email.getToUser().getEmail()),
new InternetAddress("javaarm@gmail.com")//备份一份!
};
m.setRecipients(Message.RecipientType.TO, to);
m.setSubject(email.getTitle());
m.setSentDate(new java.util.Date());
m.setText(email.getContent(), "utf-8", "html");
//
Transport.send(m);
//
return true;
}catch(Exception e){
e.printStackTrace();
return false;
}
}
private Session getEmailSession() throws Exception{
return mailSession;
}
}
缺点:
如果服务器启动的时候,网线没有插上(比如说忘记了,或者被别人不小心拔掉了),JBoss AS 7在启动的时候,会抛出下面的异常;
20:57:02,573 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-1) MSC00001: Failed to start service jboss.mail-session.java:/Mail: org.jboss.msc.service.StartException in service jboss.mail-session.java:/Mail: Failed to start service
之后,它会根据"java:/Mail"将mail session注射到EJB,此时它会发现该mail session为null,会导致这个EJB 服务(这里为EmailService )实例化失败:
jboss.deployment.subunit."ybxiang-forum.ear"."ybxiang-forum-ejb.jar".component.EmailService.START: java.lang.IllegalStateException: JBAS011048: Failed to construct component instance
当然,我们可以认为这种情况不会发生。
2.2 第二种方法:JNDI查询
去除第一种方法中的注射代码:
@Resource(name = "java:/Mail")
private Session mailSession;
然后将getEmailSession()方法改成下面的样子:
private Session getEmailSession() throws Exception{
InitialContext context = new InitialContext();
return (Session) context.lookup(EMAIL_SESSION_JNDI_PATH);
}
这样,只有在真正需要发送Email的时候,才会去查询 mail session,效果和资源注射一样,但是避免了被注射的EJB service无法实例化的情况。
2.3 第三种方法:JCA管理
我们可以抛弃在standalone.xml中配置mail session的做法,我们可以用JCA来管理对mail 服务器的连接。但是根据 https://community.jboss.org/thread/231210 " Aug 4, 2013 3:01 AM"的回复“I think you will find that Java Mail opens connections as required and closes them when done.”,好像不必要整的这么复杂。
如果我们的应用程序对邮件依赖非常大,我们完全可以通过JCA来控制对多个mail server的连接,连接失败就切换到其它邮件服务器。和SSH2配置JCA一样,参见:JBossJCA。
JBoss 的JavaMail模块相关开发人员(Tomaz Cerar)对本人发的文章 https://community.jboss.org/wiki/JBossAS720EmailSessionConfigurtion-EnglishVersion 中关于使用JCA的描述,稍微做了一点修改:
Questions: If My application in jboss is critical and I have 3 backing email server, how to use them?
Answer: JCA is a good solution.
改成了:
Questions: If My application in jboss is critical and I have 3 backing email server, how to use them?
Answer: You can configure multiple mail sessions in mail subsystem and inject/lookup ones you need, or you can use JCA.
也就是说,他优先推荐使用多个mail sessions来连接到多个 mail服务器,然后也认为JCA能解决这个问题。
Comments