Version 5

    原文: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" 处的配置代码片段。根据“7. Jan 11, 2012 12:08 PM”、“16. Dec 5, 2011 3:24 AM”和“20. Dec 12, 2011 6:07 AM”这些回复,我们还能得知:JBoss AS 7.1.x中为Email Session指定TLS可能有些问题,需要另外打补丁。
    我们参考了本文“4. 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以后版本不需这么做。

    其中“12. 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 "1. 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能解决这个问题。