×

JavaMail

Linux和Docker环境下记录一下JavaMail发送邮件中文附件名称乱码,文件名过长,系统语言不支持导致乱码

我的笔记 我的笔记 发表于2020-03-20 12:50:48 浏览2913 评论0

抢沙发发表评论

问题:

客户生产机器,每次发送邮件带有附件的时候就会导致乱码,而且乱码很奇特,有规律的那种样例就是:

 =?UTF-8?Q?=E6=96=B0=E5=BB=BA=E6=96=87=E6=9C=AC=E6=96=87=E6=A1=A3_?= =?UTF-8?Q?=5F2=29=2Etxt?=

image.png

但是我的真实的文件名称是“新建文本文件.txt”

百度各种办法,有个说没有编码。有的说系统语言有问题

无效办法一:

public static void main(String[] args) {
    String s = "=?UTF-8?Q?=E6=96=B0=E5=BB=BA=E6=96=87=E6=9C=AC=E6=96=87=E6=A1=A3_?= =?UTF-8?Q?=5F2=29=2Etxt?=";
    try{
        Map<String, String> fileMap = new HashMap<>();
        fileMap.put("文本文件.txt","/opt/uuu");
        MailBean mailBean = new MailBean();
        mailBean.setAttachments(fileMap);
        UnitedLogger.debug(mailBean.getAttachments());
        System.out.println(s);
        System.out.println("编码后的文件名称encodeWord:"+ MimeUtility.encodeWord(s));
        System.out.println("编码后的文件名称encodeWord-B:"+ MimeUtility.encodeWord(s,"UTF8","B"));
        System.out.println("编码后的文件名称encodeText:"+ MimeUtility.encodeText(s));
        System.out.println("编码后的文件名称encodeText-B:"+ MimeUtility.encodeText(s,"UTF8","B"));
        System.out.println("编码后的文件名称encodeText-B:"+ MimeUtility.encodeText(s,MimeUtility.mimeCharset("gb2312"), null));

    }catch (Exception e){

    }
}

上述办法无法解决,还是乱码

无效办法二:

因为客户生产是Redhat系统,所以我就查看了一下他们的服务器语言变量

echo $LANG

发现打印的是US的语言,我就经过对方同意后改了一下这个变量,还是不行

export LANG="zh_CN.UTF-8"
export LC_ALL="zh_CN.UTF-8"

在中午吃外卖的时候,碰到产品组一个同事,随口问了一句,然后回到工位他给我发了个链接:

https://blog.csdn.net/qq_29407009/article/details/78557886

这个解决了我的问题:

解决办法就是不让截断文件名。因为中文文件名被base64加密后肯定超过60位长度:

System.setProperty("mail.mime.splitlongparameters","false");

然而,测试环境正常,生产环境又不行了,后来想是不是docker环境不支持中文导致的

生产解决办法:

1)进入docker镜像

docker exec -it id bash

2)查看语言

locale

image.png

POSIX是不支持中文的

3)查看系统是否有中文包:

locale -a

如果有C.UTF-8或者zh_CN.UTF-8

4)执行

LANG=C.UTF-8

如果没有C.UTF-8或者zh_CN.UTF-8

就需要

yum install kde-l10n-Chinese -y
yum reinstall glibc-common -y
localedef -c -f UTF-8 -i zh_CN zh_CN.utf8

最后附上我的邮件发送代码:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.datadriver.common.entity.RunnableAsyc;
import com.datadriver.common.entity.UnitedException;
import com.datadriver.common.entity.UnitedLogger;
import com.datadriver.common.util.ThreadPoolExecutorUtil;
import com.datadriver.email.model.MailBean;
import com.datadriver.email.service.EmailSettingInfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import javax.mail.Authenticator;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.File;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;

@Component
public class GFXDMailSenderExecutor {
    private EmailSettingInfoService emailSettingInfoService;
    private JavaMailSenderImpl javaMailSender;
    private static final String TRUE = "true";
    private static final String SEND_TYPE_TEXT = "text";
    private static final String SEND_TYPE_HTML = "html";
    private static final String SEND_STATUS_FAILD = "101";
    private static final String SEND_STATUS_SUCCESS = "100";

    public GFXDMailSenderExecutor() {
    }

