最新资讯

  • Java邮件编程全指南:从入门到精通

Java邮件编程全指南:从入门到精通

2026-01-31 05:26:14 栏目:最新资讯 2 阅读

这是一份非常详细、实用、通俗易懂、权威且全面的 Java 邮件编程指南。希望这篇文章能对你有帮助,关注我,你的肯定就是我输出的最大动力!


目录

  1. 邮件基础与协议

    • 1.1 邮件是如何工作的?
    • 1.2 SMTP (简单邮件传输协议)
    • 1.3 POP3 (邮局协议第3版)
    • 1.4 IMAP (互联网消息访问协议)
    • 1.5 SMTP vs POP3 vs IMAP
    • 1.6 MIME (多用途互联网邮件扩展)
  2. JavaMail API 概览

    • 2.1 JavaMail 是什么?
    • 2.2 核心组件介绍
      • Session
      • Message
      • Transport (发送)
      • Store (接收)
      • Folder
    • 2.3 依赖引入 (Maven / Gradle / JARs)
  3. 配置与发送邮件 (SMTP)

    • 3.1 设置 Session 属性
      • 3.1.1 基本属性 (mail.smtp.host, mail.smtp.port)
      • 3.1.2 身份验证 (mail.smtp.auth)
      • 3.1.3 传输层安全 (mail.smtp.starttls.enable, mail.smtp.ssl.enable)
      • 3.1.4 调试 (mail.debug)
    • 3.2 创建邮件消息 (Message)
      • 3.2.1 设置发件人、收件人、抄送、密送 (From, To, Cc, Bcc)
      • 3.2.2 设置主题 (Subject)
      • 3.2.3 设置正文 (setText / setContent)
      • 3.2.4 设置日期 (setSentDate)
      • 3.2.5 设置邮件头 (自定义头信息)
    • 3.3 发送邮件 (Transport)
    • 3.4 发送纯文本邮件 (完整示例代码)
    • 3.5 发送 HTML 邮件
    • 3.6 发送带附件的邮件 (Multipart, MimeBodyPart)
    • 3.7 发送带内嵌图片的 HTML 邮件 (Content-ID)
    • 3.8 常见 SMTP 服务器配置示例 (Gmail, QQ, 163, 企业邮箱)
  4. 接收邮件 (POP3 / IMAP)

    • 4.1 设置 Session 属性 (接收侧)
      • 4.1.1 POP3 (mail.pop3.host, mail.pop3.port, mail.pop3.starttls.enable, mail.pop3.ssl.enable)
      • 4.1.2 IMAP (mail.imap.host, mail.imap.port, mail.imap.starttls.enable, mail.imap.ssl.enable)
    • 4.2 连接到邮件存储 (Store)
    • 4.3 打开邮箱文件夹 (Folder)
      • 4.3.1 常见文件夹 (INBOX, Sent, Drafts, Trash)
      • 4.3.2 文件夹访问模式 (READ_ONLY, READ_WRITE)
    • 4.4 获取邮件列表
    • 4.5 解析邮件内容 (Message)
      • 4.5.1 获取发件人、收件人、主题、日期
      • 4.5.2 获取纯文本正文 (getContent / getInputStream)
      • 4.5.3 获取 HTML 正文
      • 4.5.4 获取附件 (Multipart, BodyPart, getContentType, getDisposition, getInputStream, saveFile)
    • 4.6 使用 POP3 接收邮件 (完整示例代码)
    • 4.7 使用 IMAP 接收邮件 (完整示例代码)
    • 4.8 搜索邮件 (Folder.search(SearchTerm term))
    • 4.9 删除邮件 (message.setFlag(Flags.Flag.DELETED, true), folder.expunge())
    • 4.10 邮件回复
    • 4.11 邮件抄送与密送
    • 1.12 邮件转发
    • 4.13 邮件附件下载
    • 4.14 邮件标记已读与未读
    • 4.15 邮件回执
  5. 处理复杂邮件结构与 MIME

    • 5.1 Multipart 深入理解
    • 5.2 MimeBodyPart 详解
    • 5.3 内容类型 (Content-Type) 详解 (text/plain, text/html, image/jpeg, application/pdf, multipart/mixed, multipart/alternative, multipart/related)
    • 5.4 内容传输编码 (Content-Transfer-Encoding) (7bit, 8bit, base64, quoted-printable)
    • 5.5 内容处置 (Content-Disposition) (inline, attachment)
    • 5.6 处理嵌套的 Multipart 结构
  6. 安全性与最佳实践

    • 6.1 SSL/TLS 加密的重要性
    • 6.2 安全地存储密码 (避免硬编码)
    • 6.3 处理敏感信息
    • 6.4 防范邮件注入攻击
    • 6.5 连接池与资源管理 (TransportStore 的关闭)
    • 6.6 错误处理与重试机制
    • 6.7 日志记录
  7. 常见问题与故障排除

    • 7.1 认证失败 (AuthenticationFailedException)
    • 7.2 连接超时 (ConnectException)
    • 7.3 SSL/TLS 证书问题 (SSLHandshakeException)
    • 7.4 端口被阻止 (防火墙)
    • 7.5 附件无法下载或显示
    • 7.6 HTML 邮件样式丢失
    • 7.7 中文乱码问题 (字符集设置)
  8. 完整系统案例

    • 案例一:邮件发送工具类 (支持文本、HTML、附件、图片)
    • 案例二:邮件接收监控服务 (IMAP IDLE/Polling)
    • 案例三:简单的邮件客户端 (命令行或 Swing)
    • 案例四:Spring Boot 集成邮件发送

1. 邮件基础与协议

要理解 Java 邮件编程,首先要明白电子邮件系统是如何工作的。它依赖于一系列标准协议。

  • 1.1 邮件是如何工作的?

    • 当你发送邮件时,你的邮件客户端 (如 Outlook, Thunderbird) 或应用程序使用 SMTP 协议将邮件发送到你的邮件服务器 (SMTP Server)。
    • 你的邮件服务器再将邮件通过 SMTP 协议转发给收件人的邮件服务器。
    • 收件人使用邮件客户端或应用程序,通过 POP3IMAP 协议连接到他们的邮件服务器来下载或查看邮件。
    • MIME 定义了邮件内容的格式,如文本、HTML、图片、附件等如何编码和在邮件中表示。
  • 1.2 SMTP (简单邮件传输协议)

    • 作用: 负责将邮件从发送方传输到接收方的邮件服务器。只负责发送
    • 端口: 默认端口 25 (非加密)。安全端口 465 (SSL) 或 587 (STARTTLS)。
    • 过程: 建立连接 -> 身份验证 (可选) -> 发送邮件信息 (MAIL FROM, RCPT TO, DATA) -> 断开连接。
    • Java 对应: Transport 类。
  • 1.3 POP3 (邮局协议第3版)

    • 作用: 允许邮件客户端从邮件服务器下载邮件。通常下载后会从服务器删除邮件 (可配置)。
    • 端口: 默认端口 110 (非加密)。安全端口 995 (SSL)。
    • 特点: 简单,离线访问为主。邮件通常存储在本地。不支持多文件夹同步。
    • Java 对应: Store 类 (连接 POP3 服务器)。
  • 1.4 IMAP (互联网消息访问协议)

    • 作用: 允许邮件客户端访问邮件服务器上的邮件。邮件保留在服务器上。支持同步多个客户端的状态、文件夹管理、邮件搜索等。
    • 端口: 默认端口 143 (非加密)。安全端口 993 (SSL)。
    • 特点: 更强大,支持在线和离线操作。邮件状态 (已读/未读、星标等) 在服务器同步。
    • Java 对应: Store 类 (连接 IMAP 服务器)。
  • 1.5 SMTP vs POP3 vs IMAP

    协议方向主要功能邮件存储位置特点
    SMTP发送发送邮件-发送端使用
    POP3接收下载邮件本地简单,离线为主
    IMAP接收访问和同步邮件服务器功能强大,支持同步
  • 1.6 MIME (多用途互联网邮件扩展)

    • 作用: 扩展了原始只能发送纯文本的邮件协议 (RFC 822),允许在邮件中包含:
      • 非文本内容 (图片、音频、视频、应用程序文件等)。
      • 多语言字符集 (解决乱码)。
      • 富文本格式 (HTML)。
      • 组合内容 (正文+附件,正文+内嵌图片)。
    • 核心概念:
      • Content-Type: 定义内容的类型和子类型 (如 text/plain, text/html, image/jpeg, multipart/mixed)。
      • Content-Transfer-Encoding: 定义内容如何编码以便安全传输 (如 7bit, 8bit, base64, quoted-printable)。
      • Content-Disposition: 指示内容如何显示 (inline - 内嵌在邮件中显示, attachment - 作为附件下载)。
      • Multipart: MIME 消息可以包含多个部分 (BodyPart),每个部分有自己的头信息和内容。multipart/mixed 用于混合独立部分 (如正文+附件),multipart/alternative 用于同一内容的不同版本 (如纯文本+HTML),multipart/related 用于相关资源 (如 HTML + 内嵌图片)。
    • Java 对应: MimeMessage, MimeMultipart, MimeBodyPart 类。

2. JavaMail API 概览

  • 2.1 JavaMail 是什么? JavaMail API 是 Java 平台的一个标准扩展 (JSR 919),提供了一套独立于协议的框架和抽象,用于构建邮件和消息应用程序。它封装了 SMTP、POP3、IMAP 等协议的底层细节,开发者可以使用统一的 API 来发送和接收邮件。

  • 2.2 核心组件介绍

    • Session (会话):
      • 邮件操作的核心配置点。
      • 包含连接邮件服务器所需的所有属性 (主机名、端口、用户名、密码、协议、加密设置等)。
      • 通过 Properties 对象或 Authenticator 对象创建。
      • Session session = Session.getInstance(properties, authenticator);
    • Message (消息):
      • 表示一封邮件。
      • 通常是 MimeMessage (支持 MIME 格式)。
      • 包含发件人、收件人、主题、正文、日期、邮件头等信息。
      • Message message = new MimeMessage(session);
    • Transport (传输):
      • 用于发送邮件。
      • 与 SMTP 服务器通信。
      • 通过 Session 获得:Transport transport = session.getTransport("smtp");
      • 使用方法:transport.connect(); -> transport.sendMessage(message, message.getAllRecipients()); -> transport.close();
    • Store (存储):
      • 用于访问邮件存储 (邮箱)。
      • 与 POP3 或 IMAP 服务器通信。
      • 通过 Session 获得:Store store = session.getStore("imap");Store store = session.getStore("pop3");
      • 使用方法:store.connect(username, password); -> 打开 Folder -> 操作邮件 -> 关闭 Folder -> store.close();
    • Folder (文件夹):
      • 代表邮箱中的一个文件夹 (如 INBOX, Sent Mail)。
      • 通过 Store 获得:Folder folder = store.getFolder("INBOX");
      • 使用方法:folder.open(Folder.READ_ONLY);folder.open(Folder.READ_WRITE); -> 获取邮件 (Message[] messages = folder.getMessages();) -> 操作邮件 -> folder.close(false); (false 表示不删除标记为 DELETED 的邮件) 或 folder.close(true); (true 表示删除标记为 DELETED 的邮件)。
  • 2.3 依赖引入 JavaMail API 不是标准 Java SE 的一部分,需要额外引入。

    • 官方 JARs: 从 JavaMail Project 下载 javax.mail.jar
    • Maven:
      
          com.sun.mail
          javax.mail
          1.6.2 
      
      
    • Gradle:
      implementation 'com.sun.mail:javax.mail:1.6.2' // 请检查最新版本
      
    • 另外,处理邮件内容 (如解析 HTML) 可能还需要引入其他库,如 javax.activation:activation (用于 MIME 类型处理和数据源),但在较新版本中可能已包含或使用其他实现。

