feat(SendGrid): Disable SendGrid support and use Mail API instead

This commit is contained in:
Josepablo C
2025-03-02 22:33:48 -06:00
parent 7e273bc0d8
commit e4d8f7bb3e
10 changed files with 434 additions and 11 deletions

View File

@@ -73,13 +73,12 @@ async function AccountPwdResetEmail( receiver, content ){
async function ContactEmail( receiver, content ){
const templateId = "d-1090dda1091442f3a75ee8ab39ad0f10";
const subject = "[ETA] Contact Email";
const content_to_send = {
const content_to_send = {
project_name: SiteName,
user_name: content.name,
user_email: receiver
};
return await sendMailTemplate( templateId, receiver, subject, content_to_send );
}
//ContactEmail( "josepablo134@gmail.com", { email : "josepablo134@gmail.com", name:"Josepablo C.", message: "This is an example" } ).then().catch();
module.exports = { AccountVerifyEmail, AccountConfirmed, AccountPwdResetEmail, ContactEmail };

View File

@@ -1,15 +1,54 @@
'user strict';
const { ROOT_PATH, API_CONFIG } = process.env;
const nodemailer = require("nodemailer");
const apiConfig = require( '../../../config/apiConfig.json' );
const apiConfig = require( `${ROOT_PATH}/${API_CONFIG}` );
/**
* Load HTML templates
*/
const accountVerifiedTemplate = require('./StandAlone/templates/accountVerifiedTemplate');
const accountVerifyTemplate = require('./StandAlone/templates/accountVerifyTemplate');
const contactResponseTemplate = require('./StandAlone/templates/contactResponseTemplate');
const recoveryPasswordTemplate = require('./StandAlone/templates/recoveryPasswordTemplate');
const warehouseNotificationTemplate = require('./StandAlone/templates/warehouseNotificationTemplate');
const transporter = nodemailer.createTransport(
apiConfig.email_standalone
);
const default_from = apiConfig.email_standalone.auth.user;
function redirect_email( receiver ){
/**TODO: Remove in production */
const default_mail_list = [
{pattern:"alex@etaviaporte.com",redirect:"alexandro.uc@etaviaporte.com"},
{pattern:"testing@etaviaporte.com",redirect:"josepablo134@gmail.com"},
{pattern:"pablo@etaviaporte.com",redirect:"josepablo134@gmail.com"}
];
for( let i=0; i< default_mail_list.length; i++ ){
if( receiver.indexOf( default_mail_list[i].pattern ) >= 0 ){
receiver = default_mail_list[i].redirect;
break;/** Set only the first match */
}
}
return receiver
}
async function sendMailTemplate( receiver, subject, html ){
/**TODO: Remove in production */
receiver = redirect_email( receiver );
return await transporter.sendMail({
from: `ETA Viaporte <${default_from}>`,
to: receiver,
subject,
html,
attachments:[{
filename: 'eta_logo.png',
path: './StandAlone/assets/eta_logo.png',
cid: 'eta_logo'
}]
});
}
async function StandAloneContactEmail( content ){
const default_from = apiConfig.email_standalone.auth.user;
const receiver = "support@etaviaporte.com";
const {name, email, message } = content;
return await transporter.sendMail({
@@ -19,6 +58,33 @@ async function StandAloneContactEmail( content ){
text: `\n\n The following is an email from : ${email}\n\n\n` + message
});
}
//StandAloneContactEmail( { email : "josepablo134@gmail.com", name:"Josepablo C.", message: "This is an example" } ).then().catch();
module.exports = { StandAloneContactEmail };
async function AccountVerifyEmail( receiver, content ){
const subject = "[ETA] Account Verification";
const { user_name , OTP } = content;
const html = accountVerifyTemplate( user_name, OTP );
return await sendMailTemplate( receiver, subject, html );
}
async function AccountConfirmed( receiver, content){
const subject = "[ETA] Welcome to ETA";
const { user_name } = content;
const html = accountVerifiedTemplate( user_name );
return await sendMailTemplate( receiver, subject, html );
}
async function AccountPwdResetEmail( receiver, content ){
const subject = "[ETA] Password Reset";
const { user_name , OTP } = content;
const html = recoveryPasswordTemplate( user_name, OTP );
return await sendMailTemplate( receiver, subject, html );
}
async function ContactEmail( receiver, content ){
const subject = "[ETA] Contact Email";
const { user_name } = content;
const html = contactResponseTemplate( user_name );
return await sendMailTemplate( receiver, subject, html );
}
module.exports = { AccountVerifyEmail, AccountConfirmed, AccountPwdResetEmail, ContactEmail, StandAloneContactEmail };

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -0,0 +1,64 @@
'user strict';
module.exports = (name) => {
return `
<div style="
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
">
<div style="text-align: center; width: 100%;">
<img
src="cid:eta_logo"
alt="Logo ETA Viaporte"
style="width: 150px; margin-bottom: 20px;"
/>
<h1 style="color: #333; font-size: 24px;">¡Bienvenido a ETA Viaporte!</h1>
<div style="
height: 4px;
width: 100%;
background-color: #000;
margin: 20px 0;
"></div>
</div>
<div style="text-align: center;">
<h3 style="color: #555;">Hola, ${name}!</h3>
<p style="
font-size: 16px;
color: #555;
line-height: 1.5;
margin-bottom: 32px;
">
Su cuenta se registro exitosamente, estas a solo unos pasos para completar tu perfil, da click en el siguiente botón y continua con el proceso.
</p>
<a
href="https://console.etaviaporte.com/login"
style="
padding: 12px 24px;
background-color: #000;
color: #f3eeee;
font-weight: bold;
border-radius: 8px;
text-decoration: none;
"
>
Panel Eta Viaporte
</a>
</div>
<div style="margin-top: 32px;">
<p style="
font-size: 16px;
color: #333;
margin-top: 30px;
text-align: center;
">
Saludos cordiales,<br>
<strong>Equipo de cuentas - ETA Viaporte</strong>
</p>
</div>
</div>
`;
}

View File

@@ -0,0 +1,81 @@
'user strict';
module.exports = (name, otp) => {
return `
<div style="
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
">
<div style="text-align: center; width: 100%;">
<img
src="cid:eta_logo"
alt="Logo ETA Viaporte"
style="width: 150px; margin-bottom: 20px;"
/>
<h1 style="color: #333; font-size: 24px;">¡Bienvenido a ETA Viaporte!</h1>
<div style="
height: 4px;
width: 100%;
background-color: #000;
margin: 20px 0;
"></div>
</div>
<div style="text-align: center;">
<h3 style="color: #555;">Hola, ${name}!</h3>
<p style="
font-size: 16px;
color: #555;
line-height: 1.5;
">
Verifica tu dirección de correo electrónico para completar tu registro en <strong>ETA Viaporte</strong>.
</p>
<h3 style="color: #333; margin-top: 30px;">Tu código de verificación:</h3>
<div
style="
display: inline-block;
padding: 5px 32px;
border: 2px solid #ccc;
border-radius: 10px;
margin: 10px 0;
"
>
<p style="
font-size: 28px;
font-weight: bold;
color: #000;
letter-spacing: 4px;
">
${otp}
</p>
</div>
<p style="font-size: 14px; color: #777;">
Este código es válido por <strong>1 hora</strong> y solo se puede usar una vez.
</p>
</div>
<div style="margin-top: 30px;">
<p style="
font-size: 16px;
color: #555;
line-height: 1.5;
text-align: center;
">
Hemos recibido una solicitud para crear una cuenta en <strong>ETA Viaporte</strong> utilizando tu correo electrónico.
Si no hiciste esta solicitud, puedes ignorar este mensaje.
</p>
<p style="
font-size: 16px;
color: #333;
margin-top: 30px;
text-align: center;
">
Saludos cordiales,<br>
<strong>Equipo de cuentas - ETA Viaporte</strong>
</p>
</div>
</div>
`;
}

View File

@@ -0,0 +1,54 @@
'user strict';
module.exports = (name) => {
return `
<div style="
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
">
<div style="text-align: center; width: 100%;">
<img
src="cid:eta_logo"
alt="Logo ETA Viaporte"
style="width: 150px;"
/>
<div style="
height: 4px;
width: 100%;
background-color: #000;
margin: 20px 0;
"></div>
</div>
<div style="text-align: center;">
<h3 style="color: #555;">Hola, ${name}!</h3>
<div style="
font-size: 16px;
color: #555;
line-height: 1.5;
text-align: center;
">
<p>¡Gracias por contactarnos!</p>
<p>Recibimos tu consulta y puede llevar algún tiempo responderla. Mientras tanto, puedes consultar nuestras preguntas frecuentes en: <a href="https://etaviaporte.com/faq">FAQS Eta Viaporte</a></p>
<p>Nuestro horario de atención es lunes a viernes de 09:00 a 18:00 (GMT-7)</p>
<p>¡Agradecemos tu paciencia y comprensión!</p>
</div>
</div>
<div style="margin-top: 30px;">
<p style="
font-size: 16px;
color: #333;
margin-top: 30px;
text-align: center;
">
Saludos cordiales,<br>
<strong>Equipo de cuentas - ETA Viaporte</strong>
</p>
</div>
</div>
`;
}

View File

@@ -0,0 +1,73 @@
'user strict';
module.exports = (name, otp) => {
return `
<div style="
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
">
<div style="text-align: center; width: 100%;">
<img
src="cid:eta_logo"
alt="Logo ETA Viaporte"
style="width: 150px;"
/>
<div style="
height: 4px;
width: 100%;
background-color: #000;
margin: 20px 0;
"></div>
</div>
<div style="text-align: center;">
<h3 style="color: #555;">Hola, ${name}!</h3>
<p style="
font-size: 16px;
color: #555;
line-height: 1.5;
text-align: center;
">
Hemos recibido una solicitud para restablecer su contraseña de <strong>ETA Viaporte</strong> utilizando tu correo electrónico.
Si no hiciste esta solicitud, puedes ignorar este mensaje.
</p>
<h3 style="color: #333; margin-top: 30px;">Tu código de verificación:</h3>
<div
style="
display: inline-block;
padding: 5px 32px;
border: 2px solid #ccc;
border-radius: 10px;
margin: 10px 0;
"
>
<p style="
font-size: 28px;
font-weight: bold;
color: #000;
letter-spacing: 4px;
">
${otp}
</p>
</div>
<p style="font-size: 14px; color: #777;">
Este código es válido por <strong>1 hora</strong> y solo se puede usar una vez.
</p>
</div>
<div style="margin-top: 30px;">
<p style="
font-size: 16px;
color: #333;
margin-top: 30px;
text-align: center;
">
Saludos cordiales,<br>
<strong>Equipo de cuentas - ETA Viaporte</strong>
</p>
</div>
</div>
`;
}

View File

@@ -0,0 +1,88 @@
'user strict';
module.exports = (code, date, company, product, plate, truck_type, driver, note) => {
return `
<div style="
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
">
<div style="text-align: center; width: 100%;">
<img
src="cid:eta_logo"
alt="Logo ETA Viaporte"
style="width: 150px; margin-bottom: 10px;"
/>
<h1 style="color: #333; font-size: 24px;">¡Nueva carga asignada ${code}!</h1>
<div style="
height: 4px;
width: 100%;
background-color: #000;
margin: 20px 0;
"></div>
</div>
<div style="text-align: center;">
<p style="
font-size: 16px;
color: #555;
line-height: 1.5;
margin-bottom: 32px;
">
Se ha asignado nueva carga con código <strong>${code}</strong> a la bodega
</p>
<div style="
text-align: left;
padding: 0px 12px;
font-size: 16px;
margin-bottom: 32px;
">
<h3 style="color: #555;">Detalles de la carga</h3>
<ul>
<li><strong>Código de carga:</strong> ${code}</li>
<li><strong>Fecha de carga:</strong> ${date}</li>
<li><strong>Empresa:</strong> ${company}</li>
<li><strong>Producto:</strong> ${product}</li>
<li><strong>Placas tracto camión:</strong> ${plate}</li>
<li><strong>Tipo de transporte:</strong> ${truck_type}</li>
<li><strong>Operador:</strong> ${driver}</li>
<li><strong>Nota:</strong> ${note}</li>
</ul>
</div>
<a
href="https://console.etaviaporte.com/login"
style="
padding: 12px 24px;
background-color: #000;
color: #f3eeee;
font-weight: bold;
border-radius: 8px;
text-decoration: none;
"
>
Panel ETA Viaporte
</a>
</div>
<div style="margin-top: 32px;">
<p style="
font-size: 14px;
color: #777;
text-align: center;
margin-top: 20px;
">
Este correo ha sido generado automáticamente. No es necesario responder, ya que no se monitorean las respuestas a este mensaje.
</p>
<p style="
font-size: 16px;
color: #333;
margin-top: 30px;
text-align: center;
">
Equipo <strong>ETA Viaporte</strong>
</p>
</div>
</div>
`;
}

View File

@@ -1,7 +1,5 @@
'user strict';
const { ROOT_PATH, HANDLERS_PATH, MODELS_PATH, API_CONFIG } = process.env;
const { StandAloneContactEmail } = require('./StandAlone.handler');
const { AccountVerifyEmail, AccountConfirmed, AccountPwdResetEmail, ContactEmail } = require('./SendGrid.handler');
const { AccountVerifyEmail, AccountConfirmed, AccountPwdResetEmail, ContactEmail, StandAloneContactEmail } = require('./StandAlone.handler');
const EMAIL_EVENTS={
ACCOUNT_VERIFY:1,