outlook-mcp
Version:
Comprehensive MCP server for Claude to access Microsoft Outlook and Teams via Microsoft Graph API - including Email, Calendar, Contacts, Tasks, Teams, Chats, and Online Meetings
166 lines (139 loc) • 5.63 kB
JavaScript
/**
* Script to find and move existing GitHub notification emails
* to the GitHub Notifications subfolder
*/
const https = require('https');
const fs = require('fs');
const path = require('path');
// Configuration
const homePath = process.env.HOME || '/Users/ryaker';
const tokenPath = path.join(homePath, '.outlook-mcp-tokens.json');
const githubFolderId = 'AAMkAGQ0NzYwMTdmLTYzMWUtNDE1ZS04ZDYyLTZjZmQ5YjkyNWM0OQAuAAAAAAAMiw_uRKMyQ4cvWGcmDNGZAQD-pkus0juzTK_ueB_BlgMCAAGKmpqoAAA=';
const notificationsFolderId = 'AAMkAGQ0NzYwMTdmLTYzMWUtNDE1ZS04ZDYyLTZjZmQ5YjkyNWM0OQAuAAAAAAAMiw_uRKMyQ4cvWGcmDNGZAQD-pkus0juzTK_ueB_BlgMCAAGKmpqpAAA=';
// Main function
async function moveGitHubEmails() {
try {
// Read the authentication token from file
console.log(`Reading token from ${tokenPath}`);
const tokenData = JSON.parse(fs.readFileSync(tokenPath, 'utf8'));
const accessToken = tokenData.access_token;
if (!accessToken) {
console.error('No access token found in token file!');
process.exit(1);
}
console.log('Successfully read access token');
// Step 1: Search for GitHub notification emails in the inbox
console.log('\nSearching for GitHub notification emails...');
const searchParams = new URLSearchParams({
$filter: "from/emailAddress/address eq 'notifications@github.com' or from/emailAddress/address eq 'noreply@github.com'",
$top: 100,
$select: 'id,subject,from,receivedDateTime'
});
const inboxEmails = await callGraphAPI(`me/mailFolders/inbox/messages?${searchParams.toString()}`);
console.log(`Found ${inboxEmails.value.length} GitHub notification emails in inbox`);
// Step 2: Classify emails as workflow notifications or other
const workflowEmails = [];
const otherEmails = [];
inboxEmails.value.forEach(email => {
const subject = email.subject.toLowerCase();
if (
subject.includes('workflow') ||
subject.includes('run failed') ||
subject.includes('run completed') ||
subject.includes('github actions')
) {
workflowEmails.push(email);
} else if (subject.includes('[gondola')) {
workflowEmails.push(email); // These are also notifications
} else {
otherEmails.push(email);
}
});
console.log(`Workflow notifications: ${workflowEmails.length}`);
console.log(`Other GitHub emails: ${otherEmails.length}`);
// Step 3: Move workflow notifications to the Notifications subfolder
if (workflowEmails.length > 0) {
console.log('\nMoving workflow notifications to Notifications subfolder...');
let movedCount = 0;
for (const email of workflowEmails) {
try {
await callGraphAPI(`me/messages/${email.id}/move`, 'POST', {
destinationId: notificationsFolderId
});
movedCount++;
console.log(`Moved ${movedCount}/${workflowEmails.length}: "${email.subject}"`);
} catch (error) {
console.error(`Failed to move email: ${error.message}`);
}
}
console.log(`Successfully moved ${movedCount} workflow notifications to Notifications subfolder`);
}
// Step 4: Move other GitHub emails to the main GitHub folder
if (otherEmails.length > 0) {
console.log('\nMoving other GitHub emails to GitHub folder...');
let movedCount = 0;
for (const email of otherEmails) {
try {
await callGraphAPI(`me/messages/${email.id}/move`, 'POST', {
destinationId: githubFolderId
});
movedCount++;
console.log(`Moved ${movedCount}/${otherEmails.length}: "${email.subject}"`);
} catch (error) {
console.error(`Failed to move email: ${error.message}`);
}
}
console.log(`Successfully moved ${movedCount} other GitHub emails to GitHub folder`);
}
console.log('\nEmail organization complete!');
} catch (error) {
console.error('Error:', error);
}
}
/**
* Helper function to call Microsoft Graph API
*/
async function callGraphAPI(endpoint, method = 'GET', data = null) {
return new Promise((resolve, reject) => {
// Read token from file again to ensure it's fresh
const tokenData = JSON.parse(fs.readFileSync(tokenPath, 'utf8'));
const accessToken = tokenData.access_token;
const options = {
hostname: 'graph.microsoft.com',
path: `/v1.0/${endpoint}`,
method: method,
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
};
const req = https.request(options, (res) => {
let responseData = '';
res.on('data', (chunk) => {
responseData += chunk;
});
res.on('end', () => {
if (res.statusCode >= 200 && res.statusCode < 300) {
try {
const jsonResponse = responseData ? JSON.parse(responseData) : {};
resolve(jsonResponse);
} catch (error) {
reject(new Error(`Failed to parse API response: ${error.message}`));
}
} else {
reject(new Error(`API request failed with status ${res.statusCode}: ${responseData}`));
}
});
});
req.on('error', (error) => {
reject(new Error(`Network error: ${error.message}`));
});
if (data && (method === 'POST' || method === 'PATCH' || method === 'PUT')) {
req.write(JSON.stringify(data));
}
req.end();
});
}
// Run the script
moveGitHubEmails();