Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Ishaq74/concordia/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Concordia uses nodemailer for email delivery with support for multiple SMTP providers. The email system handles authentication flows (email verification, password reset) and can be extended for notifications.

SMTP Service Architecture

The SMTP service (src/lib/smtp/smtp.ts) provides:
  • Multi-provider support - Pre-configured for 10+ popular providers
  • Connection pooling - Efficient email delivery with rate limiting
  • Error classification - Distinguishes retryable vs permanent failures
  • Validation - Email address and content validation
  • Mock mode - Testing without sending real emails

Environment Configuration

Add SMTP settings to your .env file:
.env
# SMTP Configuration
SMTP_PROVIDER=provider
SMTP_USER=contact@provider.com
SMTP_PASS=your_password_here
SMTP_FROM=contact@provider.com

# Optional: Override defaults
# SMTP_HOST=smtp.provider.com
# SMTP_PORT=587
# SMTP_SECURE=false
# SMTP_POOL=true
# SMTP_MAX_CONNECTIONS=5
# SMTP_RATE_DELTA=1000
# SMTP_RATE_LIMIT=5

# Alternative: Resend API
RESEND_API_KEY=your_resend_api_key_here

Supported Providers

Concordia includes pre-configured settings for these providers:
{
  name: 'IONOS',
  host: 'smtp.ionos.fr',
  port: 587,
  secure: false,
  requireTLS: true
}

List All Providers

View all supported providers:
npm run smtp:check providers

Provider Setup

Option 1: Use Provider Preset

Set SMTP_PROVIDER to auto-configure:
.env
SMTP_PROVIDER=resend
SMTP_USER=your-api-key
SMTP_PASS=your-api-key
SMTP_FROM=noreply@yourdomain.com

Option 2: Manual Configuration

Override individual settings:
.env
SMTP_HOST=smtp.custom-provider.com
SMTP_PORT=465
SMTP_SECURE=true
SMTP_USER=user@example.com
SMTP_PASS=password123
SMTP_FROM=noreply@example.com

Advanced Settings

Connection Pooling

Optimize delivery with connection pooling:
.env
# Enable connection pool (default: true)
SMTP_POOL=true

# Max concurrent connections (default: 5)
SMTP_MAX_CONNECTIONS=5

# Rate limiting
SMTP_RATE_DELTA=1000  # 1 second
SMTP_RATE_LIMIT=5     # 5 emails per second
These settings prevent overwhelming SMTP servers and help avoid rate limit errors.

SSL/TLS Configuration

.env
# For port 465 (implicit SSL)
SMTP_PORT=465
SMTP_SECURE=true

# For port 587 (explicit TLS/STARTTLS)
SMTP_PORT=587
SMTP_SECURE=false
Most modern providers use port 587 with STARTTLS. The service automatically configures requireTLS based on the provider preset.

Testing Email Configuration

Connection Test

Verify SMTP configuration:
npm run smtp:check
Output shows:
  • Provider name and server
  • Connection status (secure, TLS, pool)
  • Connection test result

Send Test Email

Send a test message:
npm run smtp:check your-email@example.com
This sends a test email and confirms delivery.

Test Output Example

🔍 SMTP Universal Checker

Provider : Resend
Serveur  : smtp.resend.com:587
Secure   : false
RequireTLS : true
Pool     : true

⏳ Test de connexion...
✅ Connexion OK

⏳ Test d'envoi à user@example.com...
✅ Email envoyé
   ID: <message-id@resend.com>

🏁 Terminé

Email Service Usage

Basic Email Sending

import { smtp } from '@/lib/smtp/smtp';

const result = await smtp.send({
  to: 'user@example.com',
  subject: 'Welcome to Concordia',
  text: 'Plain text version',
  html: '<h1>Welcome!</h1><p>HTML version</p>',
  from: 'noreply@yourdomain.com', // Optional, uses SMTP_FROM by default
  replyTo: 'support@yourdomain.com' // Optional
});

if (result.success) {
  console.log('Email sent:', result.messageId);
} else {
  console.error('Send failed:', result.error);
}

Batch Email Sending

Send multiple emails with concurrency control:
const results = await smtp.sendBatch(
  [
    { to: 'user1@example.com', subject: 'Hello', text: 'Message 1' },
    { to: 'user2@example.com', subject: 'Hello', text: 'Message 2' },
    { to: 'user3@example.com', subject: 'Hello', text: 'Message 3' },
  ],
  3 // Concurrency: send 3 at a time
);

