From 8872ef03a376f0cbed425456560e56362048f296 Mon Sep 17 00:00:00 2001 From: Guillaume Fay Date: Fri, 8 Dec 2023 11:56:42 +0100 Subject: [PATCH] feat: add send form contact mail endpoint --- .env.sample | 3 ++- server/lib/bal-widget/controller.js | 11 ++++++++ server/lib/mailer/email.templates.js | 23 +++++++++++----- server/lib/mailer/schemas.js | 14 ++++++++++ server/lib/mailer/service.js | 39 ++++++++++++++++++++++++++-- 5 files changed, 80 insertions(+), 10 deletions(-) create mode 100644 server/lib/mailer/schemas.js diff --git a/.env.sample b/.env.sample index a69237e..46621b7 100644 --- a/.env.sample +++ b/.env.sample @@ -24,4 +24,5 @@ KEYCLOAK_ISSUER= KEYCLOAK_CLIENT_ID= KEYCLOAK_CLIENT_SECRET= NEXTAUTH_URL= -NEXTAUTH_SECRET= \ No newline at end of file +NEXTAUTH_SECRET= +RE_CAPTCHA_SECRET_KEY= \ No newline at end of file diff --git a/server/lib/bal-widget/controller.js b/server/lib/bal-widget/controller.js index 9eccfcc..2d1f18c 100644 --- a/server/lib/bal-widget/controller.js +++ b/server/lib/bal-widget/controller.js @@ -2,6 +2,7 @@ const express = require("express"); const cors = require("cors"); const {routeGuard} = require('../../route-guard') const BALWidgetService = require("./service"); +const MailerService = require("../mailer/service"); const BALWidgetRoutes = new express.Router(); @@ -28,4 +29,14 @@ BALWidgetRoutes.post("/config", routeGuard, async (req, res) => { } }); +BALWidgetRoutes.post("/send-mail", async (req, res) => { + try { + await MailerService.sendFormContactMail(req.body); + res.json(config); + } catch (err) { + console.error(err); + res.status(500).json({ error: err.message }); + } +}); + module.exports = BALWidgetRoutes; diff --git a/server/lib/mailer/email.templates.js b/server/lib/mailer/email.templates.js index 3f4d32e..52392b1 100644 --- a/server/lib/mailer/email.templates.js +++ b/server/lib/mailer/email.templates.js @@ -1,9 +1,18 @@ module.exports = { - 'candidature-partenaire-de-la-charte': { - from: process.env.SMTP_FROM || 'adresse@data.gouv.fr', - to: 'adresse@data.gouv.fr', - subject: 'Nouvelle candidature aux partenaires de la charte', + "candidature-partenaire-de-la-charte": { + from: process.env.SMTP_FROM || "adresse@data.gouv.fr", + to: "adresse@data.gouv.fr", + subject: "Nouvelle candidature aux partenaires de la charte", text: `Bonjour,\n\nUne nouvelle candidature aux partenaires de la charte a été soumise.\n\nVous pouvez la consulter sur BAL Admin.\n\nBonne journée,\n\nL’équipe BAL`, - html: `

Bonjour,

Une nouvelle candidature aux partenaires de la charte a été soumise.

Vous pouvez la consulter sur BAL Admin.

Bonne journée,

L’équipe BAL

` - } -} + html: `

Bonjour,

Une nouvelle candidature aux partenaires de la charte a été soumise.

Vous pouvez la consulter sur BAL Admin.

Bonne journée,

L’équipe BAL

`, + }, + contact: ({ firstName, lastName, email, message, subject }) => { + return { + from: process.env.SMTP_FROM || "adresse@data.gouv.fr", + to: "adresse@data.gouv.fr", + subject, + text: `Bonjour,\n\nVous avez reçu un nouveau message via le formulaire de contact de BAL Widget.\n\nNom: ${lastName}\nPrénom: ${firstName}\nEmail: ${email}\n\nMessage:\n${message}\n\nBonne journée,\n\nL’équipe BAL`, + html: `

Bonjour,

Vous avez reçu un nouveau message via le formulaire de contact de la BAL Widget.

Nom: ${lastName}

Prénom: ${firstName}

Email: ${email}

Message:

${message}

Bonne journée,

L’équipe BAL

` + }; + }, +}; diff --git a/server/lib/mailer/schemas.js b/server/lib/mailer/schemas.js new file mode 100644 index 0000000..c37b80c --- /dev/null +++ b/server/lib/mailer/schemas.js @@ -0,0 +1,14 @@ +const { validEmail } = require("../../utils/payload"); + +const mailSchema = { + firstName: { isRequired: false, type: "string" }, + lastName: { isRequired: false, type: "string" }, + email: { valid: validEmail, isRequired: true, type: "string" }, + message: { isRequired: true, type: "string" }, + subject: { isRequired: true, type: "string" }, + reCaptchaToken: { isRequired: true, type: "string" }, +}; + +module.exports = { + mailSchema, +}; diff --git a/server/lib/mailer/service.js b/server/lib/mailer/service.js index d81e482..dd0e2be 100644 --- a/server/lib/mailer/service.js +++ b/server/lib/mailer/service.js @@ -1,5 +1,7 @@ const nodemailer = require('nodemailer') const templates = require('./email.templates') +const {mailSchema} = require('./schemas') +const {validPayload} = require('../../utils/payload') function createTransport() { // Use mailhog in development @@ -27,7 +29,7 @@ function createTransport() { const transport = createTransport() -async function sendMail(templateKey) { +async function sendTemplateMail(templateKey) { const template = templates[templateKey] if (!template) { throw new Error(`Le template ${templateKey} n'existe pas`) @@ -42,6 +44,39 @@ async function sendMail(templateKey) { return true } +async function checkReCaptcha(reCaptchaToken) { + const response = await fetch(`https://www.google.com/recaptcha/api/siteverify?secret=${process.env.RE_CAPTCHA_SECRET_KEY}&response=${reCaptchaToken}`, { + method: 'POST' + }) + + const json = await response.json() + + if (!json.success) { + throw new Error('Le reCaptcha est invalide') + } + + return json.success +} + +async function sendFormContactMail(payload) { + const validatedPayload = validPayload(payload, mailSchema) + const {reCaptchaToken, ...emailData } = validatedPayload + + await checkReCaptcha(reCaptchaToken) + + const contactTemplate = templates.contact(emailData) + + const response = await transport.sendMail(contactTemplate) + + if (!response) { + throw new Error('Une erreur est survenue lors de l\'envoi de l\'email') + } + + return true +} + + module.exports = { - sendMail + sendTemplateMail, + sendFormContactMail }