загружает ли javamail вложения в память перед отправкой?

#java #email #jakarta-mail

#java #Адрес электронной почты #джакарта-почта

Вопрос:

Мне нужно создать электронное письмо с вложением, которое составляется на лету. В моем первом проекте этого я создал вложение в виде строки. Но на code walkthru другие указали, что строка может быть очень большой. Обычно это несколько тысяч байт, но иногда это могут быть мегабайты. Итак, они сказали, что я должен записать это построчно во временный файл, а затем прикрепить файл к электронному письму. В противном случае у меня может закончиться место в куче.

Мне интересно, действительно ли это помогает. Если JavaMail прочитает весь файл в память перед отправкой, это не будет иметь никакого значения. И, конечно, создание временного файла приводит к другим неприятностям, таким как поиск подходящего каталога для его размещения, проверка наличия у меня разрешений и т.д. Но если вместо этого Javamail считывает файл небольшими порциями, то это позволило бы избежать проблем с нехваткой памяти.

Побочный вопрос: насколько я понимаю, Javamail отправляет синхронно. Итак, если я создаю файл, отправляю его, а затем удаляю файл, не должно возникнуть проблемы с удалением файла до того, как он фактически завершит отправку, верно?

Комментарии:

1. Внутренние компоненты JavaMail, похоже, довольно хороши для потоковой передачи данных вместо их буферизации. Есть несколько случаев, когда он выполняет буферизацию, но это скорее исключение, чем правило. Если вы предпочитаете не переходить к исходному коду, простым экспериментом было бы выделить 8 МБ кучи вашему java-процессу и попробовать отправить файл размером 10 МБ.

2. О и да, безопасно удалять файл сразу после вызова метода отправки.

3. @dnault: Хорошая точка зрения на простой тест. Обычно я быстро провожу эмпирический тест, а не философски размышляю, но по какой-то причине у меня «заморозился мозг», и я не додумался до этого простого эксперимента.

Ответ №1:

Если вы используете реализацию DataHandler, да, вы можете передавать их в потоковом режиме. Мы делаем это постоянно

             MimeBodyPart mbp2 = new MimeBodyPart();
            //  attach the file to the message
            mbp2.setDataHandler(new DataHandler(fids[i]));
            mbp2.setFileName(fids[i].getName());
  

Где fids[i] в этом примере была нашей собственной реализацией интерфейса источника данных

 public abstract interface javax.activation.DataSource {

  // Method descriptor #4 ()Ljava/io/InputStream;
  public abstract java.io.InputStream getInputStream() throws java.io.IOException;

  // Method descriptor #8 ()Ljava/io/OutputStream;
  public abstract java.io.OutputStream getOutputStream() throws java.io.IOException;

  // Method descriptor #10 ()Ljava/lang/String;
  public abstract java.lang.String getContentType();

  // Method descriptor #10 ()Ljava/lang/String;
  public abstract java.lang.String getName();
}
  

Комментарии:

1. Спасибо. Но смысл моего вопроса был не в том, «Могу ли я использовать файл в качестве вложения?», а в том, «Что происходит в памяти, когда я это делаю?» Т.Е. загружает ли JavaMail все это в память, а затем отправляет его, или он считывает файл небольшими порциями для отправки?

2. Он считывает их как поток. Он не буферизует их в памяти. Чтобы доказать это, вложите, скажем, 100 МБ вложения в 64 МБ JVM …. без ООМ. (Я могу сказать вам, что я провел этот тест с JavaMail 1.4.несколько, но если вы хотите доказать это (хорошая и достойная цель), это легко сделать — вы вооружены всем необходимым.

Ответ №2:

Сообщение, созданное, как описано в MJB, будет отправлено как вложение, и я сомневаюсь, что это так, как вы этого хотели. Этот вариант проще и отправляет сообщение из файла в виде тела:

 File file = new File("huge-message.txt");
MimeMessage msg = new MimeMessage(mailSession);
msg.setFrom(...);
msg.setRecipient(...);
msg.setSubject(...);
msg.setDataHandler(new DataHandler(new FileDataSource(file)));
  

Комментарии:

1. На самом деле в моем данном случае я хотел, чтобы это было вложение: мы прикрепляем отчет к электронному письму. Мы хотим, чтобы в электронном письме было просто написано «Отчет XXX прикреплен», тогда у пользователя будет возможность сохранить файл отчета.

2. Ваша точка зрения верна (и фактически наш код поддерживает большие текстовые тела таким образом) — я просто придерживался проблемного пространства вопроса. Голосую за вас, потому что это хорошее дополнение