如何使用Java下载Outlook邮件中的多个附件?
问题原因分析
你遇到的报错核心来自4个问题:
- 文件名未解码:报错信息里的
=?utf-8?B?QW5udWxhdGlvbiAtIEF2ZW5hbnQgZGUgcsOpc2lsaWF0aW9uLlBERg==?=是符合MIME标准的编码后文件名,直接作为系统文件名使用会触发路径语法错误 - 路径拼接错误:你的保存路径写了
"Y:\\pdf\\" + File.separator,等于重复拼接了路径分隔符,部分系统会识别为非法路径 - 未处理文件名非法字符:Windows系统不允许文件名包含
/:*?"<>|等字符,如果附件名带这些字符也会报错 - 未校验保存目录存在性:如果Y盘下的pdf目录不存在,也会触发文件找不到异常
修复方案
第一步:调整Session配置,开启自动文件名解码
在Properties配置中新增如下配置,让Java Mail优先自动处理文件名解码:
props.put("mail.mime.decodefilename", "true");
第二步:手动解码文件名+清洗非法字符
需要导入javax.mail.internet.MimeUtility工具类,对获取到的文件名做解码和非法字符清洗
第三步:修正路径拼接逻辑
使用File构造方法拼接路径,避免手动拼接分隔符出错
第四步:提前校验保存目录是否存在,不存在则创建
修改后的完整代码
package Email_Attachment; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Files; import java.util.Properties; import javax.mail.Address; import javax.mail.Flags; import javax.mail.Folder; import javax.mail.Session; import javax.mail.Store; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeUtility; import javax.mail.search.FlagTerm; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.NoSuchProviderException; import javax.mail.Part; import javax.mail.PasswordAuthentication; public class test { public static void main(String[]args)throws Exception,FileNotFoundException { Properties props = System.getProperties(); props.setProperty("mail.store.protocol", "imap"); props.setProperty("mail.imap.ssl.enable", "true"); props.setProperty("mail.imap.partialfetch", "false"); props.put("mail.mime.base64.ignoreerrors", "true"); // 新增配置:自动解码文件名 props.put("mail.mime.decodefilename", "true"); Session mailSession = Session.getDefaultInstance(props, new javax.mail.Authenticator(){ protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("username", "password"); } }); mailSession.setDebug(true); // 提前校验保存目录,不存在则创建 File saveDir = new File("Y:\\pdf\\"); if (!saveDir.exists()) { Files.createDirectories(saveDir.toPath()); } try { Store store = mailSession.getStore("imap"); store.connect( "outlook.office365.com","username", "password"); Folder folderInbox = store.getFolder("INBOX"); folderInbox.open(Folder.READ_ONLY); Message[] messages = folderInbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false)); for (int i = 0; i < messages.length; i++) { Message message = messages[i]; Address[] fromAddress = message.getFrom(); String from = fromAddress[0].toString(); String subject = message.getSubject(); String sentDate = message.getSentDate().toString(); String contentType = message.getContentType(); String messageContent = ""; String attachFiles = ""; if (contentType.contains("multipart")) { Multipart multiPart = (Multipart) message.getContent(); int numberOfParts = multiPart.getCount(); for (int partCount = 0; partCount < numberOfParts; partCount++) { MimeBodyPart part = (MimeBodyPart) multiPart.getBodyPart(partCount); if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) { // 解码文件名+清洗非法字符 String fileName = MimeUtility.decodeText(part.getFileName()); // 替换Windows文件名非法字符 fileName = fileName.replaceAll("[\\\\/:*?\"<>|]", "_"); attachFiles += fileName + ", "; // 修正路径拼接,直接用File构造方法避免分隔符错误 part.saveFile(new File(saveDir, fileName)); } else { messageContent = part.getContent().toString(); } } if (attachFiles.length() > 1) { attachFiles = attachFiles.substring(0, attachFiles.length() - 2); } } else if (contentType.contains("text/plain") || contentType.contains("text/html")) { Object content = message.getContent(); if (content != null) { messageContent = content.toString(); } } System.out.println("Message #" + (i + 1) + ":"); System.out.println("\t From: " + from); System.out.println("\t Subject: " + subject); System.out.println("\t Sent Date: " + sentDate); System.out.println("\t Message: " + messageContent); System.out.println("\t Attachments: " + attachFiles); } folderInbox.close(false); store.close(); } catch (NoSuchProviderException ex) { System.out.println("No provider for imap."); ex.printStackTrace(); } catch (MessagingException ex) { System.out.println("Could not connect to the message store"); ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } }}
额外说明
原代码的异常捕获里错误打印了No provider for pop3,已经同步修正为imap协议的对应提示。
内容的提问来源于stack exchange,提问作者ANU PRAKASH
相关产品推荐
相关产品推荐

