文章目录
- ⭐前言
- ⭐注册azure应用
- 💖添加权限
- ⭐调用npm 实现收发邮件
- 💖安装依赖
- 💖创建appSettings.js 放置密钥
- 💖创建graphHelper.js封装功能
- 💖主文件index.js 对外暴露
- 💖效果
- ⭐结束
⭐前言
大家好,我是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 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 功能
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简陋版的邮箱登录
⭐结束
本文分享到这结束,如有错误或者不足之处欢迎指出!
👍 点赞,是我创作的动力!
⭐️ 收藏,是我努力的方向!
✏️ 评论,是我进步的财富!
💖 感谢你的阅读!