2
0

🚸 (sendEmail) Improve variable parsing in sendEmail body

Support for multi line variables as well

Closes #749
This commit is contained in:
Baptiste Arnaud
2023-09-01 11:33:45 +02:00
parent 6a0f6e4ef2
commit 37ccb5da5e
5 changed files with 45 additions and 23 deletions

View File

@@ -41,9 +41,14 @@ export const executeSendEmailBlock = async (
], ],
} }
const body = const bodyUniqueVariable = findUniqueVariableValue(typebot.variables)(
findUniqueVariableValue(typebot.variables)(options.body)?.toString() ?? options.body
parseVariables(typebot.variables, { escapeHtml: true })(options.body ?? '') )
const body = bodyUniqueVariable
? stringifyUniqueVariableValueAsHtml(bodyUniqueVariable)
: parseVariables(typebot.variables, { isInsideHtml: true })(
options.body ?? ''
)
try { try {
const sendEmailLogs = await sendEmail({ const sendEmailLogs = await sendEmail({
@@ -258,3 +263,11 @@ const getFileUrls =
if (typeof fileUrls === 'string') return fileUrls if (typeof fileUrls === 'string') return fileUrls
return fileUrls.filter(isDefined) return fileUrls.filter(isDefined)
} }
const stringifyUniqueVariableValueAsHtml = (
value: Variable['value']
): string => {
if (!value) return ''
if (typeof value === 'string') return value.replace(/\n/g, '<br />')
return value.map(stringifyUniqueVariableValueAsHtml).join('<br />')
}

View File

@@ -128,7 +128,7 @@ const parseWebhookAttributes =
bodyContent && webhook.method !== HttpMethod.GET bodyContent && webhook.method !== HttpMethod.GET
? safeJsonParse( ? safeJsonParse(
parseVariables(typebot.variables, { parseVariables(typebot.variables, {
escapeForJson: !checkIfBodyIsAVariable(bodyContent), isInsideJson: !checkIfBodyIsAVariable(bodyContent),
})(bodyContent) })(bodyContent)
) )
: { data: undefined, isJson: false } : { data: undefined, isJson: false }

View File

@@ -4,16 +4,16 @@ import { safeStringify } from '@typebot.io/lib/safeStringify'
export type ParseVariablesOptions = { export type ParseVariablesOptions = {
fieldToParse?: 'value' | 'id' fieldToParse?: 'value' | 'id'
escapeForJson?: boolean isInsideJson?: boolean
takeLatestIfList?: boolean takeLatestIfList?: boolean
escapeHtml?: boolean isInsideHtml?: boolean
} }
export const defaultParseVariablesOptions: ParseVariablesOptions = { export const defaultParseVariablesOptions: ParseVariablesOptions = {
fieldToParse: 'value', fieldToParse: 'value',
escapeForJson: false, isInsideJson: false,
takeLatestIfList: false, takeLatestIfList: false,
escapeHtml: false, isInsideHtml: false,
} }
export const parseVariables = export const parseVariables =
@@ -39,13 +39,8 @@ export const parseVariables =
if (!variable) return dollarSign + '' if (!variable) return dollarSign + ''
if (options.fieldToParse === 'id') return dollarSign + variable.id if (options.fieldToParse === 'id') return dollarSign + variable.id
const { value } = variable const { value } = variable
if (options.escapeForJson) if (options.isInsideJson)
return ( return dollarSign + parseVariableValueInJson(value)
dollarSign +
(typeof value === 'string'
? jsonParse(value)
: JSON.stringify(value))
)
const parsedValue = const parsedValue =
dollarSign + dollarSign +
safeStringify( safeStringify(
@@ -54,15 +49,22 @@ export const parseVariables =
: value : value
) )
if (!parsedValue) return dollarSign + '' if (!parsedValue) return dollarSign + ''
if (options.escapeHtml) if (options.isInsideHtml) return parseVariableValueInHtml(parsedValue)
return parsedValue.replace(/</g, '&lt;').replace(/>/g, '&gt;')
return parsedValue return parsedValue
} }
) )
} }
const jsonParse = (str: string) => const parseVariableValueInJson = (value: VariableWithValue['value']) => {
str const stringifiedValue = JSON.stringify(value)
.replace(/\n/g, `\\n`) if (typeof value === 'string') return stringifiedValue.slice(1, -1)
.replace(/"/g, `\\"`) return stringifiedValue
.replace(/\\[^n"]/g, `\\\\ `) }
const parseVariableValueInHtml = (
value: VariableWithValue['value']
): string => {
if (typeof value === 'string')
return value.replace(/</g, '&lt;').replace(/>/g, '&gt;')
return JSON.stringify(value).replace(/</g, '&lt;').replace(/>/g, '&gt;')
}

View File

@@ -149,7 +149,7 @@ export const executeWebhook =
bodyContent && webhook.method !== HttpMethod.GET bodyContent && webhook.method !== HttpMethod.GET
? safeJsonParse( ? safeJsonParse(
parseVariables(variables, { parseVariables(variables, {
escapeForJson: !checkIfBodyIsAVariable(bodyContent), isInsideJson: !checkIfBodyIsAVariable(bodyContent),
})(bodyContent) })(bodyContent)
) )
: { data: undefined, isJson: false } : { data: undefined, isJson: false }

View File

@@ -32,6 +32,13 @@ export const DefaultBotNotificationEmail = ({
<b>{key}</b>:{' '} <b>{key}</b>:{' '}
{isEmail ? ( {isEmail ? (
<a href={`mailto:${answers[key]}`}>{answers[key]}</a> <a href={`mailto:${answers[key]}`}>{answers[key]}</a>
) : answers[key].includes('\n') ? (
answers[key].split('\n').map((line) => (
<>
{line}
<br />
</>
))
) : ( ) : (
answers[key] answers[key]
)} )}