msexchange-mcp
Version:
MCP server for Microsoft Exchange/Outlook email operations via Microsoft Graph API
180 lines • 5.13 kB
JavaScript
/**
* Input validation utilities
*/
/**
* Validate date range
*/
export function validateDateRange(start, end) {
if (!start && !end) {
return { valid: true };
}
let startDate;
let endDate;
// Parse start date
if (start) {
startDate = typeof start === 'string' ? new Date(start) : start;
if (isNaN(startDate.getTime())) {
return {
valid: false,
error: 'Invalid start date format. Use YYYY-MM-DD'
};
}
}
// Parse end date
if (end) {
endDate = typeof end === 'string' ? new Date(end) : end;
if (isNaN(endDate.getTime())) {
return {
valid: false,
error: 'Invalid end date format. Use YYYY-MM-DD'
};
}
}
// Check if start is before end
if (startDate && endDate && startDate > endDate) {
return {
valid: false,
error: 'Start date must be before end date'
};
}
// Check for reasonable date range (e.g., not more than 5 years)
if (startDate && endDate) {
const diffInDays = Math.abs(endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24);
if (diffInDays > 365 * 5) {
return {
valid: false,
error: 'Date range spans more than 5 years. Please narrow your search.'
};
}
}
// Check that dates aren't too far in the future
const now = new Date();
const oneYearFromNow = new Date(now.getFullYear() + 1, now.getMonth(), now.getDate());
if (startDate && startDate > oneYearFromNow) {
return {
valid: false,
error: 'Start date is too far in the future'
};
}
if (endDate && endDate > oneYearFromNow) {
return {
valid: false,
error: 'End date is too far in the future'
};
}
return {
valid: true,
startDate,
endDate
};
}
/**
* Validate email address format
*/
export function validateEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
/**
* Validate and sanitize search query
*/
export function validateSearchQuery(query) {
// Check length
if (query.length > 1000) {
return {
valid: false,
error: 'Search query is too long (max 1000 characters)'
};
}
// Check for problematic characters that might break OData
const problematicChars = /[\x00-\x1F\x7F]/g; // Control characters
if (problematicChars.test(query)) {
return {
valid: false,
error: 'Search query contains invalid control characters'
};
}
// Sanitize by removing extra whitespace
const sanitized = query
.replace(/\s+/g, ' ') // Replace multiple spaces with single space
.trim();
if (sanitized.length === 0) {
return {
valid: false,
error: 'Search query cannot be empty'
};
}
return {
valid: true,
sanitized
};
}
/**
* Validate folder name
*/
export function validateFolderName(name) {
if (!name || name.trim().length === 0) {
return {
valid: false,
error: 'Folder name cannot be empty'
};
}
// Check length
if (name.length > 255) {
return {
valid: false,
error: 'Folder name is too long (max 255 characters)'
};
}
// Check for invalid characters (based on Outlook restrictions)
const invalidChars = /[\\/:*?"<>|]/;
if (invalidChars.test(name)) {
return {
valid: false,
error: 'Folder name contains invalid characters: \\ / : * ? " < > |'
};
}
return { valid: true };
}
/**
* Validate attachment size
*/
export function validateAttachmentSize(base64Content, maxSizeMB = 4) {
// Estimate size from base64 (base64 is ~33% larger than binary)
const estimatedSizeBytes = (base64Content.length * 3) / 4;
const estimatedSizeMB = estimatedSizeBytes / (1024 * 1024);
if (estimatedSizeMB > maxSizeMB) {
return {
valid: false,
error: `Attachment size (${estimatedSizeMB.toFixed(2)}MB) exceeds the ${maxSizeMB}MB limit`,
estimatedSizeMB
};
}
return {
valid: true,
estimatedSizeMB
};
}
/**
* Validate OR query complexity
*/
export function validateOrQueryComplexity(orParts) {
if (orParts.length > 10) {
return {
valid: false,
error: 'OR query has too many parts (max 10). Please simplify your search.'
};
}
// Check if any individual part is too complex
for (const part of orParts) {
const filterCount = (part.match(/:/g) || []).length;
if (filterCount > 5) {
return {
valid: false,
error: 'Individual OR query parts are too complex. Please simplify.'
};
}
}
return { valid: true };
}
//# sourceMappingURL=validators.js.map