【Java】Exchange Online SMTP AUTH にて OAuth認証でメール送信

◆ Live配信スケジュール ◆
サイオステクノロジーでは、Microsoft MVPの武井による「わかりみの深いシリーズ」など、定期的なLive配信を行っています。
⇒ 詳細スケジュールはこちらから
⇒ 見逃してしまった方はYoutubeチャンネルをご覧ください
【5/21開催】Azure OpenAI ServiceによるRAG実装ガイドを公開しました
生成AIを活用したユースケースで最も一番熱いと言われているRAGの実装ガイドを公開しました。そのガイドの紹介をおこなうイベントです!!
https://tech-lab.connpass.com/event/315703/

こんにちは。サイオステクノロジーの木村です。

こちらの公開情報によると、Exchange Online での基本認証の廃止に伴い、Exchange Onlineで SMTP AUTH プロトコルを使用したメール送信について、基本認証での接続は非推奨になりました。
Exchange Online で基本認証が無効になった場合でも、SMTP AUTH は引き続き基本認証が使用できるようですが、先進認証での方法に切り替えることが推奨されています。
そこで今回は、Javaでの実装を例に、SMTP AUTH にてメール送信する際に先進認証(OAuth 認証)で行う方法をご紹介します。

アプリケーションの登録

OAuth を使用するには、アプリケーションを Azure AD に登録する必要があります。以下にその手順を記載します。

