【问题标题】:Send email via console app over Microsoft Graph API using user credentials使用用户凭据通过 Microsoft Graph API 通过控制台应用发送电子邮件
【发布时间】:2020-07-07 12:24:48
【问题描述】:

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

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

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

对于此操作,需要在 Azure 门户中定义 Mail.Send 范围,并且无需管理员同意即可使用。

我使用这些 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);
        }
    }
}

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

【问题讨论】:

  • 您是否同意 Azure 门户中的租户?是您链接到的示例中的步骤 3.7。

标签: java microsoft-graph-api msal


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2021-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-28
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    相关资源
    最近更新 更多