infoalloggi-monorepo/apps/infoalloggi/src/server/services/mailer.ts
2025-08-04 17:45:44 +02:00

219 lines
5.8 KiB
TypeScript

import { render } from "@react-email/render";
import { TRPCError } from "@trpc/server";
import ContattoAdminEmail, {
type ContattoAdmin_NewMail,
} from "emails/contatto";
import EmailContattoInteressato, {
type ContattoInteressato_NewMail,
} from "emails/email-interessato";
import type { PagamentoConferma_NewMail } from "emails/pagamento-conferma";
import PagamentoConferma from "emails/pagamento-conferma";
import type { PagamentoErrore_NewMail } from "emails/pagamento-errore";
import PagamentoErrore from "emails/pagamento-errore";
import type { PagamentoRicezione_NewMail } from "emails/pagamento-ricezione";
import PagamentoRicezione from "emails/pagamento-ricezione";
import type { PwResetLink_NewMail } from "emails/pw-reset-link";
import PwResetLink from "emails/pw-reset-link";
import type { Recesso_NewMail } from "emails/recesso";
import Recesso from "emails/recesso";
import type { RegistrazioneAvvenuta_NewMail } from "emails/registrazione-avvenuta";
import RegistrazioneAvvenuta from "emails/registrazione-avvenuta";
import { createTransport } from "nodemailer";
import { htmlToText } from "nodemailer-html-to-text";
import { env } from "~/env.mjs";
import type { JSX } from "react";
import VerificaEmail, {
type VerificaEmail_NewMail,
} from "emails/VerificaEmail";
import OnboardingServizio, {
type OnboardingServizio_NewMail,
} from "emails/onboarding-servizio";
import type { ContattoAnnuncio_NewMail } from "emails/contatto_annuncio";
import ContattoAnnuncioEmail from "emails/contatto_annuncio";
import type { UsersId } from "~/schemas/public/Users";
import { StoreEmail } from "~/server/services/email.service";
import type { Generic_NewMail } from "emails/gereric-email";
import Generic from "emails/gereric-email";
import { GetFlagValueHandler } from "~/server/controllers/flags.controller";
import { db } from "~/server/db";
type MailerProps = {
to: string;
subject: string;
html: string;
};
const mailer = async ({ to, subject, html }: MailerProps) => {
const smtpTransport = createTransport({
host: "smtps.aruba.it",
logger: false,
debug: false,
secure: true,
port: 465,
auth: {
user: env.ARUBA_USER,
pass: env.ARUBA_PASS,
},
tls: {
minVersion: "TLSv1",
ciphers: "HIGH:MEDIUM:!aNULL:!eNULL:@STRENGTH:!DH:!kEDH",
},
});
smtpTransport.use("compile", htmlToText());
const message = {
from: env.ARUBA_USER,
to: to,
subject: subject,
html: html,
};
smtpTransport.sendMail(message, (err, info) => {
if (err) {
throw new Error(err.message);
}
return info;
});
};
type base_NewMailProps = {
userId?: UsersId;
to: string;
subject: string;
};
export type NewMailProps = base_NewMailProps & MailsTemplates;
export type MailsTemplates =
| ContattoAdmin_NewMail
| ContattoAnnuncio_NewMail
| ContattoInteressato_NewMail
| PagamentoConferma_NewMail
| PagamentoErrore_NewMail
| PagamentoRicezione_NewMail
| PwResetLink_NewMail
| Recesso_NewMail
| RegistrazioneAvvenuta_NewMail
| VerificaEmail_NewMail
| OnboardingServizio_NewMail
| Generic_NewMail;
export const genMail = async ({ ...mail }: MailsTemplates) => {
let mailComponent: JSX.Element | null = null;
let title = "";
switch (mail.mailType) {
case "contattoAdminEmail":
mailComponent = ContattoAdminEmail({
...mail.props,
});
title = "Contatto amministratore";
break;
case "contattoAnnuncioEmail":
mailComponent = ContattoAnnuncioEmail({
...mail.props,
});
title = "Contatto annuncio";
break;
case "emailContattoInteressato":
mailComponent = EmailContattoInteressato({
...mail.props,
});
title = "Contatto interessato";
break;
case "pagamentoConferma":
mailComponent = PagamentoConferma({
...mail.props,
});
title = "Conferma pagamento";
break;
case "pagamentoErrore":
mailComponent = PagamentoErrore();
title = "Errore pagamento";
break;
case "pagamentoRicezione":
mailComponent = PagamentoRicezione();
title = "Ricezione pagamento";
break;
case "pwResetLink":
mailComponent = PwResetLink({
...mail.props,
});
title = "Reset password";
break;
case "recesso":
mailComponent = Recesso();
title = "Recesso";
break;
case "registrazioneAvvenuta":
mailComponent = RegistrazioneAvvenuta();
title = "Registrazione avvenuta";
break;
case "verificaEmail":
mailComponent = VerificaEmail({
...mail.props,
});
title = "Verifica email";
break;
case "onboardingServizio":
mailComponent = OnboardingServizio({
...mail.props,
});
title = "Onboarding Servizio";
break;
case "generic":
mailComponent = Generic({
...mail.props,
});
title = mail.props.title || "Email Generica";
break;
}
if (mailComponent === null) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "Errore nella creazione dell'email",
});
}
return { html: await render(mailComponent), title };
};
export const NewMail = async ({
userId,
to,
subject,
...mail
}: NewMailProps) => {
const emailFlag = await GetFlagValueHandler({
db: db,
id: "EMAIL_OFF",
});
if (emailFlag === "true") {
console.warn("Email sending is disabled");
return { success: true, message: "Email sending is disabled" };
}
try {
const { html } = await genMail({ ...mail });
await mailer({
to: to,
subject: subject,
html,
});
if (userId) {
// Store the email in the database if userId is provided
await StoreEmail({ userId, data: mail });
}
} catch (e) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "Errore nell'invio dell'email: " + (e as Error).message,
});
}
};