Skip to content

Commit

Permalink
feat: à tester
Browse files Browse the repository at this point in the history
  • Loading branch information
alanlr committed Dec 6, 2023
1 parent b586ba4 commit 2a4a36f
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 142 deletions.
249 changes: 125 additions & 124 deletions server/src/http/routes/emails.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,136 @@ import config from "@/config"

import { logger } from "../../common/logger"
import { Etablissement } from "../../common/model"
import { addEmailToBlacklist, removeEmailFromLbaCompanies } from "../../services/application.service"
import { addEmailToBlacklist, findApplicationByMessageId, removeEmailFromLbaCompanies, updateApplicationStatusFromHardbounce } from "../../services/application.service"
import * as appointmentService from "../../services/appointment.service"
import { BrevoEventStatus } from "../../services/brevo.service"
import dayjs from "../../services/dayjs.service"
import * as eligibleTrainingsForAppointmentService from "../../services/eligibleTrainingsForAppointment.service"
import { Server } from "../server"

const processWebhookEvent = async (payload) => {
const { date, event, email } = payload
const messageId = payload["message-id"]

// application
if (event === BrevoEventStatus.HARD_BOUNCE) {
const application = await findApplicationByMessageId({
messageId,
email,
})

if (application) {
await updateApplicationStatusFromHardbounce({ payload, application })
return
}
}

const eventDate = dayjs.utc(date).tz("Europe/Paris").toDate()

// If mail sent from appointment model
const appointment = await appointmentService.findOne({ "to_cfa_mails.message_id": { $regex: messageId } })
if (appointment) {
const previousEmail = appointment.to_cfa_mails.find((mail) => mail.message_id.includes(messageId))

if (!previousEmail) return

await appointment.update({
$push: {
to_etablissement_emails: {
campaign: previousEmail.campaign,
status: event,
message_id: previousEmail.message_id,
webhook_status_at: eventDate,
},
},
})

// Disable eligibleTrainingsForAppointments in case of hard_bounce
if (event === BrevoEventStatus.HARD_BOUNCE) {
const eligibleTrainingsForAppointmentsWithEmail = await eligibleTrainingsForAppointmentService.find({ cfa_recipient_email: appointment.cfa_recipient_email })

await Promise.all(
eligibleTrainingsForAppointmentsWithEmail.map(async (eligibleTrainingsForAppointment) => {
await eligibleTrainingsForAppointment.update({ referrers: [] })

logger.info('Widget parameters disabled for "hard_bounce" reason', {
eligibleTrainingsForAppointmentId: eligibleTrainingsForAppointment._id,
cfa_recipient_email: appointment.cfa_recipient_email,
})
})
)
await addEmailToBlacklist(appointment.cfa_recipient_email as string, "rdv-transactional")
}

return
}

// If mail sent from etablissement model
const [etablissementFound] = await Etablissement.find({ "mailing.message_id": { $regex: messageId } })
if (etablissementFound) {
const previousEmail = etablissementFound?.to_etablissement_emails?.find((mail) => mail?.message_id?.includes(messageId))

await etablissementFound.update({
$push: {
to_etablissement_emails: {
campaign: previousEmail?.campaign,
status: event,
message_id: previousEmail?.message_id,
webhook_status_at: eventDate,
},
},
})
return
}

// If mail sent from appointment (to the candidat)
const [appointmentCandidatFound] = await appointmentService.find({
"to_applicant_mails.message_id": { $regex: messageId },
})
if (appointmentCandidatFound) {
const previousEmail = appointmentCandidatFound?.to_applicant_mails?.find((mail) => mail.message_id.includes(messageId))

if (!previousEmail) return

await appointmentCandidatFound.update({
$push: {
to_applicant_mails: {
campaign: previousEmail.campaign,
status: event,
message_id: previousEmail.message_id,
webhook_status_at: eventDate,
},
},
})
return
}

// If mail sent from appointment (to the CFA)
const [appointmentCfaFound] = await appointmentService.find({ "to_cfa_mails.message_id": { $regex: messageId } })
if (appointmentCfaFound && appointmentCfaFound?.to_cfa_mails) {
const previousEmail = appointmentCfaFound.to_cfa_mails.find((mail) => mail.message_id.includes(messageId))

if (!previousEmail) {
return
}

await appointmentCfaFound.update({
$push: {
to_cfa_mails: {
campaign: previousEmail.campaign,
status: event,
message_id: previousEmail.message_id,
webhook_status_at: eventDate,
},
},
})
return
}

if (event === BrevoEventStatus.HARD_BOUNCE) {
await Promise.all([addEmailToBlacklist(email, "campaign"), removeEmailFromLbaCompanies(email)])
}
}
/**
* Email controllers.
*/
Expand All @@ -31,129 +154,7 @@ export default (server: Server) => {
throw Boom.forbidden()
}

const { date, event, email } = req.body

if (event === BrevoEventStatus.HARD_BOUNCE) {
// ???? comment identifier la source du blacklisting

await Promise.all([addEmailToBlacklist(email, "campaign"), removeEmailFromLbaCompanies(email)])
}

// server.post(
// "/application/webhook",
// {
// schema: zRoutes.post["/application/webhook"],
// },
// async (req, res) => {
// const { apikey } = req.query
// if (apikey !== config.smtp.brevoWebhookApiKey) {
// throw Boom.unauthorized()
// }

// await updateApplicationStatus({ payload: req.body })
// return res.status(200).send({ result: "ok" })
// }
// )

