From b6e8103df796ab9a593b2a828eba188c16f024e6 Mon Sep 17 00:00:00 2001 From: martmull Date: Wed, 23 Apr 2025 11:37:40 +0200 Subject: [PATCH] Mime encode names in email headers (#11691) # Before image # After image Fixes also Emojis encoding in Subject -> image Works with microsoft accounts image Fixes https://github.com/twentyhq/twenty/issues/9194 --- .../services/messaging-send-message.service.ts | 18 +++++++++++++----- .../utils/__tests__/mime-encode.util.spec.ts | 9 +++++++++ .../utils/mime-encode.util.ts | 3 +++ 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 packages/twenty-server/src/modules/messaging/message-import-manager/utils/__tests__/mime-encode.util.spec.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-import-manager/utils/mime-encode.util.ts diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-send-message.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-send-message.service.ts index 33414aa51..31d2525dc 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-send-message.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/services/messaging-send-message.service.ts @@ -1,13 +1,14 @@ import { Injectable } from '@nestjs/common'; import { z } from 'zod'; -import { assertUnreachable } from 'twenty-shared/utils'; +import { assertUnreachable, isDefined } from 'twenty-shared/utils'; import { ConnectedAccountProvider } from 'twenty-shared/types'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { GmailClientProvider } from 'src/modules/messaging/message-import-manager/drivers/gmail/providers/gmail-client.provider'; import { MicrosoftClientProvider } from 'src/modules/messaging/message-import-manager/drivers/microsoft/providers/microsoft-client.provider'; import { OAuth2ClientProvider } from 'src/modules/messaging/message-import-manager/drivers/gmail/providers/oauth2-client.provider'; +import { mimeEncode } from 'src/modules/messaging/message-import-manager/utils/mime-encode.util'; interface SendMessageInput { body: string; @@ -41,15 +42,22 @@ export class MessagingSendMessageService { const fromName = data.name; - const message = [ - `From: "${fromName}" <${fromEmail}>`, + const headers: string[] = []; + + if (isDefined(fromName)) { + headers.push(`From: "${mimeEncode(fromName)}" <${fromEmail}>`); + } + + headers.push( `To: ${sendMessageInput.to}`, - `Subject: ${sendMessageInput.subject}`, + `Subject: ${mimeEncode(sendMessageInput.subject)}`, 'MIME-Version: 1.0', 'Content-Type: text/plain; charset="UTF-8"', '', sendMessageInput.body, - ].join('\n'); + ); + + const message = headers.join('\n'); const encodedMessage = Buffer.from(message).toString('base64'); diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/utils/__tests__/mime-encode.util.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/__tests__/mime-encode.util.spec.ts new file mode 100644 index 000000000..390a14647 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/__tests__/mime-encode.util.spec.ts @@ -0,0 +1,9 @@ +import { mimeEncode } from 'src/modules/messaging/message-import-manager/utils/mime-encode.util'; + +describe('mimeEncode', () => { + it('should encode properly', () => { + expect(mimeEncode('test-accents-é-è-ê-ë')).toBe( + '=?UTF-8?B?dGVzdC1hY2NlbnRzLcOpLcOoLcOqLcOr?=', + ); + }); +}); diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/utils/mime-encode.util.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/mime-encode.util.ts new file mode 100644 index 000000000..677f87bbb --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/mime-encode.util.ts @@ -0,0 +1,3 @@ +export const mimeEncode = (raw: string) => { + return `=?UTF-8?B?${Buffer.from(raw).toString('base64')}?=`; +};