3. 配置与发送邮件 (SMTP)

  • 3.1 设置 Session 属性 创建一个 Properties 对象来配置 Session

    Properties props = new Properties();
    
    • 3.1.1 基本属性:
      props.put("mail.smtp.host", "smtp.example.com"); // SMTP服务器地址
      props.put("mail.smtp.port", "587"); // SMTP服务器端口 (25, 465, 587)
      
    • 3.1.2 身份验证: (大多数服务器需要)
      props.put("mail.smtp.auth", "true"); // 启用认证
      
    • 3.1.3 传输层安全:
      • SSL: 直接使用 SSL 加密连接 (端口通常是 465)
        props.put("mail.smtp.ssl.enable", "true"); // 启用 SSL
        // 如果使用 SSL, 端口通常设置为 465
        props.put("mail.smtp.port", "465");
        
      • STARTTLS: 先建立非加密连接,然后升级到加密 (端口通常是 25 或 587)
        props.put("mail.smtp.starttls.enable", "true"); // 启用 STARTTLS
        // 端口通常为 587
        props.put("mail.smtp.port", "587");
        
    • 3.1.4 调试: (开发时很有用)
      props.put("mail.debug", "true"); // 启用调试输出
      

    创建带认证的 Session:

    Session session = Session.getInstance(props, new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication("your_username@example.com", "your_password");
        }
    });
    

    或者使用更简洁的方式 (Java 8+):

    Session session = Session.getInstance(props, new javax.mail.Authenticator() {
        protected javax.mail.PasswordAuthentication getPasswordAuthentication() {
            return new javax.mail.PasswordAuthentication(username, password);
        }
    });
    
  • 3.2 创建邮件消息 (Message) 使用 MimeMessage 类。

    Message message = new MimeMessage(session);
    
    • 3.2.1 设置发件人、收件人、抄送、密送:
      // 设置发件人 (可以是字符串或 Address 对象)
      message.setFrom(new InternetAddress("sender@example.com"));
      
      // 设置主收件人 (To)
      message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("recipient1@example.com, recipient2@example.com"));
      
      // 设置抄送 (Cc)
      message.setRecipients(Message.RecipientType.CC, InternetAddress.parse("cc@example.com"));
      
      // 设置密送 (Bcc)
      message.setRecipients(Message.RecipientType.BCC, InternetAddress.parse("bcc@example.com"));
      
      InternetAddress.parse 可以解析逗号分隔的地址列表。
    • 3.2.2 设置主题:
      message.setSubject("这是一封测试邮件主题");
      
    • 3.2.3 设置正文:
      • 纯文本:
      • HTML 内容 (稍后详细讲解):
        message.setContent("

        HTML 内容

        这是一封包含 HTML 格式的邮件。

        ", "text/html; charset=UTF-8");
    • 3.2.4 设置日期: (可选,默认是当前时间)
      message.setSentDate(new Date());
      
    • 3.2.5 设置邮件头: (自定义头信息,非必须)
      message.setHeader("X-Custom-Header", "MyValue");
      
  • 3.3 发送邮件 (Transport)

    try (Transport transport = session.getTransport()) {
        // 连接服务器 (如果 Session 属性中设置了用户名密码,这里通常不需要再提供)
        transport.connect(); // 或者 transport.connect(username, password); 如果 Session 未设置认证
        // 发送邮件
        transport.sendMessage(message, message.getAllRecipients());
        System.out.println("邮件发送成功!");
    } catch (MessagingException e) {
        e.printStackTrace(); // 处理发送异常
    }
    // 使用 try-with-resources 确保 Transport 自动关闭
    
  • 3.4 发送纯文本邮件 (完整示例代码)

    import java.util.Properties;
    import javax.mail.*;
    import javax.mail.internet.InternetAddress;
    import javax.mail.internet.MimeMessage;
    
    public class SimpleTextMailSender {
    
        public static void main(String[] args) {
            // 邮件服务器配置
            String host = "smtp.example.com"; // 替换为你的SMTP服务器
            int port = 587; // 常用端口 25(非SSL), 465(SSL), 587(STARTTLS)
            String username = "your_username@example.com"; // 替换为你的邮箱用户名
            String password = "your_password"; // 替换为你的邮箱密码/授权码
            String from = "sender@example.com"; // 发件人地址
            String to = "recipient@example.com"; // 收件人地址
    
            // 设置属性
            Properties props = new Properties();
            props.put("mail.smtp.host", host);
            props.put("mail.smtp.port", port);
            props.put("mail.smtp.auth", "true"); // 启用认证
            props.put("mail.smtp.starttls.enable", "true"); // 启用 STARTTLS (对于端口587)
    
            // 创建会话
            Session session = Session.getInstance(props, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
    
            try {
                // 创建邮件
                Message message = new MimeMessage(session);
                message.setFrom(new InternetAddress(from));
                message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
                message.setSubject("JavaMail 纯文本测试邮件");
                message.setText("你好,
    
    这是一封使用 JavaMail API 发送的纯文本测试邮件。
    
    祝好!");
    
                // 发送邮件
                Transport.send(message); // 简化发送方式 (内部处理 Transport)
    
                System.out.println("纯文本邮件发送成功!");
    
            } catch (MessagingException e) {
                throw new RuntimeException("邮件发送失败", e);
            }
        }
    }
    
  • 3.5 发送 HTML 邮件 修改正文设置部分:

    String htmlContent = ""
            + "

    HTML 邮件测试

    " + "

    这是一封HTML格式的邮件。

    " + "

    可以包含 样式 和 链接。

    " + ""; message.setContent(htmlContent, "text/html; charset=UTF-8");

    注意:某些邮件客户端可能只显示纯文本版本或限制部分 HTML/CSS。确保提供良好的降级体验或同时提供纯文本版本 (见 Multipart/alternative)。

  • 3.6 发送带附件的邮件 需要使用 MimeMultipartMimeBodyPart 来组合多个部分。

    import javax.mail.internet.MimeMultipart;
    import javax.mail.internet.MimeBodyPart;
    import javax.activation.DataHandler;
    import javax.activation.FileDataSource;
    import java.io.File;
    
    // ... (Session 和 Message 创建同上)
    
    // 创建一个多部分消息
    MimeMultipart multipart = new MimeMultipart();
    
    // 创建文本正文部分
    MimeBodyPart textPart = new MimeBodyPart();
    textPart.setText("邮件正文内容,附件在下面。"); // 或使用 setContent 设置 HTML
    multipart.addBodyPart(textPart);
    
    // 创建附件部分
    MimeBodyPart attachmentPart = new MimeBodyPart();
    File file = new File("/path/to/your/file.pdf"); // 附件文件路径
    FileDataSource source = new FileDataSource(file);
    attachmentPart.setDataHandler(new DataHandler(source));
    attachmentPart.setFileName(file.getName()); // 设置附件显示的文件名
    multipart.addBodyPart(attachmentPart);
    
    // 将多部分内容设置为邮件内容
    message.setContent(multipart);
    
    // ... (发送邮件同上)
    
  • 3.7 发送带内嵌图片的 HTML 邮件 原理:将图片作为 BodyPart 嵌入,并设置其 Content-ID,然后在 HTML 中使用 cid:ContentID 引用。

    // ... (Session 和 Message 创建同上)
    
    // 创建一个多部分消息 (使用 'related' 类型表示内嵌资源相关)
    MimeMultipart multipart = new MimeMultipart("related");
    
    // 创建 HTML 正文部分 (父部分)
    MimeBodyPart htmlPart = new MimeBodyPart();
    
    // HTML 内容,引用图片的 cid
    String htmlContent = ""
            + "

    包含图片的邮件

    " + "

    图片内嵌在邮件中:

    " + "" // 注意 https://blog.csdn.net/suodasheng/article/details/cid:image1 + ""; htmlPart.setContent(htmlContent, "text/html; charset=UTF-8"); multipart.addBodyPart(htmlPart); // 创建图片部分 (附件,但设置为内嵌) MimeBodyPart imagePart = new MimeBodyPart(); File imageFile = new File("/path/to/image.jpg"); FileDataSource imageSource = new FileDataSource(imageFile); imagePart.setDataHandler(new DataHandler(imageSource)); imagePart.setHeader("Content-ID", ""); // 设置 Content-ID, 与 HTML 中的 cid 对应 imagePart.setDisposition(MimeBodyPart.INLINE); // 设置为内嵌 multipart.addBodyPart(imagePart); message.setContent(multipart); // ... (发送邮件同上)
  • 3.8 常见 SMTP 服务器配置示例

    • Gmail (使用 App Password):
      • 在 Gmail 设置中启用 IMAP/POP (通常默认启用)。
      • 开启“两步验证”。
      • 生成一个“应用专用密码”。
      • 配置:
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.port", "587");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        // username 是你的完整 Gmail 地址
        // password 是你生成的应用专用密码 (不是你的 Gmail 密码)
        
    • QQ 邮箱:
      • 登录 QQ 邮箱网页版,在“设置”->“账户”中开启 POP3/SMTP 服务。可能需要短信验证。
      • 开启后会获得一个授权码 (不是邮箱密码)。
      • 配置:
        props.put("mail.smtp.host", "smtp.qq.com");
        props.put("mail.smtp.port", "465"); // 或 587 (SSL 或 STARTTLS)
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.ssl.enable", "true"); // 对于端口 465
        // 或者
        // props.put("mail.smtp.port", "587");
        // props.put("mail.smtp.starttls.enable", "true"); // 对于端口 587
        // username 是你的完整 QQ 邮箱地址
        // password 是你获得的授权码
        
    • 163/126 邮箱: 类似 QQ 邮箱,开启 SMTP 服务,使用授权码。
      props.put("mail.smtp.host", "smtp.163.com"); // 或 smtp.126.com
      props.put("mail.smtp.port", "465");
      props.put("mail.smtp.auth", "true");
      props.put("mail.smtp.ssl.enable", "true");
      // username 是你的完整邮箱地址
      // password 是你设置的授权码
      
    • 企业邮箱: 咨询你的企业邮箱管理员获取 SMTP 服务器地址、端口、加密方式、用户名 (可能是完整邮箱或用户名) 和密码 (可能是邮箱密码或特定密码)。

4. 接收邮件 (POP3 / IMAP)

  • 4.1 设置 Session 属性 (接收侧) 创建 Properties 对象。

    Properties props = new Properties();
    
    • 4.1.1 POP3:
      props.put("mail.pop3.host", "pop.example.com"); // POP3服务器地址
      props.put("mail.pop3.port", "995"); // POP3端口 (110非加密, 995 SSL)
      props.put("mail.pop3.ssl.enable", "true"); // 启用SSL (端口995)
      // 或者使用 STARTTLS (较少见)
      // props.put("mail.pop3.port", "110");
      // props.put("mail.pop3.starttls.enable", "true");
      
    • 4.1.2 IMAP:
      props.put("mail.imap.host", "imap.example.com"); // IMAP服务器地址
      props.put("mail.imap.port", "993"); // IMAP端口 (143非加密, 993 SSL)
      props.put("mail.imap.ssl.enable", "true"); // 启用SSL (端口993)
      // 或者使用 STARTTLS
      // props.put("mail.imap.port", "143");
      // props.put("mail.imap.starttls.enable", "true");
      props.put("mail.imap.partialfetch", "false"); // 可选,控制是否只获取邮件部分内容
      

    创建带认证的 Session (与发送类似):

    Session session = Session.getInstance(props, new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication("your_username@example.com", "your_password");
        }
    });
    
  • 4.2 连接到邮件存储 (Store)

    try (Store store = session.getStore("pop3")) { // 或 "imap"
        store.connect(username, password);
        System.out.println("成功连接到邮件存储");
        // ... 后续操作文件夹
    } catch (MessagingException e) {
        e.printStackTrace();
    }
    
  • 4.3 打开邮箱文件夹 (Folder)

    try (Folder folder = store.getFolder("INBOX")) { // 指定文件夹名
        // 打开文件夹 (只读模式)
        folder.open(Folder.READ_ONLY); // 或 Folder.READ_WRITE 允许修改/删除邮件
        System.out.println("邮件总数: " + folder.getMessageCount());
        System.out.println("新邮件数: " + folder.getNewMessageCount()); // 仅 IMAP 支持新邮件计数
        // ... 后续获取邮件
    } // try-with-resources 会自动关闭 Folder
    
    • 4.3.1 常见文件夹: "INBOX" (收件箱), "Sent" (已发送), "Drafts" (草稿), "Trash" (垃圾箱/已删除), "Spam" (垃圾邮件)。名称可能因服务器和语言设置而异。IMAP 支持列出所有文件夹 (store.getDefaultFolder().list())。
    • 4.3.2 文件夹访问模式:
      • Folder.READ_ONLY: 只读,不能修改邮件。
      • Folder.READ_WRITE: 可读写,可以修改邮件状态、删除邮件等。
    • 4.3.3 IMAP支持文件夹管理。原理:使用Folder类创建、重命名或移动文件夹。代码示例:
      Store store = session.getStore();
      store.connect("your-email@example.com", "your-password");
      
      // 获取根文件夹
      Folder root = store.getDefaultFolder();
      Folder[] folders = root.list(); // 列出所有文件夹
      
      // 创建新文件夹
      Folder newFolder = root.getFolder("Work");
      if (!newFolder.exists()) {
          newFolder.create(Folder.HOLDS_MESSAGES); // 创建文件夹
      }
      
      // 重命名文件夹
      Folder oldFolder = root.getFolder("Old");
      oldFolder.renameTo(newFolder);
      
      // 移动邮件到文件夹
      Message message = folder.getMessage(1); // 获取邮件
      folder.copyMessages(new Message[]{message}, newFolder); // 复制到新文件夹
      
      store.close();
       
      
  • 4.4 获取邮件列表

    // 获取所有邮件 (谨慎使用,邮件多时可能慢)
    Message[] messages = folder.getMessages();
    // 获取指定范围的邮件 (例如最新10封)
    int start = Math.max(1, folder.getMessageCount() - 9); // 邮件编号从1开始
    int end = folder.getMessageCount();
    Message[] recentMessages = folder.getMessages(start, end);
    
  • 4.5 解析邮件内容 (Message)

    for (Message message : messages) {
        // 4.5.1 获取基本信息
        Address[] fromAddresses = message.getFrom();
        String from = (fromAddresses != null && fromAddresses.length > 0) ? fromAddresses[0].toString() : "未知";
        Address[] toAddresses = message.getRecipients(Message.RecipientType.TO);
        String toList = (toAddresses != null) ? InternetAddress.toString(toAddresses) : "";
        String subject = message.getSubject();
        Date sentDate = message.getSentDate();
    
        System.out.println("邮件 #" + message.getMessageNumber());
        System.out.println("发件人: " + from);
        System.out.println("收件人: " + toList);
        System.out.println("主题: " + subject);
        System.out.println("发送日期: " + sentDate);
    
        // 4.5.2 获取纯文本正文
        Object content = message.getContent();
        if (content instanceof String) {
            // 简单文本邮件
            String textContent = (String) content;
            System.out.println("正文:
    " + textContent);
        } else if (content instanceof MimeMultipart) {
            // 复杂邮件 (多部分)
            MimeMultipart multipart = (MimeMultipart) content;
            handleMultipart(multipart); // 调用处理多部分的方法 (见下文)
        }
    
        System.out.println("------------------------------------");
    }
    

    处理多部分邮件的方法 (handleMultipart):

    private static void handleMultipart(MimeMultipart multipart) throws Exception {
        int partCount = multipart.getCount();
        for (int i = 0; i < partCount; i++) {
            BodyPart bodyPart = multipart.getBodyPart(i);
            String disposition = bodyPart.getDisposition();
            String contentType = bodyPart.getContentType();
    
            // 4.5.3 获取 HTML 正文 / 4.5.4 获取附件
            if (disposition != null && (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))) {
                // 这是一个附件或内嵌资源
                String fileName = bodyPart.getFileName();
                if (fileName != null) {
                    fileName = MimeUtility.decodeText(fileName); // 解码可能的编码文件名
                }
                System.out.println("附件/资源: " + fileName + " (类型: " + contentType + ")");
    
                // 保存附件到文件
                saveAttachment(bodyPart, "/path/to/save/dir", fileName);
            } else {
                // 可能是文本正文 (纯文本或 HTML)
                Object partContent = bodyPart.getContent();
                if (partContent instanceof String) {
                    if (contentType.toLowerCase().contains("text/html")) {
                        System.out.println("HTML 正文:
    " + partContent);
                    } else if (contentType.toLowerCase().contains("text/plain")) {
                        System.out.println("纯文本正文:
    " + partContent);
                    } else {
                        System.out.println("其他文本内容 (" + contentType + "):
    " + partContent);
                    }
                } else if (partContent instanceof MimeMultipart) {
                    // 嵌套的多部分 (递归处理)
                    handleMultipart((MimeMultipart) partContent);
                }
            }
        }
    }
    

    保存附件的方法 (saveAttachment):

    private static void saveAttachment(BodyPart bodyPart, String saveDir, String fileName) throws Exception {
        if (fileName == null || fileName.isEmpty()) {
            fileName = "attachment_" + System.currentTimeMillis() + ".dat";
        }
        File saveFile = new File(saveDir, fileName);
        try (InputStream is = bodyPart.getInputStream();
             FileOutputStream fos = new FileOutputStream(saveFile)) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }
            System.out.println("附件已保存到: " + saveFile.getAbsolutePath());
        }
    }
    
  • 4.6 使用 POP3 接收邮件 (完整示例代码)

    import java.util.Properties;
    import javax.mail.*;
    import javax.mail.internet.InternetAddress;
    import javax.mail.internet.MimeUtility;
    
    public class POP3MailReceiver {
    
        public static void main(String[] args) {
            // 邮件服务器配置
            String host = "pop.example.com"; // POP3服务器
            int port = 995; // POP3 SSL端口
            String username = "your_username@example.com";
            String password = "your_password";
            String saveDir = "/path/to/save/attachments";
    
            Properties props = new Properties();
            props.put("mail.pop3.host", host);
            props.put("mail.pop3.port", port);
            props.put("mail.pop3.ssl.enable", "true");
    
            Session session = Session.getInstance(props, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
    
            try (Store store = session.getStore("pop3")) {
                store.connect();
    
                try (Folder folder = store.getFolder("INBOX")) {
                    folder.open(Folder.READ_ONLY);
    
                    Message[] messages = folder.getMessages();
                    System.out.println("收件箱中共有 " + messages.length + " 封邮件");
    
                    for (Message message : messages) {
                        // 解析并打印邮件基本信息 (如前面4.5.1部分)
                        // ...
                        // 处理邮件内容 (调用 handleMultipart 或直接处理)
                        Object content = message.getContent();
                        if (content instanceof String) {
                            System.out.println("正文:
    " + content);
                        } else if (content instanceof MimeMultipart) {
                            handleMultipart((MimeMultipart) content, saveDir);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private static void handleMultipart(MimeMultipart multipart, String saveDir) throws Exception {
            // ... (实现如前面 handleMultipart 方法)
        }
    
        private static void saveAttachment(BodyPart bodyPart, String saveDir, String fileName) throws Exception {
            // ... (实现如前面 saveAttachment 方法)
        }
    }
    
  • 4.7 使用 IMAP 接收邮件 (完整示例代码) 结构与 POP3 示例非常相似,主要区别在于 Store 协议和 Folder 操作 (IMAP 支持更多功能如搜索、标记)。

    import java.util.Properties;
    import javax.mail.*;
    
    public class IMAPMailReceiver {
    
        public static void main(String[] args) {
            // 邮件服务器配置
            String host = "imap.example.com"; // IMAP服务器
            int port = 993; // IMAP SSL端口
            String username = "your_username@example.com";
            String password = "your_password";
            String saveDir = "/path/to/save/attachments";
    
            Properties props = new Properties();
            props.put("mail.imap.host", host);
            props.put("mail.imap.port", port);
            props.put("mail.imap.ssl.enable", "true");
            props.put("mail.imap.partialfetch", "false"); // 获取完整邮件
    
            Session session = Session.getInstance(props, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
    
            try (Store store = session.getStore("imap")) {
                store.connect();
    
                try (Folder folder = store.getFolder("INBOX")) {
                    folder.open(Folder.READ_ONLY);
    
                    // 获取所有邮件
                    Message[] messages = folder.getMessages();
                    // 或者使用搜索
                    // SearchTerm term = new SubjectTerm("重要");
                    // Message[] messages = folder.search(term);
    
                    for (Message message : messages) {
                        // 解析邮件 (同 POP3 示例)
                        // ...
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // ... handleMultipart 和 saveAttachment 方法同上
    }
    
  • 4.8 搜索邮件 (IMAP 优势) IMAP 支持强大的搜索功能。使用 SearchTerm 及其子类构建搜索条件。

    // 搜索主题包含 "报告" 的邮件
    SearchTerm subjectTerm = new SubjectTerm("报告");
    // 搜索来自特定发件人的邮件
    SearchTerm fromTerm = new FromTerm(new InternetAddress("boss@company.com"));
    // 搜索未读邮件
    SearchTerm unseenTerm = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
    // 组合搜索条件 (AND)
    SearchTerm andTerm = new AndTerm(subjectTerm, fromTerm);
    // 组合搜索条件 (OR)
    SearchTerm orTerm = new OrTerm(subjectTerm, fromTerm);
    
    Message[] foundMessages = folder.search(searchTerm);
    
  • 4.9 删除邮件 (需要 READ_WRITE 模式)

    folder.open(Folder.READ_WRITE); // 必须用读写模式打开才能删除
    message.setFlag(Flags.Flag.DELETED, true); // 将邮件标记为删除
    // 立即删除标记为删除的邮件 (谨慎使用)
    folder.expunge();
    // 或者关闭文件夹时删除
    folder.close(true); // true 表示删除标记为 DELETED 的邮件
    
  • 4.10 邮件回复

       回复邮件时引用原内容。原理:创建新邮件,设置In-Reply-To头。

Message originalMessage = folder.getMessage(1); // 获取原邮件
Message reply = new MimeMessage(session);
reply.setFrom(new InternetAddress("your-email@example.com"));
reply.setRecipients(Message.RecipientType.TO, originalMessage.getFrom());
reply.setSubject("Re: " + originalMessage.getSubject());
// 引用原内容
String content = "回复内容

原邮件:
" + originalMessage.getContent();
reply.setText(content);
// 设置回复头
reply.setHeader("In-Reply-To", originalMessage.getMessageID());
Transport.send(reply);
 
  • 4.10 邮件抄送与密送

       抄送(CC)和密送(BCC)在发送时设置收件人类型。

Message message = new MimeMessage(session);
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("to@example.com"));
message.setRecipients(Message.RecipientType.CC, InternetAddress.parse("cc@example.com")); // 抄送
message.setRecipients(Message.RecipientType.BCC, InternetAddress.parse("bcc@example.com")); // 密送
// 其余发送代码同第三章
 

  • 4.12 邮件转发

       转发邮件将原邮件作为附件发送。原理:创建新邮件,原邮件作为附件。

Message originalMessage = folder.getMessage(1);
Message forward = new MimeMessage(session);
forward.setFrom(new InternetAddress("your-email@example.com"));
forward.setRecipients(Message.RecipientType.TO, InternetAddress.parse("forward@example.com"));
forward.setSubject("转发: " + originalMessage.getSubject());

// 原邮件作为附件
MimeBodyPart attachmentPart = new MimeBodyPart();
attachmentPart.setContent(originalMessage, "message/rfc822"); // 设置邮件类型
attachmentPart.setFileName("original.eml");

Multipart multipart = new MimeMultipart();
multipart.addBodyPart(attachmentPart);
forward.setContent(multipart);
Transport.send(forward);
 
  • 4.13 邮件附件下载

       接收邮件时下载附件。原理:检查邮件内容类型,如果为Multipart,遍历BodyPart获取附件。

import javax.mail.*;
import javax.mail.internet.*;
import java.io.*;

public class AttachmentDownloader {
    public static void main(String[] args) {
        // 使用IMAP接收邮件代码获取Message对象
        try {
            if (message.getContent() instanceof Multipart) {
                Multipart multipart = (Multipart) message.getContent();
                for (int i = 0; i < multipart.getCount(); i++) {
                    BodyPart bodyPart = multipart.getBodyPart(i);
                    if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) {
                        String fileName = bodyPart.getFileName();
                        InputStream is = bodyPart.getInputStream();
                        // 保存附件到本地
                        FileOutputStream fos = new FileOutputStream("downloads/" + fileName);
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = is.read(buffer)) != -1) {
                            fos.write(buffer, 0, bytesRead);
                        }
                        fos.close();
                        is.close();
                        System.out.println("附件下载: " + fileName);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 
  • 4.14 邮件标记已读与未读

       使用IMAP标记邮件状态。原理:设置邮件的SEEN标志。

// 在接收邮件代码中,使用IMAP
Message message = folder.getMessage(i); // 获取邮件
if (!message.isSet(Flags.Flag.SEEN)) {
    message.setFlag(Flags.Flag.SEEN, true); // 标记为已读
}
 
  • 4.15 邮件回执

       邮件回执(Delivery Status Notification)通知发件人邮件是否送达。原理:发送邮件时设置请求回执头,服务器返回状态报告。

// 在发送邮件代码中,添加回执请求
Message message = new MimeMessage(session);
message.setHeader("Disposition-Notification-To", "your-email@example.com"); // 设置回执接收邮箱
// 其余发送代码同第三章
 

5. 处理复杂邮件结构与 MIME

  • 5.1 Multipart 深入理解

    • MultipartPart (如 MimeMessageMimeBodyPart) 内容的一种类型,表示该部分包含多个子部分 (BodyPart)。
    • 常见的 Multipart 子类型:
      • multipart/mixed: 包含独立的子部分。例如,一封包含正文文本和几个附件的邮件。
      • multipart/alternative: 包含表示同一信息的不同版本。例如,一封同时包含纯文本版本和 HTML 版本的邮件。邮件客户端会选择最适合显示给用户的版本。
      • multipart/related: 包含一个根部分 (通常是 HTML) 和与之相关的内嵌资源 (如图片)。根部分使用 cid 引用内嵌资源。
      • multipart/signed: 用于数字签名。
      • multipart/encrypted: 用于加密邮件。
    • 这些子类型可以嵌套。例如,一个 multipart/mixed 可能包含一个 multipart/alternative (用于正文) 和一个 attachment (用于附件)。
  • 5.2 MimeBodyPart 详解

    • 代表 Multipart 中的一个子部分。
    • 包含自己的头信息 (Content-Type, Content-Transfer-Encoding, Content-Disposition, Content-ID 等) 和内容。
    • 内容可以是:
      • 简单文本 (String)
      • 二进制数据 (InputStream / DataSource)
      • 另一个 Multipart (嵌套结构)
      • 一个 Message (表示作为附件包含的完整邮件 - message/rfc822)
  • 5.3 内容类型 (Content-Type) 详解

    • 格式:type/subtype; parameters (如 text/html; charset=UTF-8)。
    • 常见类型:
      • text/plain: 纯文本。
      • text/html: HTML 文本。
      • image/jpeg, image/png, image/gif: 图片。
      • application/pdf, application/msword, application/vnd.ms-excel: 应用程序文件。
      • application/octet-stream: 通用二进制数据。
      • multipart/*: 多部分类型 (如上所述)。
      • message/rfc822: 嵌入的完整邮件。
    • charset 参数对于文本类型非常重要 (如 charset=UTF-8, charset=GBK),指定字符编码,解决乱码问题。
  • 5.4 内容传输编码 (Content-Transfer-Encoding)

    • 用于将二进制或非 ASCII 邮件内容编码为适合在 7-bit SMTP 通道中传输的格式。
    • 常见编码:
      • 7bit: 内容已经是 7-bit ASCII,短行 (<1000字符)。
      • 8bit: 内容包含 8-bit 字符,但行不太长。
      • base64: 将二进制数据编码为 ASCII 字符 (字母、数字、+、/)。效率约为原始数据的 133%。适用于图像、可执行文件等。
      • quoted-printable: 将非 ASCII 字符和特殊字符编码为 = 后跟两个十六进制数字。适用于主要包含 ASCII 字符但包含少量非 ASCII 字符的文本 (如带有重音符号的欧洲语言)。行长度有限制。
  • 5.5 内容处置 (Content-Disposition)

    • 指示邮件客户端如何处理该部分。
    • 常见值:
      • inline: 该部分应在邮件正文中内嵌显示 (如 HTML 中的图片)。
      • attachment: 该部分应作为附件下载,不直接显示在邮件正文中。
    • 通常包含 filename 参数指定附件保存时的默认文件名 (如 Content-Disposition: attachment; filename="report.pdf")。文件名可能需要使用 MimeUtility.decodeText 解码。
  • 5.6 处理嵌套的 Multipart 结构 如前面 handleMultipart 方法所示,需要使用递归来遍历可能的多层嵌套结构。检查每个 BodyPartContent-Type 是否是 multipart/*,如果是,则递归调用处理多部分的方法。

6. 安全性与最佳实践

  • 6.1 SSL/TLS 加密的重要性

    • 始终使用 SSL/TLS (mail.smtp.ssl.enable / mail.smtp.starttls.enable / mail.pop3.ssl.enable / mail.imap.ssl.enable) 来加密邮件传输通道,防止用户名、密码和邮件内容被窃听。
    • 优先使用端口 465 (SMTP SSL), 993 (IMAP SSL), 995 (POP3 SSL) 或启用 STARTTLS 的端口 587 (SMTP), 143 (IMAP)。
  • 6.2 安全地存储密码

    • 切勿将密码硬编码在源代码中。
    • 使用安全的方式存储密码:
      • 环境变量。
      • 配置文件 (确保文件权限安全)。
      • 密钥管理系统 (如 HashiCorp Vault, AWS Secrets Manager)。
      • 在运行时提示用户输入 (对于命令行工具)。
    • 对于 Gmail 等,使用“应用专用密码”而非主密码。
  • 6.3 处理敏感信息

    • 避免在日志中记录完整的邮件内容、附件或敏感邮件头。
    • 对包含敏感数据的邮件正文和附件进行适当处理 (如脱敏、加密存储)。
  • 6.4 防范邮件注入攻击

    • 当使用用户输入构建邮件 (如发件人地址、主题、正文) 时,务必进行严格的输入验证和清理
    • 避免直接将未经验证的用户输入拼接到 SMTP 命令或邮件头中。恶意输入可能注入额外的 SMTP 命令或修改邮件结构。
    • 使用 JavaMail API 的方法 (如 setFrom, setRecipients, setSubject, setText) 来设置字段,它们内部会进行一定的处理。但仍需对输入进行验证。
  • 6.5 连接池与资源管理

    • TransportStore 对象代表网络连接,是有限资源。
    • 总是在使用完毕后关闭它们 (close() 方法)。
    • 使用 try-with-resources 语句 (Java 7+) 确保资源自动关闭,即使在发生异常时。
    • 如果需要频繁发送邮件,考虑使用连接池库 (如 Apache Commons Pool) 来管理 Transport 对象,而不是为每封邮件创建新连接。但需注意服务器可能限制并发连接数。
  • 6.6 错误处理与重试机制

    • 使用 try-catch 捕获 MessagingException 和其他可能的异常 (IOException, RuntimeException 等)。
    • 根据异常类型 (AuthenticationFailedException, SendFailedException, ConnectException 等) 进行不同的处理 (记录错误、通知用户、重试)。
    • 对于暂时性错误 (如网络波动、服务器繁忙),实现重试逻辑 (带退避策略,如指数退避)。
  • 6.7 日志记录

    • 使用日志框架 (如 SLF4J + Logback) 记录关键操作 (连接成功/失败、发送成功/失败、接收邮件数量、错误信息)。
    • 合理设置日志级别 (DEBUG 用于开发调试,INFO 用于常规操作,WARN/ERROR 用于问题和异常)。
    • 开启 mail.debug 属性时,JavaMail 会将详细的协议交互输出到控制台,对调试非常有帮助,但在生产环境中应关闭。

7. 常见问题与故障排除

  • 7.1 认证失败 (AuthenticationFailedException)

    • 原因: 用户名或密码错误;服务器未启用 SMTP/POP3/IMAP 服务;需要应用专用密码 (如 Gmail) 或授权码 (如 QQ/163) 而使用了邮箱密码;账户被锁定。
    • 解决: 仔细检查用户名密码;确认邮箱设置中已开启相应服务;对于 Gmail/QQ/163 等,使用正确的授权方式;尝试在网页邮箱登录验证账户状态。
  • 7.2 连接超时 (ConnectException)

    • 原因: 服务器地址错误;端口错误;服务器宕机;网络不通;防火墙阻止了连接。
    • 解决: 验证服务器地址和端口;使用 telnetnc 命令测试是否能连接到服务器的端口;检查网络连接;检查防火墙设置。
  • 7.3 SSL/TLS 证书问题 (SSLHandshakeException)

    • 原因: 服务器证书不受信任 (自签名证书、证书过期、域名不匹配);Java 运行环境缺少根证书。
    • 解决 (开发/测试): 对于自签名证书,可以临时信任所有证书 (不推荐生产环境):
      props.put("mail.smtp.ssl.trust", "*"); // 信任所有主机
      // 或者更精确地信任特定主机
      // props.put("mail.smtp.ssl.trust", "smtp.example.com");
      
    • 解决 (生产): 将服务器的有效证书导入 Java 的信任库 (cacerts) 或配置应用使用包含该证书的信任库。
  • 7.4 端口被阻止 (防火墙)

    • 原因: 本地防火墙或公司网络防火墙阻止了到邮件服务器端口的出站连接。
    • 解决: 联系网络管理员,请求开放相应的 SMTP (25, 465, 587) / POP3 (110, 995) / IMAP (143, 993) 端口。
  • 7.5 附件无法下载或显示

    • 原因: Content-Disposition 设置不正确;Content-Type 识别错误;文件名编码问题;保存路径权限问题;邮件本身损坏。
    • 解决: 检查代码中附件部分的处理和保存逻辑;使用 MimeUtility.decodeText 解码文件名;检查保存目录是否存在且有写入权限;尝试用其他邮件客户端下载同一附件看是否正常。
  • 7.6 HTML 邮件样式丢失

    • 原因: 邮件客户端对 HTML/CSS 的支持有限 (特别是移动客户端);样式使用了外部 CSS (通常被阻止);样式使用了客户端不支持的 CSS 属性;内嵌图片未正确加载 (cid 引用错误)。
    • 解决: 使用内联 CSS (style="..." 属性);避免使用复杂的 CSS;提供纯文本备选版本 (multipart/alternative);确保内嵌图片的 Content-ID 设置正确且在 HTML 中引用正确。
  • 7.7 中文乱码问题

    • 原因: 邮件头 (主题、发件人/收件人名称) 或正文未正确指定字符集;使用的字符集与邮件客户端解码字符集不一致;附件文件名编码问题。
    • 解决: 在设置主题、正文、附件文件名时,显式指定正确的字符集 (通常是 UTF-8)
      message.setSubject("中文主题", "UTF-8"); // 设置主题和字符集
      message.setText("中文正文", "UTF-8"); // 纯文本
      // HTML
      message.setContent("

      中文

      ", "text/html; charset=UTF-8"); // 附件文件名 attachmentPart.setFileName(MimeUtility.encodeText("中文文件名.pdf", "UTF-8", "B")); // 使用 Base64 或 Q 编码
      接收时,使用 MimeUtility.decodeText 解码可能被编码的字符串。

8. 完整系统案例

  • 案例一:邮件发送工具类 (支持文本、HTML、附件、图片)

    import javax.mail.*;
    import javax.mail.internet.*;
    import javax.activation.*;
    import java.util.*;
    
    public class MailSender {
    
        private Session session;
    
        public MailSender(String host, int port, final String username, final String password, boolean useSSL, boolean useStartTLS) {
            Properties props = new Properties();
            props.put("mail.smtp.host", host);
            props.put("mail.smtp.port", port);
            props.put("mail.smtp.auth", "true");
            if (useSSL) {
                props.put("mail.smtp.ssl.enable", "true");
            } else if (useStartTLS) {
                props.put("mail.smtp.starttls.enable", "true");
            }
    
            this.session = Session.getInstance(props, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
        }
    
        public void sendTextMail(String from, String to, String subject, String text) throws MessagingException {
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(from));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
            message.setSubject(subject, "UTF-8");
            message.setText(text, "UTF-8");
            Transport.send(message);
        }
    
        public void sendHtmlMail(String from, String to, String subject, String htmlContent) throws MessagingException {
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(from));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
            message.setSubject(subject, "UTF-8");
            message.setContent(htmlContent, "text/html; charset=UTF-8");
            Transport.send(message);
        }
    
        public void sendMailWithAttachment(String from, String to, String subject, String text, List attachments) throws MessagingException {
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(from));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
            message.setSubject(subject, "UTF-8");
    
            MimeMultipart multipart = new MimeMultipart();
    
            // 文本部分
            MimeBodyPart textPart = new MimeBodyPart();
            textPart.setText(text, "UTF-8");
            multipart.addBodyPart(textPart);
    
            // 附件部分
            for (Attachment attachment : attachments) {
                MimeBodyPart attachmentPart = new MimeBodyPart();
                attachmentPart.setDataHandler(new DataHandler(new FileDataSource(attachment.getFilePath())));
                attachmentPart.setFileName(MimeUtility.encodeText(attachment.getFileName(), "UTF-8", "B"));
                multipart.addBodyPart(attachmentPart);
            }
    
            message.setContent(multipart);
            Transport.send(message);
        }
    
        public void sendMailWithInlineImages(String from, String to, String subject, String htmlContent, Map cidImageMap) throws MessagingException {
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(from));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
            message.setSubject(subject, "UTF-8");
    
            MimeMultipart multipart = new MimeMultipart("related");
    
            // HTML 部分
            MimeBodyPart htmlPart = new MimeBodyPart();
            htmlPart.setContent(htmlContent, "text/html; charset=UTF-8");
            multipart.addBodyPart(htmlPart);
    
            // 图片部分
            for (Map.Entry entry : cidImageMap.entrySet()) {
                String cid = entry.getKey();
                String imagePath = entry.getValue();
                MimeBodyPart imagePart = new MimeBodyPart();
                imagePart.setDataHandler(new DataHandler(new FileDataSource(imagePath)));
                imagePart.setContentID("<" + cid + ">");
                imagePart.setDisposition(MimeBodyPart.INLINE);
                multipart.addBodyPart(imagePart);
            }
    
            message.setContent(multipart);
            Transport.send(message);
        }
    
        public static class Attachment {
            private String filePath;
            private String fileName;
    
            public Attachment(String filePath, String fileName) {
                this.filePath = filePath;
                this.fileName = fileName;
            }
            // Getters... (省略)
        }
    }
    
  • 案例二:邮件接收监控服务 (IMAP IDLE/Polling) 这是一个更复杂的案例,涉及持续监控邮箱 (使用 IMAP IDLE 指令或定时轮询)。

    import javax.mail.*;
    import javax.mail.event.MessageCountEvent;
    import javax.mail.event.MessageCountListener;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class MailMonitorService {
    
        private final String host;
        private final int port;
        private final String username;
        private final String password;
        private Store store;
        private Folder inbox;
        private ScheduledExecutorService scheduler;
    
        public MailMonitorService(String host, int port, String username, String password) {
            this.host = host;
            this.port = port;
            this.username = username;
            this.password = password;
        }
    
        public void start() throws MessagingException {
            Properties props = new Properties();
            props.put("mail.imap.host", host);
            props.put("mail.imap.port", port);
            props.put("mail.imap.ssl.enable", "true");
    
            Session session = Session.getInstance(props);
            store = session.getStore("imap");
            store.connect(username, password);
    
            inbox = store.getFolder("INBOX");
            inbox.open(Folder.READ_WRITE); // 需要读写权限来标记邮件
    
            // 方式一:使用 IMAP IDLE (服务器推送新邮件通知)
            try {
                if (inbox instanceof IMAPFolder) {
                    IMAPFolder imapFolder = (IMAPFolder) inbox;
                    imapFolder.addMessageCountListener(new MessageCountListener() {
                        @Override
                        public void messagesAdded(MessageCountEvent e) {
                            Message[] newMessages = e.getMessages();
                            processNewMessages(newMessages);
                        }
                        @Override
                        public void messagesRemoved(MessageCountEvent e) {
                            // 处理邮件删除事件
                        }
                    });
                    // 进入 IDLE 模式
                    imapFolder.idle();
                } else {
                    throw new IllegalStateException("IDLE only supported with IMAPFolder");
                }
            } catch (Exception e) {
                // 如果 IDLE 失败或不可用,回退到轮询
                startPolling();
            }
    
            // 方式二:定时轮询 (如果 IDLE 不可用或失败)
            // startPolling();
        }
    
        private void startPolling() {
            scheduler = Executors.newSingleThreadScheduledExecutor();
            scheduler.scheduleAtFixedRate(() -> {
                try {
                    // 检查是否有新邮件
                    if (inbox.hasNewMessages()) { // 这个方法可能不可靠
                        // 更可靠的方式:记录上次检查的UID或邮件数量
                        int oldCount = ...; // 保存上次的邮件数量或最高 UID
                        Message[] newMessages = inbox.getMessages(); // 或者根据 UID 获取新邮件
                        processNewMessages(newMessages);
                        // 更新 oldCount 或 UID
                    }
                } catch (MessagingException e) {
                    e.printStackTrace();
                    // 处理错误,可能需要重新连接
                }
            }, 0, 60, TimeUnit.SECONDS); // 每 60 秒检查一次
        }
    
        private void processNewMessages(Message[] messages) {
            for (Message message : messages) {
                try {
                    // 解析邮件内容 (同前面接收邮件部分)
                    // ...
                    System.out.println("收到新邮件: " + message.getSubject());
                    // 处理邮件业务逻辑...
                    // 标记为已读 (可选)
                    message.setFlag(Flags.Flag.SEEN, true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        public void stop() {
            try {
                if (inbox != null && inbox.isOpen()) {
                    inbox.close(false); // 不删除标记为 DELETED 的邮件
                }
                if (store != null && store.isConnected()) {
                    store.close();
                }
                if (scheduler != null) {
                    scheduler.shutdown();
                }
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        }
    }
    
  • 案例三:简单的邮件客户端 (命令行或 Swing) 这是一个较大的项目框架,涉及用户界面 (命令行菜单或 Swing GUI)、邮件列表展示、邮件查看、发送邮件等功能。核心逻辑复用前面发送和接收邮件的代码块。这里提供一个概念设计:

    • 功能模块:
      • 配置管理 (保存/加载多个邮箱账号配置)。
      • 发送邮件界面 (输入收件人、主题、正文、添加附件)。
      • 接收邮件列表 (展示收件箱邮件主题、发件人、日期)。
      • 邮件查看器 (显示邮件正文、附件列表、下载附件)。
      • 连接管理 (连接/断开 IMAP/POP3/SMTP)。
    • 技术选型:
      • 命令行: Java 控制台输入输出。
      • GUI: Java Swing 或 JavaFX。
    • 核心挑战: 邮件列表的实时刷新 (如使用 MailMonitorService)、富文本正文的渲染、附件的预览等。
  • 案例四:Spring Boot 集成邮件发送 Spring Boot 提供了强大的邮件发送支持 (spring-boot-starter-mail)。 依赖 (Maven):

    
        org.springframework.boot
        spring-boot-starter-mail
    
    

    配置文件 (application.properties):

    spring.mail.host=smtp.example.com
    spring.mail.port=587
    spring.mail.username=your_username@example.com
    spring.mail.password=your_password
    spring.mail.properties.mail.smtp.auth=true
    spring.mail.properties.mail.smtp.starttls.enable=true
    # 可选调试
    spring.mail.properties.mail.debug=true
    

    使用 JavaMailSender:

    import org.springframework.mail.SimpleMailMessage;
    import org.springframework.mail.javamail.JavaMailSender;
    import org.springframework.mail.javamail.MimeMessageHelper;
    import org.springframework.stereotype.Service;
    import javax.mail.MessagingException;
    import javax.mail.internet.MimeMessage;
    import java.io.File;
    
    @Service
    public class EmailService {
    
        private final JavaMailSender mailSender;
    
        public EmailService(JavaMailSender mailSender) {
            this.mailSender = mailSender;
        }
    
        public void sendSimpleMail(String to, String subject, String text) {
            SimpleMailMessage message = new SimpleMailMessage();
            message.setTo(to);
            message.setSubject(subject);
            message.setText(text);
            mailSender.send(message);
        }
    
        public void sendHtmlMail(String to, String subject, String htmlContent) throws MessagingException {
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true for multipart
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(htmlContent, true); // true indicates HTML
            mailSender.send(mimeMessage);
        }
    
        public void sendMailWithAttachment(String to, String subject, String text, File attachment) throws MessagingException {
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(text);
            helper.addAttachment(attachment.getName(), attachment);
            mailSender.send(mimeMessage);
        }
    
        public void sendMailWithInlineImage(String to, String subject, String htmlContent, File image, String cid) throws MessagingException {
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(htmlContent, true);
            helper.addInline(cid, image); // cid 是 HTML 中引用的 Content-ID (不带 < >)
            mailSender.send(mimeMessage);
        }
    }
    

    调用示例 (在 Controller 或 Service 中):

    @Autowired
    private EmailService emailService;
    
    public void sendWelcomeEmail(String userEmail) {
        try {
            emailService.sendHtmlMail(userEmail, "欢迎加入", "

    欢迎!

    感谢注册...

    "); } catch (MessagingException e) { // 处理异常 } }

这份指南涵盖了 Java 邮件编程的绝大部分核心内容,从基础协议、API 使用到高级技巧、安全实践和完整案例。希望它能成为你开发邮件相关应用的权威参考手册。请根据实际需求选择适用的部分进行实践。

本文地址:https://www.yitenyun.com/3839.html

搜索文章

Tags

#远程工作 #服务器 #python #pip #conda #ios面试 #ios弱网 #断点续传 #ios开发 #objective-c #ios #ios缓存 香港站群服务器 多IP服务器 香港站群 站群服务器 #kubernetes #笔记 #平面 #容器 #linux #学习方法 #运维 #进程控制 #学习 #开发语言 #云原生 #iventoy #VmWare #OpenEuler #docker #后端 #数据库 #Trae #IDE #AI 原生集成开发环境 #Trae AI #人工智能 #node.js #cpolar #fastapi #html #css #MobaXterm #ubuntu #物联网 #websocket #Conda # 私有索引 # 包管理 #低代码 #爬虫 #音视频 #数信院生信服务器 #Rstudio #生信入门 #生信云服务器 #github #git #内网穿透 #网络 #vscode #mobaxterm #深度学习 #计算机视觉 #算法 #大数据 #安全 #nginx #tcp/ip #开源 #golang #java #redis #RTP over RTSP #RTP over TCP #RTSP服务器 #RTP #TCP发送RTP #缓存 #web安全 #vllm #大模型 #Streamlit #Qwen #本地部署 #AI聊天机器人 #jvm #我的世界 #android #腾讯云 #c# #unity #游戏引擎 #kylin #需求分析 #Dell #PowerEdge620 #内存 #硬盘 #RAID5 #架构 #面试 #hadoop #hbase #hive #zookeeper #spark #kafka #flink #银河麒麟 #系统升级 #信创 #国产化 #华为 #ModelEngine #多个客户端访问 #IO多路复用 #回显服务器 #TCP相关API #qt #C++ #凤希AI伴侣 #ssh #编辑器 #ide #udp #c++ #json #jmeter #功能测试 #软件测试 #自动化测试 #职场和发展 #prometheus #gpu算力 #grafana #ping通服务器 #读不了内网数据库 #bug菌问答团队 #云计算 #银河麒麟高级服务器操作系统安装 #银河麒麟高级服务器V11配置 #设置基础软件仓库时出错 #银河麒高级服务器系统的实操教程 #生产级部署银河麒麟服务系统教程 #Linux系统的快速上手教程 #科技 #自然语言处理 #神经网络 #asp.net #sqlserver #elasticsearch #版本控制 #Git入门 #开发工具 #代码托管 #个人博客 #http #cpp #项目 #高并发 #n8n #嵌入式编译 #ccache #distcc #企业开发 #ERP #项目实践 #.NET开发 #C#编程 #编程与数学 #fiddler #gemini #gemini国内访问 #gemini api #gemini中转搭建 #Cloudflare #screen 命令 #智能路由器 #AI编程 #mvp #个人开发 #设计模式 #分阶段策略 #模型协议 #oracle #金融 #mcp #金融投资Agent #Agent #我的世界服务器搭建 #minecraft #研发管理 #禅道 #禅道云端部署 #AI #大模型学习 #javascript #windows #RAID #RAID技术 #磁盘 #存储 #毕设 #电脑 #自动化 #vue.js #前端 #todesk #ollama #ai #llm #华为云 #部署上线 #动静分离 #Nginx #新人首发 #性能优化 #asp.net大文件上传 #asp.net大文件上传下载 #asp.net大文件上传源码 #ASP.NET断点续传 #asp.net上传文件夹 #Spring AI #MCP服务器 #STDIO协议 #Streamable-HTTP #McpTool注解 #服务器能力 #Android #Bluedroid #flutter #数码相机 #debian #改行学it #创业创新 #程序员创富 #centos #压力测试 #claude #openlayers #bmap #tile #server #vue #arm开发 #c语言 #网络协议 #jenkins #1024程序员节 #jar #jupyter #YOLO # Triton # 目标检测 #lua #语音识别 #测试工具 #mysql #阿里云 #微信小程序 #小程序 #微信 #健身房预约系统 #健身房管理系统 #健身管理系统 #SRS #流媒体 #直播 #数据结构 #apache #鸭科夫 #逃离鸭科夫 #鸭科夫联机 #鸭科夫异地联机 #游戏 #开服 #web server #请求处理流程 #北京百思可瑞教育 #百思可瑞教育 #北京百思教育 #deepseek #课程设计 #react.js #分布式 #risc-v #嵌入式硬件 #制造 #守护进程 #复用 #screen #网络安全 #系统架构 #SSH公钥认证 # PyTorch # 安全加固 #单片机 #spring boot #部署 #stm32 #搜索引擎 #macos #pytorch #源码 #闲置物品交易系统 #毕业设计 #umeditor粘贴word #ueditor粘贴word #ueditor复制word #ueditor上传word图片 #IPv6 #DNS #iBMC #UltraISO #黑群晖 #虚拟机 #无U盘 #纯小白 #东方仙盟 #API限流 # 频率限制 # 令牌桶算法 #java-ee #transformer #prompt #蓝湖 #Axure原型发布 #php #django #计算机 #pycharm #树莓派4b安装系统 #llama #opencv #语言模型 #mamba #单元测试 #集成测试 #DisM++ # GLM-4.6V # 系统维护 #时序数据库 #京东云 #AIGC #ida #算力一体机 #ai算力服务器 #DeepSeek #MCP #蓝耘智算 #910B #昇腾 #aws #Ansible #Playbook #AI服务器 #AI论文写作工具 #学术写作辅助 #论文创作效率提升 #AI写论文实测 #深度优先 #DFS #svn #tomcat #sql #SSH # 双因素认证 # TensorFlow #spring #maven #intellij-idea #rustdesk #p2p #ssl #1panel #vmware #eBPF #unity3d #服务器框架 #Fantasy #YOLOFuse # Base64编码 # 多模态检测 #进程 #操作系统 #进程创建与终止 #shell #vuejs #SPA #单页应用 #flask #web3.py #高级IO #select #计算机网络 #说话人验证 #声纹识别 #CAM++ #RustDesk #IndexTTS 2.0 #本地化部署 #麒麟OS #ansible #swagger #visual studio code #FTP服务器 #车辆排放 #Windows #gitea #网站 #截图工具 #批量处理图片 #图片格式转换 #图片裁剪 #X11转发 #Miniconda #mcu #智能手机 #sqlite #journalctl #epoll #电气工程 #C# #PLC #聊天小程序 #openresty #wordpress #雨云 #tdengine #涛思数据 #Proxmox VE #虚拟化 #VMware #交互 #libosinfo #NPU #CANN #TCP #客户端 #嵌入式 #DIY机器人工房 #gitlab #GPU服务器 #8U #硬件架构 #cosmic #信令服务器 #Janus #MediaSoup #微服务 #JumpServer #堡垒机 #远程桌面 #远程控制 #振镜 #振镜焊接 #teamviewer #webrtc #idm #万悟 #联通元景 #智能体 #镜像 #scala #测试用例 #Linux #Socket网络编程 #win11 #RAG #LLM #chat # GPU租赁 # 自建服务器 #web服务器 #microsoft #经验分享 #YOLO26 #目标检测 #安卓 #远程开发 #agent #ai大模型 #milvus #springboot #知识库 #实时音视频 #业界资讯 #postman #媒体 #散列表 #哈希算法 #交通物流 #openEuler #chrome #GATT服务器 #蓝牙低功耗 #rocketmq #selenium #PyTorch #CUDA #Triton #harmonyos #ArkUI #ArkTS #鸿蒙开发 #政务 #uni-app #H5 #手机h5网页浏览器 #安卓app #苹果ios APP #手机电脑开启摄像头并排查 #硬件 #dify #go #Clawdbot #个人助理 #数字员工 #信号处理 #PowerBI #企业 #Nacos #web #KMS #slmgr #数据挖掘 #数据分析 #puppeteer #vnstat #监控 #POC #问答 #交付 #xlwings #Excel #运维开发 #文心一言 #AI智能体 #chatgpt #AutoDL #飞牛nas #fnos #支付 #spring cloud #nfs #iscsi #视频去字幕 #漏洞 #WT-2026-0001 #QVD-2026-4572 #smartermail #翻译 #前端框架 #负载均衡 #Modbus-TCP #YOLOv8 # Docker镜像 #文件管理 #NAS #文件服务器 #jetty #scanf #printf #getchar #putchar #cin #cout #大语言模型 #程序员 #esp32教程 #SA-PEKS # 关键词猜测攻击 # 盲签名 # 限速机制 #管道Pipe #system V #langchain #SAP #ebs #metaerp #oracle ebs #muduo库 #uv #uvx #uv pip #npx #Ruff #pytest #排序算法 #jdk #排序 # 高并发部署 #ddos #vps #cesium #可视化 #C语言 #aiohttp #asyncio #异步 #机器学习 #数据仓库 #html5 #软件 #本地生活 #电商系统 #商城 #计算几何 #斜率 #方向归一化 #叉积 #Anaconda配置云虚拟环境 #MQTT协议 #LoRA # lora-scripts # 模型微调 #openHiTLS #TLCP #DTLCP #密码学 #商用密码算法 #laravel #飞牛NAS #NVR #EasyNVR #.netcore #fabric #postgresql #可信计算技术 #MC #https #链表 #链表的销毁 #链表的排序 #链表倒置 #判断链表是否有环 #CPU #测评 #CCE #Dify-LLM #Flexus #服务器繁忙 #连接数据库报错 #Go并发 #高并发架构 #Goroutine #系统设计 #Dify #ARM架构 #鲲鹏 #.net #net core #kestrel #web-server #asp.net-core #cursor #spine #集成学习 #EMC存储 #存储维护 #NetApp存储 #硬件工程 #智能家居 #mybatis #Harbor #bootstrap #文件IO #输入输出流 #Termux #Samba #信息与通信 #tcpdump #PTP_1588 #gPTP #kmeans #聚类 #Java #rust #ms-swift # 大模型 # 模型训练 #ci/cd #pdf #大模型教程 #AI大模型 #结构体 #企业级存储 #网络设备 #Smokeping #鸿蒙PC #pve #进程等待 #wait #waitpid #LangGraph #CLI #Python #JavaScript #langgraph.json #zotero #WebDAV #同步失败 #代理模式 #工具集 #Android16 #音频性能实战 #音频进阶 #大模型应用 #API调用 #PyInstaller打包运行 #服务端部署 #H5网页 #网页白屏 #H5页面空白 #资源加载问题 #打包部署后网页打不开 #HBuilderX #扩展屏应用开发 #android runtime #SSE # AI翻译机 # 实时翻译 #欧拉 #VMWare Tool #麒麟 #无人机 #Deepoc #具身模型 #开发板 #未来 # IndexTTS 2.0 # 自动化运维 #心理健康服务平台 #心理健康系统 #心理服务平台 #心理健康小程序 #海外服务器安装宝塔面板 #rdp #论文笔记 #大模型部署 #mindie #大模型推理 #adb #大模型开发 #系统安全 #简单数论 #埃氏筛法 #idea #intellij idea #SSH反向隧道 # Miniconda # Jupyter远程访问 #5G #codex #yum #windows11 #系统修复 #三维 #3D #三维重建 #notepad++ #C2000 #TI #实时控制MCU #AI服务器电源 #leetcode #Llama-Factory # 树莓派 # ARM架构 #跨域 #发布上线后跨域报错 #请求接口跨域问题解决 #跨域请求代理配置 #request浏览器跨域 #rtsp #转发 #memcache #银河麒麟操作系统 #openssh #华为交换机 #信创终端 #UDP的API使用 #处理器 #CVE-2025-61686 #路径遍历高危漏洞 # 大模型推理 #统信UOS #服务器操作系统 #win10 #qemu #游戏机 #智能体来了 #智能体对传统行业冲击 #行业转型 #AI赋能 #bash #ThingsBoard MCP #sql注入 #LangFlow # 智能运维 # 性能瓶颈分析 #devops #戴尔服务器 #戴尔730 #装系统 #junit #elk #bug #HeyGem # 服务器配置 # GPU #MinIO服务器启动与配置详解 #clickhouse #代理 #muduo #TcpServer #accept #高并发服务器 # 服务器IP访问 # 端口映射 #机器人 #遛狗 #DHCP #mariadb #AI-native #自动化运维 # 一锤定音 # 大模型微调 # TTS服务器 # 键鼠锁定 #远程连接 #数据安全 #注入漏洞 #Host #渗透测试 #SSRF #WinSCP 下载安装教程 #SFTP #FTP工具 #服务器文件传输 #excel #wpf # CosyVoice3 # 批量部署 #copilot #scrapy #AI写作 #node # ControlMaster #IO #蓝牙 #LE Audio #BAP #powerbi #le audio #低功耗音频 #通信 #连接 #arm #昇腾300I DUO #参数估计 #矩估计 #概率论 #ui #分类 #模型训练 #星图GPU #googlecloud #Qwen3-14B # 大模型部署 # 私有化AI #Node.js # child_process #动态规划 #dlms #dlms协议 #逻辑设备 #逻辑设置间权限 #scikit-learn #随机森林 #vp9 #安全威胁分析 #仙盟创梦IDE #GLM-4.6V-Flash-WEB # AI视觉 # 本地部署 #攻防演练 #Java web #红队 #GB28181 #SIP信令 #SpringBoot #视频监控 #SSH跳板机 # Python3.11 #fpga开发 #LVDS #高速ADC #DDR #3d #驱动开发 #Minecraft #Minecraft服务器 #PaperMC #我的世界服务器 #screen命令 #Gunicorn #WSGI #Flask #并发模型 #容器化 #性能调优 #系统管理 #服务 #Emby #视频 #kong #Kong Audio #Kong Audio3 #KongAudio3 #空音3 #空音 #中国民乐 #ambari #门禁 #梯控 #智能一卡通 #门禁一卡通 #消费一卡通 #智能梯控 #一卡通 #源代码管理 #超时设置 #客户端/服务器 #网络编程 #挖矿 #Linux病毒 #小艺 #鸿蒙 #搜索 #ai编程 #产品经理 #就业 # 高并发 #数据恢复 #视频恢复 #视频修复 #RAID5恢复 #流媒体服务器恢复 #KMS激活 #Gateway #认证服务器集成详解 #青少年编程 #框架搭建 #状态模式 #dba #Tokio #国产化OS #国产操作系统 #V11 #kylinos #react native #vivado license #CVE-2025-68143 #CVE-2025-68144 #CVE-2025-68145 #论文阅读 #软件工程 # 批量管理 #ASR #SenseVoice #glibc #中间件 #CSDN #ONLYOFFICE #MCP 服务器 #后端框架 #zabbix #证书 #webpack #winscp # 数字人系统 # 远程部署 #reactjs #web3 # 自动化部署 # VibeThinker #serverless #数字化转型 #实体经济 #商业模式 #软件开发 #数智红包 #商业变革 #创业干货 #Tracker 服务器 #响应最快 #torrent 下载 #2026年 #Aria2 可用 #迅雷可用 #BT工具通用 #AI技术 #Zabbix #CosyVoice3 #语音合成 #FASTMCP #产品运营 #Puppet # IndexTTS2 # TTS #联机教程 #局域网联机 #局域网联机教程 #局域网游戏 #运维工具 #网络攻击模型 #pyqt #高斯溅射 #MC群组服务器 #企业微信 #ipmitool #BMC #C #云服务器 #个人电脑 #STDIO传输 #SSE传输 #WebMVC #WebFlux #unix #C/C++ #编程 #c++高并发 #百万并发 #CS2 #debian13 #embedding #ShaderGraph #图形 #uip #k8s #wsl #人大金仓 #Kingbase #VMware Workstation16 #Spring AOP #程序人生 #信创国产化 #达梦数据库 #MS #Materials #多进程 #python技巧 #paddleocr #word #GPU ##租显卡 #树莓派 #温湿度监控 #WhatsApp通知 #IoT #MySQL #SMTP # 内容安全 # Qwen3Guard #黑客技术 #文件上传漏洞 #Kylin-Server #服务器安装 #能源 #raid #raid阵列 #推荐算法 #CTF #A2A #GenAI #numpy #ue5 #平板 #零售 #智能硬件 #Langchain-Chatchat # 国产化服务器 # 信创 #vncdotool #链接VNC服务器 #如何隐藏光标 #插件 #开源软件 #database #r-tree #儿童AI #图像生成 #pjsip #FHSS #bond #服务器链路聚合 #网卡绑定 #LobeChat #vLLM #GPU加速 #开源工具 #服务器解析漏洞 #nodejs #学术论文创作 #论文效率提升 #MBA论文写作 #NFC #智能公交 #服务器计费 #FP-增长 #人脸识别sdk #视频编解码 #人脸识别 #算力建设 #练习 #基础练习 #数组 #循环 #九九乘法表 #计算机实现 #dynadot #域名 #ETL管道 #向量存储 #数据预处理 #DocumentReader #esb接口 #走处理类报异常 #ZooKeeper #ZooKeeper面试题 #面试宝典 #深入解析 #ffmpeg #n8n解惑 #tensorflow #SSH密钥 # CUDA #smtp #smtp服务器 #PHP #银河麒麟部署 #银河麒麟部署文档 #银河麒麟linux #银河麒麟linux部署教程 # 语音合成 #agi #yolov12 #研究生life #eureka #广播 #组播 #并发服务器 #x86_64 #数字人系统 #ServBay #gpu #nvcc #cuda #nvidia #其他 #AI 推理 #NV #大剑师 #nodejs面试题 #ESP32 # OTA升级 # 黄山派 #RXT4090显卡 #RTX4090 #深度学习服务器 #硬件选型 #ansys #ansys问题解决办法 # WebUI # 网络延迟 #SQL注入主机 #ranger #MySQL8.0 #echarts # 服务器IP # 端口7860 #跳槽 #工作 # 公钥认证 #Reactor #gRPC #注册中心 #odoo #空间计算 #原型模式 #HarmonyOS #VibeVoice # 云服务器 #雨云服务器 #教程 #MCSM面板 #Apple AI #Apple 人工智能 #FoundationModel #Summarize #SwiftUI #多线程 #claudeCode #content7 #I/O模型 #并发 #水平触发、边缘触发 #多路复用 #Modbus # 串口服务器 # NPort5630 #appche #c #数据访问 #gateway #Comate #C++ UA Server #SDK #跨平台开发 # 轻量化镜像 # 边缘计算 #OpenHarmony #eclipse #servlet #Python办公自动化 #Python办公 #arm64 #SSH复用 # 远程开发 #ftp #sftp #磁盘配额 #存储管理 #形考作业 #国家开放大学 #系统运维 #YOLO识别 #YOLO环境搭建Windows #YOLO环境搭建Ubuntu #lucene #微PE #硬盘克隆 #DiskGenius #opc #opc ua #opc模拟服务器 #机器视觉 #6D位姿 #UOS #海光K100 #统信 #cpu #mssql #工程设计 #预混 #扩散 #燃烧知识 #层流 #湍流 #量子计算 #串口服务器 #MOXA #密码 #firefox #safari # RTX 3090 #Docker #b树 #AI部署 # ms-swift #PN 结 #服务器线程 # SSL通信 # 动态结构体 #RWK35xx #语音流 #实时传输 #超算中心 #PBS #lsf #报表制作 #职场 #数据可视化 #信息可视化 #用数据讲故事 #语音生成 #TTS #Fun-ASR # 语音识别 #数据迁移 #windbg分析蓝屏教程 #memory mcp #Cursor #es安装 #nmodbus4类库使用教程 #docker-compose #目标跟踪 #lvs #adobe #IFix #c++20 # 远程连接 #宝塔面板部署RustDesk #RustDesk远程控制手机 #手机远程控制 #系统安装 #铁路桥梁 #DIC技术 #箱梁试验 #裂纹监测 #四点弯曲 #可再生能源 #绿色算力 #风电 #Buck #NVIDIA #算力 #交错并联 #DGX #麦克风权限 #访问麦克风并录制音频 #麦克风录制音频后在线播放 #用户拒绝访问麦克风权限怎么办 #uniapp 安卓 苹果ios #将音频保存本地或上传服务器 #内存治理 #express #cherry studio #gmssh #宝塔 #漏洞挖掘 #Exchange #gerrit #AI应用编程 # 环境迁移 # keep-alive #若依 #matplotlib #安全架构 #EN4FE #自由表达演说平台 #演说 #指针 #anaconda #虚拟环境 #AI Agent #开发者工具 # GLM-TTS # 数据安全 #xshell #host key #TTS私有化 # IndexTTS # 音色克隆 #前端开发 #计算机外设 #ip # ARM服务器 #Karalon #AI Test #编程助手 #流程图 #图论 #国产开源制品管理工具 #Hadess #一文上手 #蓝桥杯 #okhttp #范式 #健康医疗 #azure #OPCUA #ceph #ET模式 #非阻塞 #remote-ssh #turn #网安应急响应 # GLM # 服务连通性 #工程实践 #AI应用 #CMake #Make #图像识别 #高考 #多模态 #微调 #超参 #LLamafactory #SSH跳转 #流量监控 #gpt #API #taro # GPU集群 #wps #服务器开启 TLS v1.2 #IISCrypto 使用教程 #TLS 协议配置 #IIS 安全设置 #服务器运维工具 #Linux多线程 #uniapp #合法域名校验出错 #服务器域名配置不生效 #request域名配置 #已经配置好了但还是报错 #uniapp微信小程序 #Java程序员 #Java面试 #后端开发 #Spring源码 #Spring #Beidou #北斗 #SSR #华为od #华为机试 #diskinfo # 磁盘健康 #Socket #套接字 #I/O多路复用 #字节序 #信息安全 #信息收集 #weston #x11 #x11显示服务器 #poll #samba #RSO #机器人操作系统 #CPU利用率 #simulink #matlab #汽车 #传统行业 # GLM-4.6V-Flash-WEB # AI部署 #材料工程 #智能电视 #JNI #AB包 #pxe #VMware创建虚拟机 #远程更新 #缓存更新 #多指令适配 #物料关联计划 #挖漏洞 #攻击溯源 #blender #warp #STUN # TURN # NAT穿透 #MCP服务器注解 #异步支持 #方法筛选 #声明式编程 #自动筛选机制 #Aluminium #Google #MinIO #m3u8 #HLS #移动端H5网页 #APP安卓苹果ios #监控画面 直播视频流 #Prometheus #日志分析 #DooTask #free #vmstat #sar #sentinel #Ubuntu服务器 #硬盘扩容 #命令行操作 #防毒面罩 #防尘面罩 #UEFI #BIOS #Legacy BIOS #TRO #TRO侵权 #TRO和解 #Discord机器人 #云部署 #程序那些事 #r语言 #服务器IO模型 #非阻塞轮询模型 #多任务并发模型 #异步信号模型 #多路复用模型 # 黑屏模式 #身体实验室 #健康认知重构 #系统思维 #微行动 #NEAT效应 #亚健康自救 #ICT人 #云开发 #领域驱动 #KMS 激活 #AI智能棋盘 #Rock Pi S #边缘计算 #移动端h5网页 #调用浏览器摄像头并拍照 #开启摄像头权限 #拍照后查看与上传服务器端 #摄像头黑屏打不开问题 #SSH别名 #BoringSSL #工业级串口服务器 #串口转以太网 #串口设备联网通讯模块 #串口服务器选型 #IndexTTS2 # 阿里云安骑士 # 木马查杀 #云计算运维 #asp.net上传大文件 #入侵 #日志排查 # 鲲鹏 #http头信息 #ICE #群晖 #TCP服务器 #开发实战 #全文检索 #银河麒麟服务器系统 #iot #生信 #策略模式 #租显卡 #训练推理 # HiChatBox # 离线AI #bigtop #hdp #hue #kerberos #pencil #pencil.dev #设计 #轻量化 #低配服务器 #可撤销IBE #服务器辅助 #私钥更新 #安全性证明 #双线性Diffie-Hellman #Anything-LLM #IDC服务器 #私有化部署 #短剧 #短剧小程序 #短剧系统 #微剧 #hibernate #nosql #java大文件上传 #java大文件秒传 #java大文件上传下载 #java文件传输解决方案 #PyCharm # 远程调试 # YOLOFuse #docker安装seata #Syslog #系统日志 #日志监控 #生产服务器问题查询 #日志过滤 #Autodl私有云 #深度服务器配置 # 水冷服务器 # 风冷服务器 #wireshark #网络安全大赛 #VoxCPM-1.5-TTS # 云端GPU # PyCharm宕机 #全链路优化 #实战教程 #CNAS #CMA #程序文件 #stl #漏洞修复 #IIS Crypto #实时检测 #卷积神经网络 #DAG #SSH保活 #云服务器选购 #Saas #线程 #everything #outlook #错误代码2603 #无网络连接 #2603 #AI生成 # outputs目录 # 自动化 #esp32 arduino #决策树 #HistoryServer #Spark #YARN #jobhistory #HarmonyOS APP #sglang #ComfyUI # 推理服务器 #具身智能 #rabbitmq #模拟退火算法 #网路编程 #计算机毕业设计 #程序定制 #毕设代做 #课设 #Hadoop #rtmp #声源定位 #MUSIC #SSH Agent Forwarding # 容器化 #内存接口 # 澜起科技 # 服务器主板 #AI电商客服 #spring ai #oauth2 # 显卡驱动备份 #homelab #Lattepanda #Jellyfin #Plex #Kodi #开关电源 #热敏电阻 #PTC热敏电阻 #文件传输 #电脑文件传输 #电脑传输文件 #电脑怎么传输文件到另一台电脑 #电脑传输文件到另一台电脑 #性能 #优化 #RAM # 高温监控 #mongodb #fs7TF # 远程访问 #nacos #银河麒麟aarch64 #uvicorn #uvloop #asgi #event # 服务器迁移 # 回滚方案 #ROS # 局域网访问 # 批量处理 #大模型入门 #浏览器自动化 #python #企业存储 #RustFS #对象存储 #高可用 #TensorRT # 推理优化 #Xshell #Finalshell #生物信息学 #组学 #npu #SSH免密登录 #log4j #Jetty # 嵌入式服务器 #模块 #内网 # 跳板机 #音乐 #IntelliJ IDEA #Spring Boot #neo4j #NoSQL #SQL #ARM服务器 # 多模态推理 #远程软件 #Coturn #TURN # 代理转发 #代理服务器 #rsync # 数据同步 #设计师 #图像处理 #游戏美术 #技术美术 #建筑缺陷 #红外 #数据集 #视觉检测 #visual studio #分布式数据库 #集中式数据库 #业务需求 #选型误 #SMARC #ARM # Connection refused #WRF #WRFDA #RK3576 #瑞芯微 #硬件设计 #Ubuntu #UDP套接字编程 #UDP协议 #网络测试 #CA证书 #反向代理 #nas #测速 #iperf #iperf3 #session # REST API #静脉曲张 #腿部健康 #运动 #面向对象 #基础语法 #标识符 #常量与变量 #数据类型 #运算符与表达式 #数学建模 #主板 #总体设计 #电源树 #框图 #iphone #边缘AI # Kontron # SMARC-sAMX8 #模版 #函数 #类 #笔试 #WEB #OpenAI #故障 #阿里云RDS #coffeescript #mtgsig #美团医药 #美团医药mtgsig #美团医药mtgsig1.2 #二值化 #Canny边缘检测 #轮廓检测 #透视变换 #交换机 #三层交换机 #模型上下文协议 #MultiServerMCPC #load_mcp_tools #load_mcp_prompt # 权限修复 #文生视频 #WAN2.2 #AI视频生成 #游戏策划 #游戏程序 #用户体验 #TLS协议 #HTTPS #运维安全 #VS Code调试配置 #2026年美赛C题代码 #2026年美赛 #智能制造 #供应链管理 #工业工程 #库存管理 #log #WinDbg #Windows调试 #内存转储分析 #claude code #code cli #ccusage #运维 #Ascend #MindIE #FRP #上下文工程 #langgraph #意图识别 #markdown #建站 #智慧城市 #华为od机试 #华为od机考 #华为od最新上机考试题库 #华为OD题库 #华为OD机试双机位C卷 #od机考题库