210 lines
No EOL
7 KiB
TypeScript
210 lines
No EOL
7 KiB
TypeScript
#!/usr/bin/env ts-node
|
|
|
|
/**
|
|
* Bulk email sending example using Nodemailer transport
|
|
*/
|
|
|
|
import nodemailer from 'nodemailer';
|
|
import { createTransport } from '../src/index';
|
|
|
|
async function bulkEmailExample() {
|
|
console.log('Bulk Email Example using SMTP WebSocket Transport\n');
|
|
|
|
// Create the WebSocket transport
|
|
const transport = createTransport({
|
|
host: 'localhost',
|
|
port: 3000,
|
|
auth: {
|
|
user: 'your-api-key-here'
|
|
},
|
|
maxQueueSize: 1000, // Handle large queues
|
|
debug: false // Disable debug for bulk operations
|
|
});
|
|
|
|
const transporter = nodemailer.createTransporter(transport);
|
|
|
|
// Sample recipient list
|
|
const recipients = [
|
|
{ email: 'user1@example.com', name: 'User One' },
|
|
{ email: 'user2@example.com', name: 'User Two' },
|
|
{ email: 'user3@example.com', name: 'User Three' },
|
|
{ email: 'user4@example.com', name: 'User Four' },
|
|
{ email: 'user5@example.com', name: 'User Five' }
|
|
];
|
|
|
|
console.log(`Sending emails to ${recipients.length} recipients...\n`);
|
|
|
|
const results = [];
|
|
const startTime = Date.now();
|
|
|
|
// Send emails concurrently (transport handles queuing automatically)
|
|
const emailPromises = recipients.map(async (recipient, index) => {
|
|
try {
|
|
const info = await transporter.sendMail({
|
|
from: 'newsletter@example.com',
|
|
to: recipient.email,
|
|
subject: `Newsletter #${index + 1} - ${new Date().toLocaleDateString()}`,
|
|
text: `Hello ${recipient.name}!\n\nThis is your personalized newsletter.\n\nBest regards,\nThe Newsletter Team`,
|
|
html: `
|
|
<h2>Hello ${recipient.name}!</h2>
|
|
<p>This is your personalized newsletter for ${new Date().toLocaleDateString()}.</p>
|
|
<p>This email was delivered via our SMTP WebSocket transport system.</p>
|
|
<hr>
|
|
<p><small>Newsletter #${index + 1} | Sent at ${new Date().toLocaleTimeString()}</small></p>
|
|
`
|
|
});
|
|
|
|
console.log(`Email ${index + 1}/${recipients.length} sent to ${recipient.email}`);
|
|
return {
|
|
success: true,
|
|
recipient: recipient.email,
|
|
messageId: info.messageId,
|
|
response: info.response
|
|
};
|
|
|
|
} catch (error) {
|
|
console.error(`Failed to send email ${index + 1} to ${recipient.email}:`, (error as Error).message);
|
|
return {
|
|
success: false,
|
|
recipient: recipient.email,
|
|
error: (error as Error).message
|
|
};
|
|
}
|
|
});
|
|
|
|
// Wait for all emails to complete
|
|
const emailResults = await Promise.allSettled(emailPromises);
|
|
const duration = Date.now() - startTime;
|
|
|
|
// Process results
|
|
let successful = 0;
|
|
let failed = 0;
|
|
|
|
emailResults.forEach((result) => {
|
|
if (result.status === 'fulfilled') {
|
|
results.push(result.value);
|
|
if (result.value.success) {
|
|
successful++;
|
|
} else {
|
|
failed++;
|
|
}
|
|
} else {
|
|
failed++;
|
|
results.push({
|
|
success: false,
|
|
error: result.reason.message
|
|
});
|
|
}
|
|
});
|
|
|
|
// Display summary
|
|
console.log('\n--- Bulk Email Results ---');
|
|
console.log(`Total emails: ${recipients.length}`);
|
|
console.log(`Successful: ${successful}`);
|
|
console.log(`Failed: ${failed}`);
|
|
console.log(`Duration: ${(duration / 1000).toFixed(2)} seconds`);
|
|
console.log(`Average time per email: ${(duration / recipients.length).toFixed(0)}ms`);
|
|
|
|
// Display failed emails if any
|
|
if (failed > 0) {
|
|
console.log('\nFailed emails:');
|
|
results.forEach((result, index) => {
|
|
if (!result.success) {
|
|
console.log(` ${index + 1}. ${result.recipient || 'Unknown'}: ${result.error}`);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Close transport
|
|
await transport.close();
|
|
console.log('\nTransport closed');
|
|
}
|
|
|
|
// Advanced bulk email with throttling
|
|
async function throttledBulkEmail() {
|
|
console.log('\nThrottled Bulk Email Example\n');
|
|
|
|
const transport = createTransport({
|
|
host: 'localhost',
|
|
port: 3000,
|
|
auth: {
|
|
user: 'your-api-key-here'
|
|
}
|
|
});
|
|
|
|
const transporter = nodemailer.createTransporter(transport);
|
|
|
|
// Generate larger recipient list
|
|
const recipients = Array.from({ length: 20 }, (_, i) => ({
|
|
email: `user${i + 1}@example.com`,
|
|
name: `User ${i + 1}`
|
|
}));
|
|
|
|
console.log(`Sending throttled emails to ${recipients.length} recipients...`);
|
|
console.log('Processing 5 emails at a time with 1 second delay between batches\n');
|
|
|
|
const batchSize = 5;
|
|
const batches = [];
|
|
|
|
for (let i = 0; i < recipients.length; i += batchSize) {
|
|
batches.push(recipients.slice(i, i + batchSize));
|
|
}
|
|
|
|
let totalSuccessful = 0;
|
|
let totalFailed = 0;
|
|
|
|
for (let batchIndex = 0; batchIndex < batches.length; batchIndex++) {
|
|
const batch = batches[batchIndex];
|
|
console.log(`Processing batch ${batchIndex + 1}/${batches.length} (${batch.length} emails)...`);
|
|
|
|
const batchPromises = batch.map(async (recipient) => {
|
|
try {
|
|
await transporter.sendMail({
|
|
from: 'batch@example.com',
|
|
to: recipient.email,
|
|
subject: `Batch Email - ${recipient.name}`,
|
|
text: `Hello ${recipient.name}, this is a batch email.`
|
|
});
|
|
return { success: true, email: recipient.email };
|
|
} catch (error) {
|
|
return { success: false, email: recipient.email, error: (error as Error).message };
|
|
}
|
|
});
|
|
|
|
const batchResults = await Promise.all(batchPromises);
|
|
|
|
const batchSuccessful = batchResults.filter(r => r.success).length;
|
|
const batchFailed = batchResults.filter(r => !r.success).length;
|
|
|
|
totalSuccessful += batchSuccessful;
|
|
totalFailed += batchFailed;
|
|
|
|
console.log(`Batch ${batchIndex + 1} complete: ${batchSuccessful} successful, ${batchFailed} failed`);
|
|
|
|
// Wait between batches (except for the last one)
|
|
if (batchIndex < batches.length - 1) {
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
}
|
|
}
|
|
|
|
console.log(`\nThrottled bulk email complete: ${totalSuccessful} successful, ${totalFailed} failed`);
|
|
|
|
await transport.close();
|
|
}
|
|
|
|
// Run the examples
|
|
if (require.main === module) {
|
|
(async () => {
|
|
try {
|
|
await bulkEmailExample();
|
|
await throttledBulkEmail();
|
|
console.log('\nBulk email examples completed successfully');
|
|
} catch (error) {
|
|
console.error('\nExamples failed:', error);
|
|
} finally {
|
|
process.exit(0);
|
|
}
|
|
})();
|
|
}
|
|
|
|
export { bulkEmailExample, throttledBulkEmail }; |