# Email and SMTP Issues This guide covers email sending, SMTP configuration, and template-related problems in Changemaker Lite V2. ## Overview ### Email System Architecture Changemaker Lite V2 has **dual email systems**: 1. **Transactional Emails** (BullMQ + Nodemailer) - Campaign advocacy emails - Shift confirmation emails - Response verification emails - System notifications 2. **Newsletter Emails** (Listmonk) - Marketing campaigns - Newsletter broadcasts - Subscriber management ### Email Flow ``` User Action → Email Service → BullMQ Queue → Worker → SMTP Server → Recipient ``` ### Key Components - **BullMQ** - Job queue for async email sending - **Nodemailer** - SMTP client library - **Redis** - Queue backend - **MailHog** - Development email capture (test mode) - **Listmonk** - Newsletter platform (optional) --- ## SMTP Configuration ### Connection Refused **Severity:** 🔴 Critical #### Symptoms API logs: ``` Error: Connection timeout Error: connect ECONNREFUSED smtp.gmail.com:587 Error: Invalid login: 535-5.7.8 Username and Password not accepted ``` Emails not sending. #### Common Causes 1. **Wrong SMTP host** - Incorrect hostname 2. **Port blocked** - Firewall blocking port 587/465 3. **Wrong credentials** - Invalid username/password 4. **TLS/SSL mismatch** - Wrong secure setting #### Solutions **Solution 1: Test SMTP connection** ```bash # Test with telnet telnet smtp.gmail.com 587 # Should show: # 220 smtp.gmail.com ESMTP ... # Or test with openssl (for SSL) openssl s_client -connect smtp.gmail.com:465 ``` **Solution 2: Verify SMTP configuration** In `.env`: ```bash # Gmail example (requires app password) SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_SECURE=false # false for STARTTLS on 587, true for SSL on 465 SMTP_USER=your-email@gmail.com SMTP_PASS=your-app-password # NOT regular password SMTP_FROM=your-email@gmail.com # Office365 example SMTP_HOST=smtp.office365.com SMTP_PORT=587 SMTP_SECURE=false SMTP_USER=your-email@outlook.com SMTP_PASS=your-password SMTP_FROM=your-email@outlook.com # SendGrid example SMTP_HOST=smtp.sendgrid.net SMTP_PORT=587 SMTP_SECURE=false SMTP_USER=apikey # Literally "apikey" SMTP_PASS=your-sendgrid-api-key SMTP_FROM=your-verified-sender@example.com ``` **Solution 3: Use test mode** ```bash # In .env EMAIL_TEST_MODE=true # Restart API docker compose restart api # All emails now sent to MailHog # View at http://localhost:8025 ``` **Solution 4: Test email sending** ```bash # Send test email via API curl -X POST http://localhost:4000/api/test-email \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{ "to": "test@example.com", "subject": "Test Email", "text": "This is a test email from Changemaker Lite" }' # Check API logs docker compose logs api | grep -i "email\|smtp" ``` **Solution 5: Gmail app password** For Gmail (required if 2FA enabled): 1. Go to https://myaccount.google.com/apppasswords 2. Select app: Mail 3. Select device: Other (Changemaker Lite) 4. Click Generate 5. Copy 16-character password 6. Use in SMTP_PASS (no spaces) #### Prevention - **Test mode for dev** - Use MailHog locally - **Secure credentials** - Use app passwords, not real passwords - **Environment-specific** - Different SMTP per environment - **Health checks** - Test SMTP on API startup --- ### Authentication Failed **Severity:** 🔴 Critical #### Symptoms ``` Error: Invalid login: 535-5.7.8 Username and Password not accepted Error: 535 Authentication failed ``` #### Common Causes 1. **Wrong password** - Incorrect password 2. **2FA enabled** - Need app password 3. **Less secure apps** - Gmail blocking 4. **Account locked** - Too many failed attempts #### Solutions **Solution 1: Verify credentials** ```bash # Check .env cat .env | grep SMTP_ # Test login manually (if possible) # Gmail doesn't allow this, but some SMTP servers do ``` **Solution 2: Enable less secure apps (Gmail)** ⚠️ Not recommended. Use app password instead. 1. Go to https://myaccount.google.com/lesssecureapps 2. Turn on "Allow less secure apps" **Solution 3: Check account status** 1. Try logging into email account via web 2. Check for security alerts 3. Verify account not locked **Solution 4: Use OAuth2 (advanced)** For production Gmail: ```typescript // In email.service.ts const transporter = nodemailer.createTransporter({ service: 'gmail', auth: { type: 'OAuth2', user: process.env.SMTP_USER, clientId: process.env.GMAIL_CLIENT_ID, clientSecret: process.env.GMAIL_CLIENT_SECRET, refreshToken: process.env.GMAIL_REFRESH_TOKEN } }); ``` #### Prevention - **App passwords** - Always use app-specific passwords - **Test credentials** - Verify before deploying - **Monitor failures** - Alert on auth failures - **Backup SMTP** - Configure fallback SMTP server --- ### Invalid Credentials **Severity:** 🔴 Critical #### Symptoms ``` Error: Invalid SMTP credentials Error: Username and Password not accepted ``` #### Solutions See "Authentication Failed" section above. --- ### Port Blocked **Severity:** 🟠 High #### Symptoms ``` Error: connect ETIMEDOUT smtp.gmail.com:587 Error: Connection timeout ``` Connection attempt hangs, then times out after 30+ seconds. #### Common Causes 1. **Firewall blocking** - Network firewall blocking port 2. **ISP blocking** - ISP blocks port 25/587 3. **Docker network** - Container can't reach external SMTP #### Solutions **Solution 1: Test port access** ```bash # From API container docker compose exec api telnet smtp.gmail.com 587 # If timeout, port is blocked ``` **Solution 2: Try alternative port** ```bash # Try port 465 (SSL) instead of 587 (STARTTLS) SMTP_PORT=465 SMTP_SECURE=true # Or try port 2525 (some providers) SMTP_PORT=2525 SMTP_SECURE=false ``` **Solution 3: Check Docker network** ```bash # Test external connectivity docker compose exec api ping -c 3 smtp.gmail.com # Test DNS resolution docker compose exec api nslookup smtp.gmail.com # If fails, Docker network issue ``` **Solution 4: Use SMTP relay** If ISP blocks SMTP, use relay service: - SendGrid - Mailgun - Amazon SES - Postmark **Solution 5: VPN or proxy** As last resort, route SMTP through VPN/proxy. #### Prevention - **Use relay services** - More reliable than direct SMTP - **Multiple ports** - Try 587, 465, 2525 - **Test on deploy** - Verify SMTP works in production - **Documentation** - Document network requirements --- ## Template Issues ### Template Not Found **Severity:** 🟠 High #### Symptoms API logs: ``` Error: Email template not found: campaign-email Error: ENOENT: no such file or directory, open 'templates/campaign-email.html' ``` #### Common Causes 1. **Template file missing** - File doesn't exist 2. **Wrong template name** - Typo in name 3. **Wrong directory** - Looking in wrong path 4. **Deleted template** - Template was removed #### Solutions **Solution 1: List available templates** ```bash # List template files docker compose exec api ls -la templates/ # Should show: # campaign-email.html # shift-confirmation.html # verification-email.html # response-verification.html ``` **Solution 2: Create missing template** ```bash # Create template file docker compose exec api sh -c 'cat > templates/my-template.html << EOF {{title}}

