diff --git a/.cursor/rules/notes.mdc b/.cursor/rules/notes.mdc index 3ed52805ed..a15ec0f9c0 100644 --- a/.cursor/rules/notes.mdc +++ b/.cursor/rules/notes.mdc @@ -4,7 +4,7 @@ globs: alwaysApply: true --- - Do not try and run the project via `dev` or `build` command unless I explicitly ask you to. -- Prefer self-documenting code over comments; use descriptive variable and function names instead of explaining intent with comments. +- Prefer self-documenting code over comments; use descriptive variable and function names instead of explaining intent with comments. Never add comments that just describe what the code does - code should explain itself. Only add comments for "why" not "what". - Add helper functions to the bottom of files, not the top! - All imports go at the top of files, no mid-file dynamic imports. - Co-locate test files next to source files (e.g., `utils/example.test.ts`). Only E2E and AI tests go in `__tests__/`. diff --git a/apps/web/CLAUDE.md b/apps/web/CLAUDE.md index a0076ff2cd..ff36992fa3 100644 --- a/apps/web/CLAUDE.md +++ b/apps/web/CLAUDE.md @@ -20,7 +20,7 @@ - Use proper error handling with try/catch blocks - Format code with Prettier - Consult .cursor/rules for environment variable management -- Prefer self-documenting code over comments; use descriptive variable and function names instead of explaining intent with comments. +- Prefer self-documenting code over comments; use descriptive variable and function names instead of explaining intent with comments. Never add comments that just describe what the code does - code should explain itself. Only add comments for "why" not "what". - Add helper functions to the bottom of files, not the top! - All imports go at the top of files, no mid-file dynamic imports. - Co-locate test files next to source files (e.g., `utils/example.test.ts`). Only E2E and AI tests go in `__tests__/`. diff --git a/apps/web/utils/outlook/mail.ts b/apps/web/utils/outlook/mail.ts index fbd1858143..5b7d8f2bfe 100644 --- a/apps/web/utils/outlook/mail.ts +++ b/apps/web/utils/outlook/mail.ts @@ -30,11 +30,13 @@ interface OutlookMessageRequest { isDraft?: boolean; } +type SentEmailResult = Pick; + export async function sendEmailWithHtml( client: OutlookClient, body: SendEmailBody, logger: Logger, -) { +): Promise { ensureEmailSendingEnabled(); const message: OutlookMessageRequest = { @@ -59,11 +61,23 @@ export async function sendEmailWithHtml( message.conversationId = body.replyToEmail.threadId; } - const result: Message = await withOutlookRetry( - () => client.getClient().api("/me/messages").post(message), + await withOutlookRetry( + () => + client.getClient().api("/me/sendMail").post({ + message, + saveToSentItems: true, + }), logger, ); - return result; + + // /me/sendMail returns 202 with no body, so we can't get the sent message ID. + // Graph doesn't support filtering by internetMessageHeaders, so we can't query for it. + // conversationId (threadId) is preserved - that's what matters for reply tracking. + // Empty id means auto-expand won't work in EmailThread, but we don't show that for Outlook. + return { + id: "", + conversationId: message.conversationId, + }; } export async function sendEmailWithPlainText(