Add In-Reply-To to Email Workflow Node (#18641)

Co-authored-by: github-actions <github-actions@twenty.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
neo773
2026-03-22 21:19:08 +05:30
committed by GitHub
parent 7bde8a4dfa
commit 8ef32c4781
26 changed files with 259 additions and 27 deletions
@@ -1,13 +1,13 @@
import { Injectable } from '@nestjs/common';
import { z } from 'zod';
import { type MessageOutboundDriver } from 'src/modules/messaging/message-outbound-manager/interfaces/message-outbound-driver.interface';
import { OAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/services/oauth2-client-manager.service';
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { toMicrosoftRecipients } from 'src/modules/messaging/message-import-manager/utils/to-microsoft-recipients.util';
import { type SendMessageInput } from 'src/modules/messaging/message-outbound-manager/types/send-message-input.type';
import { type Client as MicrosoftGraphClient } from '@microsoft/microsoft-graph-client';
import { isDefined } from 'twenty-shared/utils';
@Injectable()
export class MicrosoftMessageOutboundService implements MessageOutboundDriver {
@@ -24,13 +24,12 @@ export class MicrosoftMessageOutboundService implements MessageOutboundDriver {
connectedAccount,
);
const message = this.composeMicrosoftMessage(sendMessageInput);
const messageId = await this.createDraftMessage(
microsoftClient,
sendMessageInput,
);
const response = await microsoftClient.api(`/me/messages`).post(message);
z.string().parse(response.id);
await microsoftClient.api(`/me/messages/${response.id}/send`).post({});
await microsoftClient.api(`/me/messages/${messageId}/send`).post({});
}
async createDraft(
@@ -42,9 +41,50 @@ export class MicrosoftMessageOutboundService implements MessageOutboundDriver {
connectedAccount,
);
await this.createDraftMessage(microsoftClient, sendMessageInput);
}
private async createDraftMessage(
microsoftClient: MicrosoftGraphClient,
sendMessageInput: SendMessageInput,
): Promise<string> {
const parentMessageGraphId = sendMessageInput.inReplyTo
? await this.findMessageByInternetMessageId(
microsoftClient,
sendMessageInput.inReplyTo,
)
: undefined;
const message = this.composeMicrosoftMessage(sendMessageInput);
await microsoftClient.api(`/me/messages`).post(message);
if (isDefined(parentMessageGraphId)) {
const reply = await microsoftClient
.api(`/me/messages/${parentMessageGraphId}/createReply`)
.post({});
await microsoftClient.api(`/me/messages/${reply.id}`).patch(message);
return reply.id;
}
const response = await microsoftClient.api('/me/messages').post(message);
return response.id;
}
private async findMessageByInternetMessageId(
microsoftClient: MicrosoftGraphClient,
internetMessageId: string,
): Promise<string | undefined> {
const encodedId = encodeURIComponent(internetMessageId);
const response = await microsoftClient
.api(
`/me/messages?$filter=internetMessageId eq '${encodedId}'&$select=id&$top=1`,
)
.get();
return response?.value?.[0]?.id;
}
private composeMicrosoftMessage(
@@ -12,4 +12,5 @@ export type SendMessageInput = {
content: Buffer;
contentType: string;
}[];
inReplyTo?: string;
};
@@ -21,5 +21,11 @@ export const toMailComposerOptions = (
})),
}
: {}),
...(sendMessageInput.inReplyTo
? {
inReplyTo: sendMessageInput.inReplyTo,
references: sendMessageInput.inReplyTo,
}
: {}),
};
};
@@ -5,4 +5,5 @@ export type WorkflowSendEmailActionInput = {
recipients: EmailRecipients;
subject?: string;
body?: string;
inReplyTo?: string;
};