Skip to content

Commit

Permalink
🚸 (sendEmail) Improve variable parsing in sendEmail body
Browse files Browse the repository at this point in the history
Support for multi line variables as well

Closes #749
  • Loading branch information
baptisteArno committed Sep 1, 2023
1 parent 6a0f6e4 commit 37ccb5d
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,14 @@ export const executeSendEmailBlock = async (
],
}

const body =
findUniqueVariableValue(typebot.variables)(options.body)?.toString() ??
parseVariables(typebot.variables, { escapeHtml: true })(options.body ?? '')
const bodyUniqueVariable = findUniqueVariableValue(typebot.variables)(
options.body
)
const body = bodyUniqueVariable
? stringifyUniqueVariableValueAsHtml(bodyUniqueVariable)
: parseVariables(typebot.variables, { isInsideHtml: true })(
options.body ?? ''
)

try {
const sendEmailLogs = await sendEmail({
Expand Down Expand Up @@ -258,3 +263,11 @@ const getFileUrls =
if (typeof fileUrls === 'string') return fileUrls
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 />')
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ const parseWebhookAttributes =
bodyContent && webhook.method !== HttpMethod.GET
? safeJsonParse(
parseVariables(typebot.variables, {
escapeForJson: !checkIfBodyIsAVariable(bodyContent),
isInsideJson: !checkIfBodyIsAVariable(bodyContent),
})(bodyContent)
)
: { data: undefined, isJson: false }
Expand Down
38 changes: 20 additions & 18 deletions apps/viewer/src/features/variables/parseVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import { safeStringify } from '@typebot.io/lib/safeStringify'

export type ParseVariablesOptions = {
fieldToParse?: 'value' | 'id'
escapeForJson?: boolean
isInsideJson?: boolean
takeLatestIfList?: boolean
escapeHtml?: boolean
isInsideHtml?: boolean
}

export const defaultParseVariablesOptions: ParseVariablesOptions = {
fieldToParse: 'value',
escapeForJson: false,
isInsideJson: false,
takeLatestIfList: false,
escapeHtml: false,
isInsideHtml: false,
}

export const parseVariables =
Expand All @@ -39,13 +39,8 @@ export const parseVariables =
if (!variable) return dollarSign + ''
if (options.fieldToParse === 'id') return dollarSign + variable.id
const { value } = variable
if (options.escapeForJson)
return (
dollarSign +
(typeof value === 'string'
? jsonParse(value)
: JSON.stringify(value))
)
if (options.isInsideJson)
return dollarSign + parseVariableValueInJson(value)
const parsedValue =
dollarSign +
safeStringify(
Expand All @@ -54,15 +49,22 @@ export const parseVariables =
: value
)
if (!parsedValue) return dollarSign + ''
if (options.escapeHtml)
return parsedValue.replace(/</g, '&lt;').replace(/>/g, '&gt;')
if (options.isInsideHtml) return parseVariableValueInHtml(parsedValue)
return parsedValue
}
)
}

const jsonParse = (str: string) =>
str
.replace(/\n/g, `\\n`)
.replace(/"/g, `\\"`)
.replace(/\\[^n"]/g, `\\\\ `)
const parseVariableValueInJson = (value: VariableWithValue['value']) => {
const stringifiedValue = JSON.stringify(value)
if (typeof value === 'string') return stringifiedValue.slice(1, -1)
return stringifiedValue
}

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;')
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export const executeWebhook =
bodyContent && webhook.method !== HttpMethod.GET
? safeJsonParse(
parseVariables(variables, {
escapeForJson: !checkIfBodyIsAVariable(bodyContent),
isInsideJson: !checkIfBodyIsAVariable(bodyContent),
})(bodyContent)
)
: { data: undefined, isJson: false }
Expand Down
7 changes: 7 additions & 0 deletions packages/emails/src/emails/DefaultBotNotificationEmail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ export const DefaultBotNotificationEmail = ({
<b>{key}</b>:{' '}
{isEmail ? (
<a href={`mailto:${answers[key]}`}>{answers[key]}</a>
) : answers[key].includes('\n') ? (
answers[key].split('\n').map((line) => (
<>
{line}
<br />
</>
))
) : (
answers[key]
)}
Expand Down

4 comments on commit 37ccb5d

@vercel
Copy link

@vercel vercel bot commented on 37ccb5d Sep 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./apps/docs

docs-typebot-io.vercel.app
docs-git-main-typebot-io.vercel.app
docs.typebot.io

@vercel
Copy link

@vercel vercel bot commented on 37ccb5d Sep 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

viewer-v2 – ./apps/viewer

kusamint.com
psmix.online
receita.info
rhino.cr8.ai
sheep.cr8.ai
snake.cr8.ai
svhm.mprs.in
tiger.cr8.ai
video.cr8.ai
webwhats.pro
yoda.riku.ai
zebra.cr8.ai
alvodelas.com
bemestar.club
bot.krdfy.com
cat.hidden.sg
cgcassets.com
cnvhub.com.br
drapamela.com
facelabko.com
filmylogy.com
goldorayo.com
rabbit.cr8.ai
shop.mexwa.my
signup.cr8.ai
start.taxt.co
theusm.com.br
turkey.cr8.ai
vhpage.cr8.ai
vitamyway.com
whatchat.site
www.wiccom.it
am.nigerias.io
an.nigerias.io
app.yvon.earth
ar.nigerias.io
bot.enreso.org
bot.mail2wa.me
bot.rslabs.pro
bots.bng.tools
bots.bridge.ai
chad.gocto.com
chat.hayuri.id
chat.uprize.hu
chatgpt.lam.ee
chicken.cr8.ai
drayumi.social
gollum.riku.ai
gsbulletin.com
journey.cr8.ai
kopibayane.com
panther.cr7.ai
panther.cr8.ai
pay.sifuim.com
penguin.cr8.ai
segredomeu.com
talk.gocare.io
test.bot.gives
viewer-v2-typebot-io.vercel.app
mdb.assessoria.rodrigo.progenbr.com
register.thailandmicespecialist.com
mdb.assessoria.desideri.progenbr.com
mdb.assessoria.fernanda.progenbr.com
mdb.assessoria.jbatista.progenbr.com
mdb.assessoria.mauricio.progenbr.com
mdb.evento.autocadastro.progenbr.com
form.shopmercedesbenzsouthorlando.com
mdb.evento.equipeinterna.progenbr.com
bot.studiotecnicoimmobiliaremerelli.it
mdb.assessoria.boaventura.progenbr.com
mdb.assessoria.jtrebesqui.progenbr.com
pesquisa.escolamodacomproposito.com.br
anamnese.clinicaramosodontologia.com.br
gabinete.baleia.formulario.progenbr.com
mdb.assessoria.carreirinha.progenbr.com
chrome-os-inquiry-system.itschromeos.com
mdb.assessoria.paulomarques.progenbr.com
viewer-v2-git-main-typebot-io.vercel.app
main-menu-for-itschromeos.itschromeos.com
mdb.assessoria.qrcode.ademir.progenbr.com
mdb.assessoria.qrcode.arthur.progenbr.com
mdb.assessoria.qrcode.danilo.progenbr.com
mdb.assessoria.qrcode.marcao.progenbr.com
mdb.assessoria.qrcode.marcio.progenbr.com
mdb.assessoria.qrcode.aloisio.progenbr.com
mdb.assessoria.qrcode.girotto.progenbr.com
mdb.assessoria.qrcode.marinho.progenbr.com
mdb.assessoria.qrcode.rodrigo.progenbr.com
mdb.assessoria.carlosalexandre.progenbr.com
mdb.assessoria.qrcode.desideri.progenbr.com
mdb.assessoria.qrcode.fernanda.progenbr.com
mdb.assessoria.qrcode.jbatista.progenbr.com
mdb.assessoria.qrcode.mauricio.progenbr.com
mdb.assessoria.fernanda.regional.progenbr.com
mdb.assessoria.qrcode.boaventura.progenbr.com
mdb.assessoria.qrcode.jtrebesqui.progenbr.com
mdb.assessoria.qrcode.carreirinha.progenbr.com
mdb.assessoria.qrcode.paulomarques.progenbr.com
mdb.assessoria.qrcode.carlosalexandre.progenbr.com
mdb.assessoria.qrcode.fernanda.regional.progenbr.com

@vercel
Copy link

@vercel vercel bot commented on 37ccb5d Sep 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 37ccb5d Sep 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

builder-v2-typebot-io.vercel.app
builder-v2-git-main-typebot-io.vercel.app
app.typebot.io

Please sign in to comment.