Скачать почтовое вложение с Java

Я просмотрел справочную документацию, и Spring, похоже, довольно хорошо поддерживает отправку почты. Однако мне нужно войти в учетную запись электронной почты, прочитать сообщения и загрузить любые вложения. Поддерживается ли загрузка почтовых вложений в Spring mail API?

Я знаю, что вы можете сделать это с помощью Java Mail API, но в прошлом я считал это очень многословным и неприятным для работы.

РЕДАКТИРОВАТЬ: Я получил несколько ответов, указывающих на руководства, в которых описывается, как отправлять почту с вложениями, но я спрашиваю, как отправлять вложения читать из почты полученный.

Ваше здоровье, Дон

пружина тоже может - static.springframework.org/spring/docs/2.0.x/reference/…> См. раздел 22.3.1. Отправка вложений и встроенных ресурсов

anjanb 01.10.2008 05:34

Спасибо, но мой вопрос касался чтения вложений, а не отправки вложений.

Dónal 01.10.2008 17:29

Почтовый клиент Apache Commons может довольно легко прикреплять вложения - commons.apache.org/email/userguide.html

anjanb 01.10.2008 05:32

Есть ли примеры, показывающие, как читать вложение из входящей почты?

Dónal 01.10.2008 17:33
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
8
4
33 063
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

До сих пор я использовал только API JavaMail (и был достаточно доволен ими для моих целей). Если полный пакет JavaMail слишком тяжел для вас, базовый механизм транспорта можно использовать без верхних уровней пакета. Чем ниже стеки SMTP, POP3 и IMAP, тем больше вы должны быть готовы сделать для себя.

С другой стороны, вы также сможете игнорировать части, которые не требуются для вашего приложения.

Ответ принят как подходящий

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

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

Сосредоточьтесь на методе doEMailDownload.

/**
  * Copyright (c) 2008 Steven M. Cherry
  * All rights reserved.
  */
package utils.scheduled;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.Timestamp;
import java.util.Properties;
import java.util.Vector;

import javax.mail.Address;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.MimeBodyPart;

import glob.ActionLogicImplementation;
import glob.IOConn;
import glob.log.Log;
import logic.utils.sql.Settings;
import logic.utils.sqldo.EMail;
import logic.utils.sqldo.EMailAttach;

/**
  * This will connect to our incoming e-mail server and download any e-mails
  * that are found on the server.  The e-mails will be stored for further processing
  * in our internal database.  Attachments will be written out to separate files
  * and then referred to by the database entries.  This is intended to be  run by 
  * the scheduler every minute or so.
  *
  * @author Steven M. Cherry
  */
public class DownloadEMail implements ActionLogicImplementation {

    protected String receiving_host;
    protected String receiving_user;
    protected String receiving_pass;
    protected String receiving_protocol;
    protected boolean receiving_secure;
    protected String receiving_attachments;

    /** This will run our logic */
    public void ExecuteRequest(IOConn ioc) throws Exception {
        Log.Trace("Enter");

        Log.Debug("Executing DownloadEMail");
        ioc.initializeResponseDocument("DownloadEMail");

        // pick up our configuration from the server:
        receiving_host = Settings.getValue(ioc, "server.email.receiving.host");
        receiving_user = Settings.getValue(ioc, "server.email.receiving.username");
        receiving_pass = Settings.getValue(ioc, "server.email.receiving.password");
        receiving_protocol = Settings.getValue(ioc, "server.email.receiving.protocol");
        String tmp_secure = Settings.getValue(ioc, "server.email.receiving.secure");
        receiving_attachments = Settings.getValue(ioc, "server.email.receiving.attachments");

        // sanity check on the parameters:
        if (receiving_host == null || receiving_host.length() == 0){
            ioc.SendReturn();
            ioc.Close();
            Log.Trace("Exit");
            return; // no host defined.
        }
        if (receiving_user == null || receiving_user.length() == 0){
            ioc.SendReturn();
            ioc.Close();
            Log.Trace("Exit");
            return; // no user defined.
        }
        if (receiving_pass == null || receiving_pass.length() == 0){
            ioc.SendReturn();
            ioc.Close();
            Log.Trace("Exit");
            return; // no pass defined.
        }
        if (receiving_protocol == null || receiving_protocol.length() == 0){
            Log.Debug("EMail receiving protocol not defined, defaulting to POP");
            receiving_protocol = "POP";
        }
        if (tmp_secure == null || 
            tmp_secure.length() == 0 ||
            tmp_secure.compareToIgnoreCase("false") == 0 ||
            tmp_secure.compareToIgnoreCase("no") == 0
        ){
            receiving_secure = false;
        } else {
            receiving_secure = true;
        }
        if (receiving_attachments == null || receiving_attachments.length() == 0){
            Log.Debug("EMail receiving attachments not defined, defaulting to ./email/attachments/");
            receiving_attachments = "./email/attachments/";
        }

        // now do the real work.
        doEMailDownload(ioc);

        ioc.SendReturn();
        ioc.Close();
        Log.Trace("Exit");
    }

