简体   繁体   English

如何使用 Java 中的 MSAL 从 Microsoft Outlook 发送电子邮件?

[英]How can I send an e-mail from Microsoft Outlook using MSAL in Java?

I'm trying to develop an application in Java / Spring that connects to an Microsoft Outlook / Exchange SMTP Relay to send e-mails using MSAL4J, but I keep getting an authentication error when I try to connect to the mail server.我正在尝试使用 Java / Spring 开发一个应用程序,该应用程序连接到 Microsoft Outlook / Exchange SMTP 中继以使用 MSAL4J 发送电子邮件,但是当我尝试连接到邮件服务器时,我不断收到身份验证错误。

Am I doing anything wrong here?我在这里做错什么了吗?

package com.email;

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 org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;

import java.net.MalformedURLException;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class SmtpTestMSAL {

    private static final String clientId = "<removed>";
    private static final String tenantId = "<removed>";
    private static final String secret = "<removed>";
    private static final String to = "<removed>";
    private static final String from = "<removed>";
    private static final String pwd = "<removed>";

    private static final String authUrl = "https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/authorize";
    private static final Set<String> scope = Set.of("https://graph.microsoft.com/.default");

    public static void main(String[] args) throws MalformedURLException, ExecutionException, InterruptedException {
        String token = getAccessToken();

        System.out.println("token: " + token);

        JavaMailSender mailSender = prepareSender(token);
        SimpleMailMessage message = new SimpleMailMessage();

        message.setFrom(from);
        message.setTo(to);
        message.setSubject("testing modern auth");
        message.setText("testing modern auth");

        mailSender.send(message);
    }

    private static String getAccessToken() throws MalformedURLException, ExecutionException, InterruptedException {
        ConfidentialClientApplication app = ConfidentialClientApplication
                .builder(
                        clientId,
                        ClientCredentialFactory.createFromSecret(secret)
                )
                .authority(authUrl)
                .build();

        ClientCredentialParameters clientCredentialParam = ClientCredentialParameters
                .builder(scope)
                .build();

        CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);

        return future.get().accessToken();
    }

    private static JavaMailSender prepareSender(String oauthToken) {

        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        Properties props = mailSender.getJavaMailProperties();

        mailSender.setHost("smtp.office365.com");
        mailSender.setPort(587);
        mailSender.setUsername(from);
        mailSender.setPassword(pwd);

        props.put("mail.debug", "true");
        props.put("mail.debug.auth", "true");
        props.put("mail.smtp.starttls.required", "true");
        props.put("mail.smtp.sasl.enable", "true");
        props.put("mail.smtp.sasl.mechanisms", "XOAUTH2");
        props.put("mail.smtp.sasl.mechanisms.oauth2.oauthToken", oauthToken);
        props.put("mail.transport.protocol", "smtp");

        return mailSender;
    }
}

this is the log of the SMTP session:这是 SMTP 会话的日志:

DEBUG: Jakarta Mail version 1.6.7
DEBUG: successfully loaded resource: /META-INF/javamail.default.providers
DEBUG: Tables of loaded providers
DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle]}
DEBUG: Providers Listed By Protocol: {imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle]}
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: enable SASL
DEBUG SMTP: useEhlo true, useAuth false
DEBUG SMTP: trying to connect to host "smtp.office365.com", port 587, isSSL false
220 <removed>.outlook.office365.com Microsoft ESMTP MAIL Service ready at Fri, 13 May 2022 13:36:12 +0000
DEBUG SMTP: connected to host "smtp.office365.com", port: 587
EHLO pc-364.home
250-<removed>.outlook.office365.com Hello [37.135.92.227]
250-SIZE 157286400
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-STARTTLS
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "157286400"
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "DSN", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "BINARYMIME", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
STARTTLS
220 2.0.0 SMTP server ready
EHLO pc-364.home
250-PAZP264CA0194.outlook.office365.com Hello [37.135.92.227]
250-SIZE 157286400
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-AUTH LOGIN XOAUTH2
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "157286400"
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "DSN", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN XOAUTH2"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "BINARYMIME", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
DEBUG SMTP: protocolConnect login, host=smtp.office365.com, user=<removed>, password=<non-null>
DEBUG SMTP: Authenticate with SASL
DEBUG SMTP: SASL mechanisms allowed: XOAUTH2
DEBUG SMTP: SASL Mechanisms:
DEBUG SMTP:  XOAUTH2
DEBUG SMTP: 
DEBUG SMTP: SASL client XOAUTH2
DEBUG SMTP: SASL callback length: 2
DEBUG SMTP: SASL callback 0: javax.security.auth.callback.NameCallback@1188e820
DEBUG SMTP: SASL callback 1: javax.security.auth.callback.PasswordCallback@2f490758
AUTH XOAUTH2 <removed>
535 5.7.3 Authentication unsuccessful [<removed>.OUTLOOK.COM]
DEBUG SMTP: SASL authentication failed

Any help is super appreciated!任何帮助都非常感谢!

Ok, I've managed to make it work using Microsoft Graph API instead of MSAL, posting an example here in case anyone ever needs it:好的,我已经设法使用 Microsoft Graph API 而不是 MSAL 使其工作,在这里发布一个示例以防万一有人需要它:

package com.email;

import com.azure.identity.UsernamePasswordCredential;
import com.azure.identity.UsernamePasswordCredentialBuilder;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.models.BodyType;
import com.microsoft.graph.models.EmailAddress;
import com.microsoft.graph.models.ItemBody;
import com.microsoft.graph.models.Message;
import com.microsoft.graph.models.Recipient;
import com.microsoft.graph.models.UserSendMailParameterSet;
import com.microsoft.graph.requests.GraphServiceClient;
import okhttp3.Request;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Set;

public class GraphAPIExample {

    private static final String clientId = System.getenv("SMTP_CLIENT_ID");
    private static final String to = "your@email.com";
    private static final String mailbox = System.getenv("SMTP_MAILBOX");
    private static final String pwd = System.getenv("SMTP_MAILBOX_PWD");

    private static final Set<String> scopes = Set.of("Mail.Send");

    public static void main(String[] args) {
        final UsernamePasswordCredential usernamePasswordCredential = new UsernamePasswordCredentialBuilder()
                .clientId(clientId)
                .username(mailbox)
                .password(pwd)
                .build();

        final TokenCredentialAuthProvider tokenCredentialAuthProvider = new TokenCredentialAuthProvider(new ArrayList<>(scopes), usernamePasswordCredential);

        final GraphServiceClient<Request> graphClient =
                GraphServiceClient
                        .builder()
                        .authenticationProvider(tokenCredentialAuthProvider)
                        .buildClient();

        graphClient.me()
                .sendMail(UserSendMailParameterSet
                        .newBuilder()
                        .withMessage(createMessage())
                        .build())
                .buildRequest()
                .post();
    }

    private static Message createMessage() {
        Message message = new Message();
        ItemBody body = new ItemBody();

        message.subject = "testing modern auth";

        body.contentType = BodyType.TEXT;
        body.content = "testing modern auth";
        message.body = body;

        LinkedList<Recipient> toRecipientsList = new LinkedList<>();
        Recipient toRecipients = new Recipient();
        EmailAddress emailAddress = new EmailAddress();
        emailAddress.address = to;
        toRecipients.emailAddress = emailAddress;
        toRecipientsList.add(toRecipients);
        message.toRecipients = toRecipientsList;

        return message;
    }
}

You're going to need the following dependencies to run this example:您将需要以下依赖项来运行此示例:

implementation("com.microsoft.graph:microsoft-graph:5.23.0")
implementation("com.azure:azure-identity:1.5.1")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM