天天看点

Javamail发送邮件后并保存邮件到已发送前言需求分析查看JavaMail Api文档编写代码遇到的问题20170918网易邮箱重复问题更新

前言

最近北京暴雨,不知道为什么,特喜欢下雨天,下雨天适合睡觉,同样也适合写作!

需求分析

最近有个需求是将发送的邮件保存到已发送,一般来说最简单的做法是在服务器上配置,但是产品说,很多用户不知道这个选项,最好技术来实现,好吧,既然这样说了,干就完了!

查看JavaMail Api文档

邮件是在邮件服务器上存储的,邮件服务器上建立了各种的文件夹,比如INBOX,Sent等,就相当于Windows上的文件夹,里面存储的就是邮件,因此很容易想到Folder这个类,里面有这么个方法.

public void appendMessages(Message[] msgs)
                    throws MessagingException
Append the given messages into this folder.
Specified by:
appendMessages in class Folder
Parameters:
msgs - array of Messages to be appended
Throws:
FolderNotFoundException - if this folder does not exist.
MessagingException - if the append failed.
           

谷歌翻译:将给定的消息附加到此文件夹,Folder还有个方法copyMessages,它实际上最后调用的还是appendMessages.

编写代码

保存到已发送文件夹,也就一个方法

private void copyIntoSent(MimeMessage msg) {
        try {
            if (Constant.imapInfo.getLoginName().contains(MailboxType.OUTLOOK.toString())) {
                Properties properties = PropertyManager.getIMAPSSLproperty(Constant.imapInfo.getServerName());
                imapSession = Session.getInstance(properties, new MyAuthenticator(Constant.imapInfo.getLoginName(), Constant.imapInfo.getPassword()));
            } else {
                imapSession = Constant.session;
            }
            IMAPStore store = (IMAPStore) imapSession.getStore("imap");
            store.connect(Constant.imapInfo.getServerName(), Constant.smtpInfo.getLoginName(), Constant.smtpInfo.getPassword());
            IMAPFolder folder = (IMAPFolder) store.getFolder(Constant.SENT_FOLDER);
            if (!folder.exists()) {
                folder.create(Folder.HOLDS_MESSAGES);
            }
            folder.open(Folder.READ_WRITE);
            if (Constant.imapInfo.getLoginName().contains(MailboxType.NETEASY126.toString()) || Constant.imapInfo.getLoginName().contains(MailboxType.NETEASY163.toString())) {
                msg.setFlag(Flags.Flag.DELETED, true);
            }
            folder.appendMessages(new Message[]{msg});
            folder.expunge();
        } catch (Exception e) {
            Logger.e(TAG, Log.getStackTraceString(e));
        }

    }
           

遇到的问题

    1.网易邮箱append后会有重复的邮件出现,很奇怪,一般来说邮件服务器都有做去重操作的,这个邮件为什么会重复,没有办法,我耍了个小聪明,判断如果是网易邮箱,appendMessages时将此message增加删除的flag,这样appendMessages里就是一封邮件了(目前先这样处理吧,暂时没有好的解决方案)

   2.其他邮箱比较QQ,腾讯企业邮箱,当然包括网易的,均会出现一个错误(虽然也保存到已发送的文件夹里了), 打开Session.setDebug(true),会出来这个错误信息, A3 NO Mail has saved by smtp!,这个错误网络上查了下,感觉都有遇到过,有的是A4,和A5,既然保存成功了,我觉得这个应该是一些警告级别的错误,应该是警告我们这封邮件没有使用smtp协议保存,但是folder.appendMessages实则是一个复制,因为只有IMAP和POP协议有Folder类,SMTP只是发送的协议,因此那个错误就先忽略吧,感觉不影响大局,大家没事可以看下这个,收集的是JavaMail的一些常见的错误和一些知识点.

  JavaMail FAQ

20170918网易邮箱重复问题更新

最近测试提出了一个问题,我自己本身也测试出来了,就是网易邮箱发邮件成功后,发现本来有很多附件的邮件,在已发送里边没显示,只有纯文本,我也很奇怪,因为之前我知道网易邮箱会有重复的问题,我就决定要解决掉这个历史遗留问题.大家直接看图吧.

Javamail发送邮件后并保存邮件到已发送前言需求分析查看JavaMail Api文档编写代码遇到的问题20170918网易邮箱重复问题更新

默认为部分保存(有点坑)

可以看到,网易默认是“部分保存”,就是说,可以看到他的解释,如果附件大于1M,就部分保存文本(这就可以解释为什么我之前附件小的“已发送”没有问题).

如果你选择了全部保存到“已发送”文件夹.

这个时候,我建议你程序里边不用做任何的操作; 但是如果你坚持还要用appendMessages,这个时候你在用我上面说的那个方式,对其设置一个delete标识即可完美解决(因为有两封邮件是一样的,不知道为什么网易没有进行去重)

IMAPFolder folder = (IMAPFolder) store.getFolder(Constant.SENT_FOLDER);
            if (!folder.exists()) {
                folder.create(Folder.HOLDS_MESSAGES);
            }
            folder.open(Folder.READ_WRITE);
            if (Constant.imapInfo.getLoginName().contains(MailboxType.NETEASY126.toString()) || Constant.imapInfo.getLoginName().contains(MailboxType.NETEASY163.toString())) {
                msg.setFlag(Flags.Flag.DELETED, true);
            }
            folder.appendMessages(new Message[]{msg});
	    folder.expuge();//彻底清除带有“deleted”标记的邮件.
           

如果你选择了不保存,那么程序中直接使用appendMessage即可(所有选项亲测可用)

IMAPFolder folder = (IMAPFolder) store.getFolder(Constant.SENT_FOLDER);
            if (!folder.exists()) {
                folder.create(Folder.HOLDS_MESSAGES);
            }
            folder.open(Folder.READ_WRITE);
            folder.appendMessages(new Message[]{msg});
           

继续阅读