results.forEach((result, i) => {
  if (result.success) {
    console.log(`Email ${i + 1} sent`);
  } else {
    console.error(`Email ${i + 1} failed:`, result.error);
  }
});

Error Handling

The service classifies errors:
const result = await smtp.send(payload);

if (!result.success) {
  const { error } = result;
  
  console.log('Error code:', error.code);
  console.log('Message:', error.message);
  console.log('Retryable:', error.retryable);
  console.log('Provider:', error.provider);
  
  if (error.code === 'AUTH_FAILED') {
    // Handle authentication errors
  } else if (error.retryable) {
    // Retry connection errors (ECONNREFUSED, ETIMEDOUT, etc.)
  }
}

Authentication Emails

Concordia uses Better Auth for authentication, which integrates with the SMTP service for:
  • Email verification - Confirm user email addresses
  • Password reset - Send reset links
  • Magic links - Passwordless login (if configured)

Email Templates

Auth emails use Better Auth’s built-in templates. Customize them in your auth configuration:
import { betterAuth } from 'better-auth';

export const auth = betterAuth({
  // ... other config
  emailAndPassword: {
    enabled: true,
    sendResetPassword: async ({ user, url }) => {
      await smtp.send({
        to: user.email,
        subject: 'Reset your password',
        html: `<p>Click to reset: <a href="${url}">${url}</a></p>`
      });
    },
  },
});

Provider-Specific Notes

Gmail

Gmail requires App Passwords when 2FA is enabled. Do not use your regular Gmail password.Generate App Password: Google Account Settings
.env
SMTP_PROVIDER=gmail
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password  # 16-character app password
SMTP_FROM=your-email@gmail.com

Resend

Resend offers both API and SMTP. For SMTP:
.env
SMTP_PROVIDER=resend
SMTP_USER=resend
SMTP_PASS=re_your_api_key
SMTP_FROM=noreply@yourdomain.com
Resend requires domain verification before sending. Add DNS records in your Resend dashboard.

SendGrid

.env
SMTP_PROVIDER=sendgrid
SMTP_USER=apikey  # Literally "apikey"
SMTP_PASS=your-sendgrid-api-key
SMTP_FROM=verified@yourdomain.com

AWS SES

.env
SMTP_PROVIDER=aws
SMTP_USER=your-smtp-username  # From SES SMTP settings
SMTP_PASS=your-smtp-password
SMTP_FROM=verified@yourdomain.com
AWS SES starts in sandbox mode. Request production access to send to unverified addresses.

Mock Mode (Testing)

Disable real email sending during development:
.env
SMTP_MOCK=1
# or
NODE_ENV=test
In mock mode:
  • SMTP service initializes but doesn’t send real emails
  • Logs show “Mode MOCK activé”
  • Perfect for running tests without email side effects

Troubleshooting

Authentication Failed

Error: AUTH_FAILED - Authentication failed: 535 Authentication failed
Solutions:
  • Verify SMTP_USER and SMTP_PASS are correct
  • Check if provider requires app-specific passwords (Gmail)
  • Ensure account isn’t locked or suspended
  • For IONOS: The service automatically uses authMethod: 'LOGIN'

Connection Timeout

Error: ETIMEDOUT - Connection timed out
Solutions:
  • Check firewall allows outbound SMTP (ports 587/465)
  • Verify SMTP_HOST is correct
  • Try alternate port (587 vs 465)
  • Check if your hosting blocks SMTP

Rate Limit Exceeded

Error: 550 - Too many emails sent
Solutions:
  • Reduce SMTP_RATE_LIMIT in .env
  • Increase SMTP_RATE_DELTA to slow sending
  • Upgrade provider plan for higher limits
  • Use sendBatch() with lower concurrency

SSL/TLS Errors

Error: unable to verify the first certificate
Solutions:
  • For port 587: Set SMTP_SECURE=false
  • For port 465: Set SMTP_SECURE=true
  • Check provider documentation for correct settings

Production Checklist

1

Choose provider

Select SMTP provider based on volume and budget.
2

Configure credentials

Add SMTP_PROVIDER, SMTP_USER, SMTP_PASS, and SMTP_FROM to production environment.
3

Verify domain

Add DNS records (SPF, DKIM, DMARC) for your sending domain.
4

Test connection

npm run smtp:check your-email@example.com
5

Configure rate limits

Set SMTP_RATE_LIMIT based on provider limits.
6

Monitor deliverability

Track bounces and spam reports in provider dashboard.

Next Steps

Database Setup

Configure PostgreSQL for production

Hosting

Deploy your application to production

Build docs developers (and LLMs) love