develop #1

Merged
eithan merged 7 commits from develop into master 2025-04-07 21:29:31 +00:00
10 changed files with 176 additions and 34 deletions
+6
View File
@@ -0,0 +1,6 @@
node_modules
dist
.git
.env
*.log
+14
View File
@@ -0,0 +1,14 @@
# Gmail
USER_GMAIL=
PASS_GMAIL=
# MariaDB database settings
db_type=mysql
db_host=mariadb # <-- uso del nombre del servicio, NO IP
db_port=3306
db_username=root # <-- te conectarás con root
db_password=mypass # <-- la misma que MARIADB_ROOT_PASSWORD
db_database=ApiCorreos
# Puerto de la aplicación
PORT=4100
+4
View File
@@ -1,3 +1,7 @@
*.tar
# compiled output
/dist
/node_modules
+23
View File
@@ -0,0 +1,23 @@
# Etapa de construcción
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Etapa de producción
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
EXPOSE 4100
CMD ["node", "dist/main"]
+32
View File
@@ -0,0 +1,32 @@
version: '3.8'
services:
mariadb:
image: mariadb:latest
container_name: mariadb-service
ports:
- "4101:3306"
environment:
MARIADB_ROOT_PASSWORD: mypass
MARIADB_DATABASE: ApiCorreos
volumes:
- mariadb_data:/var/lib/mysql
api:
image: correos_api:v0 # <--- la imagen final (comprobada en el paso anterior)
container_name: nestjs-api
environment:
# Ajustar estas vars a tu conveniencia
db_host: mariadb
db_port: 3306
db_username: root
db_password: mypass
db_database: ApiCorreos
PORT: 4100
ports:
- "4100:4100"
depends_on:
- mariadb
volumes:
mariadb_data:
+28
View File
@@ -0,0 +1,28 @@
version: '3.8'
services:
mariadb:
image: mariadb:latest
container_name: mariadb-service
ports:
- "4101:3306"
environment:
MARIADB_ROOT_PASSWORD: mypass
MARIADB_DATABASE: ApiCorreos
volumes:
- mariadb_data:/var/lib/mysql
api:
build:
context: .
dockerfile: Dockerfile
container_name: nestjs-api
env_file:
- .env
ports:
- "4100:4100"
depends_on:
- mariadb
volumes:
mariadb_data:
+17 -7
View File
@@ -31,9 +31,14 @@ export class MailController {
@ApiSendMail()
async sendMail(
@Headers() headers:{password:string},
@Body() body: { to: string; subject: string; text: string; fecha_recibido: Date }) {
@Body() body: { to: string; subject: string; text: string; fecha_recibido: Date, html:string, adjuntos:any }) {
/*
// esta parte hay que rehacerla, se tiene que obtener la contraseña del sistema en base a la clave del sistema.
// debe de existir un modulo para crear contraseñas para las apis y administrar esas contraseñas
if (!headers.password) {
throw new UnauthorizedException('Header "Password" es requerido');
}
@@ -42,12 +47,17 @@ export class MailController {
if (!sistem) {
throw new UnauthorizedException('Password incorrecto');
}
} */
const { to, subject, text, fecha_recibido } = body;
console.log("estos son los archivos adjuntos en el controller",body);
const result = await this.mailService.sendMail(to, subject, text, fecha_recibido,sistem);
const { to, subject, text, html, fecha_recibido, adjuntos } = body;
const result = await this.mailService.sendMail(to, subject, text,html, fecha_recibido,1,adjuntos); // sistem
return result;
@@ -79,7 +89,7 @@ export class MailController {
for (const email of await emails) {
try {
await this.mailService.sendMail(email, "subject", "text", fechaActual,sistem);
await this.mailService.sendMail(email, "subject", "text","html", fechaActual,sistem);
console.log(`📧 Enviado a: ${email}`);
} catch (error) {
console.error(`❌ Error enviando a ${email}:`, error.message);
+10 -23
View File
@@ -1,5 +1,5 @@
import { applyDecorators } from '@nestjs/common';
import { ApiBody, ApiConsumes, ApiOperation, ApiResponse } from '@nestjs/swagger';
import { ApiBody, ApiConsumes, ApiHeader, ApiOperation, ApiResponse } from '@nestjs/swagger';
export const ApiSendMail = () => {
return applyDecorators(
@@ -9,7 +9,14 @@ export const ApiSendMail = () => {
- **to**: Dirección de correo del destinatario.
- **subject**: Asunto del correo.
- **text**: Cuerpo del mensaje.
- **fecha_recibido**: Fecha en que se registró la solicitud.`,
- **fecha_recibido**: Fecha en que se registró la solicitud.
- **sistema**: contraseña del sistema.`,
}),
ApiHeader({
name: 'password',
description: 'Contraseña del sistema para autenticación',
required: true,
example: 'mi-password-segura'
}),
ApiBody({
description: 'Datos del correo a enviar',
@@ -22,27 +29,7 @@ export const ApiSendMail = () => {
fecha_recibido: { type: 'string', format: 'date-time', example: '2025-03-10T12:00:00Z' }
},
},
}),
ApiResponse({
status: 200,
description: 'Correo enviado con éxito',
schema: {
example: {
message: 'Correo enviado correctamente',
},
},
}),
ApiResponse({
status: 400,
description: 'Error en el envío del correo',
schema: {
example: {
statusCode: 400,
message: 'Dirección de correo inválida',
error: 'Bad Request',
},
},
}),
})
);
};
+37 -4
View File
@@ -42,18 +42,49 @@ export class MailService {
// Función para generar el reporte de correos enviados y fallidos
async sendMail(to: string, subject: string, text: string, fecha_recibido: Date, sistema) {
async sendMail(to: string, subject: string, text: string, html: string, fecha_recibido: Date, sistema, adjuntos?: any[] ) {
console.log("estos son los archivos adjuntos en el service",adjuntos);
const mailOptions = {
from: process.env.USER_GMAIL,
to,
subject,
text,
html,
// OJO: nodemailer usa 'attachments', no 'adjuntos'
attachments: (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 <img src="cid:..."/>
contentType: 'image/png' // recomendable para que sepa que es PNG
};
})
};
console.log(mailOptions);
let resMail = await this.transporter.sendMail(mailOptions);
const statusTexto = resMail.accepted.length > 0 ? "Enviado" : "Fallido";
/*
let status = await this.statusRepository.findOne({ where: { status: statusTexto } });
@@ -70,11 +101,13 @@ export class MailService {
destinatario: to,
remitente: process.env.USER_GMAIL,
});
}); */
if(!resMail){
throw new Error("fallo")
}
this.correoRepository.save(info);
//this.correoRepository.save(info);
+5
View File
@@ -6,6 +6,9 @@ import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors();
const config = new DocumentBuilder()
.setTitle('Documentacion de la api de votaciones_mails v2')
.setDescription(
@@ -18,5 +21,7 @@ async function bootstrap() {
SwaggerModule.setup('documentation', app, document);
await app.listen(process.env.PORT ?? 3000);
console.log(`Aplicación corriendo en: http://localhost:${process.env.PORT ?? 3000}`);
}
bootstrap();