You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring Boot应用中实现Outlook新邮件持续监听与附件下载?

实现方案总览

可选实现库

  • Jakarta Mail(原JavaMail):通用邮件协议实现,支持IMAP/SMTP等标准协议,适配绝大多数支持IMAP的邮件服务包括Outlook,无需额外对接第三方API
  • Spring Integration Mail:Spring生态封装的邮件处理模块,可实现邮件通道监听、自动消费,适合集成到Spring Boot项目
  • Microsoft Graph Java SDK:微软官方提供的Outlook/Exchange服务API,支持现代身份认证,适合企业级Outlook 365场景的深度集成

基于Jakarta Mail + Spring Boot 示例实现

前置要求

Outlook账号开启IMAP协议,个人账号需在安全设置中开启应用密码(替代普通登录密码),企业账号需确认管理员开放IMAP访问权限

第一步:引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>jakarta.mail</artifactId>
    <version>2.0.1</version>
</dependency>

第二步:配置application.yml

mail:
  outlook:
    host: imap.outlook.com
    port: 993
    username: 你的Outlook邮箱地址
    password: 你的应用密码/邮箱密码
    ssl-enable: true
    # 音频附件存储路径
    audio-save-path: /data/email-audio/
    # 定时任务间隔 单位毫秒
    fetch-interval: 30000

第三步:核心处理代码

import jakarta.mail.*;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.search.FlagTerm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.Properties;

@Component
@EnableScheduling
public class OutlookMailListener {

    @Value("${mail.outlook.host}")
    private String imapHost;
    @Value("${mail.outlook.port}")
    private Integer imapPort;
    @Value("${mail.outlook.username}")
    private String username;
    @Value("${mail.outlook.password}")
    private String password;
    @Value("${mail.outlook.ssl-enable}")
    private Boolean sslEnable;
    @Value("${mail.outlook.audio-save-path}")
    private String audioSavePath;

    // 支持的音频格式后缀,可自行扩展
    private static final String[] AUDIO_SUFFIX = {"mp3", "wav", "flac", "aac", "ogg"};

    @Scheduled(fixedRateString = "${mail.outlook.fetch-interval}")
    public void fetchUnreadMail() {
        Store store = null;
        Folder inbox = null;
        try {
            // 1. 配置IMAP连接参数
            Properties props = new Properties();
            props.put("mail.store.protocol", "imaps");
            props.put("mail.imaps.host", imapHost);
            props.put("mail.imaps.port", imapPort);
            props.put("mail.imaps.ssl.enable", sslEnable);
            props.put("mail.imaps.auth", "true");

            // 2. 连接邮箱服务器
            Session session = Session.getInstance(props);
            store = session.getStore("imaps");
            store.connect(username, password);

            // 3. 打开收件箱,读写模式
            inbox = store.getFolder("INBOX");
            inbox.open(Folder.READ_WRITE);

            // 4. 搜索所有未读邮件
            Message[] unreadMessages = inbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
            for (Message message : unreadMessages) {
                // 5. 处理邮件附件
                Object content = message.getContent();
                if (content instanceof Multipart multipart) {
                    for (int i = 0; i < multipart.getCount(); i++) {
                        BodyPart bodyPart = multipart.getBodyPart(i);
                        if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
                            String fileName = bodyPart.getFileName();
                            // 校验是否为音频文件
                            if (isAudioFile(fileName)) {
                                // 下载到本地路径
                                File saveDir = new File(audioSavePath);
                                if (!saveDir.exists()) saveDir.mkdirs();
                                File saveFile = new File(saveDir, System.currentTimeMillis() + "_" + fileName);
                                ((MimeBodyPart) bodyPart).saveFile(saveFile);
                            }
                        }
                    }
                }
                // 6. 标记邮件为已读
                message.setFlag(Flags.Flag.SEEN, true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 7. 关闭资源
            try {
                if (inbox != null) inbox.close(false);
                if (store != null) store.close();
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 校验是否为音频文件
     */
    private boolean isAudioFile(String fileName) {
        if (fileName == null || fileName.isEmpty()) return false;
        String lowerFileName = fileName.toLowerCase();
        for (String suffix : AUDIO_SUFFIX) {
            if (lowerFileName.endsWith("." + suffix)) {
                return true;
            }
        }
        return false;
    }
}

注意事项

  • 若使用企业版Outlook 365且开启了多因素认证,建议切换为Microsoft Graph SDK实现,避免IMAP协议认证失败
  • 生产环境建议增加邮件Message-ID持久化逻辑,避免因标记已读失败导致的附件重复下载
  • 可根据实际需求调整定时任务执行间隔,避免频繁请求邮件服务器被限制访问
  • 附件下载逻辑可增加大小校验、MIME类型二次校验提升安全性

内容的提问来源于stack exchange,提问作者YoBuss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 03:06:05