ms365-mcp-server
Version:
Microsoft 365 MCP Server for managing Microsoft 365 email through natural language interactions with full OAuth2 authentication support
391 lines (390 loc) • 14.6 kB
JavaScript
import { logger } from './api.js';
export var EmailCategory;
(function (EmailCategory) {
EmailCategory["GOVERNMENT"] = "government";
EmailCategory["TAX"] = "tax";
EmailCategory["LEGAL"] = "legal";
EmailCategory["FINANCIAL"] = "financial";
EmailCategory["HEALTHCARE"] = "healthcare";
EmailCategory["INSURANCE"] = "insurance";
EmailCategory["DEADLINE"] = "deadline";
EmailCategory["INVOICE"] = "invoice";
EmailCategory["CONTRACT"] = "contract";
EmailCategory["SECURITY"] = "security";
EmailCategory["COMPLIANCE"] = "compliance";
EmailCategory["NOTIFICATION"] = "notification";
EmailCategory["SPAM"] = "spam";
EmailCategory["PERSONAL"] = "personal";
EmailCategory["BUSINESS"] = "business";
EmailCategory["URGENT"] = "urgent";
EmailCategory["AUTOMATED"] = "automated";
})(EmailCategory || (EmailCategory = {}));
export class ProactiveIntelligence {
constructor(ms365Operations) {
this.ms365Operations = ms365Operations;
}
/**
* Classify a single email
*/
classifyEmail(email) {
const matchedRules = [];
const categories = [];
const reasons = [];
let maxPriority = 'low';
let totalConfidence = 0;
for (const rule of ProactiveIntelligence.CLASSIFICATION_RULES) {
const match = this.evaluateRule(email, rule);
if (match.isMatch) {
matchedRules.push(rule.id);
categories.push(rule.category);
reasons.push(match.reason);
totalConfidence += match.confidence;
// Update priority
if (this.getPriorityScore(rule.priority) > this.getPriorityScore(maxPriority)) {
maxPriority = rule.priority;
}
}
}
const averageConfidence = matchedRules.length > 0 ? totalConfidence / matchedRules.length : 0;
const actions = this.generateActions(categories, maxPriority);
return {
email,
categories,
priority: maxPriority,
confidence: averageConfidence,
matchedRules,
reasons,
actions
};
}
/**
* Evaluate a classification rule against an email
*/
evaluateRule(email, rule) {
let matches = 0;
let totalChecks = 0;
const matchDetails = [];
const emailText = {
senderDomain: email.from.address.split('@')[1]?.toLowerCase() || '',
senderName: email.from.name.toLowerCase(),
subject: email.subject.toLowerCase(),
body: email.bodyPreview.toLowerCase(),
combined: `${email.from.name} ${email.subject} ${email.bodyPreview}`.toLowerCase()
};
// Check sender domains
if (rule.patterns.senderDomains) {
totalChecks++;
for (const domain of rule.patterns.senderDomains) {
if (emailText.senderDomain.includes(domain.toLowerCase())) {
matches++;
matchDetails.push(`sender domain: ${domain}`);
break;
}
}
}
// Check sender names
if (rule.patterns.senderNames) {
totalChecks++;
for (const name of rule.patterns.senderNames) {
if (emailText.senderName.includes(name.toLowerCase())) {
matches++;
matchDetails.push(`sender name: ${name}`);
break;
}
}
}
// Check subject keywords
if (rule.patterns.subjectKeywords) {
totalChecks++;
for (const keyword of rule.patterns.subjectKeywords) {
if (emailText.subject.includes(keyword.toLowerCase())) {
matches++;
matchDetails.push(`subject keyword: ${keyword}`);
break;
}
}
}
// Check body keywords
if (rule.patterns.bodyKeywords) {
totalChecks++;
for (const keyword of rule.patterns.bodyKeywords) {
if (emailText.body.includes(keyword.toLowerCase())) {
matches++;
matchDetails.push(`body keyword: ${keyword}`);
break;
}
}
}
// Check combined keywords
if (rule.patterns.combinedKeywords) {
totalChecks++;
for (const keyword of rule.patterns.combinedKeywords) {
if (emailText.combined.includes(keyword.toLowerCase())) {
matches++;
matchDetails.push(`combined keyword: ${keyword}`);
break;
}
}
}
// Determine if rule matches
let isMatch = false;
const confidence = totalChecks > 0 ? matches / totalChecks : 0;
if (rule.conditions.matchType === 'any') {
isMatch = matches > 0;
}
else if (rule.conditions.matchType === 'all') {
isMatch = matches === totalChecks;
}
if (rule.conditions.minimumMatches) {
isMatch = matches >= rule.conditions.minimumMatches;
}
if (rule.conditions.confidenceThreshold) {
isMatch = isMatch && confidence >= rule.conditions.confidenceThreshold;
}
return {
isMatch,
confidence,
reason: `${rule.name}: ${matchDetails.join(', ')}`
};
}
/**
* Get priority score for comparison
*/
getPriorityScore(priority) {
switch (priority) {
case 'critical': return 4;
case 'high': return 3;
case 'medium': return 2;
case 'low': return 1;
default: return 0;
}
}
/**
* Generate recommended actions based on classification
*/
generateActions(categories, priority) {
const actions = [];
if (priority === 'critical') {
actions.push('Mark as high priority');
actions.push('Add to urgent folder');
}
if (categories.includes(EmailCategory.GOVERNMENT)) {
actions.push('File in government folder');
actions.push('Set reminder for response');
}
if (categories.includes(EmailCategory.TAX)) {
actions.push('File in tax documents');
actions.push('Check for deadline');
}
if (categories.includes(EmailCategory.DEADLINE)) {
actions.push('Set calendar reminder');
actions.push('Flag for follow-up');
}
if (categories.includes(EmailCategory.LEGAL)) {
actions.push('File in legal folder');
actions.push('Consider legal review');
}
if (categories.includes(EmailCategory.FINANCIAL)) {
actions.push('File in financial folder');
actions.push('Verify sender authenticity');
}
return actions;
}
/**
* Batch classify multiple emails
*/
async batchClassifyEmails(emails) {
const results = new Map();
logger.log(`🎯 Classifying ${emails.length} emails`);
for (const email of emails) {
try {
const classification = this.classifyEmail(email);
results.set(email.id, classification);
}
catch (error) {
logger.error(`Error classifying email ${email.id}:`, error);
}
}
const criticalEmails = Array.from(results.values()).filter(r => r.priority === 'critical').length;
const highPriorityEmails = Array.from(results.values()).filter(r => r.priority === 'high').length;
logger.log(`🎯 Classification complete: ${criticalEmails} critical, ${highPriorityEmails} high priority`);
return results;
}
/**
* Get emails by category
*/
getEmailsByCategory(classifications, category) {
return Array.from(classifications.values())
.filter(result => result.categories.includes(category))
.sort((a, b) => this.getPriorityScore(b.priority) - this.getPriorityScore(a.priority));
}
/**
* Get high priority emails
*/
getHighPriorityEmails(classifications) {
return Array.from(classifications.values())
.filter(result => result.priority === 'critical' || result.priority === 'high')
.sort((a, b) => this.getPriorityScore(b.priority) - this.getPriorityScore(a.priority));
}
/**
* Generate classification summary
*/
generateClassificationSummary(classifications) {
const results = Array.from(classifications.values());
const byPriority = {
critical: results.filter(r => r.priority === 'critical').length,
high: results.filter(r => r.priority === 'high').length,
medium: results.filter(r => r.priority === 'medium').length,
low: results.filter(r => r.priority === 'low').length
};
const categoryCount = new Map();
const reasonCount = new Map();
const actionCount = new Map();
for (const result of results) {
// Count categories
for (const category of result.categories) {
categoryCount.set(category, (categoryCount.get(category) || 0) + 1);
}
// Count reasons
for (const reason of result.reasons) {
reasonCount.set(reason, (reasonCount.get(reason) || 0) + 1);
}
// Count actions
for (const action of result.actions) {
actionCount.set(action, (actionCount.get(action) || 0) + 1);
}
}
const byCategory = Object.fromEntries(categoryCount);
const topReasons = Array.from(reasonCount.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, 10)
.map(([reason]) => reason);
const recommendedActions = Array.from(actionCount.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, 10)
.map(([action]) => action);
return {
totalEmails: results.length,
byPriority,
byCategory,
topReasons,
recommendedActions
};
}
}
ProactiveIntelligence.CLASSIFICATION_RULES = [
// Government emails
{
id: 'gov_federal',
name: 'Federal Government',
category: EmailCategory.GOVERNMENT,
priority: 'critical',
patterns: {
senderDomains: ['.gov', '.mil', 'irs.gov', 'ssa.gov', 'treasury.gov'],
senderNames: ['Internal Revenue Service', 'Social Security', 'Treasury', 'IRS'],
combinedKeywords: ['federal', 'government', 'official', 'notice']
},
conditions: { matchType: 'any', confidenceThreshold: 0.8 }
},
// Tax notices
{
id: 'tax_notice',
name: 'Tax Notice',
category: EmailCategory.TAX,
priority: 'critical',
patterns: {
subjectKeywords: ['tax', 'irs', 'notice', 'refund', 'audit', 'filing'],
bodyKeywords: ['tax return', 'refund', 'audit', 'tax due', 'payment'],
senderDomains: ['irs.gov', 'treasury.gov']
},
conditions: { matchType: 'any', minimumMatches: 2 }
},
// Legal documents
{
id: 'legal_doc',
name: 'Legal Document',
category: EmailCategory.LEGAL,
priority: 'high',
patterns: {
subjectKeywords: ['legal', 'court', 'lawsuit', 'summons', 'subpoena'],
bodyKeywords: ['attorney', 'lawyer', 'court', 'legal action', 'litigation'],
senderNames: ['Attorney', 'Legal', 'Court', 'Law Firm']
},
conditions: { matchType: 'any', minimumMatches: 1 }
},
// Financial institutions
{
id: 'financial_inst',
name: 'Financial Institution',
category: EmailCategory.FINANCIAL,
priority: 'high',
patterns: {
senderDomains: ['bank', 'credit', 'financial', 'investment'],
subjectKeywords: ['account', 'statement', 'balance', 'transaction'],
bodyKeywords: ['account number', 'balance', 'transaction', 'payment']
},
conditions: { matchType: 'any', minimumMatches: 1 }
},
// Healthcare
{
id: 'healthcare',
name: 'Healthcare',
category: EmailCategory.HEALTHCARE,
priority: 'high',
patterns: {
senderNames: ['Hospital', 'Medical', 'Doctor', 'Clinic', 'Health'],
subjectKeywords: ['appointment', 'medical', 'health', 'prescription'],
bodyKeywords: ['patient', 'medical', 'health', 'appointment', 'prescription']
},
conditions: { matchType: 'any', minimumMatches: 1 }
},
// Insurance
{
id: 'insurance',
name: 'Insurance',
category: EmailCategory.INSURANCE,
priority: 'high',
patterns: {
senderNames: ['Insurance', 'Policy', 'Claims'],
subjectKeywords: ['policy', 'claim', 'coverage', 'premium'],
bodyKeywords: ['policy number', 'claim', 'coverage', 'premium', 'deductible']
},
conditions: { matchType: 'any', minimumMatches: 1 }
},
// Deadline-sensitive
{
id: 'deadline',
name: 'Deadline/Urgent',
category: EmailCategory.DEADLINE,
priority: 'critical',
patterns: {
subjectKeywords: ['deadline', 'due', 'expires', 'urgent', 'asap'],
bodyKeywords: ['deadline', 'due date', 'expires', 'urgent', 'immediately']
},
conditions: { matchType: 'any', minimumMatches: 1 }
},
// Invoices
{
id: 'invoice',
name: 'Invoice/Bill',
category: EmailCategory.INVOICE,
priority: 'medium',
patterns: {
subjectKeywords: ['invoice', 'bill', 'payment', 'receipt'],
bodyKeywords: ['invoice number', 'amount due', 'payment', 'bill']
},
conditions: { matchType: 'any', minimumMatches: 1 }
},
// Security alerts
{
id: 'security',
name: 'Security Alert',
category: EmailCategory.SECURITY,
priority: 'critical',
patterns: {
subjectKeywords: ['security', 'alert', 'breach', 'unauthorized', 'suspicious'],
bodyKeywords: ['security', 'breach', 'unauthorized', 'login', 'password']
},
conditions: { matchType: 'any', minimumMatches: 1 }
}
];