用Java下载邮件附件

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

我知道您可以使用Java Mail API执行此操作,但在过去,我发现使用它非常冗长和令人不快。

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

干杯,唐

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

一般的想法是所有附件都保存为文件系统中的单个文件,并且每个电子邮件都作为记录保存在数据库中,并带有一组指向所有附件文件路径的子记录。

专注于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 vema = new Vector(); 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; } } 

我稍微研究了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 downloadPop3(String host, String user, String pass, String downloadDir) throws Exception { List emails = new ArrayList(); // 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 to = new ArrayList(); public List cc = new ArrayList(); public String subject; public String body; public List attachments = new ArrayList(); } 

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

这是一个错误:

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

它应该是:

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

谢谢@Stevenmcherry的回答

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

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

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

 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"; } }