-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix(outlook): actually send emails instead of creating drafts #1239
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9c9dc47
85c90d4
a41a578
d9e05f4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,11 +30,13 @@ interface OutlookMessageRequest { | |
| isDraft?: boolean; | ||
| } | ||
|
|
||
| type SentEmailResult = Pick<Message, "id" | "conversationId">; | ||
|
|
||
| export async function sendEmailWithHtml( | ||
| client: OutlookClient, | ||
| body: SendEmailBody, | ||
| logger: Logger, | ||
| ) { | ||
| ): Promise<SentEmailResult> { | ||
| 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, | ||
| }; | ||
|
Comment on lines
+64
to
+80
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new flow queries SentItems immediately after sending, but that folder is eventually consistent—without retries, we might return empty IDs to clients. Could we add polling with exponential backoff here? Prompt for AI Agents: Finding type: Heads up! Your free trial ends in 3 days.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Commit d9e05f4 addressed this comment by removing the problematic SentItems query entirely rather than adding polling with exponential backoff. The code now returns an empty id immediately and preserves only the conversationId, eliminating the eventual consistency issue altogether. The comments explain that Graph API doesn't support the necessary filtering and that conversationId is sufficient for reply tracking.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed the SentItems query entirely since Graph doesn't support filtering by internetMessageHeaders. Now returning empty messageId with preserved conversationId (which is what matters for reply tracking).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it, that makes sense given Graph’s limitations—returning an empty messageId while preserving conversationId for reply tracking is a good adjustment. I’ll save this behavior to memory after the PR is merged. |
||
| } | ||
|
|
||
| export async function sendEmailWithPlainText( | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.