调用azure的npm实现outlook_api模拟查看邮件、发送邮件(实现web版接受outlook邮件第一步)

文章目录

⭐前言

大家好,我是yma16,本文分享 调用azure的npm实现outlook_api模拟查看邮件、发送邮件。

背景:

模拟outlook邮件客户端收发邮件

该系列往期文章:
前端笔记_OAuth规则机制下实现个人站点接入qq三方登录
OAuth机制_web站点接入微软azure账号进行三方登录

官网教程:
https://learn.microsoft.com/zh-cn/graph/tutorials/javascript?context=outlook%2Fcontext&tabs=aad

⭐注册azure应用

记住客户端id和租户id,验证使用

💖添加权限

身份验证打开允许客户端流

添加email api

⭐调用npm 实现收发邮件

💖安装依赖

安装官方身份验证库 @azure/identity

bash 复制代码
npm install @azure/identity @microsoft/microsoft-graph-client isomorphic-fetch readline-sync

💖创建appSettings.js 放置密钥

管理密钥文件appSettings.js

javascript 复制代码
const settings = {
    'clientId': '应用客户端id',
    'tenantId': '应用租户id',
    'graphUserScopes': [
        'user.read',
        'mail.read',
        'mail.send'
    ]
};

module.exports = settings;

💖创建graphHelper.js封装功能

graphHelper.js放置功能

javascript 复制代码
require('isomorphic-fetch');
const azure = require('@azure/identity');
const graph = require('@microsoft/microsoft-graph-client');
const authProviders =
    require('@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials');

let _settings = undefined;
let _deviceCodeCredential = undefined;
let _userClient = undefined;

function initializeGraphForUserAuth(settings, deviceCodePrompt) {
    // Ensure settings isn't null
    if (!settings) {
        throw new Error('Settings cannot be undefined');
    }

    _settings = settings;

    _deviceCodeCredential = new azure.DeviceCodeCredential({
        clientId: settings.clientId,
        tenantId: settings.tenantId,
        userPromptCallback: deviceCodePrompt
    });

    const authProvider = new authProviders.TokenCredentialAuthenticationProvider(
        _deviceCodeCredential, {
            scopes: settings.graphUserScopes
        });

    _userClient = graph.Client.initWithMiddleware({
        authProvider: authProvider
    });
}
async function getUserTokenAsync() {
    // Ensure credential isn't undefined
    if (!_deviceCodeCredential) {
        throw new Error('Graph has not been initialized for user auth');
    }

    // Ensure scopes isn't undefined
    if (!_settings?.graphUserScopes) {
        throw new Error('Setting "scopes" cannot be undefined');
    }

    // Request token with given scopes
    const response = await _deviceCodeCredential.getToken(_settings?.graphUserScopes);
    return response.token;
}
async function getUserAsync() {
    // Ensure client isn't undefined
    if (!_userClient) {
        throw new Error('Graph has not been initialized for user auth');
    }

    return _userClient.api('/me')
    // Only request specific properties
        .select(['displayName', 'mail', 'userPrincipalName'])
        .get();
}
async function getInboxAsync() {
    // Ensure client isn't undefined
    if (!_userClient) {
        throw new Error('Graph has not been initialized for user auth');
    }

    return _userClient.api('/me/mailFolders/inbox/messages')
        .select(['from', 'isRead', 'receivedDateTime', 'subject'])
        .top(25)
        .orderby('receivedDateTime DESC')
        .get();
}
async function sendMailAsync(subject, body, recipient) {
    // Ensure client isn't undefined
    if (!_userClient) {
        throw new Error('Graph has not been initialized for user auth');
    }

    // Create a new message
    const message = {
        subject: subject,
        body: {
            content: body,
            contentType: 'text'
        },
        toRecipients: [
            {
                emailAddress: {
                    address: recipient
                }
            }
        ]
    };

    // Send the message
    return _userClient.api('me/sendMail')
        .post({
            message: message
        });
}
// This function serves as a playground for testing Graph snippets
// or other code
async function makeGraphCallAsync() {
    // INSERT YOUR CODE HERE
}
module.exports.makeGraphCallAsync = makeGraphCallAsync;
module.exports.sendMailAsync = sendMailAsync;
module.exports.getInboxAsync = getInboxAsync;
module.exports.getUserAsync = getUserAsync;
module.exports.getUserTokenAsync = getUserTokenAsync;
module.exports.initializeGraphForUserAuth = initializeGraphForUserAuth;

💖主文件index.js 对外暴露

index.js 功能

javascript 复制代码
const readline = require('readline-sync');

const settings = require('./appSettings');
const graphHelper = require('./graphHelper');

