Skip to content

Commit

Permalink
feat(integrations): 🚸 Add Reply-To field for email sending
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Mar 22, 2022
1 parent d4022c6 commit ddb6798
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Stack, useDisclosure, Text } from '@chakra-ui/react'
import { CredentialsDropdown } from 'components/shared/CredentialsDropdown'
import { Input, Textarea } from 'components/shared/Textbox'
import { useTypebot } from 'contexts/TypebotContext'
import { CredentialsType, SendEmailOptions } from 'models'
import React, { useState } from 'react'
import React, { useEffect, useState } from 'react'
import { isDefined } from 'utils'
import { SmtpConfigModal } from './SmtpConfigModal'

type Props = {
Expand All @@ -11,9 +13,16 @@ type Props = {
}

export const SendEmailSettings = ({ options, onOptionsChange }: Props) => {
const { owner } = useTypebot()
const { isOpen, onOpen, onClose } = useDisclosure()
const [refreshCredentialsKey, setRefreshCredentialsKey] = useState(0)

useEffect(() => {
if (isDefined(options.replyTo) || !owner?.email) return
handleReplyToChange(owner.email)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

const handleCredentialsSelect = (credentialsId?: string) => {
setRefreshCredentialsKey(refreshCredentialsKey + 1)
onOptionsChange({
Expand Down Expand Up @@ -60,6 +69,12 @@ export const SendEmailSettings = ({ options, onOptionsChange }: Props) => {
body,
})

const handleReplyToChange = (replyTo: string) =>
onOptionsChange({
...options,
replyTo,
})

return (
<Stack spacing={4}>
<Stack>
Expand All @@ -75,6 +90,14 @@ export const SendEmailSettings = ({ options, onOptionsChange }: Props) => {
refreshDropdownKey={refreshCredentialsKey}
/>
</Stack>
<Stack>
<Text>Reply to: </Text>
<Input
onChange={handleReplyToChange}
defaultValue={options.replyTo}
placeholder={owner?.email ?? 'email@gmail.com'}
/>
</Stack>
<Stack>
<Text>To: </Text>
<Input
Expand Down
11 changes: 10 additions & 1 deletion apps/builder/components/shared/Textbox/TextBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,21 @@ export const TextBox = ({
null
)
const [carretPosition, setCarretPosition] = useState<number>(0)
const [value, setValue] = useState(props.defaultValue)
const [value, setValue] = useState(props.defaultValue ?? '')
const [isTouched, setIsTouched] = useState(false)
const debounced = useDebouncedCallback(
(value) => {
onChange(value)
},
process.env.NEXT_PUBLIC_E2E_TEST ? 0 : debounceTimeout
)

useEffect(() => {
if (props.defaultValue !== value && value === '' && !isTouched)
setValue(props.defaultValue ?? '')
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.defaultValue])

useEffect(
() => () => {
debounced.flush()
Expand All @@ -54,12 +61,14 @@ export const TextBox = ({
const handleChange = (
e: ChangeEvent<HTMLInputElement & HTMLTextAreaElement>
) => {
setIsTouched(true)
setValue(e.target.value)
debounced(e.target.value)
}

const handleVariableSelected = (variable?: Variable) => {
if (!textBoxRef.current || !variable) return
setIsTouched(true)
const cursorPosition = carretPosition
const textBeforeCursorPosition = textBoxRef.current.value.substring(
0,
Expand Down
3 changes: 2 additions & 1 deletion apps/viewer/pages/api/integrations/email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const defaultFrom = {
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
await cors(req, res)
if (req.method === 'POST') {
const { credentialsId, recipients, body, subject, cc, bcc } = (
const { credentialsId, recipients, body, subject, cc, bcc, replyTo } = (
typeof req.body === 'string' ? JSON.parse(req.body) : req.body
) as SendEmailOptions

Expand All @@ -50,6 +50,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
cc: cc?.join(''),
bcc: bcc?.join(''),
to: recipients.join(', '),
replyTo,
subject,
text: body,
})
Expand Down
2 changes: 2 additions & 0 deletions packages/bot-engine/src/services/integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ const sendEmail = async (
return step.outgoingEdgeId
}
const { options } = step
const replyTo = parseVariables(variables)(options.replyTo)
const { error } = await sendRequest({
url: `${apiHost}/api/integrations/email`,
method: 'POST',
Expand All @@ -251,6 +252,7 @@ const sendEmail = async (
body: parseVariables(variables)(options.body ?? ''),
cc: (options.cc ?? []).map(parseVariables(variables)),
bcc: (options.bcc ?? []).map(parseVariables(variables)),
replyTo: replyTo !== '' ? replyTo : undefined,
},
})
onNewLog(
Expand Down
1 change: 1 addition & 0 deletions packages/models/src/typebot/steps/integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export type SendEmailStep = StepBase & {
export type SendEmailOptions = {
credentialsId: string | 'default'
recipients: string[]
replyTo?: string
cc?: string[]
bcc?: string[]
subject?: string
Expand Down

3 comments on commit ddb6798

@vercel
Copy link

@vercel vercel bot commented on ddb6798 Mar 22, 2022

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 ddb6798 Mar 22, 2022

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-git-main-typebot-io.vercel.app
builder-v2-typebot-io.vercel.app
app.typebot.io

Please sign in to comment.