Guide - Gmail SMTP Setup
This guide explains how to generate a Gmail App Password and configure the GMAIL_USER and GMAIL_APP_PASSWORD environment variables for the booki-api Node service. It covers Nodemailer usage, CI secrets, testing, troubleshooting, and security recommendations.
Summary
GMAIL_USER: your full Gmail address (for exampleyou@gmail.com).GMAIL_APP_PASSWORD: a 16-character App Password generated from your Google account (used instead of your regular Google password when 2-Step Verification is enabled).
App Passwords let you authenticate SMTP clients when 2-Step Verification is enabled. They are safer than using your primary Google password and can be revoked independently.
Prerequisites
- Enable 2-Step Verification (2FA) on the Google account you intend to use.
- App Passwords are available for personal Google accounts. For Google Workspace (G Suite) accounts your admin may need to enable or allow App Passwords.
- Never commit credentials to source control. Use
.envfor local development and a secret manager for production/CI.
Create an App Password
- Open: https://myaccount.google.com/security
- Under "Signing in to Google" enable "2-Step Verification" (if not already enabled).
- After enabling 2-Step Verification, click "App passwords".
- Create a new app password:
- App: choose
Mail(orOtherand give a descriptive name likebooki-api). - Device: choose an appropriate device or enter a custom name.
- Click "Generate" and copy the 16-character password (groups of 4). You won't be able to view it again.
- App: choose
Store the value somewhere secure and add it to your .env as GMAIL_APP_PASSWORD.
Local Setup
Create or update booki-api/.env (do not commit this file):
GMAIL_USER=you@gmail.com
GMAIL_APP_PASSWORD=abcdefghijklmnop
Do not include spaces — Google displays the password in groups of 4 for readability, but enter the 16 characters without spaces.
Minimal Nodemailer Example (test script)
Save this as booki-api/test-email.ts and run it to verify SMTP connectivity.
// booki-api/test-email.ts
import nodemailer from "nodemailer";
import dotenv from "dotenv";
dotenv.config();
async function sendTest() {
const transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 587,
secure: false, // use TLS via STARTTLS
auth: {
user: process.env.GMAIL_USER,
pass: process.env.GMAIL_APP_PASSWORD,
},
});
const info = await transporter.sendMail({
from: `Booking App <${process.env.GMAIL_USER}>`,
to: process.env.GMAIL_USER, // send to yourself for quick test
subject: "booki-api: SMTP test",
text: "This is a test email sent from booki-api using an App Password.",
});
console.log("Message sent:", info.messageId);
}
sendTest().catch((err) => {
console.error("Failed to send test email:", err);
process.exit(1);
});
Run the script:
npx ts-node test-email.ts
If it succeeds you should see a Message ID in the console and an email in the recipient inbox.
Optional: Using OAuth2 (recommended for production)
App Passwords are convenient for simple setups. For production-grade Gmail usage prefer OAuth2 with a service account or delegated OAuth flow — more secure, revocable, and auditable. Nodemailer supports OAuth2; see the Nodemailer docs for details.
GitHub Actions / CI
In CI or production, store credentials in repository or organization secrets — never in code.
- Go to GitHub repository → Settings → Secrets and variables → Actions → New repository secret.
- Add
GMAIL_USERandGMAIL_APP_PASSWORD. - Reference them in workflows as environment variables:
env:
GMAIL_USER: ${{ secrets.GMAIL_USER }}
GMAIL_APP_PASSWORD: ${{ secrets.GMAIL_APP_PASSWORD }}
Use these env vars in any CI step that needs to send email (for example integration tests that send notifications).
Troubleshooting
Authentication errors (535, Authentication unsuccessful):
- Confirm the App Password was copied exactly (no leading/trailing spaces).
- Verify 2-Step Verification is enabled on the Google account.
- For Workspace accounts, check with the admin to ensure App Passwords are permitted.
- Inspect recent security events in the Google account (Google may block suspicious sign-ins).
Connection errors (Could not connect to SMTP host, timeouts):
- Ensure outbound SMTP (ports 587 or 465) is allowed from your environment (firewall, cloud provider, or corporate network may block these).
- Try using port 465 with
secure: trueif 587 fails with STARTTLS issues.
Lost App Password: Revoke it in Google Security → App passwords and generate a new one.
Security Recommendations
- Never commit
.envfiles or credentials to version control. Add.envto.gitignore. - Prefer a dedicated email provider (SendGrid, Mailgun, SES) for production workloads; they offer better deliverability and analytics.
- Rotate and revoke App Passwords periodically.
- Store secrets in a secrets manager (GitHub Secrets, cloud provider secret manager, HashiCorp Vault).
