• JavaMail 邮件发送,有意思的附件名乱码 → 客户端正常,web端乱码


    开心一刻

      昨晚,媳妇很感伤的看着我

      媳妇:以后岁数大了,我要走你前面去了,你再找个老伴

      我:我不想找

      媳妇:你找一个,不用替我守着,以后你说你头疼发烧,也得有个给你端水递药的呀

      媳妇抹着眼泪:到老是个伴

      我:我想找个年轻的

      现在我左脸还有一个掌印,火辣辣的

    问题背景

      基于 JavaMail 1.5.5 ,实现了邮件发送功能,也对接了一些客户,没出现什么问题

      代码如下

    /**
     * 邮件发送
     * @param message 邮件内容
     * @param to 收件人邮箱
     * @param attachment 附件
     */
    public static void sendEmail(String message, String to, File attachment) throws Exception {
        //设置邮件会话参数
        Properties props = new Properties();
        //邮箱的发送服务器地址
        props.setProperty("mail.smtp.host", MAIL_HOST);
        props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.setProperty("mail.smtp.socketFactory.fallback", "false");
        props.put("mail.smtp.ssl.enable", "true");
    
        //邮箱发送服务器端口,这里设置为465端口
        props.setProperty("mail.smtp.port", "465");
        props.setProperty("mail.smtp.socketFactory.port", "465");
        props.put("mail.smtp.auth", "true");
    
        //获取到邮箱会话,利用匿名内部类的方式,将发送者邮箱用户名和密码授权给jvm
        Session session = Session.getDefaultInstance(props, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(MAIL_USER_NAME, MAIL_AUTH_CODE);
            }
        });
    
        // 开启调试,生产不开启
        session.setDebug(true);
    
        Multipart multipart = new MimeMultipart();
        BodyPart contentPart = new MimeBodyPart();
        //contentPart.setContent(message, "text/html;charset=UTF-8");
        contentPart.setText(message);
        multipart.addBodyPart(contentPart);
    
        if (attachment != null) {
            BodyPart attachmentBodyPart = new MimeBodyPart();
            DataSource source = new FileDataSource(attachment);
            attachmentBodyPart.setDataHandler(new DataHandler(source));
            //MimeUtility.encodeWord可以避免附件文件名乱码
            attachmentBodyPart.setFileName(MimeUtility.encodeWord(attachment.getName()));
            multipart.addBodyPart(attachmentBodyPart);
        }
    
        //通过会话,得到一个邮件,用于发送
        Message msg = new MimeMessage(session);
        //设置发件人
        msg.setFrom(new InternetAddress(MAIL_USER_NAME));
        //设置收件人,to为收件人,cc为抄送,bcc为密送
        msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to, false));
        // msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(to, false));
        // msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(to, false));
        msg.setSubject("我是主题");
        //设置邮件消息
        msg.setContent(multipart);
        //设置发送的日期
        msg.setSentDate(new Date());
    
        //调用Transport的send方法去发送邮件
        Transport.send(msg);
    }
    View Code

      附件名是做了编码处理的

      我们来看下接收情况

      Foxmail

      outlook windows 版本

      一切看似都很平静

     

      直到她们的出现,让我慌了神

      QQ邮箱(web 端)

      outlook web 版本

      此刻,我们的脑中应该有 2 个问题

      1、乱码该如何修复

      2、为什么客户端版(Foxmail、outlook windows版)接收正常,而 web版 却出现了乱码?

    乱码处理

      这个上网一搜,很容易就能找到答案,加一个系统属性即可

       mail.mime.splitlongparameters 默认值是 true ,表示编码后的附件名文件名长度超过 60 之后会进行多段拆分,每 60 个字符作为一个参数,最后不足 60 个字符的作为一个参数

       我们把 mail.mime.splitlongparameters 设置成 false ,再看下效果

      QQ 邮箱

       outlook web

      有人可能会有疑问了:你说 60 就 60,你说拆分就拆分?

      既然不信我,那我们从源码找答案

      源码解析

      设置附件名的时候,有这样一段代码

      注意第一个 if 中的条件,是有三个

        1、附件名编码后的长度

        2、 mail.mime.splitlongparameters 

        3、 mail.mime.encodeparameters ,默认值是 true 

      当三个条件都为 true ,才会以 60 字符为单位进行多段拆分

       你好_好久不见_别来无恙_20230306.txt 编码后再拆分得到的结果是

      文件名被拆分成了三段,我可曾欺你们?

    为什么只有 web 版“乱码”

      此刻需要纠正下,web 版出现的附件名不是乱码,而是编码之后未能正确解码

      为什么未能正确解码?

      那是因为不支持 RFC2231 style encoded parameters 

      其实可能不只是 web 版不支持,可能还有其他的邮件客户端不支持,只是楼主未去尝试而已

    总结

      1、是要满足三个条件才会对附件名进行多段拆分,忘记了的往上翻一翻

      2、为什么要进行附件名的多段拆分? 呃呃呃...,由你们来回答

  • 相关阅读:
    npm改变npm缓存路径和改变环境变量
    当涉及到PDF中的数据挖掘,PDFPlumber是您的得力助手
    掌握 Scikit-Learn: Python 中的机器学习库入门
    前端进击笔记第二十四节 如何进行技术方案调研与设计?
    LeetCode125验证一个字符串是否是回文 415字符串相加 541反转字符串 II
    【无标题】
    每日方法分享:图片文件太大怎么压缩变小
    tomcat安装、部署JSPGOU项目、Tomcat多实例
    [毕业设计]机器学习的运动目标跟踪-opencv
    十大开源机器人 智能体
  • 原文地址:https://www.cnblogs.com/youzhibing/p/17084304.html