Email Providers
Overview
sails-hook-mail supports multiple email providers through its transport system. The transport determines how emails are physically delivered. You configure transports in config/mail.js and switch between them using the MAIL_MAILER environment variable.
Available transports:
| Transport | Package Required | Use Case |
|---|---|---|
log |
None | Development/testing -- prints to console |
smtp |
nodemailer |
Production -- any SMTP provider (Mailgun, SendGrid, AWS SES, Postmark) |
resend |
resend |
Production -- Resend API |
Environment Variables
All email provider configuration uses environment variables. Never hardcode credentials in config files.
Core Variables
# Which mailer to use (matches a key in config/mail.js mailers)
MAIL_MAILER=log # Development
MAIL_MAILER=smtp # Production with SMTP
MAIL_MAILER=resend # Production with ResendSMTP Variables
SMTP_HOST=smtp.mailgun.org
SMTP_PORT=587
SMTP_USER=postmaster@mg.myapp.com
SMTP_PASS=your-smtp-passwordResend Variables
RESEND_API_KEY=re_123456789SMTP Configuration
The SMTP transport uses Nodemailer under the hood. Install it first:
npm install nodemailerBasic SMTP Setup
// config/mail.js
module.exports.mail = {
default: process.env.MAIL_MAILER || 'log',
mailers: {
smtp: {
transport: 'smtp'
},
log: {
transport: 'log'
}
},
from: {
address: 'hello@myapp.com',
name: 'My App'
}
}The SMTP transport reads connection details from environment variables (SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS). Set these in your .env file or hosting platform.
Mailgun
Mailgun provides an SMTP relay service.
MAIL_MAILER=smtp
SMTP_HOST=smtp.mailgun.org
SMTP_PORT=587
SMTP_USER=postmaster@mg.myapp.com
SMTP_PASS=your-mailgun-smtp-passwordTo find your SMTP credentials in Mailgun:
- Go to Sending > Domains > select your domain
- Click SMTP credentials
- Use the login and password shown
The from address must use a verified domain in Mailgun. Verify your domain under Sending > Domains before sending production emails.
SendGrid
SendGrid SMTP relay:
MAIL_MAILER=smtp
SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_USER=apikey
SMTP_PASS=SG.your-sendgrid-api-keyNote: SendGrid uses apikey as the literal SMTP username, and your API key as the password.
To create an API key:
- Go to Settings > API Keys
- Click Create API Key
- Grant Mail Send permission
- Copy the generated key -- it is only shown once
AWS SES
Amazon Simple Email Service SMTP interface:
MAIL_MAILER=smtp
SMTP_HOST=email-smtp.us-east-1.amazonaws.com
SMTP_PORT=587
SMTP_USER=your-ses-smtp-username
SMTP_PASS=your-ses-smtp-passwordReplace us-east-1 with your AWS region. To get SMTP credentials:
- Go to Amazon SES > SMTP settings
- Click Create SMTP credentials
- Download the credentials (username and password)
Important: New SES accounts start in sandbox mode. You must request production access and verify sender/recipient addresses before sending to arbitrary email addresses.
Postmark
Postmark SMTP:
MAIL_MAILER=smtp
SMTP_HOST=smtp.postmarkapp.com
SMTP_PORT=587
SMTP_USER=your-postmark-server-api-token
SMTP_PASS=your-postmark-server-api-tokenPostmark uses the same Server API Token for both username and password.
Custom SMTP Server
Any standard SMTP server works:
MAIL_MAILER=smtp
SMTP_HOST=mail.mycompany.com
SMTP_PORT=587
SMTP_USER=noreply@mycompany.com
SMTP_PASS=your-passwordCommon SMTP Ports
| Port | Encryption | Use Case |
|---|---|---|
| 587 | STARTTLS | Recommended for most providers |
| 465 | SSL/TLS | Legacy secure SMTP |
| 25 | None | Not recommended (often blocked by ISPs) |
Use port 587 unless your provider specifically requires a different port.
Resend Configuration
Resend is a modern email API with a developer-friendly interface. Install the package:
npm install resendSetup
// config/mail.js
module.exports.mail = {
default: process.env.MAIL_MAILER || 'log',
mailers: {
resend: {
transport: 'resend'
},
log: {
transport: 'log'
}
},
from: {
address: 'hello@myapp.com',
name: 'My App'
}
}MAIL_MAILER=resend
RESEND_API_KEY=re_123456789To get an API key:
- Sign up at resend.com
- Go to API Keys and create a new key
- Add and verify your sending domain under Domains
Resend Advantages
- Simple API with excellent developer experience
- Built-in analytics and delivery tracking
- React Email template support (if using their SDK directly)
- Generous free tier (100 emails/day)
Per-Environment Configuration
Development (Default)
No configuration needed. The default log transport prints emails to the console:
// config/mail.js
module.exports.mail = {
default: process.env.MAIL_MAILER || 'log' // Falls back to 'log'
// ...
}Test Environment
Force the log transport in tests to prevent accidentally sending real emails:
// config/env/test.js
module.exports = {
mail: {
default: 'log',
mailers: {
log: {
transport: 'log'
}
}
}
}This overrides any MAIL_MAILER environment variable during tests.
Production
Set environment variables on your hosting platform. The config/mail.js file reads them automatically via process.env:
# .env or hosting platform environment variables
MAIL_MAILER=smtp
SMTP_HOST=smtp.mailgun.org
SMTP_PORT=587
SMTP_USER=postmaster@mg.myapp.com
SMTP_PASS=your-passwordYou can also add production-specific mail overrides in config/env/production.js:
// config/env/production.js
module.exports = {
// ... other production config ...
// Example: Override from address for production
mail: {
from: {
address: 'noreply@myapp.com',
name: 'My App'
}
}
}Staging
For staging environments, you might want to use a real transport but with a sandboxed domain:
MAIL_MAILER=smtp
SMTP_HOST=smtp.mailgun.org
SMTP_PORT=587
SMTP_USER=postmaster@sandbox123.mailgun.org
SMTP_PASS=your-sandbox-passwordMailgun sandbox domains only deliver to verified recipients, preventing accidental emails to real users.
Local Testing Tools
Log Transport
The simplest approach -- emails are printed to the Sails console. This is the default behavior:
info: -----------------------------------------------------------------
info: Sending email...
info: To: user@example.com
info: Subject: Verify your email
info: -----------------------------------------------------------------
info: [HTML content of the email]
info: -----------------------------------------------------------------Good for verifying that emails are being triggered with the correct data. Not useful for testing visual appearance.
Mailpit
Mailpit is a local SMTP server with a web-based email viewer. It catches all outgoing emails and displays them in a UI.
# Install
brew install mailpit
# Run (SMTP: port 1025, Web UI: port 8025)
mailpitConfigure your app to use it:
MAIL_MAILER=smtp
SMTP_HOST=localhost
SMTP_PORT=1025
# No username/password needed for MailpitThen open http://localhost:8025 to see emails as they arrive. Mailpit shows the full HTML rendering, plain text version, headers, and raw source.
Mailtrap
Mailtrap is a cloud-hosted email testing service. It provides a fake SMTP server that captures emails without delivering them.
MAIL_MAILER=smtp
SMTP_HOST=sandbox.smtp.mailtrap.io
SMTP_PORT=587
SMTP_USER=your-mailtrap-username
SMTP_PASS=your-mailtrap-passwordSign up at mailtrap.io to get credentials. The free tier includes 100 emails/month. Mailtrap provides additional features like spam score analysis and HTML/CSS compatibility checks.
Testing Workflow Recommendation
- During development: Use
logtransport (default) for quick iteration - For visual testing: Use Mailpit locally to preview email rendering
- Before deployment: Use Mailtrap to verify emails look correct across clients
- In staging: Use a sandboxed SMTP domain (e.g., Mailgun sandbox)
- In production: Use a verified SMTP or Resend configuration
Sender Domain Verification
Before sending production emails, you must verify your sending domain with your email provider. This involves adding DNS records (SPF, DKIM, DMARC) to prove you own the domain.
SPF Record
Authorizes specific servers to send email on behalf of your domain:
Type: TXT
Host: @
Value: v=spf1 include:mailgun.org ~allDKIM Record
Adds a cryptographic signature to verify email authenticity:
Type: TXT
Host: smtp._domainkey
Value: (provided by your email provider)DMARC Record
Tells receiving servers what to do with emails that fail SPF/DKIM checks:
Type: TXT
Host: _dmarc
Value: v=DMARC1; p=quarantine; rua=mailto:dmarc@myapp.comEach provider has its own verification flow -- check their documentation for specific DNS records to add.
Multiple Providers
You can configure multiple providers and switch between them per-email:
// config/mail.js
module.exports.mail = {
default: process.env.MAIL_MAILER || 'log',
mailers: {
smtp: { transport: 'smtp' },
resend: { transport: 'resend' },
log: { transport: 'log' }
},
from: {
address: 'hello@myapp.com',
name: 'My App'
}
}Send through a specific provider by passing the mailer parameter:
// Use default mailer
await sails.helpers.mail.send.with({
subject: 'Welcome',
template: 'email-welcome',
to: user.email,
templateData: { fullName: user.fullName }
})
// Use a specific mailer (overrides default)
await sails.helpers.mail.send.with({
subject: 'Important notification',
template: 'email-notification',
to: user.email,
mailer: 'resend',
templateData: { message: 'Your account was updated.' }
})This is useful for sending through different providers based on email type (e.g., transactional emails via SMTP, marketing via Resend).
Troubleshooting
Emails Not Sending in Production
- Verify
MAIL_MAILERis set tosmtporresend(notlog) - Check that all required environment variables are set (
SMTP_HOST,SMTP_PORT, etc.) - Confirm your
fromaddress uses a verified domain - Check Sails logs for transport errors
Emails Going to Spam
- Verify SPF, DKIM, and DMARC records are properly configured
- Use a verified sending domain (not a free email address)
- Ensure the
fromaddress matches the verified domain - Avoid spam trigger words in subject lines
SMTP Connection Timeouts
- Verify the SMTP host and port are correct
- Check if your hosting provider blocks outbound SMTP (port 587 or 465)
- Some providers (e.g., Railway, Render) block outbound SMTP -- use Resend API instead
Resend API Errors
- Verify
RESEND_API_KEYis set correctly - Confirm your sending domain is verified in the Resend dashboard
- Check the Resend dashboard for delivery logs and error details