feat(viewer): 🐛 Fix multiple cc bcc email
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import prisma from 'libs/prisma'
|
import prisma from 'libs/prisma'
|
||||||
import { SendEmailOptions, SmtpCredentialsData } from 'models'
|
import { SendEmailOptions, SmtpCredentialsData } from 'models'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
import { createTransport } from 'nodemailer'
|
import { createTransport, getTestMessageUrl } from 'nodemailer'
|
||||||
import { decrypt, initMiddleware } from 'utils'
|
import { decrypt, initMiddleware } from 'utils'
|
||||||
|
|
||||||
import Cors from 'cors'
|
import Cors from 'cors'
|
||||||
@@ -47,15 +47,19 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
})
|
})
|
||||||
const info = await transporter.sendMail({
|
const info = await transporter.sendMail({
|
||||||
from: `"${from.name}" <${from.email}>`,
|
from: `"${from.name}" <${from.email}>`,
|
||||||
cc: cc?.join(''),
|
cc,
|
||||||
bcc: bcc?.join(''),
|
bcc,
|
||||||
to: recipients.join(', '),
|
to: recipients,
|
||||||
replyTo,
|
replyTo,
|
||||||
subject,
|
subject,
|
||||||
text: body,
|
text: body,
|
||||||
})
|
})
|
||||||
|
|
||||||
res.status(200).send({ message: 'Email sent!', info })
|
res.status(200).send({
|
||||||
|
message: 'Email sent!',
|
||||||
|
info,
|
||||||
|
previewUrl: getTestMessageUrl(info),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
122
apps/viewer/playwright/fixtures/typebots/sendEmail.json
Normal file
122
apps/viewer/playwright/fixtures/typebots/sendEmail.json
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
{
|
||||||
|
"id": "cl1rxxg6l334509lhv44f8qnx",
|
||||||
|
"createdAt": "2022-04-09T14:16:43.053Z",
|
||||||
|
"updatedAt": "2022-04-12T14:34:44.287Z",
|
||||||
|
"icon": null,
|
||||||
|
"name": "My typebot",
|
||||||
|
"ownerId": "ckzmhmiey001009mnzt5nkxu8",
|
||||||
|
"publishedTypebotId": null,
|
||||||
|
"folderId": null,
|
||||||
|
"blocks": [
|
||||||
|
{
|
||||||
|
"id": "cl1rxxg6k000009lhd0mgfy5i",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"id": "cl1rxxg6k000109lh2is0gfua",
|
||||||
|
"type": "start",
|
||||||
|
"label": "Start",
|
||||||
|
"blockId": "cl1rxxg6k000009lhd0mgfy5i",
|
||||||
|
"outgoingEdgeId": "cl1w8rhzs000f2e694836a1k3"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Start",
|
||||||
|
"graphCoordinates": { "x": 0, "y": 0 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cl1w8repd000b2e69fwiqsd00",
|
||||||
|
"graphCoordinates": { "x": 364, "y": -2 },
|
||||||
|
"title": "Group #1",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"id": "cl1w8repg000c2e699jqwrepg",
|
||||||
|
"blockId": "cl1w8repd000b2e69fwiqsd00",
|
||||||
|
"type": "choice input",
|
||||||
|
"options": { "buttonLabel": "Send", "isMultipleChoice": false },
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "cl1w8repg000d2e69d8xnkqeq",
|
||||||
|
"stepId": "cl1w8repg000c2e699jqwrepg",
|
||||||
|
"type": 0,
|
||||||
|
"content": "Send email",
|
||||||
|
"outgoingEdgeId": "cl1w8rkoo000i2e69hs60pk0q"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cl1w8rjaf000g2e69cqd2bwvk",
|
||||||
|
"graphCoordinates": { "x": 715, "y": -10 },
|
||||||
|
"title": "Group #2",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"id": "cl1w8rjai000h2e695uvoimq7",
|
||||||
|
"blockId": "cl1w8rjaf000g2e69cqd2bwvk",
|
||||||
|
"type": "Email",
|
||||||
|
"options": {
|
||||||
|
"credentialsId": "send-email-credentials",
|
||||||
|
"recipients": ["baptiste.arnaud95@gmail.com"],
|
||||||
|
"replyTo": "contact@baptiste-arnaud.fr",
|
||||||
|
"cc": ["test1@gmail.com", "test2@gmail.com"],
|
||||||
|
"bcc": ["test3@gmail.com", "test4@gmail.com"],
|
||||||
|
"subject": "Hey!",
|
||||||
|
"body": "Test email"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"variables": [
|
||||||
|
{ "id": "vcl1rxxovn000z2e69y6t9dxge", "name": "Score" },
|
||||||
|
{ "id": "vcl1rylq5v00042e69tdml6hi3", "name": "Age" }
|
||||||
|
],
|
||||||
|
"edges": [
|
||||||
|
{
|
||||||
|
"from": {
|
||||||
|
"blockId": "cl1rxxg6k000009lhd0mgfy5i",
|
||||||
|
"stepId": "cl1rxxg6k000109lh2is0gfua"
|
||||||
|
},
|
||||||
|
"to": { "blockId": "cl1w8repd000b2e69fwiqsd00" },
|
||||||
|
"id": "cl1w8rhzs000f2e694836a1k3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": {
|
||||||
|
"blockId": "cl1w8repd000b2e69fwiqsd00",
|
||||||
|
"stepId": "cl1w8repg000c2e699jqwrepg",
|
||||||
|
"itemId": "cl1w8repg000d2e69d8xnkqeq"
|
||||||
|
},
|
||||||
|
"to": { "blockId": "cl1w8rjaf000g2e69cqd2bwvk" },
|
||||||
|
"id": "cl1w8rkoo000i2e69hs60pk0q"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme": {
|
||||||
|
"chat": {
|
||||||
|
"inputs": {
|
||||||
|
"color": "#303235",
|
||||||
|
"backgroundColor": "#FFFFFF",
|
||||||
|
"placeholderColor": "#9095A0"
|
||||||
|
},
|
||||||
|
"buttons": { "color": "#FFFFFF", "backgroundColor": "#0042DA" },
|
||||||
|
"hostAvatar": {
|
||||||
|
"url": "https://avatars.githubusercontent.com/u/16015833?v=4",
|
||||||
|
"isEnabled": true
|
||||||
|
},
|
||||||
|
"hostBubbles": { "color": "#303235", "backgroundColor": "#F7F8FF" },
|
||||||
|
"guestBubbles": { "color": "#FFFFFF", "backgroundColor": "#FF8E21" }
|
||||||
|
},
|
||||||
|
"general": { "font": "Open Sans", "background": { "type": "None" } }
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"general": {
|
||||||
|
"isBrandingEnabled": true,
|
||||||
|
"isInputPrefillEnabled": true,
|
||||||
|
"isNewResultOnRefreshEnabled": false
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"description": "Build beautiful conversational forms and embed them directly in your applications without a line of code. Triple your response rate and collect answers that has more value compared to a traditional form."
|
||||||
|
},
|
||||||
|
"typingEmulation": { "speed": 300, "enabled": true, "maxDelay": 1.5 }
|
||||||
|
},
|
||||||
|
"publicId": null,
|
||||||
|
"customDomain": null
|
||||||
|
}
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
import {
|
import {
|
||||||
|
CredentialsType,
|
||||||
defaultSettings,
|
defaultSettings,
|
||||||
defaultTheme,
|
defaultTheme,
|
||||||
PublicTypebot,
|
PublicTypebot,
|
||||||
|
SmtpCredentialsData,
|
||||||
Step,
|
Step,
|
||||||
Typebot,
|
Typebot,
|
||||||
} from 'models'
|
} from 'models'
|
||||||
import { PrismaClient } from 'db'
|
import { PrismaClient } from 'db'
|
||||||
import { readFileSync } from 'fs'
|
import { readFileSync } from 'fs'
|
||||||
|
import { encrypt } from 'utils'
|
||||||
|
|
||||||
const prisma = new PrismaClient()
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
@@ -184,3 +187,20 @@ const createAnswers = () => {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const createSmtpCredentials = (
|
||||||
|
id: string,
|
||||||
|
smtpData: SmtpCredentialsData
|
||||||
|
) => {
|
||||||
|
const { encryptedData, iv } = encrypt(smtpData)
|
||||||
|
return prisma.credentials.create({
|
||||||
|
data: {
|
||||||
|
id,
|
||||||
|
data: encryptedData,
|
||||||
|
iv,
|
||||||
|
name: smtpData.from.email as string,
|
||||||
|
type: CredentialsType.SMTP,
|
||||||
|
ownerId: 'proUser',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
45
apps/viewer/playwright/tests/sendEmail.spec.ts
Normal file
45
apps/viewer/playwright/tests/sendEmail.spec.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import test, { expect } from '@playwright/test'
|
||||||
|
import {
|
||||||
|
createSmtpCredentials,
|
||||||
|
importTypebotInDatabase,
|
||||||
|
} from '../services/database'
|
||||||
|
import cuid from 'cuid'
|
||||||
|
import path from 'path'
|
||||||
|
import { typebotViewer } from '../services/selectorUtils'
|
||||||
|
import { SmtpCredentialsData } from 'models'
|
||||||
|
|
||||||
|
const mockSmtpCredentials: SmtpCredentialsData = {
|
||||||
|
from: {
|
||||||
|
email: 'tobin.tillman65@ethereal.email',
|
||||||
|
name: 'John Smith',
|
||||||
|
},
|
||||||
|
host: 'smtp.ethereal.email',
|
||||||
|
port: 587,
|
||||||
|
isTlsEnabled: false,
|
||||||
|
username: 'tobin.tillman65@ethereal.email',
|
||||||
|
password: 'Ty9BcwCBrK6w8AG2hx',
|
||||||
|
}
|
||||||
|
|
||||||
|
test('should send an email', async ({ page }) => {
|
||||||
|
const typebotId = cuid()
|
||||||
|
const credentialsId = 'send-email-credentials'
|
||||||
|
await createSmtpCredentials(credentialsId, mockSmtpCredentials)
|
||||||
|
await importTypebotInDatabase(
|
||||||
|
path.join(__dirname, '../fixtures/typebots/sendEmail.json'),
|
||||||
|
{ id: typebotId, publicId: `${typebotId}-public` }
|
||||||
|
)
|
||||||
|
await page.goto(`/${typebotId}-public`)
|
||||||
|
await typebotViewer(page).locator('text=Send email').click()
|
||||||
|
const response = await page.waitForResponse((resp) =>
|
||||||
|
resp.request().url().includes(`/api/integrations/email`)
|
||||||
|
)
|
||||||
|
const { previewUrl } = await response.json()
|
||||||
|
await page.goto(previewUrl)
|
||||||
|
await expect(page.locator('text="Hey!"')).toBeVisible()
|
||||||
|
await expect(page.locator('text="John Smith"')).toBeVisible()
|
||||||
|
await expect(page.locator('text="<test1@gmail.com>" >> nth=0')).toBeVisible()
|
||||||
|
await expect(page.locator('text="<test2@gmail.com>" >> nth=0')).toBeVisible()
|
||||||
|
await expect(
|
||||||
|
page.locator('text="<baptiste.arnaud95@gmail.com>" >> nth=0')
|
||||||
|
).toBeVisible()
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user