import { Injectable, UnauthorizedException } from '@nestjs/common'; import * as nodemailer from 'nodemailer'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Correo, Sistema, Status } from '../typeorm/entidades'; import { SistemaService } from 'src/sistema/sistema.service'; import { SendCorreoDto } from 'src/mail/dto/send-email.dto'; import { AuthService } from 'src/auth/auth.service'; import { decrypt } from '../crypto/crypto.util'; @Injectable() export class MailService { constructor( private readonly sistemaService: SistemaService, private readonly authService: AuthService, @InjectRepository(Correo) private readonly correoRepository: Repository, @InjectRepository(Status) private readonly statusRepository: Repository, @InjectRepository(Sistema) private readonly sistemaRepositosistemaRepositoryry: Repository ) { /* this.transporter = nodemailer.createTransport({ host: 'smtp-relay.gmail.com', port: 587, secure: false, requireTLS: true, auth: { user: process.env.USER_GMAIL, pass: process.env.PASS_GMAIL, }, }); */ /* this.transporter = nodemailer.createTransport({ host: 'smtp.gmail.com', // o smtp‑relay.gmail.com (ver punto 2) port: 587, secure: false, requireTLS: true, // TLS STARTTLS auth: { user: process.env.USER_GMAIL, pass: process.env.PASS_GMAIL }, pool: true, // <‑‑ activa reuse maxConnections: 1, // una sola conexión viva maxMessages: 100, // reabrir después de 100 envíos rateDelta: 2000, // ventana 1 s rateLimit: 1 // máx. 5 mensajes/seg }); */ /* this.transporter = nodemailer.createTransport({ host: 'localhost', port: 1025, ignoreTLS: true, }); */ } async findAllBySistema(TOKEN:string,nombreSistema:string){ if (!TOKEN) { throw new UnauthorizedException('Header "Password" es requerido'); } const sistem=await this.sistemaService.acceso(TOKEN) if(!sistem){ throw new UnauthorizedException('Password incorrecto'); } const result= await this.correoRepository.find({where:{ id_sistema:{nombre_sistema:nombreSistema} }, relations: { id_sistema: true, id_status: true, },} ) return result } async sendMail(sendEmail:SendCorreoDto,token:string) { let payload payload = await this.authService.verificarToken(token); if (!payload || !payload.nombre) { throw new UnauthorizedException('Token inválido o incompleto'); } const sistem= await this.sistemaService.findByNombre(payload.nombre) if(!sistem){ throw new UnauthorizedException('sistema No encontrado'); } const decryptedPassword = decrypt( sistem.email_password_encrypted, sistem.email_password_iv ); const decryptedToken = decrypt( sistem.refreshToken_encrypted, sistem.refreshToken_iv ); const transporter = nodemailer.createTransport({ /* host: 'smtp.gmail.com', // o smtp‑relay.gmail.com (ver punto 2) port: 587, secure: false, requireTLS: true, // TLS STARTTLS auth: { user:sistem.email, pass:decryptedPassword}, pool: true, // <‑‑ activa reuse maxConnections: 1, // una sola conexión viva maxMessages: 100, // reabrir después de 100 envíos rateDelta: 2000, // ventana 1 s rateLimit: 1 // máx. 5 mensajes/seg */ service: 'gmail', auth: { type: 'OAuth2', user: sistem.email, clientId: sistem.clientId, clientSecret: decryptedPassword, refreshToken: decryptedToken, //accessToken: sistem.accessToken, // opcional }, pool: true, maxConnections: 1, maxMessages: 100, rateDelta: 2000, rateLimit: 1 }); console.log("estos son los archivos adjuntos en el service",sendEmail.adjuntos); const mailOptions = { from: sistem.email, to:sendEmail.to, subject:sendEmail.subject, text: sendEmail.text, html:sendEmail.html, // OJO: nodemailer usa 'attachments', no 'adjuntos' attachments: (sendEmail.adjuntos || []).map((adj) => { // Asegúrate de no incluir 'data:image/png;base64,' en 'content' let base64Clean = adj.content; // Si viene con prefijo "data:image...", lo quitamos if (base64Clean.startsWith('data:image/')) { base64Clean = base64Clean.split('base64,')[1]; } return { filename: adj.filename || 'qr.png', content: Buffer.from(base64Clean, adj.encoding || 'base64'), cid: adj.cid || 'qrCode', // el mismo que uses en contentType: 'image/png' // recomendable para que sepa que es PNG }; }) }; console.log(mailOptions); let resMail = await transporter.sendMail(mailOptions); if(!resMail) throw new Error("") 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, id_sistema: sistem, fecha_recibido: sendEmail.fecha_recibido, fecha_enviado: new Date(), destinatario: sendEmail.to, remitente: sistem.email, }); if(!resMail){ throw new Error("fallo") } this.correoRepository.save(info); return (statusTexto); } }