497 lines
15 KiB
TypeScript
497 lines
15 KiB
TypeScript
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
|
import { startTestSmtpServer } from '../../helpers/server.loader.js';
|
|
import { createSmtpClient } from '../../helpers/smtp.client.js';
|
|
import { Email } from '../../../ts/mail/core/classes.email.js';
|
|
|
|
let testServer: any;
|
|
|
|
tap.test('setup test SMTP server', async () => {
|
|
testServer = await startTestSmtpServer();
|
|
expect(testServer).toBeTruthy();
|
|
expect(testServer.port).toBeGreaterThan(0);
|
|
});
|
|
|
|
tap.test('CEP-09: Basic priority headers', async () => {
|
|
const smtpClient = createSmtpClient({
|
|
host: testServer.hostname,
|
|
port: testServer.port,
|
|
secure: false,
|
|
connectionTimeout: 5000,
|
|
debug: true
|
|
});
|
|
|
|
await smtpClient.connect();
|
|
|
|
// Test different priority levels
|
|
const priorityLevels = [
|
|
{ priority: 'high', headers: { 'X-Priority': '1', 'Importance': 'high' } },
|
|
{ priority: 'normal', headers: { 'X-Priority': '3', 'Importance': 'normal' } },
|
|
{ priority: 'low', headers: { 'X-Priority': '5', 'Importance': 'low' } }
|
|
];
|
|
|
|
for (const level of priorityLevels) {
|
|
console.log(`\nTesting ${level.priority} priority email...`);
|
|
|
|
const email = new Email({
|
|
from: 'sender@example.com',
|
|
to: ['recipient@example.com'],
|
|
subject: `${level.priority.toUpperCase()} Priority Test`,
|
|
text: `This is a ${level.priority} priority message`,
|
|
priority: level.priority as 'high' | 'normal' | 'low'
|
|
});
|
|
|
|
// Monitor headers
|
|
const sentHeaders: { [key: string]: string } = {};
|
|
const originalSendCommand = smtpClient.sendCommand.bind(smtpClient);
|
|
|
|
smtpClient.sendCommand = async (command: string) => {
|
|
if (command.includes(':') && !command.startsWith('MAIL') && !command.startsWith('RCPT')) {
|
|
const [key, value] = command.split(':').map(s => s.trim());
|
|
if (key === 'X-Priority' || key === 'Importance' || key === 'X-MSMail-Priority') {
|
|
sentHeaders[key] = value;
|
|
}
|
|
}
|
|
return originalSendCommand(command);
|
|
};
|
|
|
|
const result = await smtpClient.sendMail(email);
|
|
expect(result).toBeTruthy();
|
|
|
|
console.log('Priority headers sent:');
|
|
Object.entries(sentHeaders).forEach(([key, value]) => {
|
|
console.log(` ${key}: ${value}`);
|
|
});
|
|
}
|
|
|
|
await smtpClient.close();
|
|
});
|
|
|
|
tap.test('CEP-09: Multiple priority header formats', async () => {
|
|
const smtpClient = createSmtpClient({
|
|
host: testServer.hostname,
|
|
port: testServer.port,
|
|
secure: false,
|
|
connectionTimeout: 5000,
|
|
debug: true
|
|
});
|
|
|
|
await smtpClient.connect();
|
|
|
|
// Test various priority header combinations
|
|
const email = new Email({
|
|
from: 'sender@example.com',
|
|
to: ['recipient@example.com'],
|
|
subject: 'Multiple Priority Headers Test',
|
|
text: 'Testing various priority header formats',
|
|
headers: {
|
|
'X-Priority': '1 (Highest)',
|
|
'X-MSMail-Priority': 'High',
|
|
'Importance': 'high',
|
|
'Priority': 'urgent',
|
|
'X-Message-Flag': 'Follow up'
|
|
}
|
|
});
|
|
|
|
// Capture all priority-related headers
|
|
const priorityHeaders: string[] = [];
|
|
const originalSendCommand = smtpClient.sendCommand.bind(smtpClient);
|
|
|
|
smtpClient.sendCommand = async (command: string) => {
|
|
const priorityKeywords = ['priority', 'importance', 'urgent', 'flag'];
|
|
if (command.includes(':') && priorityKeywords.some(kw => command.toLowerCase().includes(kw))) {
|
|
priorityHeaders.push(command.trim());
|
|
}
|
|
return originalSendCommand(command);
|
|
};
|
|
|
|
await smtpClient.sendMail(email);
|
|
|
|
console.log('\nAll priority-related headers:');
|
|
priorityHeaders.forEach(header => {
|
|
console.log(` ${header}`);
|
|
});
|
|
|
|
await smtpClient.close();
|
|
});
|
|
|
|
tap.test('CEP-09: Client-specific priority mappings', async () => {
|
|
const smtpClient = createSmtpClient({
|
|
host: testServer.hostname,
|
|
port: testServer.port,
|
|
secure: false,
|
|
connectionTimeout: 5000,
|
|
debug: true
|
|
});
|
|
|
|
await smtpClient.connect();
|
|
|
|
// Test how priority maps to different email clients
|
|
const clientMappings = [
|
|
{
|
|
client: 'Outlook',
|
|
high: { 'X-Priority': '1', 'X-MSMail-Priority': 'High', 'Importance': 'High' },
|
|
normal: { 'X-Priority': '3', 'X-MSMail-Priority': 'Normal', 'Importance': 'Normal' },
|
|
low: { 'X-Priority': '5', 'X-MSMail-Priority': 'Low', 'Importance': 'Low' }
|
|
},
|
|
{
|
|
client: 'Thunderbird',
|
|
high: { 'X-Priority': '1', 'Importance': 'High' },
|
|
normal: { 'X-Priority': '3', 'Importance': 'Normal' },
|
|
low: { 'X-Priority': '5', 'Importance': 'Low' }
|
|
},
|
|
{
|
|
client: 'Apple Mail',
|
|
high: { 'X-Priority': '1' },
|
|
normal: { 'X-Priority': '3' },
|
|
low: { 'X-Priority': '5' }
|
|
}
|
|
];
|
|
|
|
console.log('\nClient-specific priority header mappings:');
|
|
|
|
for (const mapping of clientMappings) {
|
|
console.log(`\n${mapping.client}:`);
|
|
console.log(' High priority:', JSON.stringify(mapping.high));
|
|
console.log(' Normal priority:', JSON.stringify(mapping.normal));
|
|
console.log(' Low priority:', JSON.stringify(mapping.low));
|
|
}
|
|
|
|
// Send test email with comprehensive priority headers
|
|
const email = new Email({
|
|
from: 'sender@example.com',
|
|
to: ['recipient@example.com'],
|
|
subject: 'Cross-client Priority Test',
|
|
text: 'This should appear as high priority in all clients',
|
|
priority: 'high'
|
|
});
|
|
|
|
await smtpClient.sendMail(email);
|
|
|
|
await smtpClient.close();
|
|
});
|
|
|
|
tap.test('CEP-09: Sensitivity and confidentiality headers', async () => {
|
|
const smtpClient = createSmtpClient({
|
|
host: testServer.hostname,
|
|
port: testServer.port,
|
|
secure: false,
|
|
connectionTimeout: 5000,
|
|
debug: true
|
|
});
|
|
|
|
await smtpClient.connect();
|
|
|
|
// Test sensitivity levels
|
|
const sensitivityLevels = [
|
|
{ level: 'Personal', description: 'Personal information' },
|
|
{ level: 'Private', description: 'Private communication' },
|
|
{ level: 'Company-Confidential', description: 'Internal use only' },
|
|
{ level: 'Normal', description: 'No special handling' }
|
|
];
|
|
|
|
for (const sensitivity of sensitivityLevels) {
|
|
const email = new Email({
|
|
from: 'sender@example.com',
|
|
to: ['recipient@example.com'],
|
|
subject: `${sensitivity.level} Message`,
|
|
text: sensitivity.description,
|
|
headers: {
|
|
'Sensitivity': sensitivity.level,
|
|
'X-Sensitivity': sensitivity.level
|
|
}
|
|
});
|
|
|
|
// Monitor sensitivity headers
|
|
let sensitivityHeader = '';
|
|
const originalSendCommand = smtpClient.sendCommand.bind(smtpClient);
|
|
|
|
smtpClient.sendCommand = async (command: string) => {
|
|
if (command.toLowerCase().includes('sensitivity:')) {
|
|
sensitivityHeader = command.trim();
|
|
}
|
|
return originalSendCommand(command);
|
|
};
|
|
|
|
await smtpClient.sendMail(email);
|
|
|
|
console.log(`\nSensitivity: ${sensitivity.level}`);
|
|
console.log(` Header sent: ${sensitivityHeader}`);
|
|
}
|
|
|
|
await smtpClient.close();
|
|
});
|
|
|
|
tap.test('CEP-09: Auto-response suppression headers', async () => {
|
|
const smtpClient = createSmtpClient({
|
|
host: testServer.hostname,
|
|
port: testServer.port,
|
|
secure: false,
|
|
connectionTimeout: 5000,
|
|
debug: true
|
|
});
|
|
|
|
await smtpClient.connect();
|
|
|
|
// Headers to suppress auto-responses (vacation messages, etc.)
|
|
const email = new Email({
|
|
from: 'noreply@example.com',
|
|
to: ['recipient@example.com'],
|
|
subject: 'Automated Notification',
|
|
text: 'This is an automated message. Please do not reply.',
|
|
headers: {
|
|
'X-Auto-Response-Suppress': 'All', // Microsoft
|
|
'Auto-Submitted': 'auto-generated', // RFC 3834
|
|
'Precedence': 'bulk', // Traditional
|
|
'X-Autoreply': 'no',
|
|
'X-Autorespond': 'no',
|
|
'List-Id': '<notifications.example.com>', // Mailing list header
|
|
'List-Unsubscribe': '<mailto:unsubscribe@example.com>'
|
|
}
|
|
});
|
|
|
|
// Capture auto-response suppression headers
|
|
const suppressionHeaders: string[] = [];
|
|
const originalSendCommand = smtpClient.sendCommand.bind(smtpClient);
|
|
|
|
smtpClient.sendCommand = async (command: string) => {
|
|
const suppressionKeywords = ['auto', 'precedence', 'list-', 'bulk'];
|
|
if (command.includes(':') && suppressionKeywords.some(kw => command.toLowerCase().includes(kw))) {
|
|
suppressionHeaders.push(command.trim());
|
|
}
|
|
return originalSendCommand(command);
|
|
};
|
|
|
|
await smtpClient.sendMail(email);
|
|
|
|
console.log('\nAuto-response suppression headers:');
|
|
suppressionHeaders.forEach(header => {
|
|
console.log(` ${header}`);
|
|
});
|
|
|
|
await smtpClient.close();
|
|
});
|
|
|
|
tap.test('CEP-09: Expiration and retention headers', async () => {
|
|
const smtpClient = createSmtpClient({
|
|
host: testServer.hostname,
|
|
port: testServer.port,
|
|
secure: false,
|
|
connectionTimeout: 5000,
|
|
debug: true
|
|
});
|
|
|
|
await smtpClient.connect();
|
|
|
|
// Set expiration date for the email
|
|
const expirationDate = new Date();
|
|
expirationDate.setDate(expirationDate.getDate() + 7); // Expires in 7 days
|
|
|
|
const email = new Email({
|
|
from: 'sender@example.com',
|
|
to: ['recipient@example.com'],
|
|
subject: 'Time-sensitive Information',
|
|
text: 'This information expires in 7 days',
|
|
headers: {
|
|
'Expiry-Date': expirationDate.toUTCString(),
|
|
'X-Message-TTL': '604800', // 7 days in seconds
|
|
'X-Auto-Delete-After': expirationDate.toISOString(),
|
|
'X-Retention-Date': expirationDate.toISOString()
|
|
}
|
|
});
|
|
|
|
// Monitor expiration headers
|
|
const expirationHeaders: { [key: string]: string } = {};
|
|
const originalSendCommand = smtpClient.sendCommand.bind(smtpClient);
|
|
|
|
smtpClient.sendCommand = async (command: string) => {
|
|
if (command.includes(':')) {
|
|
const [key, value] = command.split(':').map(s => s.trim());
|
|
if (key.toLowerCase().includes('expir') || key.toLowerCase().includes('retention') ||
|
|
key.toLowerCase().includes('ttl') || key.toLowerCase().includes('delete')) {
|
|
expirationHeaders[key] = value;
|
|
}
|
|
}
|
|
return originalSendCommand(command);
|
|
};
|
|
|
|
await smtpClient.sendMail(email);
|
|
|
|
console.log('\nExpiration and retention headers:');
|
|
Object.entries(expirationHeaders).forEach(([key, value]) => {
|
|
console.log(` ${key}: ${value}`);
|
|
});
|
|
|
|
await smtpClient.close();
|
|
});
|
|
|
|
tap.test('CEP-09: Message flags and categories', async () => {
|
|
const smtpClient = createSmtpClient({
|
|
host: testServer.hostname,
|
|
port: testServer.port,
|
|
secure: false,
|
|
connectionTimeout: 5000,
|
|
debug: true
|
|
});
|
|
|
|
await smtpClient.connect();
|
|
|
|
// Test various message flags and categories
|
|
const flaggedEmails = [
|
|
{
|
|
flag: 'Follow up',
|
|
category: 'Action Required',
|
|
color: 'red'
|
|
},
|
|
{
|
|
flag: 'For Your Information',
|
|
category: 'Informational',
|
|
color: 'blue'
|
|
},
|
|
{
|
|
flag: 'Review',
|
|
category: 'Pending Review',
|
|
color: 'yellow'
|
|
}
|
|
];
|
|
|
|
for (const flaggedEmail of flaggedEmails) {
|
|
const email = new Email({
|
|
from: 'sender@example.com',
|
|
to: ['recipient@example.com'],
|
|
subject: `${flaggedEmail.flag}: Important Document`,
|
|
text: `This email is flagged as: ${flaggedEmail.flag}`,
|
|
headers: {
|
|
'X-Message-Flag': flaggedEmail.flag,
|
|
'X-Category': flaggedEmail.category,
|
|
'X-Color-Label': flaggedEmail.color,
|
|
'Keywords': flaggedEmail.flag.replace(' ', '-')
|
|
}
|
|
});
|
|
|
|
console.log(`\nSending flagged email: ${flaggedEmail.flag}`);
|
|
const result = await smtpClient.sendMail(email);
|
|
expect(result).toBeTruthy();
|
|
}
|
|
|
|
await smtpClient.close();
|
|
});
|
|
|
|
tap.test('CEP-09: Priority with delivery timing', async () => {
|
|
const smtpClient = createSmtpClient({
|
|
host: testServer.hostname,
|
|
port: testServer.port,
|
|
secure: false,
|
|
connectionTimeout: 5000,
|
|
debug: true
|
|
});
|
|
|
|
await smtpClient.connect();
|
|
|
|
// Test deferred delivery with priority
|
|
const futureDate = new Date();
|
|
futureDate.setHours(futureDate.getHours() + 2); // Deliver in 2 hours
|
|
|
|
const email = new Email({
|
|
from: 'sender@example.com',
|
|
to: ['recipient@example.com'],
|
|
subject: 'Scheduled High Priority Message',
|
|
text: 'This high priority message should be delivered at a specific time',
|
|
priority: 'high',
|
|
headers: {
|
|
'Deferred-Delivery': futureDate.toUTCString(),
|
|
'X-Delay-Until': futureDate.toISOString(),
|
|
'X-Priority': '1',
|
|
'Importance': 'High'
|
|
}
|
|
});
|
|
|
|
// Monitor timing headers
|
|
let deferredDeliveryHeader = '';
|
|
const originalSendCommand = smtpClient.sendCommand.bind(smtpClient);
|
|
|
|
smtpClient.sendCommand = async (command: string) => {
|
|
if (command.toLowerCase().includes('defer') || command.toLowerCase().includes('delay')) {
|
|
deferredDeliveryHeader = command.trim();
|
|
}
|
|
return originalSendCommand(command);
|
|
};
|
|
|
|
await smtpClient.sendMail(email);
|
|
|
|
console.log('\nScheduled delivery with priority:');
|
|
console.log(` Priority: High`);
|
|
console.log(` Scheduled for: ${futureDate.toUTCString()}`);
|
|
if (deferredDeliveryHeader) {
|
|
console.log(` Header sent: ${deferredDeliveryHeader}`);
|
|
}
|
|
|
|
await smtpClient.close();
|
|
});
|
|
|
|
tap.test('CEP-09: Priority impact on routing', async () => {
|
|
const smtpClient = createSmtpClient({
|
|
host: testServer.hostname,
|
|
port: testServer.port,
|
|
secure: false,
|
|
connectionTimeout: 5000,
|
|
debug: true
|
|
});
|
|
|
|
await smtpClient.connect();
|
|
|
|
// Test batch of emails with different priorities
|
|
const emails = [
|
|
{ priority: 'high', subject: 'URGENT: Server Down', delay: 0 },
|
|
{ priority: 'high', subject: 'Critical Security Update', delay: 0 },
|
|
{ priority: 'normal', subject: 'Weekly Report', delay: 100 },
|
|
{ priority: 'low', subject: 'Newsletter', delay: 200 },
|
|
{ priority: 'low', subject: 'Promotional Offer', delay: 200 }
|
|
];
|
|
|
|
console.log('\nSending emails with different priorities:');
|
|
const sendTimes: { priority: string; time: number }[] = [];
|
|
|
|
for (const emailData of emails) {
|
|
// Simulate priority-based delays
|
|
if (emailData.delay > 0) {
|
|
await new Promise(resolve => setTimeout(resolve, emailData.delay));
|
|
}
|
|
|
|
const email = new Email({
|
|
from: 'sender@example.com',
|
|
to: ['recipient@example.com'],
|
|
subject: emailData.subject,
|
|
text: `Priority: ${emailData.priority}`,
|
|
priority: emailData.priority as 'high' | 'normal' | 'low'
|
|
});
|
|
|
|
const startTime = Date.now();
|
|
await smtpClient.sendMail(email);
|
|
const sendTime = Date.now() - startTime;
|
|
|
|
sendTimes.push({ priority: emailData.priority, time: sendTime });
|
|
console.log(` ${emailData.priority.padEnd(6)} - ${emailData.subject} (${sendTime}ms)`);
|
|
}
|
|
|
|
// Analyze send times by priority
|
|
const avgByPriority = ['high', 'normal', 'low'].map(priority => {
|
|
const times = sendTimes.filter(st => st.priority === priority);
|
|
const avg = times.reduce((sum, st) => sum + st.time, 0) / times.length;
|
|
return { priority, avg };
|
|
});
|
|
|
|
console.log('\nAverage send time by priority:');
|
|
avgByPriority.forEach(({ priority, avg }) => {
|
|
console.log(` ${priority}: ${avg.toFixed(2)}ms`);
|
|
});
|
|
|
|
await smtpClient.close();
|
|
});
|
|
|
|
tap.test('cleanup test SMTP server', async () => {
|
|
if (testServer) {
|
|
await testServer.stop();
|
|
}
|
|
});
|
|
|
|
export default tap.start(); |