如何使用JavaMail获取QQ邮箱等的Starred星标文件夹
store.defaultFolder.list("*")仅会返回服务端主动公开、已订阅的根目录系统文件夹,星标文件夹不属于通用标准系统文件夹,不同邮件服务商的命名、存储路径、IMAP可见权限不统一,因此不会被默认列出。
解决步骤
1. 连接时开启全量文件夹获取权限
默认 JavaMail/Jakarta Mail 的 list 方法仅返回已订阅的文件夹,需要在初始化 Session 时添加对应属性,才能拿到未订阅的文件夹列表:
val props = new Properties() // 普通IMAP服务添加该配置 props.put("mail.imap.listunsubscribed", "true") // IMAPS加密服务(QQ邮箱、Gmail等主流服务商均使用)添加该配置 props.put("mail.imaps.listunsubscribed", "true") val session = Session.getDefaultInstance(props) val store = session.getStore("imaps") // 后续正常连接逻辑即可,你之前能拿到INBOX等文件夹,说明连接逻辑无需调整
2. 两种获取星标文件夹的方案
方案A:已知服务商固定路径,直接访问(最稳定)
主流服务商的星标文件夹路径是固定的,不需要遍历列表,直接通过路径获取即可:
// 以QQ邮箱为例,星标文件夹路径为"Starred"(部分中文环境返回为"星标邮件",可二选一尝试) val starredFolder = store.getFolder("Starred") // 如果是Gmail,路径为"[Gmail]/Starred" // val starredFolder = store.getFolder("[Gmail]/Starred") // 打开文件夹,不需要修改邮件的话用READ_ONLY模式 starredFolder.open(Folder.READ_ONLY) val starredMails = starredFolder.getMessages()
方案B:不确定路径时,递归遍历全量文件夹匹配
如果不知道服务商的具体路径,递归获取所有层级的文件夹后匹配名称即可:
val rootFolder = store.getFolder("") // 递归列出所有层级、包括未订阅的文件夹 val allFolders = rootFolder.list("*", true) // 匹配名称含"Starred"或中文"星标邮件"的文件夹 val starredFolder = allFolders.find(_.fullName.matches(".*(Starred|星标邮件).*")) starredFolder match { case Some(folder) => { folder.open(Folder.READ_ONLY) val starredMails = folder.getMessages() } case None => { // 未找到独立文件夹的情况:部分服务商的星标是邮件标记,不是独立文件夹 // 此时遍历所有文件夹,搜索带FLAGGED标记的星标邮件 val allStarredMails = allFolders.flatMap { folder => folder.open(Folder.READ_ONLY) val flaggedMails = folder.search( new FlagTerm(new Flags(Flags.Flag.FLAGGED), true) ) folder.close(false) flaggedMails } } }
注意事项
- QQ邮箱需要先在网页端「设置-账号」的IMAP服务配置页,勾选「星标邮件」为IMAP可见,否则无论怎么配置代码都无法获取该文件夹
- Gmail的星标文件夹固定存放在
[Gmail]层级下,根目录列表默认不会显示,必须递归遍历才能拿到 - 如果访问未订阅的星标文件夹报权限错误,先调用
starredFolder.setSubscribed(true)订阅后再打开 - 部分服务商(如早期Outlook)不提供独立星标文件夹,星标仅作为邮件的
FLAGGED标记存在,这种情况不要硬找独立文件夹,直接用FlagTerm搜索即可
内容的提问来源于stack exchange,提问作者赵春宇
相关产品推荐
相关产品推荐

