This commit is contained in:
vadim committed 2026-10-23 19:26:26 +03:00
1 parent de1b3754df
commit f085517732
3 files changed
+45 -18

No files matched your search

+11 -15
View File
@@ -12,10 +12,7 @@ export const auth = betterAuth({
emailOTP({
async sendVerificationOTP({ email, otp, type }) {
if (type === 'sign-in') {
// Send the OTP for sign in
console.log({ email, otp, type });
void EmailSender.getTransporter().sendMail({
EmailSender.sendInBackground({
to: email,
subject: `Your OTP code is: ${otp}`,
text: `Your OTP code is: ${otp}`,
@@ -23,8 +20,13 @@ export const auth = betterAuth({
} else if (type === 'email-verification') {
// Send the OTP for email verification
console.log({ email, otp, type });
} else if (type === 'forget-password') {
EmailSender.sendInBackground({
to: email,
subject: `Your password reset code is: ${otp}`,
text: `Your password reset code is: ${otp}`,
});
} else {
// Send the OTP for password reset
console.log({ email, otp, type });
}
},
@@ -47,26 +49,21 @@ export const auth = betterAuth({
autoSignIn: false,
requireEmailVerification: true,
onExistingUserSignUp: async ({ user }, request) => {
console.log('onExistingUserSignUp', { user });
void EmailSender.getTransporter().sendMail({
EmailSender.sendInBackground({
to: user.email,
subject: 'Sign-up attempt with your email',
text: 'Someone tried to create an account using your email address. If this was you, try signing in instead. If not, you can safely ignore this email.',
});
},
sendResetPassword: async ({ user, url, token }, request) => {
console.log('sendResetPassword', { user, url, token });
void EmailSender.getTransporter().sendMail({
EmailSender.sendInBackground({
to: user.email,
subject: 'Reset your password',
text: `Click the link to reset your password: ${url}`,
});
},
onPasswordReset: async ({ user }, request) => {
// your logic here
console.log('onPasswordReset', { user });
void EmailSender.getTransporter().sendMail({
EmailSender.sendInBackground({
to: user.email,
subject: 'Reset your password result',
text: `Password for user ${user.email} has been reset.`,
@@ -77,8 +74,7 @@ export const auth = betterAuth({
sendOnSignIn: true,
autoSignInAfterVerification: true,
sendVerificationEmail: async ({ user, url }) => {
console.log('emailVerification', { user, url });
void EmailSender.getTransporter().sendMail({
EmailSender.sendInBackground({
to: user.email,
subject: 'Verify your email address',
text: `Click the link to verify your email: ${url}`,
+33 -2
View File
@@ -1,13 +1,44 @@
import { Logger } from '@nestjs/common';
import nodemailer, { SendMailOptions, Transporter } from 'nodemailer';
export default class EmailSender {
static getTransporter() {
return nodemailer.createTransport({
private static readonly logger = new Logger(EmailSender.name);
private static transporter?: Transporter;
private static isLocal() {
return process.env.NODE_ENV === 'local';
}
private static getTransporter() {
this.transporter ??= nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.GOOGLE_APP_USER,
pass: process.env.GOOGLE_APP_PASSWORD,
},
});
return this.transporter;
}
/** Sends an email; throws on failure. In local env only logs the message. */
static async send(options: SendMailOptions): Promise<void> {
if (this.isLocal()) {
this.logger.log(
`[local] email not sent\n to: ${String(options.to)}\n subject: ${options.subject}\n text: ${String(options.text)}`,
);
return;
}
await this.getTransporter().sendMail(options);
}
/** Fire-and-forget variant: never throws, errors are logged. */
static sendInBackground(options: SendMailOptions): void {
this.send(options).catch((error: unknown) => {
this.logger.error(
`Failed to send email "${options.subject}" to ${String(options.to)}`,
error instanceof Error ? error.stack : String(error),
);
});
}
}
@@ -16,7 +16,7 @@ export class EmailChannelSender implements NotificationChannelSender {
select: { email: true },
});
await EmailSender.getTransporter().sendMail({
await EmailSender.send({
to: user.email,
subject: params.subject ?? 'Уведомление',
text: params.content,