    protected void doEMailDownload(IOConn ioc) throws Exception {
        // Create empty properties
        Properties props = new Properties();
        // Get the session
        Session session = Session.getInstance(props, null);

        // Get the store
        Store store = session.getStore(receiving_protocol);
        store.connect(receiving_host, receiving_user, receiving_pass);

        // Get folder
        Folder folder = store.getFolder("INBOX");
        folder.open(Folder.READ_WRITE);

        try {

            // Get directory listing
            Message messages[] = folder.getMessages();

            for (int i=0; i < messages.length; i++) {
                // get the details of the message:
                EMail email = new EMail();
                email.fromaddr = messages[i].getFrom()[0].toString();
                Address[] to = messages[i].getRecipients(Message.RecipientType.TO);
                email.toaddr = "";
                for(int j = 0; j < to.length; j++){
                    email.toaddr += to[j].toString() + "; ";
                }
                Address[] cc;
                try {
                    cc = messages[i].getRecipients(Message.RecipientType.CC);
                } catch (Exception e){
                    Log.Warn("Exception retrieving CC addrs: %s", e.getLocalizedMessage());
                    cc = null;
                }
                email.cc = "";
                if (cc != null){
                    for(int j = 0; j < cc.length; j++){
                        email.cc += cc[j].toString() + "; ";
                    }
                }
                email.subject = messages[i].getSubject();
                if (messages[i].getReceivedDate() != null){
                    email.received_when = new Timestamp(messages[i].getReceivedDate().getTime());
                } else {
                    email.received_when = new Timestamp( (new java.util.Date()).getTime());
                }


                email.body = "";
                Vector<EMailAttach> vema = new Vector<EMailAttach>();
                Object content = messages[i].getContent();
                if (content instanceof java.lang.String){
                    email.body = (String)content;
                } else if (content instanceof Multipart){
                    Multipart mp = (Multipart)content;

                    for (int j=0; j < mp.getCount(); j++) {
                        Part part = mp.getBodyPart(j);

                        String disposition = part.getDisposition();

                        if (disposition == null) {
                            // Check if plain
                            MimeBodyPart mbp = (MimeBodyPart)part;
                            if (mbp.isMimeType("text/plain")) {
                                Log.Debug("Mime type is plain");
                                email.body += (String)mbp.getContent();
                            } else {
                                Log.Debug("Mime type is not plain");
                                // Special non-attachment cases here of 
                                // image/gif, text/html, ...
                                EMailAttach ema = new EMailAttach();
                                ema.name = decodeName(part.getFileName());
                                File savedir = new File(receiving_attachments);
                                savedir.mkdirs();
                                File savefile = File.createTempFile("emailattach", ".atch", savedir );
                                ema.path = savefile.getAbsolutePath();
                                ema.size = part.getSize();
                                vema.add(ema);
                                ema.size = saveFile(savefile, part);
                            }
                        } else if ((disposition != null) && 
                            (disposition.equals(Part.ATTACHMENT) || disposition.equals(Part.INLINE) ) 
                        ){
                            // Check if plain
                            MimeBodyPart mbp = (MimeBodyPart)part;
                            if (mbp.isMimeType("text/plain")) {
                                Log.Debug("Mime type is plain");
                                email.body += (String)mbp.getContent();
                            } else {
                                Log.Debug("Save file (%s)", part.getFileName() );
                                EMailAttach ema = new EMailAttach();
                                ema.name = decodeName(part.getFileName());
                                File savedir = new File(receiving_attachments);
                                savedir.mkdirs();
                                File savefile = File.createTempFile("emailattach", ".atch", savedir );
                                ema.path = savefile.getAbsolutePath();
                                ema.size = part.getSize();
                                vema.add(ema);
                                ema.size = saveFile( savefile, part);
                            }
                        }
                    }
                }

                // Insert everything into the database:
                logic.utils.sql.EMail.insertEMail(ioc, email);
                for(int j = 0; j < vema.size(); j++){
                    vema.get(j).emailid = email.id;
                    logic.utils.sql.EMail.insertEMailAttach(ioc, vema.get(j) );
                }

                // commit this message and all of it's attachments
                ioc.getDBConnection().commit();

                // Finally delete the message from the server.
                messages[i].setFlag(Flags.Flag.DELETED, true);
            }

            // Close connection 
            folder.close(true); // true tells the mail server to expunge deleted messages.
            store.close();
        } catch (Exception e){
            folder.close(true); // true tells the mail server to expunge deleted messages.
            store.close();
            throw e;
        }

    }

