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

文章目录

    • ⭐前言
    • ⭐注册azure应用
      • 💖添加权限
    • ⭐调用npm 实现收发邮件
      • 💖安装依赖
      • 💖创建appSettings.js 放置密钥
      • 💖创建graphHelper.js封装功能
      • 💖主文件index.js 对外暴露
      • 💖效果
    • ⭐结束

yma16-logo

⭐前言

大家好,我是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

npm install @azure/identity @microsoft/microsoft-graph-client isomorphic-fetch readline-sync

💖创建appSettings.js 放置密钥

管理密钥文件appSettings.js

const settings = {'clientId': '应用客户端id','tenantId': '应用租户id','graphUserScopes': ['user.read','mail.read','mail.send']
};module.exports = settings;

💖创建graphHelper.js封装功能

graphHelper.js放置功能

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 nullif (!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 undefinedif (!_deviceCodeCredential) {throw new Error('Graph has not been initialized for user auth');}// Ensure scopes isn't undefinedif (!_settings?.graphUserScopes) {throw new Error('Setting "scopes" cannot be undefined');}// Request token with given scopesconst response = await _deviceCodeCredential.getToken(_settings?.graphUserScopes);return response.token;
}
async function getUserAsync() {// Ensure client isn't undefinedif (!_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 undefinedif (!_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 undefinedif (!_userClient) {throw new Error('Graph has not been initialized for user auth');}// Create a new messageconst message = {subject: subject,body: {content: body,contentType: 'text'},toRecipients: [{emailAddress: {address: recipient}}]};// Send the messagereturn _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 功能

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 GraphinitializeGraph(settings);// Greet the user by nameawait 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:// Exitconsole.log('Goodbye...');break;case 0:// Display access tokenawait displayAccessTokenAsync();break;case 1:// List emails from user's inboxawait listInboxAsync();break;case 2:// Send an email messageawait sendMailAsync();break;case 3:// Run any Graph codeawait makeGraphCallAsync();break;default:console.log('Invalid choice! Please try again.');}}
}
function initializeGraph(settings) {// TODOgraphHelper.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() {// TODOtry {const user = await graphHelper.getUserAsync();console.log(`Hello, ${user?.displayName}!`);// For Work/school accounts, email is in mail property// Personal accounts, email is in userPrincipalNameconsole.log(`Email: ${user?.mail ?? user?.userPrincipalName ?? ''}`);} catch (err) {console.log(`Error getting user: ${err}`);}
}async function displayAccessTokenAsync() {// TODOtry {const userToken = await graphHelper.getUserTokenAsync();console.log(`User token: ${userToken}`);} catch (err) {console.log(`Error getting user access token: ${err}`);}}async function listInboxAsync() {// TODOtry {const messagePage = await graphHelper.getInboxAsync();const messages = messagePage.value;// Output each message's detailsfor (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 serverconst moreAvailable = messagePage['@odata.nextLink'] != undefined;console.log(`\nMore messages available? ${moreAvailable}`);} catch (err) {console.log(`Error getting user's inbox: ${err}`);}
}async function sendMailAsync() {// TODOtry {// Send mail to the signed-in user// Get the user for their email addressconst 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() {// TODOtry {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简陋版的邮箱登录

⭐结束

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

👍 点赞,是我创作的动力!
⭐️ 收藏,是我努力的方向!
✏️ 评论,是我进步的财富!
💖 感谢你的阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/394171.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter GPU 是什么?为什么它对 Flutter 有跨时代的意义?

Flutter 3.24 版本引入了 Flutter GPU 概念的新底层图形 API flutter_gpu ,还有 flutter_scene 的 3D 渲染支持库,它们目前都是预览阶段,只能在 main channel 上体验,并且依赖 Impeller 的实现。 Flutter GPU 是 Flutter 内置的底…

2024最新Mysql锁机制与优化实践以及MVCC底层原理剖析

锁机制详解 锁是计算机协调多个进程或线程并发访问某一资源的机制。 在数据库中,除了传统的计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供需要用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解…

3Done学习笔记

一、基本操作 1、旋转视角 使用左下角立方体选择; 右键可以拖动视角; 中间滑轮按住拖动整个舞台界面。 2、平移和旋转 右键选择移动,有两种方式。 第一种选择起始点,按照起始点位置移动到终止点。第二种直接根据轮盘旋转或…

【docker】docker容器部署常用服务

1、容器部署nginx,并且新增一个页面 docker run -d -p 81:80 --name nginx2 nginx docker exec -it nginx2 /bin/bashcd /usr/share/nginx/html/ echo "hello world">>hello.html2、容器部署redis,成功部署后向redis中添加一条数据 do…

【C/C++笔记】:易错难点3 (二叉树)

选择题 🌈eg1 一棵有15个节点的完全二叉树和一棵同样有15个节点的普通二叉树,叶子节点的个数最多会差多少个()? 正确答案: C A. 3 B. 5 C. 7 D. 9 解析:普通二叉树的叶子节…

WPF学习笔记

WPF WPF(Windows Presentation Foundation,Windows呈现基础)是微软推出的基于Windows 的用户界面框架,属于.NET Framework 3.0的一部分。它提供了统一的编程模型、语言和框架,真正做到了分离界面设计人员与开发人员的…

C语言----计算开机时间

计算开机时间 实例说明 编程实现计算开机时间&#xff0c;要求在每次开始计算开机时间时都能接着上次记录的结果向下记录。 实现过程&#xff1a; 1. 在TC中创建一个C文件。 2. 引用头文件&#xff0c;代码如下: #include <stdio.h> 3. 定义结构体time&#xff0c;用来…

如何在Chrome、Edge、360、Firefox等浏览器查看网站SSL证书信息?

在如今的网络环境中&#xff0c;保障网络安全、数据安全尤其重要&#xff0c;市面上大部分网站都部署了SSL证书以实现HTTPS加密保护数据传输安全以及验证网站身份&#xff0c;确保网站安全可信。那么如何查看网站的SSL证书信息&#xff1f;接下来&#xff0c;我们将详细介绍如何…

【Android】网络技术知识总结之WebView,HttpURLConnection,OKHttp,XML的pull解析方式

文章目录 webView使用步骤示例 HttpURLConnection使用步骤示例GET请求POST请求 okHttp使用步骤1. 添加依赖2. 创建OkHttpClient实例3. 创建Request对象构建请求4. 发送请求5. 获取响应 Pull解析方式1. 准备XML数据2. 创建数据类3. 使用Pull解析器解析XML webView WebView 是 An…

【Nacos无压力源码领读】(三) Nacos 配置中心与热更新原理详解 敢说全网最细

本文将从 Nacos 配置中心的基本使用入手, 详细介绍 Nacos 客户端发布配置, 拉取配置, 订阅配置的过程以及服务器对应的处理过程; 配置订阅以及热更新原理相关的部分, 我看了主流的博客网站, 绝对没有比这更详细的讲解; 如果在阅读过程中对文中提到的 SpringBoot 启动过程以及…

Milvus与Zilliz Cloud:向量数据库高可用性的双重飞跃

向量数据库高可用性的重要性及其在现代数据分析中的关键作用 在数据爆炸式增长的今天,企业对于高效、准确地处理和分析大规模数据集的需求日益迫切。尤其是在人工智能、机器学习、图像识别、自然语言处理等领域,向量数据库因其对高维数据的高效存储与检索能力,成为了不可或…

Elasticsearch未授权访问漏洞

步骤一:使用以下Fofa语法进行Elasticsearch产品搜索.. fofa语法"Elasticsearch" && port"9200" 步骤二:存在未授权访问则直接进入到信息页面...不需要输入用户密码登陆. http://localhost:9200/_plugin/head/web管理界面 http://localhost:9200/…

【JavaEE】线程池

目录 前言 什么是线程池 线程池的优点 ThreadPollExecutor中的构造方法 corePoolSize && maximumPoolSize keepAliveTime && unit workQueue threadFactory 如何在java中使用线程池 1.创建线程池对象 2.调用submit添加任务 3.调用shutdown关闭线程池…

【Python】requests的response.text 和 urllib.request 的 response.read()的区别

刚写代码的时候&#xff0c;我经常会把requests 和 urllib下的request 包搞混&#xff0c;这两个请求响应的方法看起来很相似&#xff0c;但是写获取的方法是不一样的。 前者requests 是用response.text 来获取源码&#xff0c;而 urllib.request是用 response.read() 来获取h…

数学建模--智能算法之免疫算法

目录 基本原理 应用实例 代码示例 总结 免疫算法在免疫系统研究中的应用和进展是什么&#xff1f; 如何量化评估免疫算法在不同优化问题中的性能和效率&#xff1f; 免疫算法与其他智能优化算法&#xff08;如遗传算法、粒子群优化&#xff09;相比有哪些独特优势和局限性…

【C++】C++11的新特性 — 线程库 ,原子操作 , 条件变量

勇敢就是接受发生在你身上的事&#xff0c;并把它尽力做到最好。 -- 约翰・欧文 -- C11的新特性 1 线程1.1 线程概念1.2 C中的线程1.3 线程并行1.4 锁 2 原子操作3 条件变量Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;&#xff01;&#xff01;下…

编译和汇编的区别

一、编译 编译是将高级语言&#xff08;如C、C、Java等&#xff09;编写的源代码转换成计算机可以直接执行的低级语言&#xff08;通常是机器语言或汇编语言&#xff09;的过程 编译 —— 将人类可读的源代码转换为计算机可执行的指令集 编译过程 通常包括词法分析、语法分…

正点原子imx6ull-mini-Linux驱动之Linux 网络驱动实验

网络驱动是 linux 里面驱动三巨头之一&#xff0c;linux 下的网络功能非常强大&#xff0c;嵌入式 linux 中也常 常用到网络功能。前面我们已经讲过了字符设备驱动和块设备驱动&#xff0c;本章我们就来学习一下 linux 里面的网络设备驱动。 1&#xff1a;嵌入式网络简介 1.1…

如何给源代码加密?这款加密软件教给你操作步骤

给源代码加密是保护软件知识产权和商业机密的重要手段。以这款加密软件安企神为例&#xff0c;给源代码加密的过程可以概述为以下几个方面。 一、安企神软件概述 安企神是一款功能强大的企业安全加密软件&#xff0c;它提供了全面的源代码防泄漏解决方案。该软件通过透明文件加…

扩散模型系列笔记(一)——DDPM

直观理解 扩散模型分为前向过程&#xff08;扩散过程&#xff0c;Data → \to →Noise&#xff09;和后向过程&#xff08;生成过程或逆扩散过程&#xff0c;Noise → \to →Data&#xff09;。在前向过程中&#xff0c;对于每一个观测样本&#xff0c;不断向样本中添加少量噪…