调用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简陋版的邮箱登录

⭐结束

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

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

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

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

💖 感谢你的阅读!

相关推荐
玩电脑的辣条哥2 小时前
Python如何播放本地音乐并在web页面播放
开发语言·前端·python
ew452182 小时前
ElementUI表格表头自定义添加checkbox,点击选中样式不生效
前端·javascript·elementui
suibian52352 小时前
AI时代:前端开发的职业发展路径拓宽
前端·人工智能
Moon.92 小时前
el-table的hasChildren不生效?子级没数据还显示箭头号?树形数据无法展开和收缩
前端·vue.js·html
垚垚 Securify 前沿站2 小时前
深入了解 AppScan 工具的使用:筑牢 Web 应用安全防线
运维·前端·网络·安全·web安全·系统安全
工业甲酰苯胺5 小时前
Vue3 基础概念与环境搭建
前端·javascript·vue.js
mosquito_lover16 小时前
怎么把pyqt界面做的像web一样漂亮
前端·python·pyqt
柴柴的小记9 小时前
前端vue引入特殊字体不生效
前端·javascript·vue.js
柠檬豆腐脑9 小时前
从前端到全栈:新闻管理系统及多个应用端展示
前端·全栈
bin91539 小时前
DeepSeek 助力 Vue 开发:打造丝滑的颜色选择器(Color Picker)
前端·javascript·vue.js·ecmascript·deepseek