繁体   English   中英

使用用户凭据通过 Microsoft Graph API 通过控制台应用程序发送 email

[英]Send email via console app over Microsoft Graph API using user credentials

我已经调整了Java 控制台应用程序,让用户使用用户名/密码登录以代表他们调用 Microsoft Graph API,而不是检索基本用户数据来发送电子邮件。

但是,虽然原始示例运行良好(我得到用户 email,请参见下面的注释代码),但在发送电子邮件时出现此错误:

Graph service exception Error code: NoPermissionsInAccessToken
Error message: The token contains no permissions, or permissions can not be understood.

对于此操作 Mail.Send scope 需要在 Azure 门户中定义,并且无需管理员同意即可使用。 在此处输入图像描述

我使用这些 Microsoft 依赖项:

<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>msal4j</artifactId>
    <version>1.6.1</version>
</dependency>
<dependency>
    <groupId>com.microsoft.graph</groupId>
    <artifactId>microsoft-graph</artifactId>
    <version>1.6.0</version>
</dependency>

这是实际的代码:

public class MicrosoftGraphMailer {

    private final static String CLIENT_APP_ID = "{real-client-app-id}";
    private final static String AUTHORITY = "https://login.microsoftonline.com/{real-tenant-id}/";

    public static void main(String[] args) throws Exception {

        String user = "{real-user}";
        String password = "{real-password}";

        String token = getUserPasswordAccessToken(user, password).accessToken();
        System.out.println(token);

        SimpleAuthProvider authProvider = new SimpleAuthProvider(token);
        IGraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();

        Message message = new Message();
        message.subject = "My subject";

        ItemBody body = new ItemBody();
        body.contentType = BodyType.HTML;
        body.content = "<h1>My HTML body</h1>";
        message.body = body;

        List<Recipient> toRecipientList = new LinkedList<>();
        Recipient toRecipient = new Recipient();
        EmailAddress emailAddress = new EmailAddress();
        emailAddress.address = "{real-recipient}";
        toRecipient.emailAddress = emailAddress;
        toRecipientList.add(toRecipient);
        message.toRecipients = toRecipientList;

        graphClient.me()
                .sendMail(message, false)
                .buildRequest()
                .post();

/*
         String mail = graphClient.me()
                .buildRequest()
                .get().mail;

         System.out.println(mail);
*/
    }

    private static IAuthenticationResult getUserPasswordAccessToken(String user, String password) throws Exception {

        PublicClientApplication app = PublicClientApplication.builder(CLIENT_APP_ID).authority(AUTHORITY).build();

        Set<String> scopes = new HashSet<>(Arrays.asList("Mail.Send"));

        UserNamePasswordParameters userNamePasswordParam = UserNamePasswordParameters.builder(
                scopes, user, password.toCharArray())
                .build();

        return app.acquireToken(userNamePasswordParam).get();
    }

    private static class SimpleAuthProvider implements IAuthenticationProvider {

        private String accessToken = null;

        public SimpleAuthProvider(String accessToken) {
            this.accessToken = accessToken;
        }

        @Override
        public void authenticateRequest(IHttpRequest request) {
            request.addHeader("Authorization", "Bearer " + accessToken);
        }
    }
}

基本上我需要控制台守护程序应用程序来代表我发送电子邮件而无需任何用户交互。 凭据将存储在应用程序之外。 我不需要代表任意用户发送电子邮件的权限。

通常,只有当它没有向图形发送令牌或向图形发送有效令牌时,才会出现该错误消息。 要进行调试,我将首先获取令牌并通过将其粘贴到 jwt.ms 或查看所需范围是否按预期在令牌中进行解码。 我还想知道是否不请求 user.read scope 会导致 mail.send 出现问题

另外,您说不需要给予管理员同意,但在您的情况下确实如此。 因为如果管理员不同意,那么用户必须同意。 但是由于您是无头执行此操作,因此用户没有机会同意。 这意味着没有人同意此应用程序以您的身份发送邮件。

暂无
暂无

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

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