邮件发送异常

在工作开发中用到了通过调用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("java_mail_001@163.com"));
        
        Transport transport = session.getTransport();
        // 连接邮件服务器
        transport.connect("java_mail_001", "javamail");
        // 发送邮件
        transport.sendMessage(msg, new Address[] {new InternetAddress("java_mail_002@163.com")});
        // 关闭连接
        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()来设置当前线程的上下文类加载器,从而解决了邮件发送的问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一。它使得 Java 类可以被动态加载到...
    CHSmile阅读 1,619评论 0 12
  • 作者:成 富, 软件工程师, IBM 中国软件开发中心 类加载器(class loader)是 Java™中的一个...
    Android技术研究阅读 3,916评论 0 74
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,026评论 19 139
  • 七夕的那个晚上,沉寂很久的好友突然发来消息,问我: “女孩子是都喜欢花吗,我坐电梯的时候看见一个女孩手里捧着花看起...
    有友友阅读 354评论 1 0
  • 有人问我,带小孩最大的收获是什么?我说我快成哲人了。这不是玩笑话,从tt出生到现在快两年,获得的生活技能和...
    spark_90b5阅读 418评论 0 1