Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions apps/sim/tools/gmail/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ describe('escapeHtml', () => {
})

describe('plainTextToHtml', () => {
it('renders blank lines as paragraph breaks and single newlines as <br>', () => {
it('converts newlines to <br> without paragraph margins', () => {
const html = plainTextToHtml('Hi Janice,\n\nHope you are well.\nSecond line.')
expect(html).toContain('<p>Hi Janice,</p>')
expect(html).toContain('<p>Hope you are well.<br>Second line.</p>')
expect(html).not.toContain('<p>')
expect(html).toContain('Hi Janice,<br><br>Hope you are well.<br>Second line.')
})

it('escapes HTML in the source text', () => {
Expand Down Expand Up @@ -150,7 +150,7 @@ describe('buildSimpleEmailMessage', () => {
expect(plainIdx).toBeGreaterThan(-1)
expect(htmlIdx).toBeGreaterThan(plainIdx)
expect(decodePart(decoded, 'text/plain')).toBe('Hi Janice,\n\nQuick question.')
expect(decodePart(decoded, 'text/html')).toContain('<p>Hi Janice,</p>')
expect(decodePart(decoded, 'text/html')).toContain('Hi Janice,<br><br>Quick question.')
})

it('encodes bodies as base64 so UTF-8 (emoji, accents) round-trips cleanly', () => {
Expand Down Expand Up @@ -242,7 +242,7 @@ describe('buildMimeMessage', () => {
expect(message).toMatch(/Content-Type: multipart\/alternative; boundary="([^"]+)"/)
expect(message).toContain('Content-Disposition: attachment; filename="note.txt"')
expect(decodePart(message, 'text/plain')).toBe('Hello')
expect(decodePart(message, 'text/html')).toContain('<p>Hello</p>')
expect(decodePart(message, 'text/html')).toContain('Hello')
})

it('emits multipart/alternative without multipart/mixed when no attachments', () => {
Expand Down
15 changes: 8 additions & 7 deletions apps/sim/tools/gmail/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,17 +339,18 @@ export function escapeHtml(value: string): string {

/**
* Convert a plain-text body to an HTML body that flows naturally in Gmail.
* Blank lines become paragraph breaks; single newlines become `<br>`.
* Newlines become `<br>` rather than per-paragraph `<p>` tags or a CSS
* `white-space` rule — `<p>` margins are what Gmail's "Remove formatting"
* button strips, and `white-space` has inconsistent support across email
* clients (including Gmail for non-Google accounts). Plain `<br>` line
* breaks are the standard, client-agnostic way to preserve plain-text
* formatting in an HTML alternative part.
* This avoids the narrow hard-wrapped rendering Gmail uses for `text/plain`.
*/
export function plainTextToHtml(body: string): string {
const normalized = body.replace(/\r\n/g, '\n').replace(/\r/g, '\n')
Comment thread
greptile-apps[bot] marked this conversation as resolved.
const paragraphs = normalized.split(/\n{2,}/)
const htmlParagraphs = paragraphs.map((paragraph) => {
const escaped = escapeHtml(paragraph).replace(/\n/g, '<br>')
return `<p>${escaped}</p>`
})
return `<!DOCTYPE html><html><body>${htmlParagraphs.join('')}</body></html>`
const escaped = escapeHtml(normalized).replace(/\n/g, '<br>')
return `<!DOCTYPE html><html><body>${escaped}</body></html>`
}

/**
Expand Down
Loading