8

我查看了参考文档,Spring 似乎对发送邮件有很好的支持。但是,我需要登录到一个邮件帐户,阅读邮件并下载任何附件。Spring 邮件 API 是否支持下载邮件附件?

我知道您可以使用 Java Mail API 来做到这一点,但过去我发现使用它非常冗长且令人不快。

编辑:我收到了一些回复,这些回复指向描述如何发送带有附件的邮件的教程,但我要问的是如何从收到的邮件中读取附件。

干杯,唐

4

6 回答 6

21

这是我用于下载电子邮件的类(带有附件处理)。您必须浏览一下它正在做的一些事情(比如忽略日志记录类和数据库写入)。为了便于阅读,我还重新命名了一些包。

总体思路是将所有附件保存为文件系统中的单个文件,并且将每封电子邮件保存为数据库中的一条记录,其中包含一组指向所有附件文件路径的子记录。

专注于 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;
    }

}
于 2008-10-01T16:30:53.333 回答
12

我对 Steven 的示例进行了一些处理,并删除了 Steven 特定的代码部分。如果有附件,我的代码将不会读取电子邮件的正文。这对我的情况很好,但你可能想为你的情况进一步完善它。

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找到

于 2010-12-24T19:33:23.293 回答
3

这是一个错误:

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

它应该是:

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

感谢@Stevenmcherry 的回答

于 2009-09-29T01:05:49.140 回答
1

我使用 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=真的)。

于 2013-12-09T09:53:08.330 回答
0

到目前为止,我只使用了 JavaMail API(出于我的目的,我对它们相当满意)。如果完整的 JavaMail 包对您来说太重,则可以使用底层传输引擎而无需包的顶层。您在 SMTP、POP3 和 IMAP 堆栈中的位置越低,您需要为自己做的准备就越多。

从好的方面来说,您还可以忽略应用程序不需要的部分。

于 2008-09-30T23:07:29.330 回答
-1
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";
    }
}
于 2013-10-11T12:00:23.380 回答