Skip to content

Commit

Permalink
🛂 Prevent duplicate email sends and limit to 5 max email sending in o…
Browse files Browse the repository at this point in the history
…ne go
  • Loading branch information
baptisteArno committed Oct 11, 2024
1 parent 5fb10d2 commit a6db54c
Showing 1 changed file with 38 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defaultSendEmailOptions } from "@typebot.io/blocks-integrations/sendEmail/constants";
import { TRPCError } from "@trpc/server";
import type {
SendEmailBlock,
SmtpCredentials,
Expand Down Expand Up @@ -35,14 +35,22 @@ import { defaultFrom, defaultTransportOptions } from "./constants";
export const sendEmailSuccessDescription = "Email successfully sent";
export const sendEmailErrorDescription = "Email not sent";

let prevHash: string | undefined;
let emailSendingCount = 0;
const maxEmailSending = 5;

export const executeSendEmailBlock = async (
state: SessionState,
block: SendEmailBlock,
): Promise<ExecuteIntegrationResponse> => {
const logs: ChatLog[] = [];
const { options } = block;
if (!state.typebotsQueue[0]) throw new Error("No typebot in queue");
const { typebot, resultId, answers } = state.typebotsQueue[0];
const {
typebot: { id, variables },
resultId,
answers,
} = state.typebotsQueue[0];
const isPreview = !resultId;
if (isPreview)
return {
Expand All @@ -55,12 +63,12 @@ export const executeSendEmailBlock = async (
],
};

const bodyUniqueVariable = findUniqueVariable(typebot.variables)(
const bodyUniqueVariable = findUniqueVariable(variables)(
options?.body,
)?.value;
const body = bodyUniqueVariable
? stringifyUniqueVariableValueAsHtml(bodyUniqueVariable)
: parseVariables(typebot.variables, { isInsideHtml: !options?.isBodyCode })(
: parseVariables(variables, { isInsideHtml: !options?.isBodyCode })(
options?.body ?? "",
);

Expand All @@ -75,26 +83,28 @@ export const executeSendEmailBlock = async (
});
return { outgoingEdgeId: block.outgoingEdgeId, logs };
}

if (emailSendingCount >= maxEmailSending)
throw new TRPCError({
code: "FORBIDDEN",
message: "Attempt to send more than 5 emails",
});
try {
const sendEmailLogs = await sendEmail({
typebot,
typebot: { id, variables },
answers,
credentialsId: options.credentialsId,
recipients: options.recipients.map(parseVariables(typebot.variables)),
recipients: options.recipients.map(parseVariables(variables)),
subject: options.subject
? parseVariables(typebot.variables)(options?.subject)
? parseVariables(variables)(options?.subject)
: undefined,
body,
cc: options.cc
? options.cc.map(parseVariables(typebot.variables))
: undefined,
bcc: options.bcc
? options.bcc.map(parseVariables(typebot.variables))
: undefined,
cc: options.cc ? options.cc.map(parseVariables(variables)) : undefined,
bcc: options.bcc ? options.bcc.map(parseVariables(variables)) : undefined,
replyTo: options.replyTo
? parseVariables(typebot.variables)(options.replyTo)
? parseVariables(variables)(options.replyTo)
: undefined,
fileUrls: getFileUrls(typebot.variables)(options.attachmentsVariableId),
fileUrls: getFileUrls(variables)(options.attachmentsVariableId),
isCustomBody: options.isCustomBody,
isBodyCode: options.isBodyCode,
});
Expand All @@ -107,6 +117,8 @@ export const executeSendEmailBlock = async (
});
}

emailSendingCount += 1;

return { outgoingEdgeId: block.outgoingEdgeId, logs };
};

Expand All @@ -133,7 +145,7 @@ const sendEmail = async ({
replyTo: string | undefined;
isBodyCode: boolean | undefined;
isCustomBody: boolean | undefined;
typebot: TypebotInSession;
typebot: Pick<TypebotInSession, "id" | "variables">;
answers: AnswerInSessionState[];
fileUrls?: string | string[];
}): Promise<ChatLog[] | undefined> => {
Expand Down Expand Up @@ -191,6 +203,15 @@ const sendEmail = async ({
attachments: await parseAttachments(fileUrls, typebot.id),
...emailBody,
};

const hash = JSON.stringify(email);
if (prevHash && prevHash === hash)
throw new TRPCError({
code: "FORBIDDEN",
message: "Attempt to send the same email twice",
});
prevHash = hash;

try {
await transporter.sendMail(email);
logs.push({
Expand Down Expand Up @@ -251,7 +272,7 @@ const getEmailBody = async ({
typebot,
answersInSession,
}: {
typebot: TypebotInSession;
typebot: Pick<TypebotInSession, "id" | "variables">;
answersInSession: AnswerInSessionState[];
} & Pick<
NonNullable<SendEmailBlock["options"]>,
Expand Down

0 comments on commit a6db54c

Please sign in to comment.