/** * Email Testing Interface * Handles email preview, testing, and logging functionality */ class EmailTesting { constructor() { this.apiClient = new APIClient(); this.currentFilter = 'all'; // 'all', 'test', 'live' this.logLimit = 50; this.logOffset = 0; } /** * Initialize the email testing interface */ async init() { this.bindEvents(); await this.loadConfiguration(); await this.loadEmailLogs(); } /** * Bind event listeners to UI elements */ bindEvents() { // Quick test buttons document.getElementById('quick-test-btn').addEventListener('click', () => this.sendQuickTest()); document.getElementById('smtp-test-btn').addEventListener('click', () => this.testSMTPConnection()); // Email form buttons document.getElementById('preview-btn').addEventListener('click', () => this.previewEmail()); document.getElementById('send-test-btn').addEventListener('click', () => this.sendTestEmail()); // Log control buttons document.getElementById('refresh-logs-btn').addEventListener('click', () => this.loadEmailLogs()); document.getElementById('filter-test-btn').addEventListener('click', () => this.filterLogs('test')); document.getElementById('filter-all-btn').addEventListener('click', () => this.filterLogs('all')); // Form validation document.getElementById('email-test-form').addEventListener('input', () => this.validateForm()); } /** * Send a quick test email with default content */ async sendQuickTest() { const button = document.getElementById('quick-test-btn'); button.disabled = true; button.textContent = 'Sending...'; try { const response = await this.apiClient.post('/api/emails/test', { subject: 'Quick Test Email', message: 'This is a quick test email sent from the Alberta Influence Campaign Tool email testing interface.' }); if (response.success) { this.showMessage(`Test email sent successfully to ${response.sentTo}`, 'success'); await this.loadEmailLogs(); // Refresh logs } else { this.showMessage(`Failed to send test email: ${response.message}`, 'error'); } } catch (error) { this.showMessage(`Error sending test email: ${error.message}`, 'error'); } finally { button.disabled = false; button.textContent = 'Send Quick Test Email'; } } /** * Test SMTP connection */ async testSMTPConnection() { const button = document.getElementById('smtp-test-btn'); button.disabled = true; button.textContent = 'Testing...'; try { // Note: This endpoint would need to be added to the API const response = await this.apiClient.get('/api/test-smtp'); if (response.success) { this.showMessage('SMTP connection test successful', 'success'); } else { this.showMessage(`SMTP connection failed: ${response.message}`, 'error'); } } catch (error) { this.showMessage(`SMTP test error: ${error.message}`, 'error'); } finally { button.disabled = false; button.textContent = 'Test SMTP Connection'; } } /** * Preview email content */ async previewEmail() { const formData = this.getFormData(); if (!formData) return; const button = document.getElementById('preview-btn'); button.disabled = true; try { const recipientEmail = formData.recipientEmail || 'recipient@example.com'; const response = await this.apiClient.post('/api/emails/preview', { recipientEmail: recipientEmail, subject: formData.subject, message: formData.message }); if (response.success) { this.displayEmailPreview(response.preview, response.html); } else { this.showMessage(`Preview failed: ${response.message}`, 'error'); } } catch (error) { this.showMessage(`Preview error: ${error.message}`, 'error'); } finally { button.disabled = false; } } /** * Send test email */ async sendTestEmail() { const formData = this.getFormData(); if (!formData) return; const button = document.getElementById('send-test-btn'); button.disabled = true; button.textContent = 'Sending...'; try { const response = await this.apiClient.post('/api/emails/test', { subject: formData.subject, message: formData.message }); if (response.success) { this.showMessage(`Test email sent successfully to ${response.sentTo}`, 'success'); await this.loadEmailLogs(); // Refresh logs } else { this.showMessage(`Failed to send test email: ${response.message}`, 'error'); } } catch (error) { this.showMessage(`Error sending test email: ${error.message}`, 'error'); } finally { button.disabled = false; button.textContent = 'Send Test Email'; } } /** * Get form data and validate */ getFormData() { const subject = document.getElementById('test-subject').value.trim(); const message = document.getElementById('test-message').value.trim(); const recipientEmail = document.getElementById('test-recipient').value.trim(); if (!subject || !message) { this.showMessage('Please fill in subject and message', 'error'); return null; } return { subject, message, recipientEmail: recipientEmail || null }; } /** * Validate form and update button states */ validateForm() { const subject = document.getElementById('test-subject').value.trim(); const message = document.getElementById('test-message').value.trim(); const isValid = subject && message; document.getElementById('preview-btn').disabled = !isValid; document.getElementById('send-test-btn').disabled = !isValid; } /** * Display email preview */ displayEmailPreview(preview, html) { const previewDiv = document.getElementById('email-preview'); previewDiv.classList.remove('empty'); const testModeWarning = preview.testMode ? `
TEST MODE: Email will be redirected to ${preview.redirectTo}
` : ''; previewDiv.innerHTML = ` ${testModeWarning}
From: ${preview.from}
To: ${preview.to}
Subject: ${preview.subject}
Timestamp: ${new Date(preview.timestamp).toLocaleString()}
Message Content:
${html}
`; } /** * Load and display email logs */ async loadEmailLogs() { const logsDiv = document.getElementById('email-logs'); logsDiv.innerHTML = '
Loading email logs...
'; try { const params = new URLSearchParams(); params.append('limit', this.logLimit); params.append('offset', this.logOffset); if (this.currentFilter === 'test') { params.append('testMode', 'true'); } else if (this.currentFilter === 'live') { params.append('testMode', 'false'); } const response = await this.apiClient.get(`/api/emails/logs?${params.toString()}`); if (response.success) { this.displayEmailLogs(response.logs); } else { logsDiv.innerHTML = `
Failed to load logs: ${response.message}
`; } } catch (error) { logsDiv.innerHTML = `
Error loading logs: ${error.message}
`; } } /** * Display email logs */ displayEmailLogs(logs) { const logsDiv = document.getElementById('email-logs'); if (!logs || logs.length === 0) { logsDiv.innerHTML = '
No email logs found
'; return; } logsDiv.innerHTML = logs.map(log => { const statusClass = log.Status === 'sent' ? 'sent' : 'failed'; const testModeClass = log['Test Mode'] ? 'test-mode' : ''; const statusIndicator = log['Test Mode'] ? 'test' : statusClass; return `
${log.Subject}
To: ${log.Recipient}
${log['Actual Recipient'] && log['Actual Recipient'] !== log.Recipient ? `
Actually sent to: ${log['Actual Recipient']}
` : ''} ${log.Error ? `
Error: ${log.Error}
` : ''}
${log.Status} ${log['Test Mode'] ? 'TEST' : ''}
${log['Sent At'] ? new Date(log['Sent At']).toLocaleString() : (log.CreatedAt ? new Date(log.CreatedAt).toLocaleString() : 'Unknown time')} ${log['Message ID'] ? ` • ID: ${log['Message ID']}` : ''}
`; }).join(''); } /** * Filter logs by type */ async filterLogs(filter) { this.currentFilter = filter; this.logOffset = 0; // Reset offset when filtering // Update button states document.getElementById('filter-all-btn').classList.toggle('btn-success', filter === 'all'); document.getElementById('filter-test-btn').classList.toggle('btn-warning', filter === 'test'); await this.loadEmailLogs(); } /** * Load and display current configuration */ async loadConfiguration() { const configDiv = document.getElementById('config-status'); // Since we don't have a dedicated config endpoint, we'll show env-based info const isTestMode = true; // Assuming test mode based on .env const testRecipient = 'admin@example.com'; // From .env configDiv.innerHTML = `

Email Test Mode

${isTestMode ? 'ENABLED' : 'DISABLED'}
${isTestMode ? 'All emails will be redirected to test recipient' : 'Emails will be sent to actual recipients'}

Test Email Recipient

${testRecipient}
Emails will be sent here in test mode
`; } /** * Show success or error message */ showMessage(message, type) { const messageContainer = document.getElementById('message-container'); const messageClass = type === 'success' ? 'success-message' : 'error-message'; const messageDiv = document.createElement('div'); messageDiv.className = messageClass; messageDiv.textContent = message; messageDiv.style.position = 'fixed'; messageDiv.style.top = '20px'; messageDiv.style.left = '50%'; messageDiv.style.transform = 'translateX(-50%)'; messageDiv.style.zIndex = '1000'; messageDiv.style.maxWidth = '500px'; messageContainer.appendChild(messageDiv); // Auto-remove after 5 seconds setTimeout(() => { if (messageDiv.parentNode) { messageDiv.parentNode.removeChild(messageDiv); } }, 5000); } } // Export for use in other modules if (typeof module !== 'undefined' && module.exports) { module.exports = EmailTesting; }