使用 JavaMail 将“mail.imaps.fetchsize”属性设置为大数字有啥影响?

Posted

技术标签:

【中文标题】使用 JavaMail 将“mail.imaps.fetchsize”属性设置为大数字有啥影响?【英文标题】:Setting the "mail.imaps.fetchsize" property to a large number using JavaMail have any impacts?使用 JavaMail 将“mail.imaps.fetchsize”属性设置为大数字有什么影响? 【发布时间】:2020-06-19 16:26:45 【问题描述】:

我有一个计划作业来从文件夹中获取最近的电子邮件并将这些电子邮件写入文件(.eml 文件)。但它需要很长时间(阅读一封 9mb 大小的电子邮件需要 5 到 6 分钟)才能完成。由于我使用的是 JavaMail API,因此我在代码中设置了如下属性,以提高性能,这样花费的时间非常少(20 秒)。

props.setProperty("mail.imaps.partialfetch","false");
props.setProperty("mail.imaps.fetchsize", "1048576");
    这(将fetchsize 设置为更大的值)是否会在我的应用程序中产生任何其他问题?。 将 fetchsize 设置为 1048576 意味着我的计划作业将占用 总是有这么多内存,剩余的内存将分配给 我的应用程序的其余部分。我的理解在这里正确吗?如果不 , 有人可以通过示例帮助我更好地理解这一点吗?

整个代码如下,

package com.indiscover;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import java.util.Properties;

import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.search.FlagTerm;

public class ReadMail 

    public static void main(String[] args) throws InterruptedException, IOException 
        String protocol="imaps";
        String emailAddress = "email_id";
        String password = "password";

        Properties props = new Properties();
        props.setProperty("mail.store.protocol", protocol);
        props.setProperty("mail.imaps.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.setProperty("mail.imaps.socketFactory.fallback", "false");
        props.setProperty("mail.imaps.port", "993");
        props.setProperty("mail.imaps.socketFactory.port", "993");
        props.setProperty("mail.imaps.partialfetch","false");
        props.setProperty("mail.imaps.fetchsize", "1048576"); 

        Session session = Session.getInstance(props, null);

        try 

            Store store = session.getStore(protocol);
            store.connect("imap-mail.outlook.com", emailAddress, password);
            Folder inbox = store.getFolder("Archive/Test");
            inbox.open(Folder.READ_WRITE);

            //search for all "unseen" messages
            Flags recent = new Flags(Flags.Flag.RECENT);
            FlagTerm recentFlagTerm = new FlagTerm(recent, true);
            Message messages[] = inbox.search(recentFlagTerm);


            for (int i = 0; i < messages.length; i++) 
                Message message = messages[i];
                String subject = message.getSubject();

                processSaveToFile(message,subject);
            

            inbox.close(false);
            store.close();

        catch (NoSuchProviderException ex) 
            System.out.println("No provider.");
            ex.printStackTrace();
         catch (MessagingException ex) 
            System.out.println("Could not connect to the message store.");
            ex.printStackTrace();
        

    

    private static void processSaveToFile (Message msg, String subject) throws MessagingException, IOException
    
       String whereToSave = "/Users/XXX/Documents/" + "some_random_name" + ".eml";

       OutputStream out = new FileOutputStream(new File(whereToSave));
       try 
           msg.writeTo(out);
       
       finally 
           if (out != null)  out.flush(); out.close(); 
       
     


【问题讨论】:

【参考方案1】:

来自 JakartaMail 常见问题解答Retrieving large message bodies seems inefficient at times:

如果您使用 IMAP 提供程序,您可以尝试增加 mail.imap.fetchsize 属性(当前默认值为 16k)。这将导致数据以更大的块从服务器获取。请注意,这样做可能会导致 JVM 内存不足。

正如您所指出的,您只需要足够的堆空间。

将 fetchsize 设置为 1048576 意味着我的计划作业将始终占用这么多内存,剩余的内存将分配给我的应用程序的其余部分。

挖掘源代码for the imap package,看起来 fetchsize 用于为每个IMAPInputStream 分配一个可增长的字节数组。看来这将取决于 IMAPInputStream 的生命周期以及内存中可访问的 IMAPInputStream 数量将决定堆使用的行为方式。从您的源代码看来,它应该是相当可预测的。

Run a memory profile 在您的应用程序上调整您的堆设置。

【讨论】:

以上是关于使用 JavaMail 将“mail.imaps.fetchsize”属性设置为大数字有啥影响?的主要内容,如果未能解决你的问题,请参考以下文章

IMAP 读取含有附件邮件超慢问题

将 JavaMail 与 TLS 一起使用

将JavaMail与TLS结合使用

无法使用 javamail 将 HTML 电子邮件发送到 Gmail

如何使用 javamail 将 base64 图像嵌入到电子邮件中

Javamail 无法将套接字转换为 TLS GMail