import { render } from "@react-email/render"; import { TRPCError } from "@trpc/server"; import ContattoAdminEmail, { type ContattoAdmin_NewMail, } from "emails/contatto"; import type { ContattoAnnuncio_NewMail } from "emails/contatto_annuncio"; import ContattoAnnuncioEmail from "emails/contatto_annuncio"; import EmailContattoInteressato, { type ContattoInteressato_NewMail, } from "emails/email-interessato"; import type { Generic_NewMail } from "emails/gereric-email"; import Generic from "emails/gereric-email"; import type { Invito_NewMail } from "emails/invito"; import Invito from "emails/invito"; import OnboardingServizio, { type OnboardingServizio_NewMail, } from "emails/onboarding-servizio"; 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 EmailSchedaContatto, { type SchedaContatto_NewMail, } from "emails/scheda-annuncio"; import VerificaEmail, { type VerificaEmail_NewMail, } from "emails/VerificaEmail"; import { createTransport } from "nodemailer"; import type { Options } from "nodemailer/lib/mailer"; import { htmlToText } from "nodemailer-html-to-text"; import type { JSX } from "react"; import { env } from "~/env"; import type { UsersId } from "~/schemas/public/Users"; import { GetFlagValueHandler } from "~/server/controllers/flags.controller"; import { db } from "~/server/db"; import { StoreEmail } from "~/server/services/email.service"; const mailer = async (options: Options) => { const smtpTransport = createTransport({ auth: { pass: env.ARUBA_PASS, user: env.ARUBA_USER, }, debug: false, host: "smtps.aruba.it", logger: false, port: 465, secure: true, tls: { ciphers: "HIGH:MEDIUM:!aNULL:!eNULL:@STRENGTH:!DH:!kEDH", minVersion: "TLSv1", }, }); smtpTransport.use("compile", htmlToText()); const message: Options = { from: `"InfoAlloggi" <${env.ARUBA_USER}>`, ...options, }; smtpTransport.sendMail(message, (err, info) => { if (err) { throw new Error(err.message); } return info; }); }; export type NewMailProps = { template?: MailsTemplates; userId?: UsersId; mail: Options; }; 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 | SchedaContatto_NewMail | Invito_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; case "emailSchedaContatto": mailComponent = EmailSchedaContatto({ ...mail.props, }); title = "Scheda Contatto Annuncio"; break; case "invito": mailComponent = Invito({ ...mail.props, }); title = "Invito al sito"; break; default: mailComponent = null; 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 ({ template, userId, mail }: NewMailProps) => { const emailFlag = await GetFlagValueHandler({ db: db, id: "EMAIL_ENABLED", }); if (emailFlag) { try { if (template) { const { html } = await genMail({ ...template }); await mailer({ html, ...mail, }); } else { await mailer({ ...mail, }); } } catch (e) { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: `Errore nell'invio dell'email: ${(e as Error).message}`, }); } } else { console.warn( `Email sending is disabled to:${mail.to} subj:${mail.subject} msgType: ${template?.mailType}`, ); } if (userId && template) { // Store the email in the database if userId is provided await StoreEmail({ data: template, userId }); } };