Hello {{name}}

{{message}}

EOF' ``` **Solution 3: Use email template system** Navigate to `/app/email-templates`: 1. Click "Create Template" 2. Fill in details 3. Design template 4. Save (creates file + DB record) **Solution 4: Check template name** ```typescript // In code, template name must match filename (without .html) await emailService.sendEmail({ to: email, subject: 'Campaign Email', template: 'campaign-email', // Looks for templates/campaign-email.html variables: { ... } }); ``` **Solution 5: Verify template path** In `api/src/services/email.service.ts`: ```typescript const templatePath = path.join(__dirname, '../../templates', `${template}.html`); // Resolves to: api/templates/campaign-email.html ``` #### Prevention - **Seed templates** - Include default templates in seed - **Template management** - Use admin UI to manage - **Version control** - Keep templates in git - **Validation** - Check template exists before sending --- ### Variable Not Replaced **Severity:** 🟡 Medium #### Symptoms Email received with unreplaced placeholders: ``` Hello {{name}}, Your campaign {{campaignName}} is ready. ``` #### Common Causes 1. **Variable not provided** - Missing from variables object 2. **Typo in variable name** - Mismatch between template and code 3. **Wrong delimiter** - Using ${} instead of {{}} 4. **Escaping issue** - HTML entities interfering #### Solutions **Solution 1: List template variables** ```bash # Find all variables in template docker compose exec api grep -o '{{[^}]*}}' templates/campaign-email.html # Shows: # {{name}} # {{campaignName}} # {{campaignUrl}} ``` **Solution 2: Provide all variables** ```typescript await emailService.sendEmail({ to: email, subject: 'Campaign Ready', template: 'campaign-email', variables: { name: user.name, // Must provide ALL variables in template campaignName: campaign.name, campaignUrl: `${process.env.PUBLIC_URL}/campaigns/${campaign.id}` } }); ``` **Solution 3: Check variable delimiter** ```html

