2025-02-27 12:41:56 -06:00
|
|
|
import { Injectable } from '@nestjs/common';
|
|
|
|
|
import * as nodemailer from 'nodemailer';
|
|
|
|
|
import * as dotenv from 'dotenv';
|
2025-03-07 14:14:37 -06:00
|
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
|
|
|
import { Repository } from 'typeorm';
|
|
|
|
|
import { Correo, Status } from 'src/typeorm/votacionesPrueba.entity';
|
2025-02-28 14:44:40 -06:00
|
|
|
|
2025-02-27 12:41:56 -06:00
|
|
|
dotenv.config();
|
|
|
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
|
export class MailService {
|
|
|
|
|
private transporter;
|
|
|
|
|
|
2025-03-07 14:14:37 -06:00
|
|
|
constructor(
|
|
|
|
|
@InjectRepository(Correo) private readonly correoRepository: Repository<Correo>,
|
|
|
|
|
@InjectRepository(Status) private readonly statusRepository: Repository<Status>,
|
|
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
2025-02-27 12:41:56 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
this.transporter = nodemailer.createTransport({
|
|
|
|
|
service: 'gmail',
|
|
|
|
|
auth: {
|
|
|
|
|
user: process.env.USER_GMAIL, // tu dirección de correo de Gmail
|
|
|
|
|
pass: process.env.PASS_GMAIL, // contraseña de aplicación generada en Google
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
this.transporter = nodemailer.createTransport({
|
|
|
|
|
host: 'localhost',
|
|
|
|
|
port: 1025,
|
|
|
|
|
ignoreTLS: true,
|
|
|
|
|
});
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Función para generar el reporte de correos enviados y fallidos
|
|
|
|
|
private generateReport(
|
|
|
|
|
sentEmails: string[],
|
|
|
|
|
failedEmails: { email: string; error: any }[],
|
|
|
|
|
totalTime: number,
|
|
|
|
|
) {
|
|
|
|
|
console.log('--- Reporte de envío de correos ---');
|
|
|
|
|
console.log(`Tiempo total de envío: ${totalTime} segundos`);
|
|
|
|
|
|
|
|
|
|
console.log('\nCorreos enviados con éxito:');
|
|
|
|
|
sentEmails.forEach((email) => console.log(email));
|
|
|
|
|
|
|
|
|
|
console.log('\nCorreos fallidos:');
|
|
|
|
|
failedEmails.forEach((failed) =>
|
|
|
|
|
console.log(`Correo: ${failed.email} - Error: ${failed.error.message}`),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
console.log(`\nTotal de correos enviados: ${sentEmails.length}`);
|
|
|
|
|
console.log(`Total de correos fallidos: ${failedEmails.length}`);
|
|
|
|
|
|
|
|
|
|
if (failedEmails.length > 0) {
|
|
|
|
|
console.log(
|
|
|
|
|
'\nAlgunos correos fallaron. Inténtalos de nuevo de manera manual.',
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-07 14:14:37 -06:00
|
|
|
async sendMail(to: string, subject: string, text: string, fecha_recibido: Date) {
|
2025-02-27 12:41:56 -06:00
|
|
|
const mailOptions = {
|
|
|
|
|
from: process.env.USER_GMAIL,
|
|
|
|
|
to,
|
|
|
|
|
subject,
|
|
|
|
|
text,
|
|
|
|
|
};
|
|
|
|
|
|
2025-03-07 14:14:37 -06:00
|
|
|
let resMail = await this.transporter.sendMail(mailOptions);
|
|
|
|
|
const statusTexto = resMail.accepted.length > 0 ? "Enviado" : "Fallido";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let status = await this.statusRepository.findOne({ where: { status: statusTexto } });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!status) {
|
|
|
|
|
status = this.statusRepository.create({ status: statusTexto });
|
|
|
|
|
await this.statusRepository.save(status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const info= this.correoRepository.create({
|
|
|
|
|
id_status: status,
|
|
|
|
|
|
|
|
|
|
fecha_recibido: fecha_recibido,
|
|
|
|
|
fecha_enviado: new Date(),
|
|
|
|
|
destinatario: to,
|
|
|
|
|
remitente: process.env.USER_GMAIL,
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
if(!resMail){
|
|
|
|
|
throw new Error("fallo")
|
|
|
|
|
}
|
|
|
|
|
this.correoRepository.save(info);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return
|
2025-02-27 12:41:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async sendBulkMailsOld(emails: string[], subject: string, text: string) {
|
|
|
|
|
const batchSize = 100; // Número de correos por lote
|
|
|
|
|
for (let i = 0; i < emails.length; i += batchSize) {
|
|
|
|
|
const batch = emails.slice(i, i + batchSize);
|
|
|
|
|
const promises = batch.map((email) =>
|
|
|
|
|
this.transporter.sendMail({
|
|
|
|
|
from: process.env.USER_GMAIL,
|
|
|
|
|
to: email,
|
|
|
|
|
subject,
|
|
|
|
|
text,
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Esperar que se envíen todos los correos del lote
|
|
|
|
|
await Promise.all(promises);
|
|
|
|
|
|
|
|
|
|
// Delay entre lotes para no sobrecargar el servidor de Gmail
|
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 segundos de pausa
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async sendBulkMails(emails: string[], subject: string, text: string) {
|
|
|
|
|
const batchSize = 100;
|
|
|
|
|
const sentEmails: string[] = [];
|
|
|
|
|
const failedEmails: { email: string; error: any }[] = [];
|
|
|
|
|
const startTime = Date.now(); // Inicia el temporizador
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < emails.length; i += batchSize) {
|
|
|
|
|
const batch = emails.slice(i, i + batchSize);
|
|
|
|
|
const promises = batch.map(async (email) => {
|
|
|
|
|
try {
|
|
|
|
|
await this.transporter.sendMail({
|
|
|
|
|
from: process.env.USER_GMAIL,
|
|
|
|
|
to: email,
|
|
|
|
|
subject,
|
|
|
|
|
text,
|
|
|
|
|
});
|
|
|
|
|
sentEmails.push(email); // Agregar a lista de enviados exitosamente
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
|
|
failedEmails.push({ email, error }); // Agregar a lista de fallos
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Espera a que todos los correos del lote se envíen
|
|
|
|
|
await Promise.all(promises);
|
|
|
|
|
|
|
|
|
|
// Delay para evitar saturar el servidor de correo
|
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const totalTime = (Date.now() - startTime) / 1000; // Tiempo total en segundos
|
|
|
|
|
|
|
|
|
|
// Generar el reporte final
|
|
|
|
|
this.generateReport(sentEmails, failedEmails, totalTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async retryFailedEmails(
|
|
|
|
|
failedEmails: { email: string; error: any }[],
|
|
|
|
|
subject: string,
|
|
|
|
|
text: string,
|
|
|
|
|
) {
|
|
|
|
|
const retrySuccess: string[] = [];
|
|
|
|
|
const retryFailed: { email: string; error: any }[] = [];
|
|
|
|
|
|
|
|
|
|
for (const failed of failedEmails) {
|
|
|
|
|
try {
|
|
|
|
|
await this.transporter.sendMail({
|
|
|
|
|
from: process.env.USER_GMAIL,
|
|
|
|
|
to: failed.email,
|
|
|
|
|
subject,
|
|
|
|
|
text,
|
|
|
|
|
});
|
|
|
|
|
retrySuccess.push(failed.email); // Reintento exitoso
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
|
|
retryFailed.push({ email: failed.email, error }); // Reintento fallido
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.log('--- Reintento de correos fallidos ---');
|
|
|
|
|
console.log('\nCorreos reenviados con éxito:');
|
|
|
|
|
retrySuccess.forEach((email) => console.log(email));
|
|
|
|
|
|
|
|
|
|
console.log('\nCorreos que fallaron nuevamente:');
|
|
|
|
|
retryFailed.forEach((failed) =>
|
|
|
|
|
console.log(`Correo: ${failed.email} - Error: ${failed.error.message}`),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|