1. 管理者でAzureポータル(https://portal.azure.com/)にログインします。

2. メニューより「Azure Active Directory」をクリックします。

3. 「アプリの登録」をクリックし「+新規登録」をクリックします。
4. アプリケーションの登録ページで、以下を入力し「登録」をクリックします。

  • 名前:任意の名称
  • サポートされているアカウントの種類:この組織ディレクトリのみに含まれるアカウント
  • リダイレクトURI(省略可能):何も入力しない


5. 表示された [アプリケーション (クライアント) ID] と、[ディレクトリ (テナント) ID ]の値をメモしておきます。

6. 「証明書とシークレット」をクリックし、「+新しいクライアントシークレット」をクリックします。

7. 説明を入力して有効期限を選択し「追加」をクリックします。

8. 作成されたクライアントシークレット の値をメモしておきます。

9. 「APIのアクセス許可」をクリックし、「+アクセス許可の追加」をクリックします。

10. 「所属する組織で使用しているAPI」タブを選択し、検索欄に「Office 365 Exchange Online」と入力して検索されたものをクリックします。

11. 「アプリケーションの許可」をクリックします。

12. 「SMTP.Send.App」にチェックを入れ、「アクセス許可の追加」をクリックします。

13. 「[テナント名]に管理者の同意を与えます」をクリックします。

14. 「はい」をクリックします。

以上でアプリケーションの登録は完了です。

Exchange に サービスプリンシパル を登録

アプリケーションの登録の手順で登録したアプリケーションで Exchange Online に接続できるようにするために、アプリケーションのサービスプリンシパル をExchange に登録します。以下にその手順を記載します。

オブジェクトID を確認

アプリケーションのサービスプリンシパル をExchange に登録する際に、「オブジェクトID」を指定する必要があるため、以下の手順で「オブジェクトID」を確認します。([アプリの登録] の [概要] のオブジェクトID とは異なる値です。)

1. メニューより「Azure Active Directory」をクリックします。

2. 「エンタープライズ アプリケーション」をクリックします。

3. すべてのアプリケーションの一覧にて、アプリケーションの登録の手順で作成したアプリケーションを検索し、クリックします。

4. プロパティに表示される「オブジェクトID」をコピーしてメモしておきます。

サービスプリンシパル の登録とアクセス権の付与

アプリケーションのサービスプリンシパル を Exchange へ登録し、メールボックスへのアクセス権を付与します。これらの操作は、PowerShellで行います。

1. PowerShellを管理者で起動し、以下のコマンドを実行して、ExchangeOnlineManagement をインストールし、モジュールを読み込みます。


Install-Module -Name ExchangeOnlineManagement
Import-module ExchangeOnlineManagement

2. 以下のコマンドを実行して Exchange Online に接続します。


Connect-ExchangeOnline -Organization 

3. 以下のコマンドを実行して、アプリケーションのサービスプリンシパルを Exchange に登録します。


New-ServicePrincipal -AppId [APPLICATION_ID] -ServiceId [OBJECT_ID]
  • APPLICATION_ID:「アプリケーションの登録」の 5. の手順でメモした アプリケーション (クライアント) ID
  • OBJECT_ID:「オブジェクトID を確認」の 4. の手順でメモした オブジェクトID

4. 以下のコマンドを実行して、アプリケーションのサービスプリンシパルに、メール送信時に送信元に指定するアカウントのメールボックスへのアクセス権を付与します。


Add-MailboxPermission -Identity "xxx@xxx.onmicrosoft.com(送信元に指定するアカウントのメールアドレス)" -User [APPLICATION_ID] -AccessRights FullAccess

※ 送信元に指定するアカウントのメールボックスの SMTP AUTH が無効の場合は、以下のコマンドで有効に設定しておきます。


Set-CASMailbox -Identity "xxx@xxx.onmicrosoft.com(送信元に指定するアカウントのメールアドレス)" -SmtpClientAuthenticationDisabled $false

メール送信

メール送信時のユーザー認証の実装には、Java 用 Microsoft 認証ライブラリ「Microsoft Authentication Library (MSAL) for Java」を使用します。(Microsoft Authentication Library (MSAL)については、こちらを参照。)
メール送信にはJavaMailを使用します。
Mavenの場合、pom.xmlへ以下のように依存関係を追加します。

pom.xml


<dependency>
  <groupId>com.microsoft.azure</groupId>
  <artifactId>msal4j</artifactId>
  <version>1.13.10</version>
</dependency>
<dependency>
  <groupId>com.sun.mail</groupId>
  <artifactId>javax.mail</artifactId>
  <version>1.6.1</version>
</dependency>

以下のようにコードを実装します。
App.java


import java.util.Collections;
import java.util.Properties;
import java.util.Set;

import com.microsoft.aad.msal4j.ClientCredentialFactory;
import com.microsoft.aad.msal4j.ClientCredentialParameters;
import com.microsoft.aad.msal4j.ConfidentialClientApplication;
import com.microsoft.aad.msal4j.IAuthenticationResult;
import com.microsoft.aad.msal4j.IClientCredential;

import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.Message;


public class App 
{
    public static void main( String[] args )
    {
        String CLIENT_ID = "<クライアントID>";
        String AUTHORITY = "https://login.microsoftonline.com/<テナントID>/";
        String CLIENT_SECRET = "<クライアントシークレット>";
        Set SCOPE = Collections.singleton("https://outlook.office365.com/.default");
        String FROM_ADDRESS = "<送信元メールアドレス>";

        try {

            //アクセストークン取得
            IClientCredential credential = ClientCredentialFactory.createFromSecret(CLIENT_SECRET);
            ConfidentialClientApplication cca = ConfidentialClientApplication
                .builder(CLIENT_ID, credential)
                .authority(AUTHORITY)
                .build();

            ClientCredentialParameters parameters =
                        ClientCredentialParameters
                                .builder(SCOPE)
                                .build();
            IAuthenticationResult result = cca.acquireToken(parameters).join();

            //メール送信
            Properties properties = new Properties();
            properties.put("mail.smtp.auth", "true");
            properties.put("mail.smtp.auth.mechanisms", "XOAUTH2");
            properties.put("mail.smtp.starttls.enable", "true");
            properties.put("mail.smtp.ssl.protocols", "TLSv1.3");

            Session session = Session.getInstance(properties);
            Transport transport = session.getTransport("smtp");
            transport.connect("smtp.office365.com", 587, FROM_ADDRESS, result.accessToken());

            MimeMessage message = new MimeMessage(session);
            message.addRecipients(Message.RecipientType.TO, "<送信先メールアドレス>");
            message.setFrom(new InternetAddress(FROM_ADDRESS));
            message.setSubject("テストメール", "ISO-2022-JP");
            message.setText("テスト", "ISO-2022-JP");

            transport.sendMessage(message, message.getAllRecipients());

        }catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

  • クライアントID:「アプリケーションの登録」の 5. の手順でメモした アプリケーション (クライアント) ID
  • テナントID:「アプリケーションの登録」の 5. の手順でメモした テナントID
  • クライアントシークレット:「アプリケーションの登録」の 8. の手順でメモした クライアントシークレット

App.java を実行すると、送信先メールアドレスにメールが送信されます。

※ 当記事の検証で使用したJavaのバージョン:17

アバター画像
About 木村 29 Articles
Azureなどのクラウドでの稼働を主としたアプリケーション開発を行なっています。
ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。


ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる