Repository navigation
ACI0106595: Graph mail pull notifications dispatch @removed entries as onCreate/onModify - #121
Open
e-marchand wants to merge 1 commit into
Open
e-marchand wants to merge 1 commit into
e-marchand wants to merge 1 commit into
Conversation
e-marchand
force-pushed
the
erm/fix/ACI0106595
branch
from
October 13, 2026 17:39
2a6a2fd to
d4f5efa
Compare
…lta streams Microsoft Graph returns @removed entries (deleted or moved messages) and read/unread changes on every changeType-filtered message delta stream, not only on changeType=deleted. Each entry was labelled with its stream type, so a deleted mail could be dispatched to onCreate and onModify as well as onDelete. - _pollDeltaForChangeType: an entry with @removed is reported as "deleted" whatever stream returned it - _pollDeltaUsingChangeTypeStreams: merge the streams, report an item deleted during the poll only as "deleted", drop duplicate (id, changeType) pairs and keep only change types with a registered callback ACI0106595 [ai]
e-marchand
force-pushed
the
erm/fix/ACI0106595
branch
from
October 13, 2026 17:41
d4f5efa to
586859a
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
ACI0106595: a user running the NetkitNotification_webinar21R4 demo reports that
onDeleteis sometimes not received for Office 365 mails.onDeleteis actually received. The problem is that NetKit also sendsonCreateandonModifyfor the same deleted mail, in the same dispatch. The demo then adds back a row for that mail, so it looks as if the delete never arrived.How mail pull mode works
In pull mode (no
endPoint),GraphNotificationpolls the message delta API as three separate streams, one per change type. Each stream has its owndeltaLink:_pollDeltaForChangeTypelabelled every entry returned by a stream with that stream's change type. It never looked at the@removedannotation.What the Graph API actually returns
The
changeTypefilter is not strict. The message delta documentation says:So when a mail is deleted (or moved out of the Inbox, which is what Outlook "Delete" does), the
createdand/orupdatedstreams can also return an entry like this:{ "@odata.type": "#microsoft.graph.message", "id": "AAMkAD…", "@removed": { "reason": "deleted" } }Resulting behaviour (before this fix)
For one deleted mail, a single poll could produce:
created@removedonCreate❌updated@removedonModify❌deleted@removedonDelete✅_NotificationHelper.dispatchCallbacksalways calls them in the orderonCreate→onModify→onDelete. In the webinar demo:onCreate:getMail(id)returnsNullbecause the mail is gone, and an empty row with the same id is still pushed to the list.onModify: the first matching row is replaced.onDelete: only the first matching row is removed. The duplicate row stays visible.It's intermittent because Graph doesn't always put the
@removedentry in thecreated/updatedstreams.Fix
_pollDeltaForChangeTypeAn entry carrying
@removedis reported as"deleted", whatever stream returned it:_pollDeltaUsingChangeTypeStreamsThe three streams are merged and then cleaned up:
"deleted". Itscreated/updatedentries are dropped.(changeType, id)pairs are dropped. The same@removedentry can come back on all three streams._shouldDispatchPullChangeType. The calendarknownIdspath already does this.After the fix, the same scenario dispatches a single
onDelete.Scope / not changed
_pollDeltaUsingKnownIds) already checks@removedand needs no change. Note that the calendarView delta also returns events added/updated outside thestartDateTime/endDateTimewindow as@removed. The window is fixed whenstart()is called, from that moment to one year later.changeTypesent by Graph in each notification.createdstream are still reported asonCreate. The$select=iddelta gives no way to tell them apart from new mails. A follow-up could selectreceivedDateTimein the initial sync and downgradecreatedentries received beforestart()toupdated.isCancelled: true), not a delete. Applications should handle that inonModify. That isn't a NetKit issue.Testing
{"success":true,"errors":[]}).onCreate/onModify/onDelete, receive a mail, then delete it from Outlook. OnlyonDeleteshould be called, with that mail's id.A matching fix for the demo handlers (skip mails
getMailcan't find, remove every matching row, handleisCancelledevents) is on branchfix/notification-deletefor the webinar repo.