    protected int saveFile(File saveFile, Part part) throws Exception {

        BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream(saveFile) );

        byte[] buff = new byte[2048];
        InputStream is = part.getInputStream();
        int ret = 0, count = 0;
        while( (ret = is.read(buff)) > 0 ){
            bos.write(buff, 0, ret);
            count += ret;
        }
        bos.close();
        is.close();
        return count;
    }

    protected String decodeName( String name ) throws Exception {
        if (name == null || name.length() == 0){
            return "unknown";
        }
        String ret = java.net.URLDecoder.decode( name, "UTF-8" );

        // also check for a few other things in the string:
        ret = ret.replaceAll("=\?utf-8\?q\?", "");
        ret = ret.replaceAll("\? = ", "");
        ret = ret.replaceAll("=20", " ");

        return ret;
    }

}

у кого-нибудь есть maven pom?

jechaviz 24.09.2014 05:46

Вот ошибка:

else if ((disposition != null) && (disposition.equals(Part.ATTACHMENT)
 || disposition.equals(Part.INLINE) ) 

должен быть:

else if ((disposition.equalsIgnoreCase(Part.ATTACHMENT)
 || disposition.equalsIgnoreCase(Part.INLINE))

Спасибо @Stevenmcherry за ваш ответ

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

package utils;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.MimeBodyPart;

public class IncomingMail {

 public static List<Email> downloadPop3(String host, String user, String pass, String downloadDir) throws Exception {

  List<Email> emails = new ArrayList<Email>();

  // Create empty properties
  Properties props = new Properties();

  // Get the session
  Session session = Session.getInstance(props, null);

  // Get the store
  Store store = session.getStore("pop3");
  store.connect(host, user, pass);

  // Get folder
  Folder folder = store.getFolder("INBOX");
  folder.open(Folder.READ_WRITE);

  try {
   // Get directory listing
   Message messages[] = folder.getMessages();
   for (int i = 0; i < messages.length; i++) {

    Email email = new Email();

    // from 
    email.from = messages[i].getFrom()[0].toString();

    // to list
    Address[] toArray = messages[i] .getRecipients(Message.RecipientType.TO);
    for (Address to : toArray) { email.to.add(to.toString()); }

    // cc list
    Address[] ccArray = null;
    try {
     ccArray = messages[i] .getRecipients(Message.RecipientType.CC);
    } catch (Exception e) { ccArray = null; }
    if (ccArray != null) {
     for (Address c : ccArray) {
      email.cc.add(c.toString());
     }
    }

    // subject
    email.subject = messages[i].getSubject();

    // received date
    if (messages[i].getReceivedDate() != null) {
     email.received = messages[i].getReceivedDate();
    } else {
     email.received = new Date();
    }

    // body and attachments
    email.body = "";
    Object content = messages[i].getContent();
    if (content instanceof java.lang.String) {

     email.body = (String) content;

    } else if (content instanceof Multipart) {

     Multipart mp = (Multipart) content;

     for (int j = 0; j < mp.getCount(); j++) {

      Part part = mp.getBodyPart(j);
      String disposition = part.getDisposition();

      if (disposition == null) {

       MimeBodyPart mbp = (MimeBodyPart) part;
       if (mbp.isMimeType("text/plain")) {
        // Plain
        email.body += (String) mbp.getContent();
       } 

      } else if ((disposition != null) && (disposition.equals(Part.ATTACHMENT) || disposition .equals(Part.INLINE))) {

       // Check if plain
       MimeBodyPart mbp = (MimeBodyPart) part;
       if (mbp.isMimeType("text/plain")) {
        email.body += (String) mbp.getContent();
       } else {
        EmailAttachment attachment = new EmailAttachment();
        attachment.name = decodeName(part.getFileName());
        File savedir = new File(downloadDir);
        savedir.mkdirs();
        // File savefile = File.createTempFile( "emailattach", ".atch", savedir);
        File savefile = new File(downloadDir,attachment.name);
        attachment.path = savefile.getAbsolutePath();
        attachment.size = saveFile(savefile, part);
        email.attachments.add(attachment);
       }
      }
     } // end of multipart for loop 
    } // end messages for loop

    emails.add(email);

    // Finally delete the message from the server.
    messages[i].setFlag(Flags.Flag.DELETED, true);
   }

   // Close connection
   folder.close(true); // true tells the mail server to expunge deleted messages
   store.close();

  } catch (Exception e) {
   folder.close(true); // true tells the mail server to expunge deleted
   store.close();
   throw e;
  }

  return emails;
 }

 private static String decodeName(String name) throws Exception {
  if (name == null || name.length() == 0) {
   return "unknown";
  }
  String ret = java.net.URLDecoder.decode(name, "UTF-8");

  // also check for a few other things in the string:
  ret = ret.replaceAll("=\?utf-8\?q\?", "");
  ret = ret.replaceAll("\? = ", "");
  ret = ret.replaceAll("=20", " ");

  return ret;
 }

 private static int saveFile(File saveFile, Part part) throws Exception {

  BufferedOutputStream bos = new BufferedOutputStream(
    new FileOutputStream(saveFile));

  byte[] buff = new byte[2048];
  InputStream is = part.getInputStream();
  int ret = 0, count = 0;
  while ((ret = is.read(buff)) > 0) {
   bos.write(buff, 0, ret);
   count += ret;
  }
  bos.close();
  is.close();
  return count;
 }

}

Вам также понадобятся эти два вспомогательных класса

package utils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class Email {

 public Date received;
 public String from;
 public List<String> to = new ArrayList<String>();
 public List<String> cc = new ArrayList<String>();
 public String subject;
 public String body;
 public List<EmailAttachment> attachments = new ArrayList<EmailAttachment>();
}

и

package utils;

public class EmailAttachment {

 public String name;
 public String path;
 public int size;
}

Я использовал это для тестирования вышеуказанных классов

package utils;

import java.util.List;


public class Test {

 public static void main(String[] args) {

  String host = "some host";
  String user = "some user";
  String pass = "some pass";
  String downloadDir = "/Temp";
  try {
   List<Email> emails = IncomingMail.downloadPop3(host, user, pass, downloadDir);
   for ( Email email : emails ) {
    System.out.println(email.from);
    System.out.println(email.subject);
    System.out.println(email.body);
    List<EmailAttachment> attachments = email.attachments;
    for ( EmailAttachment attachment : attachments ) {
     System.out.println(attachment.path+" "+attachment.name);
    }
   }
  } catch (Exception e) { e.printStackTrace(); }

 }

}

Более подробную информацию можно найти на http://java.sun.com/developer/onlineTraining/JavaMail/contents.html

Код отлично работает при отображении текста электронной почты, но не загружает вложения. Я попробовал несколько вещей, но код не загрузил вложения электронной почты. Спасибо, что предоставили такое прекрасное решение для чтения электронных писем, но было бы здорово, если бы оно также могло загружать вложения.

Manpreet Singh 22.05.2012 04:30

import java.io.IOException;
import java.io.InputStream;

import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

@Controller
@RequestMapping("/sendEmail.do")
public class SendEmailAttachController {
    @Autowired
    private JavaMailSender mailSender;

    @RequestMapping(method = RequestMethod.POST)
    public String sendEmail(HttpServletRequest request,
            final @RequestParam CommonsMultipartFile attachFile) {

        // Input here
        final String emailTo = request.getParameter("mailTo");
        final String subject = request.getParameter("subject");
        final String yourmailid = request.getParameter("yourmail");
        final String message = request.getParameter("message");

        // Logging
        System.out.println("emailTo: " + emailTo);
        System.out.println("subject: " + subject);
        System.out.println("Your mail id is: "+yourmailid);
        System.out.println("message: " + message);
        System.out.println("attachFile: " + attachFile.getOriginalFilename());

        mailSender.send(new MimeMessagePreparator() {

            @Override
            public void prepare(MimeMessage mimeMessage) throws Exception {
                MimeMessageHelper messageHelper = new MimeMessageHelper(
                        mimeMessage, true, "UTF-8");
                messageHelper.setTo(emailTo);
                messageHelper.setSubject(subject);
                messageHelper.setReplyTo(yourmailid);
                messageHelper.setText(message);

                // Attachment with mail
                String attachName = attachFile.getOriginalFilename();
                if (!attachFile.equals("")) {

                    messageHelper.addAttachment(attachName, new InputStreamSource() {

                        @Override
                        public InputStream getInputStream() throws IOException {
                            return attachFile.getInputStream();
                        }
                    });
                }

            }

        });

        return "Result";
    }
}

Этот код предназначен для отправки электронных писем, OP попросил прочитать электронные письма.

Jason 04.08.2014 06:47

Я использовал Apache Commons Mail для этой задачи:

import java.util.List;
import javax.activation.DataSource; 
import javax.mail.internet.MimeMessage;   
import org.apache.commons.mail.util.MimeMessageParser;   

public List<DataSource> getAttachmentList(MimeMessage message) throws Exception {
    msgParser = new MimeMessageParser(message);
    msgParser.parse();
    return msgParser.getAttachmentList();
}

Из объекта DataSource вы можете получить InputStream (помимо имени и типа) вложения (см. API: http://docs.oracle.com/javase/6/docs/api/javax/activation/DataSource.html?is-external=true).

Другие вопросы по теме