https://betterprogramming.pub/how-to-create-a-signup-confirmation-email-with-node-js-c2fea602872a
Image by [vectorjuice](https://br.freepik.com/vetores-gratis/email-marketing-chat-na-internet-suporte-24-horas-entre-em-contato-inicie-contato-fale-conosco-feedback-formulario-online-fale-com-o-conceito-de-clientes_10780041.htm#page=1&query=mail vectorjuice&position=0) available on Freepik
Електронні листи з підтвердженням реєстрації користувачів є важливим кроком як для маркетингу, так і для безпеки. З точки зору маркетингу, електронні листи з підтвердженням встановлюють перше спілкування з клієнтом, гарантуючи надсилання важливої інформації до завершення процесу реєстрації, дотримання положень GDPR і гарантує, що наступні листи не потраплять до спаму.
З точки зору безпеки, ці електронні листи гарантують, що користувач не реєструється за допомогою підробленої електронної пошти.
У цьому підручнику я розповім вам про впровадження електронних листів із підтвердженням функції реєстрації за допомогою React і Node.js.
Цей підручник призначений для тих, хто вже має базові знання веб-розробки за допомогою фреймворків JavaScript. Я пропоную вам інтегрувати нові функції в уже існуючий процес автентифікації.
Я дам вам увесь необхідний код, якщо ви захочете використовувати цей підручник як вправу з програмування. Однак якщо у вас уже є веб-програма, і ви хочете лише додати власний електронний лист із підтвердженням реєстрації, ви зможете виконати кожен крок цього посібника, щоб зробити це самостійно, навіть якщо ви використовуєте різні фреймворки JavaScript.
Для цього підручника я використовував програму Node.js із базою даних Mongo DB, яку можна клонувати тут.
Для інтерфейсу я використовував реєстраційну форму React з автентифікацією JWT, яку можна знайти за посиланням.
Якщо ви використовуєте початковий код, про який я згадував у попередньому розділі, ви можете знайти модель користувача у файлі models/user.model.js
. Поточна модель містить три поля:username
, email
, та password
. Потрібно додати ще два:
status
: кожен новий користувач повинен бути створений зі статусом "Pending" (Очікує на розгляд) за умовчанням. Після реєстрації він отримає лист-підтвердження з посиланням для активації. Якщо натиснути на нього, його статус буде оновлено до «Active».confirmationCode
: унікальний маркер для кожного користувача.
// models/user.model.js
// Модель користувача
const mongoose = require("mongoose");
const User = mongoose.model(
"User",
new mongoose.Schema({
username: String,
email: String,
password: String,
status: {
type: String,
enum: ['Pending', 'Active'],
default: 'Pending'
},
confirmationCode: {
type: String,
unique: true },
roles: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Role"
}
]
})
);
module.exports = User;
Лише користувачі зі статусом «Active» мають мати змогу ввійти, тому ми повинні включити повідомлення про помилку в метод signin
, яке відображатиметься, коли користувач зі статусом «Pending» спробує ввійти. Цей метод можна знайти в controllers/auth.controller.js
:
// controllers/auth.controller.js
// Повідомлення про помилку, яке буде включено в метод signing().
if (user.status != "Active") {
return res.status(401).send({
message: "Pending Account. Please Verify Your Email!",
});
}
Метод signup
знаходиться у файлі controllers/auth.controller.js
. Його потрібно оновити, щоб створити confirmationCode
і додати до об’єкта користувача, який буде зберігатися в базі даних.
confirmationCode
можна створити кількома способами. Я пропоную два:
- Обчисліть свій власний унікальний маркер за допомогою функції
Math.random()
:
// controllers/auth.controller.js
// Код підтвердження реєстрації, створений за допомогою функції Math.random().
const characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
let token = '';
for (let i = 0; i < 25; i++) {
token += characters[Math.floor(Math.random() * characters.length )];
}
- Використовуйте відповідний пакет npm. Вам є з чого вибрати. Для цього підручника я використав jwt-encode, який створює веб-токени JSON за допомогою секрету та функції
sign()
.
// Код підтвердження реєстрації, створений за допомогою пакета jwt-encode
const config = require("../config/auth.config");
const db = require("../models");
const User = db.user;
const Role = db.role;
var jwt = require("jsonwebtoken");
var bcrypt = require("bcryptjs");
exports.signup = (req, res) => {
const token = jwt.sign({email: req.body.email}, config.secret)
const user = new User({
username: req.body.username,
email: req.body.email,
password: bcrypt.hashSync(req.body.password, 8),
confirmationCode: token
});
Зауважте, що для функції sign()
я використав константу з назвою secret
, яка вже визначена у файлі config/auth.config.js
.
nodemailer
— ідеальний пакет npm для надсилання електронних листів. Якщо ви ще цього не зробили, встановіть цей пакет:
npm install nodemailer
Потім вам потрібно включити облікові дані відправника, а саме його адресу електронної пошти та пароль, у файл конфігурації програми. Для цього підручника я спеціально створив обліковий запис електронної пошти, і я настійно рекомендую не використовувати особисту електронну адресу для цієї вправи, якщо ви не маєте глибокого розуміння питань безпеки.
Важливо: Щоб використовувати Gmail із nodemailer, потрібно ввімкнути доступ для менш безпечних програм* , інакше він не надсилатиме жодних електронних листів.*
З метою узгодженості (будь ласка, пам’ятайте, що я не використовую власний код як відправну точку для цього підручника), я зберіг облікові дані у файлі configs/auth.config.js
. Однак я наполегливо рекомендую вам зберігати цю інформацію у файлі .env
і включити її у свій файл .gitignore
.
// configs/auth.config.js
// Облікові дані для автентифікації електронної пошти зберігаються
module.exports = {
secret: "bezkoder-secret-key",
user: "[email protected]",
pass: "medium2021t",
};
Після цього нам потрібно додати новий файл у папку config
, щоб налаштувати службу електронної пошти. Я створив nodemailer.config.js
. Щоб налаштувати SMTP-з’єднання, нам потрібно створити об’єкт транспортера, викликавши функцію createTransport у nodemailer. Ми також маємо передати йому облікові дані відправника разом із вибраною службою електронної пошти.
// nodemailer.config.js
// Налаштування служби електронної пошти
const nodemailer = require("nodemailer");
const config = require("../config/auth.config");
const user = config.user;
const pass = config.pass;
const transport = nodemailer.createTransport({
service: "Gmail",
auth: {
user: user,
pass: pass,
},
});
Наступним кроком є створення самого електронного листа за допомогою методу sendEmail()
, викликаного через transporter
. Є багато додаткових полів, які можна додати до електронного повідомлення. Для цього підручника я використав:
from
— адреса електронної пошти відправника.to
— електронні адреси одержувачів.subject
— тема електронного листа.html
— HTML-версія повідомлення електронної пошти, щоб служба електронної пошти могла його відкрити.
Електронне повідомлення має містити URL-адресу з confirmationCode
. Це необхідно для порівняння з відповідним полем confirmationCode
користувача, що зберігається в базі даних.
// Email configuration
module.exports.sendConfirmationEmail = (name, email, confirmationCode) => {
console.log("Check");
transport.sendMail({
from: user,
to: email,
subject: "Please confirm your account",
html: `<h1>Email Confirmation</h1>
<h2>Hello ${name}</h2>
<p>Thank you for subscribing. Please confirm your email by clicking on the following link</p>
<a href=http://localhost:8081/confirm/${confirmationCode}> Click here</a>
</div>`,
}).catch(err => console.log(err));
};
Нарешті, щоб надіслати електронний лист із підтвердженням після створення нового користувача, ми можемо викликати sendEmail()
всередині методу signup
.
// Уривок методу реєстрації, включаючи виклик sendEmail().
user.save((err) => {
if (err) {
res.status(500).send({ message: err });
return;
}
res.send({
message:
"User was registered successfully! Please check your email",
});
nodemailer.sendConfirmationEmail(
user.username,
user.email,
user.confirmationCode
);
});
Нам потрібно налаштувати маршрут для зміни статусу користувача з «Pending» на «Active». Тому я включив новий маршрут у файл auth.rotes.js
і налаштував новий контролер для обробки процедури. Контролер verifyUser
шукає в базі даних користувача з confirmationCode
, отриманим в URL-адресі, і виконує відповідне оновлення статусу.
app.get("/api/auth/confirm/:confirmationCode", controller.verifyUser)
Кінцева точка, визначена для процесу перевірки користувача
// Метод VerifyUser() запитує колекцію користувачів за вказаним кодом підтвердження та оновлює його статус із «Pending» на «Active», якщо знайдено збіг.
exports.verifyUser = (req, res, next) => {
User.findOne({
confirmationCode: req.params.confirmationCode,
})
.then((user) => {
if (!user) {
return res.status(404).send({ message: "User Not found." });
}
user.status = "Active";
user.save((err) => {
if (err) {
res.status(500).send({ message: err });
return;
}
});
})
.catch((e) => console.log("error", e));
};
У цей момент, якщо користувач клацне посилання для підтвердження в електронному листі, він побачить порожню сторінку та все одно не зможе ввійти. Тому нам потрібно внести деякі зміни в інтерфейс, щоб завершити процедуру реєстрації.
Нам потрібно додати новий метод у src/components/services/auth.service.js
для виклику кінцевої точки, визначеної на останньому кроці.
// Додайте метод verifyUser() до auth.service.js,
// щоб встановити з’єднання з серверною частиною
const verifyUser = (code) => {
return axios.get(API_URL + "confirm/" + code).then((response) => {
return response.data;
});
};
Після цього ми маємо створити новий компонент, який відображатиметься під час натискання URL-адреси підтвердження. Не забудьте включити відповідний маршрут у файл App
!
// Вітальний компонент
import React from "react";
import AuthService from "../services/auth.service";
import { Link } from "react-router-dom";
const Welcome = (props) => {
if (props.match.path === "/confirm/:confirmationCode") {
AuthService.verifyUser(props.match.params.confirmationCode);
}
return (
<div className="container">
<header className="jumbotron">
<h3>
<strong>Account confirmed!</strong>
</h3>
</header>
<Link to={"/login"}">
Please Login
</Link>
</div>
);
};
export default Welcome;
Frontend route to exhibit Welcome Component when the confirmation link is clicked
<Route path="/confirm/:confirmationCode" component={Welcome} />
Давайте зберемо все разом і перевіримо, чи працює наш додаток.
Це повідомлення, яке ви можете побачити:
І якщо ви спробуєте ввійти, ви побачите ось цю помилку:
Можливо, ви отримали такий електронний лист, як мій:
Натисніть на посилання та підтвердьте, що це веб-сторінка, на яку ви перенаправлені:
Тепер, якщо ви спробуєте ввійти знову, ви будете автоматично перенаправлені на сторінку свого профілю.
Оскільки ви завершили цей підручник, ви навчилися створювати електронний лист із підтвердженням реєстрації за допомогою Node.js і тепер можете створювати надійну функцію реєстрації. Щиро вітаю!
Ви можете знайти повне рішення, розроблене в цьому посібнику, у цьому репозиторії GitHub. Щасливого кодування!