    public void initMailSetting() {
        boolean empty = ObjectUtils.isEmpty(this.javaMailSender);
        boolean notEmpty = !ObjectUtils.isEmpty(this.javaMailSender);
        boolean fieldEmpty = notEmpty && (StringUtils.isBlank(this.javaMailSender.getUsername()) || StringUtils.isBlank(this.javaMailSender.getPassword()));
        if (empty || fieldEmpty) {
            this.javaMailSender = this.javaMailSender();
        }

    }

    public void senderEmail(MailBean mailBean) {
        this.submit(mailBean);
    }

    private void submit(MailBean m) {
        try {
            ThreadPoolExecutorUtil.submit(new GFXDMailSenderExecutor.SendMailThread(m, this.emailSettingInfoService));
        } catch (ExecutionException | InterruptedException var3) {
            UnitedLogger.error("MailSenderExecutor.submit******* 邮件异常 ID=" + m.getRecordId() + "Error:", var3);
            Thread.currentThread().interrupt();
        }

    }

    private void send(MailBean mailBean) throws Exception {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(this.javaMailSender.getUsername());
        String[] emails = getEmails(mailBean.getRecipientsEmail());
        message.setTo(emails);
        message.setSubject(mailBean.getSubject());
        message.setText(mailBean.getContent());
        message.setSentDate(new Date());
        UnitedLogger.info("线程运行正在发送至 " + mailBean.getRecipientsEmail() + " ....\n");
        this.javaMailSender.send(message);
    }

    private void sendHtml(MailBean mailBean) throws Exception {
        UnitedLogger.debug("getAttachments:"+mailBean.getAttachments());
        MimeMessage message = this.javaMailSender.createMimeMessage();

        MimeMessageHelper messageHelper;
        try {
            messageHelper = new MimeMessageHelper(message, true, "UTF-8");
        } catch (MessagingException var11) {
            throw new UnitedException("I18N-MSG-999900000230");
        }

        messageHelper.setFrom(this.javaMailSender.getUsername());
        String[] emails = getEmails(mailBean.getRecipientsEmail());
        messageHelper.setTo(emails);
        if (org.apache.commons.lang3.ObjectUtils.anyNotNull(new Object[]{mailBean.getSubject()})) {
            messageHelper.setSubject(mailBean.getSubject());
        }

        messageHelper.setText(mailBean.getContent(), true);
        Iterator it;
        Entry entry;
        String cid;
        String filePath;
        File file;
        FileSystemResource fileResource;
        if (org.apache.commons.lang3.ObjectUtils.anyNotNull(new Object[]{mailBean.getPictures()})) {
            it = mailBean.getPictures().entrySet().iterator();

            while(it.hasNext()) {
                entry = (Entry)it.next();
                cid = (String)entry.getKey();
                filePath = (String)entry.getValue();
                if (StringUtils.isBlank(cid) || StringUtils.isBlank(filePath)) {
                    UnitedLogger.debug("请确认每张图片的ID和图片地址是否齐全\n");
                    throw new UnitedException("I18N-MSG-999900000240");
                }

                file = new File(filePath);
                if (!file.exists()) {
                    UnitedLogger.debug("图片路径[" + filePath + "]不存在\n");
                    throw new UnitedException("I18N-MSG-999900000250");
                }

                fileResource = new FileSystemResource(file);
                messageHelper.addInline(cid, fileResource);
            }
        }

        if (org.apache.commons.lang3.ObjectUtils.anyNotNull(new Object[]{mailBean.getAttachments()})) {
            it = mailBean.getAttachments().entrySet().iterator();
            UnitedLogger.debug("getAttachments:"+mailBean.getAttachments());
            while(it.hasNext()) {
                entry = (Entry)it.next();
                cid = (String)entry.getKey();
                filePath = (String)entry.getValue();
                if (StringUtils.isBlank(cid) || StringUtils.isBlank(filePath)) {
                    UnitedLogger.debug("请确认每个附件的ID和地址是否齐全\n");
                    throw new UnitedException("I18N-MSG-999900000260");
                }

                file = new File(filePath);
                if (!file.exists()) {
                    UnitedLogger.debug("附件路径[" + filePath + "]不存在\n");
                    throw new UnitedException("I18N-MSG-999900000270");
                }

                fileResource = new FileSystemResource(file);
                messageHelper.addAttachment(cid, fileResource);
            }
        }

        messageHelper.setSentDate(new Date());
        UnitedLogger.info("线程运行正在发送至 " + mailBean.getRecipientsEmail() + " ....\n");
        this.javaMailSender.send(message);
    }

    private static String[] getEmails(String emailstr) throws UnitedException {
        String[] toEmailArray = null;
        if (StringUtils.isNotBlank(emailstr)) {
            toEmailArray = emailstr.split(",");
            List<String> toEmailList = new ArrayList();
            if (!org.apache.commons.lang3.ObjectUtils.anyNotNull(toEmailArray)) {
                UnitedLogger.debug("收件人邮箱不得为空\n");
                throw new UnitedException("I18N-MSG-999900000280");
            }

            String[] var3 = toEmailArray;
            int var4 = toEmailArray.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                String s = var3[var5];
                if (StringUtils.isNotBlank(s)) {
                    toEmailList.add(s);
                }
            }

            if (!org.apache.commons.lang3.ObjectUtils.anyNotNull(new Object[]{toEmailList})) {
                UnitedLogger.debug("收件人邮箱不得为空\n");
                throw new UnitedException("I18N-MSG-999900000280");
            }

            toEmailArray = new String[toEmailList.size()];
            if (org.apache.commons.lang3.ObjectUtils.anyNotNull(new Object[]{toEmailList})) {
                for(int i = 0; i < toEmailList.size(); ++i) {
                    toEmailArray[i] = (String)toEmailList.get(i);
                }
            }
        }

        return toEmailArray;
    }

    private JavaMailSenderImpl javaMailSender() {
        JavaMailSenderImpl sender = new JavaMailSenderImpl();

        try {
            System.setProperty("mail.mime.splitlongparameters","false");
            String jsonstr = this.emailSettingInfoService.getEmailSettingInfo();
            if (StringUtils.isNotBlank(jsonstr)) {
                JSONObject json = JSON.parseObject(jsonstr);
                String host = (String)json.get("host");
                Integer port = Integer.parseInt((String)json.get("port"));
                final String emailname = (String)json.get("username");
                final String password = (String)json.get("password");
                String protocol = (String)json.get("protocol");
                String auth = (String)json.get("auth");
                String starttls = (String)json.get("starttls");
                String ssl = (String)json.get("ssl");
                sender.setHost(host);
                sender.setPort(port);
                sender.setProtocol(protocol);
                sender.setUsername(emailname);
                sender.setPassword(password);
                sender.setDefaultEncoding("UTF-8");
                Properties props = new Properties();
                props.setProperty("mail.smtp.auth", auth);

                if (StringUtils.equals("true", ssl)) {
                    props.setProperty("mail.smtp.ssl.enable", ssl);
                    props.setProperty("mail.smtp.ssl.trust", host);
                    props.setProperty("mail.smtp.socketFactory.port", String.valueOf(port));
                    props.setProperty("mail.smtp.socketFactory.fallback", "false");
                    props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
                }

                if (StringUtils.equals("true", starttls)) {
                    props.setProperty("mail.smtp.starttls.enable", starttls);
                    props.setProperty("mail.smtp.starttls.required", starttls);
                }

                props.setProperty("mail.transport.protocol", protocol);
                Session session = Session.getDefaultInstance(props, new Authenticator() {
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(emailname, password);
                    }
                });
                sender.setSession(session);
                sender.setJavaMailProperties(props);
            }
        } catch (UnitedException var14) {
            UnitedLogger.error(var14);
        }

        return sender;
    }

    private EmailSettingInfoService getEmailSettingInfoService() {
        return this.emailSettingInfoService;
    }

    @Resource(
            name = "emailSettingInfoService"
    )
    private void setEmailSettingInfoService(EmailSettingInfoService emailSettingInfoService) {
        this.emailSettingInfoService = emailSettingInfoService;
    }

    private class SendMailThread extends RunnableAsyc {
        private MailBean mailBean;
        private EmailSettingInfoService emailSettingInfoService;

        public void run() {
            String status = "101";

            try {
                UnitedLogger.info("------------ 线程运行正在发送 ----------\n");
                if ("text".equals(this.mailBean.getSendType())) {
                    GFXDMailSenderExecutor.this.send(this.mailBean);
                } else if ("html".equals(this.mailBean.getSendType())) {
                    GFXDMailSenderExecutor.this.sendHtml(this.mailBean);
                }

                UnitedLogger.info("------------ 发送邮件至 " + this.mailBean.getRecipientsEmail() + " 完成 ----------\n");
                status = "100";
            } catch (Exception var3) {
                UnitedLogger.error(var3);
                status = "101";
            }

            if (StringUtils.isNotBlank(this.mailBean.getRecordId())) {
                this.emailSettingInfoService.updateMessageRecordStatusById(status, this.mailBean.getRecordId());
            }

        }

        public SendMailThread(MailBean mailBean, EmailSettingInfoService emailSettingInfoService) {
            this.mailBean = mailBean;
            this.emailSettingInfoService = emailSettingInfoService;
        }
    }

}

