邮件发送异常

在工作开发中用到了通过调用java核心库中的mail API,在发送邮件的时候遇到了这样的问题

Failed message 1:
javax.mail.MessagingException: IOException while sending message;
nested exception is:
javax.activation.UnsupportedDataTypeException: no object DCH for MIME type text/plain; charset=us-ascii

这个问题困扰了我很久,在网上搜索了很多解决办法,最终有一种解决办法可以解决
邮件发送代码类似如下:

public class JavaMailTest {
    public static void sendEmail(String[] args) throws MessagingException {
        Properties props = new Properties();
        // 开启debug调试
        props.setProperty("mail.debug", "true");
        // 发送服务器需要身份验证
        props.setProperty("mail.smtp.auth", "true");
        // 设置邮件服务器主机名
        props.setProperty("mail.host", "smtp.163.com");
        // 发送邮件协议名称
        props.setProperty("mail.transport.protocol", "smtp");
        
        // 设置环境信息
        Session session = Session.getInstance(props);
        
        // 创建邮件对象
        Message msg = new MimeMessage(session);
        msg.setSubject("JavaMail测试");
        // 设置邮件内容
        msg.setText("这是一封由JavaMail发送的邮件!");
        // 设置发件人
        msg.setFrom(new InternetAddress("[email protected]"));
        
        Transport transport = session.getTransport();
        // 连接邮件服务器
        transport.connect("java_mail_001", "javamail");
        // 发送邮件
        transport.sendMessage(msg, new Address[] {new InternetAddress("[email protected]")});
        // 关闭连接
        transport.close();
    }
}

但是在transport.sendMessage的时候总是抛文初的那个异常
最终解决办法是,在sendMessge之前加上如下代码

Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());

但为什么此方法有效呢?
项目环境的是部署在osgi框架下,首先要了解OSGi框架中的类加载器是如何运作的
OSGI的类加载器
OSGI的每个bundle都包含了java包和类,模块的minifest文件中声明了这个bundle的 Import-Package,即模块的导入类,和 Export-Package,模块的到处类。OSGI通过特有的类加载机制来进行类的加载。OSGI中每个bundle有自己的类加载器,它负责加载模块自己包含的java类和jar包,如果它需要加载核心类库的时候,就会代理给父类加载器(通常是启动类加载器)进行加载,当它需要加载导入的类是,则会代理给这个导入类本身的那个bundle进行加载

好,回到我们开头的那个问题,为什么发送邮件时会抛出异常呢?
邮件发送模块我们调用了javaMail,然而JavaMail是由Sun定义的一套收发电子邮件的API,不同的厂商可以提供自己的实现类。但它并没有包含在JDK中,而是作为JavaEE的一部分。
因此在osgi中对javaMail(SPI 接口)的加载,是利用线程上下文类加载器来加载 SPI 实现的 Java 类,有可能会找不到 Java 类。该类加载器应该是该模块对应的类加载器。因此可以首先通过 class.getClassLoader()来得到模块对应的类加载器,再通过 Thread.currentThread().setContextClassLoader()来设置当前线程的上下文类加载器,从而解决了邮件发送的问题。

你可能感兴趣的:(邮件发送异常)