Skip to content

Commit e7008c1

Browse files
committed
refactor: changing nodemailer for render
1 parent 1e65282 commit e7008c1

File tree

3 files changed

+105
-53
lines changed

3 files changed

+105
-53
lines changed

backend/package-lock.json

Lines changed: 73 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@
3232
"class-transformer": "^0.5.1",
3333
"class-validator": "^0.15.1",
3434
"mongoose": "^9.3.3",
35-
"nodemailer": "^8.0.4",
3635
"pg": "^8.20.0",
3736
"reflect-metadata": "^0.2.2",
37+
"resend": "^6.10.0",
3838
"rxjs": "^7.8.1",
3939
"typeorm": "^0.3.28"
4040
},

backend/src/mail/mail.service.ts

Lines changed: 31 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,49 @@
11
import { Injectable, InternalServerErrorException } from '@nestjs/common';
2-
import * as nodemailer from 'nodemailer';
2+
import { Resend } from 'resend';
33

44
@Injectable()
55
export class MailService {
6-
private transporter: nodemailer.Transporter;
6+
private resend: Resend;
77

88
constructor() {
9-
this.transporter = nodemailer.createTransport({
10-
host: 'smtp.gmail.com',
11-
port: 587,
12-
secure: false,
13-
requireTLS: true,
14-
auth: {
15-
user: process.env.EMAIL_USER,
16-
pass: process.env.EMAIL_PASS,
17-
},
18-
});
19-
this.transporter.verify((error, success) => {
20-
if (error) {
21-
console.error('❌ ERROR CRÍTICO SMTP EN RENDER:', error);
22-
} else {
23-
console.log('✅ CONEXIÓN SMTP ESTABLECIDA. Listo para enviar correos.');
24-
}
25-
});
9+
// Inicializamos Resend con la llave que pusiste en Render
10+
this.resend = new Resend(process.env.RESEND_API_KEY);
2611
}
2712

2813
async sendPasswordResetEmail(to: string, token: string) {
2914
const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:5173';
3015
const resetLink = `${frontendUrl}/reset-password?token=${token}`;
3116

32-
const mailOptions = {
33-
from: `"DevTrack Pro" <${process.env.EMAIL_USER}>`,
34-
to: to,
35-
subject: 'Password Reset Request - DevTrack Pro',
36-
html: `
37-
<div style="font-family: Arial, sans-serif; max-w: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e2e8f0; border-radius: 10px;">
38-
<h2 style="color: #1e293b; text-align: center;">DevTrack Pro</h2>
39-
<p style="color: #475569; font-size: 16px;">Hello,</p>
40-
<p style="color: #475569; font-size: 16px;">You recently requested to reset your password. Click the button below to proceed:</p>
41-
<div style="text-align: center; margin: 30px 0;">
42-
<a href="${resetLink}" style="background-color: #4f46e5; color: white; padding: 12px 24px; text-decoration: none; border-radius: 8px; font-weight: bold; font-size: 16px;">
43-
Reset Password
44-
</a>
17+
try {
18+
const { data, error } = await this.resend.emails.send({
19+
// IMPORTANTE: En el plan gratis sin dominio propio, debes usar este correo exacto de Resend:
20+
from: 'DevTrack Pro <onboarding@resend.dev>',
21+
to: to, // Ojo: en el plan gratis, solo puedes enviar correos a la dirección con la que te registraste en Resend.
22+
subject: 'Password Reset Request - DevTrack Pro',
23+
html: `
24+
<div style="font-family: Arial, sans-serif; max-w: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e2e8f0; border-radius: 10px;">
25+
<h2 style="color: #1e293b; text-align: center;">DevTrack Pro</h2>
26+
<p style="color: #475569; font-size: 16px;">Hello,</p>
27+
<p style="color: #475569; font-size: 16px;">You recently requested to reset your password. Click the button below to proceed:</p>
28+
<div style="text-align: center; margin: 30px 0;">
29+
<a href="${resetLink}" style="background-color: #4f46e5; color: white; padding: 12px 24px; text-decoration: none; border-radius: 8px; font-weight: bold; font-size: 16px;">
30+
Reset Password
31+
</a>
32+
</div>
33+
<p style="color: #475569; font-size: 14px;">If you did not request a password reset, please ignore this email or reply to let us know. This link will expire in 1 hour.</p>
34+
<hr style="border: none; border-top: 1px solid #e2e8f0; margin: 20px 0;" />
35+
<p style="color: #94a3b8; font-size: 12px; text-align: center;">© 2026 DevTrack Pro. All rights reserved.</p>
4536
</div>
46-
<p style="color: #475569; font-size: 14px;">If you did not request a password reset, please ignore this email or reply to let us know. This link will expire in 1 hour.</p>
47-
<hr style="border: none; border-top: 1px solid #e2e8f0; margin: 20px 0;" />
48-
<p style="color: #94a3b8; font-size: 12px; text-align: center;">© 2026 DevTrack Pro. All rights reserved.</p>
49-
</div>
50-
`,
51-
};
37+
`,
38+
});
5239

53-
try {
54-
await this.transporter.sendMail(mailOptions);
55-
console.log(`Email sent successfully to ${to}`);
40+
if (error) {
41+
throw new Error(error.message);
42+
}
43+
44+
console.log(`Email sent via HTTP API to ${to}`);
5645
} catch (error) {
57-
console.error('Error sending email:', error);
46+
console.error('Error sending email via Resend:', error);
5847
throw new InternalServerErrorException('Error sending the reset email');
5948
}
6049
}

0 commit comments

Comments
 (0)