2、MailBean

import java.util.Map;

public class MailBean {
    private String recipientsEmail;
    private String subject;
    private String content;
    private String recordId;
    private String sendType = "html";
    private Map<String, Object> params;
    private Map<String, String> pictures;
    private Map<String, String> attachments;
    private String sendStatus;

    public MailBean() {
    }

    public MailBean(String recipientsEmail, String subject, String content) {
        this.recipientsEmail = recipientsEmail;
        this.subject = subject;
        this.content = content;
    }

    public MailBean(String recipientsEmail, String subject, String content, String recordId) {
        this.recipientsEmail = recipientsEmail;
        this.subject = subject;
        this.content = content;
        this.recordId = recordId;
    }

    public MailBean(String recipientsEmail, String subject, String content, String recordId, String sendType) {
        this.recipientsEmail = recipientsEmail;
        this.subject = subject;
        this.content = content;
        this.recordId = recordId;
        this.sendType = sendType;
    }

    public MailBean(String recipientsEmail, String subject, String content, String recordId, Map<String, String> pictures, Map<String, String> attachments) {
        this.recipientsEmail = recipientsEmail;
        this.subject = subject;
        this.content = content;
        this.recordId = recordId;
        this.pictures = pictures;
        this.attachments = attachments;
    }

    public MailBean(String recipientsEmail, String subject, String content, String recordId, String sendType, Map<String, String> pictures, Map<String, String> attachments) {
        this.recipientsEmail = recipientsEmail;
        this.subject = subject;
        this.content = content;
        this.recordId = recordId;
        this.sendType = sendType;
        this.pictures = pictures;
        this.attachments = attachments;
    }

    public MailBean(String recipientsEmail, String subject, String content, String recordId, String sendType, Map<String, String> pictures, Map<String, String> attachments, Map<String, Object> params) {
        this.recipientsEmail = recipientsEmail;
        this.subject = subject;
        this.content = content;
        this.recordId = recordId;
        this.sendType = sendType;
        this.pictures = pictures;
        this.attachments = attachments;
        this.params = params;
    }

    public String getRecipientsEmail() {
        return this.recipientsEmail;
    }

    public void setRecipientsEmail(String recipientsEmail) {
        this.recipientsEmail = recipientsEmail;
    }

    public String getSubject() {
        return this.subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getContent() {
        return this.content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getRecordId() {
        return this.recordId;
    }

    public void setRecordId(String recordId) {
        this.recordId = recordId;
    }

    public String getSendType() {
        return this.sendType;
    }

    public void setSendType(String sendType) {
        this.sendType = sendType;
    }

    public Map<String, Object> getParams() {
        return this.params;
    }

    public void setParams(Map<String, Object> params) {
        this.params = params;
    }

    public Map<String, String> getPictures() {
        return this.pictures;
    }

    public void setPictures(Map<String, String> pictures) {
        this.pictures = pictures;
    }

    public Map<String, String> getAttachments() {
        return this.attachments;
    }

    public void setAttachments(Map<String, String> attachments) {
        this.attachments = attachments;
    }

    public String getSendStatus() {
        return this.sendStatus;
    }

    public void setSendStatus(String sendStatus) {
        this.sendStatus = sendStatus;
    }
}



我的笔记博客版权我的笔记博客版权