Skip to content

Commit ff1d352

Browse files
update in codenbase Done
1 parent 1150d0c commit ff1d352

3 files changed

Lines changed: 36 additions & 13 deletions

File tree

.env.example

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,19 @@ ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173
6060

6161
# ─── Email ─────────────────────────────────────────────────────
6262
# Dev: use Ethereal (https://ethereal.email) — free fake SMTP inbox
63-
# Prod: use SendGrid, Resend, SES, etc.
64-
SMTP_HOST=smtp.ethereal.email
63+
# Prod: use Gmail App Password, SendGrid, Resend, SES, etc.
64+
SMTP_HOST=smtp.gmail.com
6565
SMTP_PORT=587
6666
SMTP_SECURE=false
67-
SMTP_USER=your-ethereal-user
68-
SMTP_PASS=your-ethereal-pass
67+
# REQUIRED: your Gmail address (or SMTP username for other providers)
68+
SMTP_USER=your-email@gmail.com
69+
# REQUIRED: Gmail App Password (NOT your regular password)
70+
# Generate at: myaccount.google.com → Security → 2-Step Verification → App Passwords
71+
SMTP_PASS=your-gmail-app-password
6972
EMAIL_FROM=noreply@lexai.io
73+
# Legacy aliases (optional — SMTP_USER/SMTP_PASS take precedence if both are set)
74+
# MAIL_USER=your-email@gmail.com
75+
# MAIL_PASS=your-gmail-app-password
7076

7177
# ─── External APIs ─────────────────────────────────────────────
7278
REST_COUNTRIES_URL=https://restcountries.com/v3.1

src/config/env.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,13 @@ const envSchema = z.object({
8989
SMTP_HOST: z.string().default('smtp.gmail.com'),
9090
SMTP_PORT: z.coerce.number().default(587),
9191
SMTP_SECURE: z.string().transform((v) => v === 'true').default('false'),
92+
// Canonical SMTP credentials — set these in your .env
9293
SMTP_USER: z.string().default(''),
9394
SMTP_PASS: z.string().default(''),
9495
EMAIL_FROM: z.string().default('noreply@lexai.io'),
95-
// Gmail credentialsused directly by the nodemailer transporter
96-
MAIL_USER: z.string().min(1, 'MAIL_USER (Gmail address) is required'),
97-
MAIL_PASS: z.string().min(1, 'MAIL_PASS (Gmail App Password) is required'),
96+
// Legacy aliaseskept for backwards compatibility; SMTP_USER/SMTP_PASS take precedence
97+
MAIL_USER: z.string().default(''),
98+
MAIL_PASS: z.string().default(''),
9899

99100
// ─── Redis Token TTLs ─────────────────────────────────────
100101
// How long password reset tokens live in Redis (seconds)
@@ -129,6 +130,17 @@ if (!parsed.success) {
129130
// Freeze the config to prevent accidental mutation anywhere in the app
130131
const env = Object.freeze(parsed.data);
131132

133+
// ─── Email credential check ────────────────────────────────────────────────
134+
// Ensure at least one SMTP credential pair is configured so emails don't
135+
// silently fail at runtime. SMTP_USER/SMTP_PASS are preferred; MAIL_USER/MAIL_PASS
136+
// are accepted as legacy aliases.
137+
const emailUser = parsed.data.SMTP_USER || parsed.data.MAIL_USER;
138+
const emailPass = parsed.data.SMTP_PASS || parsed.data.MAIL_PASS;
139+
if (!emailUser || !emailPass) {
140+
console.error('❌ Email configuration missing: set SMTP_USER and SMTP_PASS (or MAIL_USER and MAIL_PASS) in your .env file.');
141+
process.exit(1);
142+
}
143+
132144
// ─── Production Safety Checks ─────────────────────────────────────────────
133145
// Fail fast if placeholder secrets are used in production
134146
if (env.NODE_ENV === 'production') {

src/services/email.service.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,22 @@ let transporter = null;
3737
* in server.js.
3838
*/
3939
function _initTransporter() {
40+
// Prefer SMTP_USER/SMTP_PASS (canonical names); fall back to MAIL_USER/MAIL_PASS
41+
// for backwards compatibility with existing .env files.
42+
const smtpUser = env.SMTP_USER || env.MAIL_USER;
43+
const smtpPass = env.SMTP_PASS || env.MAIL_PASS;
44+
4045
transporter = nodemailer.createTransport({
41-
host: env.SMTP_HOST, // smtp.gmail.com
42-
port: env.SMTP_PORT, // 587
43-
secure: false, // false = STARTTLS (upgrades from plain to encrypted)
46+
host: env.SMTP_HOST, // smtp.gmail.com
47+
port: env.SMTP_PORT, // 587
48+
secure: env.SMTP_SECURE, // true = TLS (port 465), false = STARTTLS (port 587)
4449
auth: {
45-
user: env.MAIL_USER, // Gmail address (from MAIL_USER in .env)
46-
pass: env.MAIL_PASS, // Gmail App Password (from MAIL_PASS in .env)
50+
user: smtpUser, // Gmail address
51+
pass: smtpPass, // Gmail App Password
4752
},
4853
});
4954

50-
logger.info('Email transporter ready (Gmail SMTP)');
55+
logger.info(`Email transporter ready (${env.SMTP_HOST}:${env.SMTP_PORT})`);
5156
}
5257

5358
/**

0 commit comments

Comments
 (0)