9
Отправка писем в NestJS используя nodemailer. Публикация скриптов.
Мне понадобилось отправить сообщение по почте о подтверждении регистрации на сайте. На текущий момент проверенное, хорошо зарекомендовавшее себя решение это Nodemailer. В роли бек-сервера у меня NestJS. Для NestJS есть модуль Nest JS Mailer, вот с ним и решил работать. Сперва установим пакеты @nestjs-modules/mailer, nodemailer и в dev-зависимость будет не лишним поставить @types/nodemailer . В качестве сервера почты я решил воспользоваться услугами яндекс.
После того, как получена учётная запись от яндекса, записал в файл .env такие переменные:
MAIL_TRANSPORT строка подключения к smtp-серверу для отправки почты (см. https://nodemailer.com/smtp/)
MAIL_FROM_NAME от чьего имени будет приходить почта.
Пример:
MAIL_TRANSPORT=smtps://[email protected]:[email protected]
MAIL_FROM_NAME=WebWork
Написал в файле src/configs/mail.config.ts формирование настройки почтовой службы:
import { ConfigService } from '@nestjs/config';
import { EjsAdapter } from '@nestjs-modules/mailer/dist/adapters/ejs.adapter';
export const getMailConfig = async (
configService: ConfigService,
): Promise<any> => {
const transport = configService.get<string>('MAIL_TRANSPORT');
const mailFromName = configService.get<string>('MAIL_FROM_NAME');
const mailFromAddress = transport.split(':')[1].split('//')[1];
return {
transport,
defaults: {
from: `"${mailFromName}" <${mailFromAddress}>`,
},
template: {
adapter: new EjsAdapter(),
options: {
strict: false,
},
},
};
};
Что я здесь задаю: defaults.from - задаётся имя/адрес отправителя, template - у меня было больше практики с ejs, поэтому выбран такой формат для шаблонов писем.
Завершающий шаг установки - подключение модуля почты в приложение:
import { MailerModule } from '@nestjs-modules/mailer';
@Module({
imports: [
MailerModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: getMailConfig,
}),
],
})
У меня уже есть шаблон почты в файле confirmReg.ejs:
<main>
Доброго дня, <%= locals.username %>!<br />
От Вас поступила регистрация на сайте post-life.<br />
Для окончания регистрации пройдите пожалуйста по
<a href="<%= urlConfirmAddress %><%= id %>">ссылке</a> .
</main>
Вот как он используется для отправки почты:
import { MailerService } from '@nestjs-modules/mailer';
@Injectable()
export class UserService {
constructor(
// помимо всего прочего подключение сервиса отправки
private readonly mailerService: MailerService,
) {}
///
}
async sendConfirmMail(user: UserEntity) {
const urlConfirmAddress = this.configService.get<string>(
'URL_CONFIRM_ADDRESS',
);
// Отправка почты
return await this.mailerService
.sendMail({
to: user.email,
subject: 'Подтверждение регистрации',
template: join(__dirname, '/../templates', 'confirmReg'),
context: {
id: user.id,
username: user.username,
urlConfirmAddress,
},
})
.catch((e) => {
throw new HttpException(
`Ошибка работы почты: ${JSON.stringify(e)}`,
HttpStatus.UNPROCESSABLE_ENTITY,
);
});
}
Описываемый проект после публикации и проверки отправки почты выдал ошибку о том, что не может найти файл confirmReg.ejs . Почему шаблоны писем потерялись? - Компилятор из TS в JS "не заметил" файлы с раcширением ejs и после билда проекта каталог src/templates не оказался в папке назначения dist . Мои поиски решения привели меня вот на эту страницу . Суть того, что можно оттуда вынести: у NestJS есть свои опции настройки для typescript и в них можно указать файлы, которые ts должен скопировать "как есть" в каталог назначения. Теперь nest-cli.json стал таким:
{
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"assets": [
"**/*.ejs"
],
"watchAssets": true
}
}
Ссылка на проект : https://github.com/SLKarol/post-life
9