How to Send Emails in Express.js: SMTP and API Guide
Source: Dev.to
Prerequisites
- Node.js installed on your machine. Download the latest version here.
- Code editor (e.g., Visual Studio Code).
- Basic knowledge of JavaScript.
- A SendLayer account. You can start a free trial that lets you send up to 200 emails for free. Start your free trial at SendLayer.
After creating your SendLayer account, authorize your sending domain to improve email deliverability.
Setting Up an Express.js Server
# Create project folder
mkdir send-email
cd send-email
# Initialize npm project
npm init -y
# Install dependencies
npm install express dotenv
Create server.js in the project root:
// server.js
const express = require('express');
const dotenv = require('dotenv');
dotenv.config(); // Load environment variables
const app = express();
const port = process.env.PORT || 3000;
// Middleware to parse JSON data
app.use(express.json());
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
Run the server:
node server.js
You should see:
Server running on port 3000
You can now access the server at http://localhost:3000.
Send Emails Via SMTP
Install Nodemailer
npm install nodemailer
Configure Environment Variables
Create a .env file and add your SMTP credentials (example uses SendLayer):
SMTP_HOST=smtp.sendlayer.net
SMTP_PORT=587
SMTP_USER=your-smtp-username
SMTP_PASS=your-smtp-password
FROM_EMAIL=sender@example.com
Note: For SendLayer, the sender email must belong to an authorized domain (e.g.,
@example.com).
Update server.js with Email Logic
// server.js (continued)
const nodemailer = require('nodemailer');
// Function to send email via SMTP
const sendEmail = async (to, subject, message) => {
try {
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
secure: false, // false for TLS (587), true for SSL (465)
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
const mailOptions = {
from: process.env.FROM_EMAIL,
to,
subject,
text: message,
};
const info = await transporter.sendMail(mailOptions);
console.log('Email sent:', info.messageId);
} catch (error) {
console.error('Error sending email:', error);
throw error;
}
};
// POST route to trigger email
app.post('/send-email', async (req, res) => {
const { to, subject, message } = req.body;
if (!to || !subject || !message) {
return res.status(400).json({ status: 'error', message: 'Missing required fields' });
}
try {
await sendEmail(to, subject, message);
res.status(200).json({ status: 'success', message: 'Email sent successfully' });
} catch (err) {
res.status(500).json({ status: 'error', message: 'Failed to send email' });
}
});
Sending Attachments (Optional)
Add an attachments array to mailOptions:
const mailOptions = {
from: process.env.FROM_EMAIL,
to,
subject,
text: message,
attachments: [
{
filename: 'example.pdf',
path: './path/to/example.pdf', // Update with the correct path
},
],
};
Test the Endpoint
Start the server:
node server.js
Use cURL or Postman to POST to http://localhost:3000/send-email with a JSON body:
{
"to": "recipient@example.com",
"subject": "Test Email",
"message": "Hello from Express.js!"
}
A successful response looks like:
{
"status": "success",
"message": "Email sent successfully"
}
Check the recipient’s inbox to confirm delivery.
To send to multiple recipients, separate email addresses with commas in the to field.
Send Emails Via API
This section outlines using an email service’s HTTP API (e.g., SendLayer) instead of SMTP. The approach offers better deliverability and scalability for bulk sending.
Install Axios (or any HTTP client)
npm install axios
Add API Credentials to .env
SENDLAYER_API_KEY=your-api-key
Implement API‑Based Sending
// server.js (continued)
const axios = require('axios');
const sendEmailViaAPI = async (to, subject, message) => {
try {
const response = await axios.post(
'https://api.sendlayer.com/v1/email',
{
from: process.env.FROM_EMAIL,
to,
subject,
text: message,
},
{
headers: {
Authorization: `Bearer ${process.env.SENDLAYER_API_KEY}`,
'Content-Type': 'application/json',
},
}
);
console.log('API email sent:', response.data);
return response.data;
} catch (error) {
console.error('API error:', error.response?.data || error.message);
throw error;
}
};
// Example route using the API method
app.post('/send-email-api', async (req, res) => {
const { to, subject, message } = req.body;
if (!to || !subject || !message) {
return res.status(400).json({ status: 'error', message: 'Missing required fields' });
}
try {
await sendEmailViaAPI(to, subject, message);
res.status(200).json({ status: 'success', message: 'Email sent via API' });
} catch (err) {
res.status(500).json({ status: 'error', message: 'Failed to send email via API' });
}
});
The API method eliminates the need to manage SMTP connections and often provides richer features such as templates, tracking, and rate limiting.
Troubleshooting Common Errors
| Symptom | Possible Cause | Fix |
|---|---|---|
Error: self signed certificate | TLS verification failure | Set secure: false and add tls: { rejectUnauthorized: false } in the transporter config (only for development). |
550 5.1.1 (recipient not found) | Invalid to address | Verify the email address format and that the domain exists. |
401 Unauthorized from API | Wrong or missing API key | Ensure SENDLAYER_API_KEY is correct and included in the Authorization header. |
| No email received | Emails landing in spam | Check SPF/DKIM records for your domain and use a verified sender address. |
Server crashes on sendMail | Unhandled promise rejection | Wrap sendEmail calls in try/catch and return proper HTTP status codes. |
Frequently Asked Questions
Q: Should I use SMTP or an email API?
A: For simple or low‑volume use, SMTP with Nodemailer works fine. For higher volume, better deliverability, and advanced features (templates, analytics), an email API is recommended.
Q: How do I send HTML emails?
A: Add an html property to mailOptions (SMTP) or include html in the API payload.
const mailOptions = {
from: process.env.FROM_EMAIL,
to,
subject,
html: '
## Hello
This is an HTML email.
',
};
Q: Can I schedule emails?
A: Neither Nodemailer nor most email APIs provide built‑in scheduling. Use a job scheduler like node-cron or a task queue (e.g., Bull) to trigger the send at a later time.
Q: How do I handle rate limits?
A: Respect the limits documented by your email provider. Implement retry logic with exponential backoff, or batch requests when sending bulk mail.