async function main() {
    console.log('JavaScript Graph Tutorial');

    let choice = 0;

    // Initialize Graph
    initializeGraph(settings);

    // Greet the user by name
    await greetUserAsync();

    const choices = [
        'Display access token',
        'List my inbox',
        'Send mail',
        'Make a Graph call'
    ];

    while (choice != -1) {
        choice = readline.keyInSelect(choices, 'Select an option', { cancel: 'Exit' });

        switch (choice) {
            case -1:
                // Exit
                console.log('Goodbye...');
                break;
            case 0:
                // Display access token
                await displayAccessTokenAsync();
                break;
            case 1:
                // List emails from user's inbox
                await listInboxAsync();
                break;
            case 2:
                // Send an email message
                await sendMailAsync();
                break;
            case 3:
                // Run any Graph code
                await makeGraphCallAsync();
                break;
            default:
                console.log('Invalid choice! Please try again.');
        }
    }
}
function initializeGraph(settings) {
    // TODO
    graphHelper.initializeGraphForUserAuth(settings, (info) => {
        // Display the device code message to
        // the user. This tells them
        // where to go to sign in and provides the
        // code to use.
        console.log(info.message);
    });
}

async function greetUserAsync() {
    // TODO

    try {
        const user = await graphHelper.getUserAsync();
        console.log(`Hello, ${user?.displayName}!`);
        // For Work/school accounts, email is in mail property
        // Personal accounts, email is in userPrincipalName
        console.log(`Email: ${user?.mail ?? user?.userPrincipalName ?? ''}`);
    } catch (err) {
        console.log(`Error getting user: ${err}`);
    }
}



async function displayAccessTokenAsync() {
    // TODO
    try {
        const userToken = await graphHelper.getUserTokenAsync();
        console.log(`User token: ${userToken}`);
    } catch (err) {
        console.log(`Error getting user access token: ${err}`);
    }

}

async function listInboxAsync() {
    // TODO
    try {
        const messagePage = await graphHelper.getInboxAsync();
        const messages = messagePage.value;

        // Output each message's details
        for (const message of messages) {
            console.log(`Message: ${message.subject ?? 'NO SUBJECT'}`);
            console.log(`  From: ${message.from?.emailAddress?.name ?? 'UNKNOWN'}`);
            console.log(`  Status: ${message.isRead ? 'Read' : 'Unread'}`);
            console.log(`  Received: ${message.receivedDateTime}`);
        }

        // If @odata.nextLink is not undefined, there are more messages
        // available on the server
        const moreAvailable = messagePage['@odata.nextLink'] != undefined;
        console.log(`\nMore messages available? ${moreAvailable}`);
    } catch (err) {
        console.log(`Error getting user's inbox: ${err}`);
    }
}

async function sendMailAsync() {
    // TODO
    try {
        // Send mail to the signed-in user
        // Get the user for their email address
        const user = await graphHelper.getUserAsync();
        const userEmail = user?.mail ?? user?.userPrincipalName;

        if (!userEmail) {
            console.log('Couldn\'t get your email address, canceling...');
            return;
        }

        await graphHelper.sendMailAsync('Testing Microsoft Graph',
            'Hello world!', userEmail);
        console.log('Mail sent.');
    } catch (err) {
        console.log(`Error sending mail: ${err}`);
    }
}

async function makeGraphCallAsync() {
    // TODO
    try {
        await graphHelper.makeGraphCallAsync();
    } catch (err) {
        console.log(`Error making Graph call: ${err}`);
    }
}

main();

💖效果

运行首先需要授权

To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code S6HDWLLQ3 to authenticate.

手动授权输入返回的验证码

登录outlook

登录成功

可以打印token

后续把这个放在koa暴露接口可以实现web简陋版的邮箱登录

⭐结束

本文分享到这结束,如有错误或者不足之处欢迎指出!

👍 点赞,是我创作的动力!

⭐️ 收藏,是我努力的方向!

✏️ 评论,是我进步的财富!

💖 感谢你的阅读!

相关推荐
粥里有勺糖1 天前
视野修炼-技术周刊第126期 | TypeScript #1
前端·node.js·github
冰暮流星1 天前
css3新增过渡
前端·css·css3
天黑请闭眼1 天前
视频文件上传至服务器后浏览器无法在线播放
前端
一位搞嵌入式的 genius1 天前
前端实战开发(四):从迭代器到异步编程:ES6 Generator 全面解析 + 实战问题排查
开发语言·前端·es6·前端实战
拉不动的猪1 天前
# 关于初学者对于JS异步编程十大误区
前端·javascript·面试
玖釉-1 天前
解决PowerShell执行策略导致的npm脚本无法运行问题
前端·npm·node.js
Larcher1 天前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐1 天前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭1 天前
如何理解HTML语义化
前端·html
jump6801 天前
url输入到网页展示会发生什么?
前端