const messageId = req.body["message-id"]
const eventDate = dayjs.utc(date).tz("Europe/Paris").toDate()

const appointment = await appointmentService.findOne({ "to_cfa_mails.message_id": { $regex: messageId } })

// If mail sent from appointment model
if (appointment) {
const previousEmail = appointment.to_cfa_mails.find((mail) => mail.message_id.includes(messageId))

if (!previousEmail) return

await appointment.update({
$push: {
to_etablissement_emails: {
campaign: previousEmail.campaign,
status: event,
message_id: previousEmail.message_id,
webhook_status_at: eventDate,
},
},
})

// Disable eligibleTrainingsForAppointments in case of hard_bounce
if (event === BrevoEventStatus.HARD_BOUNCE) {
const eligibleTrainingsForAppointmentsWithEmail = await eligibleTrainingsForAppointmentService.find({ cfa_recipient_email: appointment.cfa_recipient_email })

await Promise.all(
eligibleTrainingsForAppointmentsWithEmail.map(async (eligibleTrainingsForAppointment) => {
await eligibleTrainingsForAppointment.update({ referrers: [] })

logger.info('Widget parameters disabled for "hard_bounce" reason', {
eligibleTrainingsForAppointmentId: eligibleTrainingsForAppointment._id,
cfa_recipient_email: appointment.cfa_recipient_email,
})
})
)
await addEmailToBlacklist(appointment.cfa_recipient_email as string, "rdv-transactional")
}
}

const [etablissementFound] = await Etablissement.find({ "mailing.message_id": { $regex: messageId } })

// If mail sent from etablissement model
if (etablissementFound) {
const previousEmail = etablissementFound?.to_etablissement_emails?.find((mail) => mail?.message_id?.includes(messageId))

await etablissementFound.update({
$push: {
to_etablissement_emails: {
campaign: previousEmail?.campaign,
status: event,
message_id: previousEmail?.message_id,
webhook_status_at: eventDate,
},
},
})
}

const [appointmentCandidatFound] = await appointmentService.find({
"to_applicant_mails.message_id": { $regex: messageId },
})

// If mail sent from appointment (to the candidat)
if (appointmentCandidatFound) {
const previousEmail = appointmentCandidatFound?.to_applicant_mails?.find((mail) => mail.message_id.includes(messageId))

if (!previousEmail) return

await appointmentCandidatFound.update({
$push: {
to_applicant_mails: {
campaign: previousEmail.campaign,
status: event,
message_id: previousEmail.message_id,
webhook_status_at: eventDate,
},
},
})
}

const [appointmentCfaFound] = await appointmentService.find({ "to_cfa_mails.message_id": { $regex: messageId } })

// If mail sent from appointment (to the CFA)
if (appointmentCfaFound && appointmentCfaFound?.to_cfa_mails) {
const previousEmail = appointmentCfaFound.to_cfa_mails.find((mail) => mail.message_id.includes(messageId))

if (!previousEmail) return

await appointmentCfaFound.update({
$push: {
to_cfa_mails: {
campaign: previousEmail.campaign,
status: event,
message_id: previousEmail.message_id,
webhook_status_at: eventDate,
},
},
})
}
await processWebhookEvent(req.body)

return res.status(200).send({})
}
Expand Down
21 changes: 3 additions & 18 deletions server/src/services/application.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { prepareMessageForMail } from "../common/utils/fileUtils.js"
import { sentryCaptureException } from "../common/utils/sentryUtils.js"
import config from "../config.js"

import { BrevoEventStatus } from "./brevo.service.js"
import { scan } from "./clamav.service"
import { getOffreAvecInfoMandataire } from "./formulaire.service"
import mailer from "./mailer.service.js"
Expand Down Expand Up @@ -86,7 +85,7 @@ export const addEmailToBlacklist = async (email: string, blacklistingOrigin: str
* @param {string} email
* @returns {Promise<IApplication>}
*/
const findApplicationByMessageId = async ({ messageId, email }: { messageId: string; email: string }) =>
export const findApplicationByMessageId = async ({ messageId, email }: { messageId: string; email: string }) =>
Application.findOne({ company_email: email, to_company_message_id: messageId })

/**
Expand Down Expand Up @@ -552,7 +551,7 @@ export const sendNotificationToApplicant = async ({
/**
* @description updates application and triggers action from email webhook
*/
export const updateApplicationStatus = async ({ payload }: { payload: any }): Promise<void> => {
export const updateApplicationStatusFromHardbounce = async ({ payload, application }: { payload: any; application: IApplication }): Promise<void> => {
/* Format payload cf. https://developers.brevo.com/docs/how-to-use-webhooks
{
"event": "delivered",
Expand All @@ -572,27 +571,13 @@ export const updateApplicationStatus = async ({ payload }: { payload: any }): Pr
}
*/

const { event, subject, email } = payload

if (event !== BrevoEventStatus.HARD_BOUNCE) {
return
}
const { subject, email } = payload

if (!subject.startsWith("Candidature en alternance") && !subject.startsWith("Candidature spontanée")) {
// les messages qui ne sont pas de candidature vers une entreprise sont ignorés
return
}

const application = await findApplicationByMessageId({
messageId: payload["message-id"],
email,
})

if (!application) {
logger.error(`Application webhook : application not found. message_id=${payload["message-id"]} email=${email} subject=${subject}`)
return
}

await addEmailToBlacklist(email, application.job_origin ?? "unknown")

if (application.job_origin === "lba") {
Expand Down

0 comments on commit 2a4a36f

Please sign in to comment.