Nodemailer — SMTP, Gmail, email yuborish
Muammodan boshlaylik
Foydalanuvchi ro'yxatdan o'tdi. Endi unga "Xush kelibsiz!" emaili yuborilishi kerak. Yoki parolni unutdi — tasdiqlash kodi kerak. Buyurtma qildi — chek emaili kerak.
Bularning barchasida server o'zi email yuborishi lozim. Lekin email qanday ishlaydi? Server qayerdan yuboradi?
SMTP nima?
SMTP (Simple Mail Transfer Protocol) — emaillarni yuborish uchun protokol. Xuddi pochta idorasi kabi: siz konvert topshirasiz, ular manzilga yetkazadi.
Sizning server Gmail SMTP Qabul qiluvchi
| | |
|--- email (SMTP) ---->| |
| |--- yetkazish ------->|
|<-- OK ---------------| |
Nodemailer — Node.js da email yuborish uchun kutubxona. SMTP server bilan gaplashadi.
O'rnatish
npm install nodemailer
Transporter nima?
Tasavvur qiling: kuryer xizmati. Siz paketni berasiz, kuryer yetkazadi. Transporter — o'sha kuryer. Bir marta sozlanadi, keyin qayta-qayta ishlatiladi.
import nodemailer from 'nodemailer';
const transporter = nodemailer.createTransport({
host: 'smtp.gmail.com', // ← SMTP server manzili
port: 587, // ← 587 (TLS) yoki 465 (SSL)
secure: false, // ← 587 da false, 465 da true
auth: {
user: process.env.EMAIL_USER, // ← gmail manzili
pass: process.env.EMAIL_PASS, // ← app password (parol emas!)
},
});
⚠️
pass— Gmail parolingiz emas. Google "App Password" yaratishni talab qiladi. Quyida tushuntiriladi.
Gmail App Password olish
Google oddiy parolni SMTP uchun qabul qilmaydi — xavfsizlik sababli. "App Password" — maxsus yaratilgan 16 belgili kod.
- Google Account → Security
- 2-Step Verification — yoqing (majburiy)
- App passwords → "Mail" → "Other" → nom bering
- 16 belgili kodni
.envga yozing
EMAIL_USER=siz@gmail.com
EMAIL_PASS=abcd efgh ijkl mnop
Email yuborish
const emailYuborish = async ({ kimga, mavzu, matn }) => {
await transporter.sendMail({
from: `"DevDocs" <${process.env.EMAIL_USER}>`, // ← kimdan
to: kimga, // ← kimga
subject: mavzu, // ← mavzu
text: matn, // ← oddiy matn
});
};
// Ishlatish
await emailYuborish({
kimga: 'ali@example.com',
mavzu: 'Xush kelibsiz!',
matn: 'DevDocs ga ro\'yxatdan o\'tdingiz.',
});
HTML email
await transporter.sendMail({
from: `"DevDocs" <${process.env.EMAIL_USER}>`,
to: 'ali@example.com',
subject: 'Parolni tiklash',
text: 'Parolni tiklash uchun: http://...', // ← HTML ko'rsatmasa fallback
html: `
<h2>Parolni tiklash</h2>
<p>Quyidagi tugmani bosing:</p>
<a href="http://localhost:3000/reset?token=abc123"
style="background:#3b82f6;color:white;padding:12px 24px;text-decoration:none;border-radius:6px;">
Parolni tiklash
</a>
<p>Link 1 soat davomida amal qiladi.</p>
`,
});
💡
textni ham yozing — ba'zi email mijozlar HTML ko'rsatmaydi. Ikkalasi birga bo'lsa — HTML ko'rsatsa HTML, ko'rsatmasatext.
Route bilan birlashtirish
// routes/auth.js
import express from 'express';
import crypto from 'crypto';
import nodemailer from 'nodemailer';
const router = express.Router();
const transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 587,
secure: false,
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
});
// Parolni tiklash so'rovi
router.post('/forgot-password', async (req, res) => {
const { email } = req.body;
const foydalanuvchi = await db.users.findOne({ where: { email } });
if (!foydalanuvchi) {
// ← foydalanuvchi bormi yo'qmi aytmang — xavfsizlik
return res.json({ xabar: 'Email yuborildi' });
}
// Tasdiqlash tokeni
const token = crypto.randomBytes(32).toString('hex');
const muddati = new Date(Date.now() + 60 * 60 * 1000); // 1 soat
await db.resetTokens.create({ userId: foydalanuvchi.id, token, muddati });
await transporter.sendMail({
from: `"DevDocs" <${process.env.EMAIL_USER}>`,
to: email,
subject: 'Parolni tiklash',
html: `
<p>Parolni tiklash uchun bosing:</p>
<a href="${process.env.CLIENT_URL}/reset?token=${token}">Parolni tiklash</a>
<p>Link 1 soat amal qiladi.</p>
`,
});
res.json({ xabar: 'Email yuborildi' });
});
Ulanishni tekshirish
Development da email yuborish o'rniga ulanishni tekshirish:
transporter.verify((error) => {
if (error) {
console.log('SMTP xatosi:', error.message);
} else {
console.log('SMTP tayyor');
}
});
Ethereal — test uchun
Development da real email yuborishning hojati yo'q. Ethereal — soxta SMTP: email "yuboriladi", lekin aslida brauzerda ko'rib chiqasiz.
// Test transporter yaratish
const testTransporter = await nodemailer.createTestAccount();
const transporter = nodemailer.createTransport({
host: 'smtp.ethereal.email',
port: 587,
auth: {
user: testTransporter.user,
pass: testTransporter.pass,
},
});
const info = await transporter.sendMail({
from: 'test@example.com',
to: 'ali@example.com',
subject: 'Test',
text: 'Bu test email',
});
// Brauzerde ko'rish uchun URL
console.log('Preview:', nodemailer.getTestMessageUrl(info));
// → https://ethereal.email/message/...
💡 Ethereal — real emailga o'tishdan oldin shablonni tekshirishning eng qulay usuli. Real manzilga hech narsa ketmaydi.
Tez-tez uchraydigan xatolar
1. "Invalid login" xatosi
Error: Invalid login: 535-5.7.8 Username and Password not accepted
Sababi: oddiy Gmail parol ishlamaydi. App Password kerak (yuqorida tushuntirilgan).
2. "Less secure app access" xatosi
Google bu funksiyani 2022 yilda o'chirib tashladi. Yechim — faqat App Password.
3. Port xatosi
// ❌ — port va secure mos kelmayapti
{ port: 465, secure: false }
{ port: 587, secure: true }
// ✅
{ port: 465, secure: true } // SSL
{ port: 587, secure: false } // TLS (STARTTLS)
4. Email spamga tushishi
fromda to'g'ri manzil ko'rsatingtextfallback qo'shing- Bir vaqtda juda ko'p email yubormang
Xulosa
- Nodemailer — Node.js da email yuborish kutubxonasi; SMTP orqali ishlaydi
- Gmail uchun App Password kerak — oddiy parol ishlamaydi
textvahtmlikkalasini yozing — email mijozlar farq qiladi- Development da Ethereal — real email yuborilmaydi, brauzerde ko'rasiz
transporter.verify()— ulanishni tekshirish
Keyingi dars: 47-dars: Email template — HTML email, Handlebars