文章目录
- ⭐前言
- ⭐注册azure应用
- 💖添加权限
- ⭐调用npm 实现收发邮件
- 💖安装依赖
- 💖创建appSettings.js 放置密钥
- 💖创建graphHelper.js封装功能
- 💖主文件index.js 对外暴露
- 💖效果
- ⭐结束
⭐前言
大家好,我是yma16,本文分享 调用azure的npm实现outlook_api模拟查看邮件、发送邮件。
背景:
模拟outlook邮件客户端收发邮件
官网教程:
https://learn.microsoft.com/zh-cn/graph/tutorials/javascript?context=outlook%2Fcontext&tabs=aad
⭐注册azure应用
记住客户端id和租户id,验证使用
💖添加权限
身份验证打开允许客户端流
添加email api
⭐调用npm 实现收发邮件
💖安装依赖
安装官方身份验证库 @azure/identity
💖创建appSettings.js 放置密钥
管理密钥文件appSettings.js
💖创建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;
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
💖主文件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();
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
💖效果
运行首先需要授权
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简陋版的邮箱登录
⭐结束
本文分享到这结束,如有错误或者不足之处欢迎指出!
👍 点赞,是我创作的动力!
⭐️ 收藏,是我努力的方向!
✏️ 评论,是我进步的财富!
💖 感谢你的阅读!