Java 對接 Office 365 郵箱全攻略:OAuth2 認證 + JDK8 兼容 + Spring Boot 集成(2025 版)

🚨 重要通知:微軟強制 OAuth2,傳統認證已失效!

2023 年 10 月起,Office 365 全面禁用用戶名 + 密碼認證,Java 開發者必須通過OAuth 2.0實現郵件發送。本文針對 CSDN 技術棧,提供從 Azure AD 配置到生產級代碼的全流程方案,附 JDK 8 兼容實現和 Spring Boot 集成示例。

一、Office 365 對接核心流程(圖示)
二、Azure AD 應用注冊(分步教程)
  1. 創建應用

    • 登錄Azure 門戶?→?Azure AD?→?應用注冊?→?新建注冊
    • 記錄:Client IDClient SecretTenant ID(租戶域名或 ID)
  2. 配置權限

    • API 權限中添加Microsoft GraphMail.Send權限(選擇應用權限
    • 點擊授予管理員同意(需管理員賬號操作)
  3. 獲取令牌端點

    plaintext

    令牌URL:https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token
    
三、Java 原生 API 實現(JDK 8 兼容)
1. 核心依賴(Maven)

xml

<dependency><groupId>com.sun.mail</groupId><artifactId>mail</artifactId><version>1.6.2</version> <!-- JDK8唯一兼容版本 -->
</dependency>
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version> <!-- HTTP請求工具 -->
</dependency>
2. 完整代碼示例

java

import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;public class Office365MailClient {private static final String TOKEN_URL = "https://login.microsoftonline.com/%s/oauth2/v2.0/token";private static final String SCOPE = "https://outlook.office365.com/.default";private final String tenantId, clientId, clientSecret, senderEmail;private final ConcurrentHashMap<String, String> tokenCache = new ConcurrentHashMap<>();public Office365MailClient(String tenantId, String clientId, String clientSecret, String senderEmail) {this.tenantId = tenantId;this.clientId = clientId;this.clientSecret = clientSecret;this.senderEmail = senderEmail;}public void sendHtmlEmail(String to, String subject, String htmlContent) throws Exception {String accessToken = getAccessToken();Properties props = getSmtpProperties(accessToken);Session session = Session.getInstance(props);MimeMessage msg = createMimeMessage(session, to, subject, htmlContent);try (Transport transport = session.getTransport("smtp")) {transport.connect(); // 自動觸發XOAUTH2認證transport.sendMessage(msg, msg.getAllRecipients());System.out.println("發送成功,響應碼:" + ((SMTPTransport) transport).getLastServerResponse());}}private Properties getSmtpProperties(String accessToken) {Properties props = new Properties();props.put("mail.smtp.host", "smtp.office365.com");props.put("mail.smtp.port", "587");props.put("mail.smtp.auth", "true");props.put("mail.smtp.starttls.enable", "true");props.put("mail.smtp.auth.mechanisms", "XOAUTH2");// 注入OAuth2認證器props.put("mail.smtp.user", senderEmail);props.put("mail.smtp.password", accessToken);return props;}private MimeMessage createMimeMessage(Session session, String to, String subject, String htmlContent) throws MessagingException {MimeMessage msg = new MimeMessage(session);msg.setFrom(new InternetAddress(senderEmail));msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));msg.setSubject(subject, "UTF-8");msg.setContent(htmlContent, "text/html; charset=utf-8");return msg;}// 令牌獲取與緩存(簡化實現)private String getAccessToken() throws Exception {// 實際需實現HTTP請求獲取令牌,參考后文Spring Boot方案return "your_oauth2_token";}
}
四、Spring Boot 集成方案(生產級)
1. 依賴配置

xml

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId><exclusions><exclusion><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>com.sun.mail</groupId><artifactId>javax.mail</artifactId><version>1.6.2</version>
</dependency>
2. 配置文件(application.properties)

properties

spring.mail.host=smtp.office365.com
spring.mail.port=587
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.auth.mechanisms=XOAUTH2office365.tenant-id=your_tenant_id
office365.client-id=your_client_id
office365.client-secret=your_client_secret
office365.sender-email=your_sender@example.com
3. 服務類實現

java

import org.springframework.beans.factory.annotation.Value;
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;@Service
public class Office365MailService {private final JavaMailSender mailSender;private final String tenantId, clientId, clientSecret, senderEmail;private final Office365TokenProvider tokenProvider;public Office365MailService(JavaMailSender mailSender,@Value("${office365.tenant-id}") String tenantId,@Value("${office365.client-id}") String clientId,@Value("${office365.client-secret}") String clientSecret,@Value("${office365.sender-email}") String senderEmail) {this.mailSender = mailSender;this.tenantId = tenantId;this.clientId = clientId;this.clientSecret = clientSecret;this.senderEmail = senderEmail;this.tokenProvider = new Office365TokenProvider(tenantId, clientId, clientSecret);}public void sendEmail(String to, String subject, String htmlContent) throws MessagingException {MimeMessage message = mailSender.createMimeMessage();MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");helper.setFrom(senderEmail);helper.setTo(to);helper.setSubject(subject);helper.setText(htmlContent, true); // 支持HTML// 注入令牌到郵件頭(非必須,Spring自動處理認證)message.setHeader("Authorization", "Bearer " + tokenProvider.getAccessToken());mailSender.send(message);}
}
五、常見錯誤與解決方案
錯誤碼 / 提示原因分析解決方案
535 Authentication failed令牌無效或權限不足檢查 Azure AD 應用權限,重新獲取令牌
550 5.7.1 SendAs permission缺少發送權限通過 PowerShell 分配SendAs權限
421 Service not available服務器臨時繁忙添加重試機制,設置指數退避(如 1s→2s→4s)
ClassNotFoundException: SMTPTransportJDK 版本不兼容確保使用 JavaMail 1.6.2+,JDK 8 需顯式引入com.sun.mail:mail:1.6.2
六、性能優化與安全實踐
  1. 令牌緩存
    使用ConcurrentHashMap或 Redis 緩存令牌,設置提前 5 分鐘刷新:

    java

    private static final long TOKEN_EXPIRE = 3600; // 有效期1小時
    private static final long REFRESH_BUFFER = 300; // 提前5分鐘刷新
    
  2. 連接池配置
    在 Spring Boot 中配置連接池參數:

    properties

    spring.mail.properties.mail.smtp.connectionpool.size=20
    spring.mail.properties.mail.smtp.connectionpool.timeout=5000
    
  3. 敏感信息管理

    • 禁止硬編碼,使用環境變量或 Spring 配置中心
    • 通過azure-keyvault組件從 Key Vault 獲取Client Secret
七、權威參考
  1. 微軟官方文檔

    • Office 365 SMTP OAuth2 認證
    • Azure AD 應用權限配置
  2. JavaMail 最佳實踐

    • XOAUTH2 認證示例
    • JDK 8 兼容性指南
🌟 總結

本文提供了 Java 對接 Office 365 郵箱的完整解決方案,覆蓋原生 API 和 Spring Boot 集成,特別針對 JDK 8 兼容性和 OAuth 2.0 認證做了深度優化。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85125.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85125.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85125.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

一文詳談Linux中的時間管理和定時器編程

&#xff08;目錄&#xff09; 先說一些在計算機中需要用到時間的地方&#xff1a;系統日志log、OS調度(時間片、定時器)等等~~ 時間的計量 計時的方式發展&#xff1a;日晷、沙漏 -> 機械鐘 -> 石英振蕩器、晶振 -> 銫原子鐘 -> 氫原子鐘 計算機中的計時方式&…

使用FastAPI+Sqlalchemy從一個數據庫向另一個數據庫更新數據(sql語句版)

from sqlalchemy import create_engine, text from sqlalchemy.orm import sessionmaker # 配置數據庫連接&#xff08;示例為PostgreSQL->MySQL&#xff09; SRC_DB_URL postgresql://user:passsource_host:5432/source_db DST_DB_URL mysqlpymysql://user:passdest_hos…

基于python腳本進行Maxwell自動化仿真

本文為博主進行Maxwell自動化研究過程的學習記錄&#xff0c;同時對Maxwell自動化腳本&#xff08;pythonIron&#xff09;實現方法進行分享。 文章目錄 腳本使用方法腳本錄制與查看常用腳本代碼通用開頭定義項目調整設計變量軟件內對應位置腳本 設置求解器軟件內對應位置腳本…

pikachu通關教程-RCE

目錄 RCE(remote command/code execute)概述: exec "ping" 管道符 亂碼問題 RCE(remote command/code execute)概述: RCE漏洞&#xff0c;可以讓攻擊者直接向后臺服務器遠程注入操作系統命令或者代碼&#xff0c;從而控制后臺系統 分為遠程代碼和遠程命令兩種.當…

JavaScript性能優化全景指南

JavaScript性能優化全景指南 Ⅰ. 加載性能優化 1.1 代碼分割與懶加載 動態導入(ES2020) javascript // 路由級代碼分割 const ProductPage () > import(/* webpackChunkName: "product" */ ./ProductPage.vue); // 交互驅動加載 document.querySelector(#char…

BaseTypeHandler用法-筆記

1.BaseTypeHandler簡介 org.apache.ibatis.type.BaseTypeHandler 是 MyBatis 提供的一個抽象類&#xff0c;通過繼承該類并實現關鍵方法&#xff0c;可用于實現 Java 類型 與 JDBC 類型 之間的雙向轉換。當數據庫字段類型與 Java 對象屬性類型不一致時&#xff08;如&#xff…

t015-預報名管理系統設計與實現 【含源碼!!!】

項目演示地址 摘 要 傳統辦法管理信息首先需要花費的時間比較多&#xff0c;其次數據出錯率比較高&#xff0c;而且對錯誤的數據進行更改也比較困難&#xff0c;最后&#xff0c;檢索數據費事費力。因此&#xff0c;在計算機上安裝預報名管理系統軟件來發揮其高效地信息處理的…

Day12 - 計算機網絡 - HTTP

HTTP常用狀態碼及含義&#xff1f; 301和302區別&#xff1f; 301&#xff1a;永久性移動&#xff0c;請求的資源已被永久移動到新位置。服務器返回此響應時&#xff0c;會返回新的資源地址。302&#xff1a;臨時性性移動&#xff0c;服務器從另外的地址響應資源&#xff0c;但…

【python深度學習】Day 40 訓練和測試的規范寫法

知識點回顧&#xff1a; 彩色和灰度圖片測試和訓練的規范寫法&#xff1a;封裝在函數中展平操作&#xff1a;除第一個維度batchsize外全部展平dropout操作&#xff1a;訓練階段隨機丟棄神經元&#xff0c;測試階段eval模式關閉dropout 作業&#xff1a;仔細學習下測試和訓練代碼…

亡羊補牢與持續改進 - SRE 的安全日志、審計與事件響應

亡羊補牢與持續改進 - SRE 的安全日志、審計與事件響應 如果說我們之前討論的安全措施(如 IAM、網絡策略、密鑰管理、漏洞補丁)是為我們的“數字城堡”修筑堅固的城墻、設置精密的門鎖、定期檢查和修補潛在的裂縫,那么安全日志就像是遍布城堡內外的監控攝像頭和出入登記簿,…

CppCon 2014 學習第2天:Using Web Services in C++

概述 這是一個會議或演講的概述內容&#xff0c;主要介紹一個關于C Rest SDK的分享&#xff0c;翻譯和理解如下&#xff1a; 翻譯 概述 先介紹什么是典型的Web服務結構和它的特征講講調用這些Web服務的幾種方式重點介紹自己團隊開發的一個C庫&#xff08;C Rest SDK&#xf…

【OpenHarmony】【交叉編譯】使用gn在Linux編譯3568a上運行的可執行程序

linux下編譯arm64可執行程序 一.gn ninja安裝二.交叉編譯工具鏈安裝1.arm交叉編譯工具2.安裝arm64編譯器 三. gn文件添加arm及arm64工具鏈四.編譯驗證 本文以gn nijia安裝中demo為例&#xff0c;將其編譯為在arm64(rk_3568_a開發板)環境下可運行的程序 一.gn ninja安裝 安裝g…

【開發心得】AstrBot對接飛書失敗的問題探究

飛書與AstrBot的集成使用中,偶爾出現連接不穩定的現象。盡管不影響核心功能,但為深入探究技術細節并推動后續優化,需系統性記錄該問題。先從底層通信機制入手,分析連接建立的邏輯與數據交互流程。基于實際現象,明確問題發生的具體場景和表現特征,進而梳理潛在影響因素,為…

Spring Boot 3.5.0中文文檔上線

Spring Boot 3.5.0 中文文檔翻譯完成&#xff0c;需要的可收藏 傳送門&#xff1a;Spring Boot 3.5.0 中文文檔

7.atlas安裝

1.服務器規劃 軟件版本參考&#xff1a; https://cloud.google.com/dataproc/docs/concepts/versioning/dataproc-release-2.2?hlzh-cn 由于hive3.1.3不完全支持jdk8,所以將hive的版本調整成4.0.1。這個版本沒有驗證過&#xff0c;需要讀者自己抉擇。 所有的軟件都安裝再/op…

c# 獲取電腦 分辨率 及 DPI 設置

using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices;/// <summary> /// 這個可以 /// </summary> class Program {static void Main(){//設置DPI感知try{SetProcessDpiAwareness(…

LangChain表達式(LCEL)實操案例1

案例1&#xff1a;寫一篇短文&#xff0c;然后對這篇短文進行打分 from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.runnables import RunnableWithMessageHist…

OleDbParameter.Value 與 DataTable.Rows.Item.Value 的性能對比

OleDbParameter.Value 與 DataTable.Rows.Item.Value 的性能對比 您提到的兩種賦值操作屬于不同場景&#xff0c;它們的性能和穩定性取決于具體使用方式。下面從幾個維度進行分析&#xff1a; 1. 操作本質對比 &#xff08;1&#xff09;OleDbParameter.Value 用途&#xf…

【Opencv+Yolo】Day2_圖像處理

目錄 一、圖像梯度計算 圖像梯度-sobal算子&#xff1a; Scharr&#xff1a;權重變化更大&#xff08;線條更加豐富&#xff0c;比Sobel更加細致捕捉更多梯度信息&#xff09; Laplacian算子&#xff1a;對噪音點敏感&#xff08;可以和其他一起結合使用&#xff09; 二、邊…

STM32通過rt_hw_hard_fault_exception中的LR寄存器追溯程序問題?

1. 問題現象 程序運行導致rt_hw_hard_fault_exception 如圖 顯示錯誤相關代碼 struct exception_stack_frame {uint32_t r0;uint32_t r1;uint32_t r2;uint32_t r3;uint32_t r12; uint32_t lr; // 鏈接寄存器 (LR)uint32_t pc; // 程序計數器 (PC)uint32_t psr; // 程序狀態…