Hello {{name}}

Your campaign {{campaignName}} is ready.

Hello ${name}

Your campaign {campaignName} is ready.

``` **Solution 4: Test template rendering** ```bash # Test template rendering curl -X POST http://localhost:4000/api/test-template \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{ "template": "campaign-email", "variables": { "name": "John", "campaignName": "Save the Planet", "campaignUrl": "https://example.com/campaigns/123" } }' # Returns rendered HTML ``` **Solution 5: Use default values** ```html

Hello {{name || "Friend"}}

``` Or in code: ```typescript const variables = { name: user.name || 'Friend', campaignName: campaign.name || 'Campaign', campaignUrl: campaignUrl || '#' }; ``` #### Prevention - **Template validation** - Check all variables exist - **TypeScript types** - Type template variables - **Default values** - Always provide defaults - **Testing** - Test all templates with sample data --- ### Syntax Errors **Severity:** 🟠 High #### Symptoms ``` Error: Parse error in template at line 15 Error: Unexpected token in template ``` Email fails to send. #### Common Causes 1. **Invalid HTML** - Malformed HTML 2. **Unclosed tags** - Missing closing tags 3. **Special characters** - Unescaped < > & 4. **Handlebars syntax** - Invalid {{}} usage #### Solutions **Solution 1: Validate HTML** ```bash # Use HTML validator # Copy template content to https://validator.w3.org/nu/ # Or validate locally docker compose exec api npx html-validate templates/campaign-email.html ``` **Solution 2: Check common errors** ```html
Content here
Content here
Price: $50 < $100 Price: $50 < $100 {{if name}} {{#if name}}...{{/if}} ``` **Solution 3: Escape HTML** ```typescript // In email.service.ts import handlebars from 'handlebars'; // Register escape helper handlebars.registerHelper('escape', (str) => { return handlebars.escapeExpression(str); }); // In template

Message: {{escape message}}

``` **Solution 4: Test template compilation** ```typescript // Test if template compiles import handlebars from 'handlebars'; import fs from 'fs'; const templateSource = fs.readFileSync('templates/campaign-email.html', 'utf8'); try { const template = handlebars.compile(templateSource); console.log('Template compiles successfully'); } catch (error) { console.error('Template error:', error.message); } ``` #### Prevention - **HTML validation** - Validate before saving - **Linting** - Use HTML linter in editor - **Simple templates** - Keep templates simple - **Testing** - Test rendering before deploying --- ## Queue Issues ### Queue Stuck **Severity:** 🟠 High #### Symptoms Emails queued but not sending. Queue shows jobs but no progress. #### Solutions **Solution 1: Check queue status** ```bash # View queue stats curl http://localhost:4000/api/influence/email-queue/stats \ -H "Authorization: Bearer YOUR_TOKEN" # Shows: # { # "waiting": 50, # "active": 0, # Should be > 0 if processing # "completed": 1000, # "failed": 5 # } ``` **Solution 2: Check worker is running** ```bash # Worker should log processing docker compose logs api | grep -i "email worker\|processing email" # Should show: # Email worker started # Processing email job for campaign: abc-123 ``` **Solution 3: Restart worker** ```bash # Restart API (restarts worker) docker compose restart api # Check worker started docker compose logs api | grep "Email worker started" ``` **Solution 4: Check Redis** ```bash # Test Redis connection docker compose exec redis redis-cli -a YOUR_REDIS_PASSWORD ping # Check queue keys docker compose exec redis redis-cli -a YOUR_REDIS_PASSWORD keys "bull:email-queue:*" ``` **Solution 5: Process stuck jobs** ```bash # Retry failed jobs curl -X POST http://localhost:4000/api/influence/email-queue/retry-failed \ -H "Authorization: Bearer YOUR_TOKEN" # Clean old jobs curl -X POST http://localhost:4000/api/influence/email-queue/clean \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{"status": "completed", "grace": 86400000}' # Clean completed > 1 day ``` #### Prevention - **Health checks** - Monitor worker health - **Auto-restart** - Restart worker if stuck - **Alerting** - Alert if queue backed up - **Dead letter queue** - Move repeatedly failed jobs --- ### Jobs Failing **Severity:** 🟠 High #### Symptoms High failed job count. Emails not reaching recipients. #### Solutions **Solution 1: View failed jobs** ```bash # Get failed job details curl http://localhost:4000/api/influence/email-queue/failed \ -H "Authorization: Bearer YOUR_TOKEN" # Shows: # [ # { # "id": "123", # "data": { "to": "user@example.com", "subject": "..." }, # "failedReason": "SMTP connection failed", # "attemptsMade": 3 # } # ] ``` **Solution 2: Check error patterns** ```bash # Common failure reasons docker compose logs api | grep "Email failed" | sort | uniq -c # Example output: # 25 Email failed: Invalid email address # 10 Email failed: SMTP connection refused # 3 Email failed: Recipient mailbox full ``` **Solution 3: Retry with fixes** ```bash # Fix SMTP config if needed # Then retry failed jobs curl -X POST http://localhost:4000/api/influence/email-queue/retry-failed \ -H "Authorization: Bearer YOUR_TOKEN" ``` **Solution 4: Manual intervention** For repeatedly failing emails: 1. Check email address validity 2. Verify SMTP configuration 3. Test with different recipient 4. Check if recipient's mailbox full #### Prevention - **Retry logic** - Auto-retry with exponential backoff - **Email validation** - Validate before queuing - **Error categorization** - Permanent vs transient failures - **Bounce handling** - Handle bounce notifications --- ## Delivery Issues ### Emails Not Arriving **Severity:** 🔴 Critical #### Symptoms Emails sent successfully (no errors) but not received. #### Common Causes 1. **Spam folder** - Filtered to spam 2. **Email delay** - Taking long to deliver 3. **Email blocking** - Recipient server blocking 4. **Wrong address** - Typo in email address #### Solutions **Solution 1: Check spam folder** 1. Check spam/junk folder 2. Check promotions tab (Gmail) 3. Mark as "Not Spam" to whitelist **Solution 2: Check email logs** ```bash # Verify email was sent docker compose logs api | grep "Email sent" # Should show: # Email sent to user@example.com: Campaign Email ``` **Solution 3: Use MailHog to test** ```bash # In .env EMAIL_TEST_MODE=true # Restart API docker compose restart api # Send test email curl -X POST http://localhost:4000/api/test-email \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{"to": "test@example.com", "subject": "Test", "text": "Test"}' # Check MailHog # http://localhost:8025 # If appears in MailHog, SMTP working # If not appearing in real inbox, delivery issue ``` **Solution 4: Check email headers** In MailHog or received email: 1. View full headers 2. Check "Received" path 3. Look for spam scores 4. Check SPF/DKIM/DMARC status **Solution 5: Test with different address** ```bash # Try sending to different email provider # Gmail vs Outlook vs Yahoo # If some work and others don't, specific provider blocking ``` #### Prevention - **Email authentication** - SPF, DKIM, DMARC - **Reputation management** - Maintain good sender reputation - **Bounce handling** - Monitor bounces - **Testing** - Regular delivery tests --- ### Marked as Spam **Severity:** 🟠 High #### Symptoms Emails consistently go to spam folder. #### Solutions **Solution 1: Configure SPF** Add TXT record to DNS: ``` v=spf1 include:_spf.google.com ~all ``` Or for SendGrid: ``` v=spf1 include:sendgrid.net ~all ``` **Solution 2: Configure DKIM** 1. Generate DKIM keys (via email provider) 2. Add DKIM TXT record to DNS 3. Enable DKIM signing in SMTP settings **Solution 3: Configure DMARC** Add TXT record to DNS: ``` v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com ``` **Solution 4: Improve email content** - Use plain text version alongside HTML - Avoid spam trigger words ("FREE", "CLICK HERE", "ACT NOW") - Proper from/reply-to addresses - Unsubscribe link - Physical address in footer **Solution 5: Warm up IP** If using dedicated IP: 1. Start with low volume 2. Gradually increase over weeks 3. Monitor reputation scores #### Prevention - **Email authentication** - SPF, DKIM, DMARC mandatory - **Content quality** - Professional, non-spammy content - **Reputation monitoring** - Monitor sender scores - **Engagement** - High engagement = good reputation --- ### Bounce Errors **Severity:** 🟡 Medium #### Symptoms ``` Email bounced: user@example.com 554 Recipient address rejected: User unknown ``` #### Common Causes 1. **Invalid address** - Email doesn't exist 2. **Full mailbox** - Recipient mailbox full 3. **Temporary failure** - Server temporarily unavailable 4. **Blocked sender** - Your domain/IP blocked #### Solutions **Solution 1: Categorize bounces** Hard bounces (permanent): - User unknown - Domain doesn't exist - Invalid address format Soft bounces (temporary): - Mailbox full - Server temporarily unavailable - Message too large **Solution 2: Handle hard bounces** ```bash # Remove hard bounce addresses docker compose exec v2-postgres psql -U changemaker -d changemaker_v2 \ -c "UPDATE \"User\" SET \"emailBounced\" = true WHERE email = 'bounced@example.com';" # Don't send to bounced addresses ``` **Solution 3: Retry soft bounces** ```bash # Retry soft bounces after delay curl -X POST http://localhost:4000/api/influence/email-queue/retry-failed \ -H "Authorization: Bearer YOUR_TOKEN" ``` **Solution 4: Validate emails before sending** ```typescript import validator from 'validator'; const isValidEmail = validator.isEmail(email); if (!isValidEmail) { throw new Error('Invalid email address'); } ``` #### Prevention - **Email validation** - Validate before saving - **Bounce tracking** - Track bounces per address - **Automatic removal** - Don't send to bounced addresses - **Double opt-in** - Confirm email addresses work --- ## Listmonk Integration ### API Connection Failed **Severity:** 🟠 High #### Symptoms ``` Error: Failed to connect to Listmonk API Error: ECONNREFUSED localhost:9001 ``` #### Solutions **Solution 1: Check Listmonk is running** ```bash docker compose ps listmonk # Should show "Up" # If not: docker compose up -d listmonk ``` **Solution 2: Verify API credentials** ```bash # Check .env cat .env | grep LISTMONK_ # Required: LISTMONK_URL=http://listmonk:9001 LISTMONK_ADMIN_USER=admin LISTMONK_ADMIN_PASSWORD=password ``` **Solution 3: Test API connection** ```bash # From API container docker compose exec api curl -u admin:password http://listmonk:9001/api/health # Should return: # {"data": "OK"} ``` **Solution 4: Check Docker network** ```bash # Both on same network? docker inspect changemaker-lite-api-1 | grep NetworkMode docker inspect changemaker-lite-listmonk-1 | grep NetworkMode # Should both show "changemaker-lite" ``` #### Prevention - **Health checks** - Verify Listmonk health on API startup - **Proper credentials** - Use API user (not web admin) - **Network config** - Ensure same Docker network - **Error handling** - Graceful degradation if Listmonk down --- ### Sync Errors **Severity:** 🟡 Medium #### Symptoms ``` Error: Failed to sync subscribers to Listmonk Error: 400 Bad Request: Invalid email format ``` #### Solutions **Solution 1: Check sync status** Navigate to `/app/listmonk`: - View sync statistics - See last sync time - Check error count **Solution 2: View sync logs** ```bash docker compose logs api | grep -i "listmonk\|sync" # Shows: # Syncing 150 participants to Listmonk # Created list: Campaign Participants # Added 145 subscribers, 5 failed ``` **Solution 3: Manual sync** ```bash # Trigger manual sync curl -X POST http://localhost:4000/api/listmonk/sync \ -H "Authorization: Bearer YOUR_TOKEN" ``` **Solution 4: Check subscriber data** ```bash # View failed subscribers docker compose logs api | grep "Failed to add subscriber" # Common issues: # - Invalid email format # - Email already exists # - Missing required fields ``` #### Prevention - **Data validation** - Validate before sync - **Duplicate handling** - Handle existing subscribers - **Error logging** - Log sync errors - **Regular syncs** - Automated periodic syncs --- ## Performance Issues ### Slow Email Sending **Severity:** 🟡 Medium #### Symptoms Sending emails takes several seconds each. Bulk sends very slow. #### Solutions **Solution 1: Use queue system** ```bash # Don't send synchronously # Queue emails instead curl -X POST http://localhost:4000/api/influence/campaigns/CAMPAIGN_ID/send-bulk \ -H "Authorization: Bearer YOUR_TOKEN" # Processes in background via queue ``` **Solution 2: Increase worker concurrency** In `api/src/services/email-queue.service.ts`: ```typescript const worker = new Worker('email-queue', processor, { concurrency: 5, // Process 5 emails at a time (default: 1) limiter: { max: 50, // Max 50 emails per second duration: 1000 } }); ``` **Solution 3: Use batch sending** For transactional email services: ```typescript // Some SMTP services support batch sending // Send 100 emails in single API call instead of 100 separate calls ``` **Solution 4: Check SMTP performance** ```bash # Test SMTP connection speed time curl -X POST http://localhost:4000/api/test-email \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{"to": "test@example.com", "subject": "Test", "text": "Test"}' # Should complete in < 2 seconds # If > 5 seconds, SMTP server slow ``` **Solution 5: Use email service** For high volume, use transactional email service: - SendGrid - Mailgun - Amazon SES - Postmark Faster and more reliable than SMTP. #### Prevention - **Queue system** - Never send synchronously - **Worker concurrency** - Process multiple at once - **Email service** - Use dedicated email service - **Rate limiting** - Respect provider limits --- ### Queue Backlog **Severity:** 🟡 Medium #### Symptoms Thousands of emails waiting in queue. Taking hours to process. #### Solutions **Solution 1: Increase worker count** Start multiple API instances: ```yaml # In docker-compose.yml api: deploy: replicas: 3 # 3 API instances ``` Each instance runs its own worker. **Solution 2: Increase concurrency** See "Slow Email Sending" section above. **Solution 3: Pause new emails** ```bash # Pause queue curl -X POST http://localhost:4000/api/influence/email-queue/pause \ -H "Authorization: Bearer YOUR_TOKEN" # Process backlog # Resume when caught up curl -X POST http://localhost:4000/api/influence/email-queue/resume \ -H "Authorization: Bearer YOUR_TOKEN" ``` **Solution 4: Clean old jobs** ```bash # Remove completed jobs curl -X POST http://localhost:4000/api/influence/email-queue/clean \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{"status": "completed", "grace": 3600000}' # Older than 1 hour ``` #### Prevention - **Monitor queue size** - Alert when > 1000 waiting - **Rate limiting** - Don't queue faster than can process - **Capacity planning** - Size workers for expected load - **Cleanup jobs** - Regular cleanup of old jobs --- ## Useful Commands ### Testing Email ```bash # Send test email curl -X POST http://localhost:4000/api/test-email \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{ "to": "test@example.com", "subject": "Test Email", "text": "This is a test email", "html": "

Test Email

This is a test email

" }' # Test with template curl -X POST http://localhost:4000/api/test-template-email \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{ "to": "test@example.com", "subject": "Test Template", "template": "campaign-email", "variables": { "name": "Test User", "campaignName": "Test Campaign" } }' ``` ### Queue Management ```bash # Get queue stats curl http://localhost:4000/api/influence/email-queue/stats \ -H "Authorization: Bearer YOUR_TOKEN" # Pause queue curl -X POST http://localhost:4000/api/influence/email-queue/pause \ -H "Authorization: Bearer YOUR_TOKEN" # Resume queue curl -X POST http://localhost:4000/api/influence/email-queue/resume \ -H "Authorization: Bearer YOUR_TOKEN" # Retry failed curl -X POST http://localhost:4000/api/influence/email-queue/retry-failed \ -H "Authorization: Bearer YOUR_TOKEN" # Clean completed curl -X POST http://localhost:4000/api/influence/email-queue/clean \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{"status": "completed", "grace": 86400000}' ``` ### Listmonk Operations ```bash # Test Listmonk connection curl -u admin:password http://localhost:9001/api/health # Get lists curl -u admin:password http://localhost:9001/api/lists # Sync subscribers curl -X POST http://localhost:4000/api/listmonk/sync \ -H "Authorization: Bearer YOUR_TOKEN" # Get sync status curl http://localhost:4000/api/listmonk/status \ -H "Authorization: Bearer YOUR_TOKEN" ``` --- ## Related Documentation ### Email Documentation - [Email Issues](email-issues.md) - This guide - [Email Templates Feature](../features/influence/email-templates.md) - Template management - [Email Queue](../features/influence/email-queue.md) - Queue monitoring ### Other Troubleshooting - [Common Errors](common-errors.md) - General errors - [Performance Optimization](performance-optimization.md) - Email performance ### External Resources - [Nodemailer Documentation](https://nodemailer.com/) - [BullMQ Documentation](https://docs.bullmq.io/) - [Listmonk Documentation](https://listmonk.app/docs/) - [Gmail SMTP Settings](https://support.google.com/a/answer/176600) - [SPF/DKIM/DMARC Guide](https://www.dmarcanalyzer.com/) --- **Last Updated:** February 2026 **Version:** V2.0 **Status:** Complete