MS Graph Webhook report new email that doesn't exist - microsoft-graph-api

I have a multi-tenant application that has webhooks setup to monitor for new emails arriving in the SentItems folder. Sometimes I get a notification for a random tenant, that a new email has arrived, but I can't find it in the user's mailbox through Microsoft Graph or EWS.
I get a notification that this ID has arrived:
AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK3wAAAA==
but the only messages in the SentItems folder are these:
[0]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK6wAAAA=="
[1]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK6gAAAA=="
[2]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK6QAAAA=="
[3]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK6AAAAA=="
[4]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK5wAAAA=="
[5]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK5AAAAA=="
[6]: "AAMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAAAAAAnaThn6c3YR6wA5CaaALt2BwD45xsfmmj8TKVOa3R-3Ss0AAAAAAEJAAD45xsfmmj8TKVOa3R-3Ss0AAA9xTdMAAA="
[7]: "AAMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAAAAAAnaThn6c3YR6wA5CaaALt2BwD45xsfmmj8TKVOa3R-3Ss0AAAAAAEJAAD45xsfmmj8TKVOa3R-3Ss0AAAHDRc_AAA="
[8]: "AQMkAGE1YmY5ZTM3LTdhYjYtNGU2MS05MDJkLWQzMDgxNDZlN2EwMQBGAAADJ2k4Z_nN2EesAOQmmgC7dgcA_OcbH5po-EylTmt0f90rNAAAAgEJAAAA_OcbH5po-EylTmt0f90rNAAAAQOK1wAAAA=="
and the email is not to be found anywhere in the mailbox. I actually think it's strange that two of the IDs don't match the parent folder's ID, but the rest do.
UPDATE 04/07:
Mark requested the complete notification, but I don't have it for this ID. Hovever I got a new one, where the item does not exist. The notification was part of multiple, but the one that I can't find is this one:
{
"subscriptionId":"70f45211-1096-4282-b34a-b37219ff7756",
"subscriptionExpirationDateTime":"2018-07-04T23:00:02.7089152+00:00",
"changeType":"created",
"resource":"Users/2e1b31b1-9ba8-43b0-92e2-d7e7eb740017/Messages/AAMkADZhMWJhNjQ3LTJkZGQtNGViYS05MTBlLWExYzg1YWU4YjU1OABGAAAAAAC0KduT98_pQLvg9lqbswvNBwCXszCEea-1T5Fvw2GeYIEvAAAAAAEJAACXszCEea-1T5Fvw2GeYIEvAAAAH3cQAAA=",
"resourceData":{
"#odata.type":"#Microsoft.Graph.Message",
"#odata.id":"Users/2e1b31b1-9ba8-43b0-92e2-d7e7eb740017/Messages/AAMkADZhMWJhNjQ3LTJkZGQtNGViYS05MTBlLWExYzg1YWU4YjU1OABGAAAAAAC0KduT98_pQLvg9lqbswvNBwCXszCEea-1T5Fvw2GeYIEvAAAAAAEJAACXszCEea-1T5Fvw2GeYIEvAAAAH3cQAAA=",
"#odata.etag":"W/\"CQAAABYAAACXszCEea/1T5Fvw2GeYIEvAABTkl6J\"",
"id":"AAMkADZhMWJhNjQ3LTJkZGQtNGViYS05MTBlLWExYzg1YWU4YjU1OABGAAAAAAC0KduT98_pQLvg9lqbswvNBwCXszCEea-1T5Fvw2GeYIEvAAAAAAEJAACXszCEea-1T5Fvw2GeYIEvAAAAH3cQAAA="
},
"clientState":"e698cb6b-03f6-4ecb-847d-aa142a21176d"
},
UPDATE 05-07:
Another one:
{
"subscriptionId":"3f7f0518-1e1c-4126-b046-ead9251692e8",
"subscriptionExpirationDateTime":"2018-07-06T19:00:11.8955691+00:00",
"changeType":"created",
"resource":"Users/dcfcac62-511b-425c-93ad-e7f786f67f90/Messages/AAMkADdjMzk2ZmE5LWFhZTgtNDY4MC04NTQ3LWQ1NTc1N2FhYWU5OQBGAAAAAADHkc19ugpQQYziYaUQfoyOBwB4OcB73fiVTK3E3hTiQwPfAAAAAAEJAAB4OcB73fiVTK3E3hTiQwPfAAMSo0tHAAA=",
"resourceData":{
"#odata.type":"#Microsoft.Graph.Message",
"#odata.id":"Users/dcfcac62-511b-425c-93ad-e7f786f67f90/Messages/AAMkADdjMzk2ZmE5LWFhZTgtNDY4MC04NTQ3LWQ1NTc1N2FhYWU5OQBGAAAAAADHkc19ugpQQYziYaUQfoyOBwB4OcB73fiVTK3E3hTiQwPfAAAAAAEJAAB4OcB73fiVTK3E3hTiQwPfAAMSo0tHAAA=",
"#odata.etag":"W/\"CQAAABYAAAB4OcB73fiVTK3E3hTiQwPfAAMTQCkA\"",
"id":"AAMkADdjMzk2ZmE5LWFhZTgtNDY4MC04NTQ3LWQ1NTc1N2FhYWU5OQBGAAAAAADHkc19ugpQQYziYaUQfoyOBwB4OcB73fiVTK3E3hTiQwPfAAAAAAEJAAB4OcB73fiVTK3E3hTiQwPfAAMSo0tHAAA="
},
"clientState":"59f393b1-6200-4c4e-9ce3-7d70a009359c"
}

It's seems you were right Marc. It was due to messages being moved from the sentItems folder. The user archived the email manually in my system, and moved the email to another folder, to indicate that it was archived. Strange behavior :)

Related

Send message to self-Chat in Microsoft Teams using Graph API

I'm trying to send a message to my self-Chat in Microsoft Teams through a Graph API call but can't find the ID of this specific chat. For the record, this type of chat was introduced to Teams in June, 2022.
By reading the Graph API documentation, it's possible to list all chats available for a specific user using the following API call (in this case, myself):
[GET] https://graph.microsoft.com/beta/me/chats/
Yet, I can't seem to find my self-chat in there. The chat itself is already created since I wrote messages in it but it doesn't appear in the call response.
I've tried to filter the results by most recent results, by filtering on my own name or by filtering by ChatType, but it was still missing.
Is anyone aware of a way to get the ID of a user self-chat in Microsoft Teams?
Thanks!
Self chat is a special kind, You can use this endpoint to communicate with it:
https://graph.microsoft.com/v1.0/me/chats/48:notes/messages
Hope that helps :)
Answering harrywyn's question regarding the pop up notification, you can set it as unread the same as any chat like this:
EndPoint = f'https://graph.microsoft.com/v1.0/chats/48:notes/markChatUnreadForUser'
update_chat = {
"user": {
"id" : uid,
"tenantId": TENANT_ID
}
}
resp = requests.post(EndPoint, headers=headers, verify=False, json=update_chat)

Microsoft Graph returning Resource Not Found

I've registered an app in Azure AD and given it API permissions(both Application and delegated) to read all AD groups (Group.Read.All, also Directory.Read.All etc). Using this app I am using Graph Service Client to make a call to get user's AD groups.
public async Task<IEnumerable<GroupInfo>> GetAllGroupsOfUser(string mail)
{
IList<GroupInfo> result = new List<GroupInfo>();
IUserMemberOfCollectionWithReferencesPage memberOfGroups = await _graphServiceClient.Users[mail].MemberOf.Request().GetAsync();
.......... More code ........
}
It works fine for most of the users email but for few emails, which are present in the active directory, I'm getting the following exception
Code: Request_ResourceNotFound Message: Resource 'someuser#somedomain.co' does not exist or one of its queried reference-property objects are not present.
Your error is not that you lack certain permissions, and it has nothing to do with which api testing tool you are using. Your error is very simple. As your error message says, it is that you entered the wrong user email.
Your error message has clearly stated that there is no'someuser#somedomain.co' email, because this is not a correct email, it should be .com instead of .co.
So you must make sure that you enter the correct email without special characters or spaces.
This is my test result:
1.
2.

Multiple Immutable Id's for same mail message?

I am writing an Office Outlook add-in that has a React frontend and a dotnet core backend. I have set up a subscription using the Graph API to receive notifications when a new email appears on the SentItems folder. I want to correlate the email from the notification with information I have stored in a database.
Unfortunately the item id changes when the email is sent and moves from the Drafts folder into SentItems so it isn't useful for matching.
There is a new ImmutableId that doesn't change when the email is moved between folders. I've been unable to get the Office.js lib to generate an ImmutableId but there is a translateExchangeIds method that when given an email item id will return an immutable id.
// convert to immutable
var translateRequest = new {
inputIds = new string [] { mailMessage.ItemId },
targetIdType = "restImmutableEntryId",
sourceIdType = "restId"
};
var immutableResponse = await graphClient.PostAsJsonAsync("me/translateExchangeIds", translateRequest);
var immutableId = await immutableResponse.Content.ReadAsStringAsync();
I can use that immutable id to retrieve the email message using the Graph request:
await graphClient.GetAsync($"Users/cccccccc-dddd-eeee-ffff-ba0c52e56d99/Messages/AAkALgAAAAAAHYQDEapmEc2byACqAC-EWg0AQ-irLc2NFESKcGAhz1k_GBBDB5JMOwAA/
But the immutable id that is returned with the subscription notification is a different immutable id for the same message. So it's not possible to match the notification mail message with the message info stored in my database. So I still have to attach a custom property to the message for the sole purpose of matching the database entry with the SentItems notification.
Is there a better way to deal with this issue?
Update: my theory is the difference occurs because the immutable id is derived when the item is in different folders? When translating the item id to an immutable id, the item is still in the Drafts folder. When the subscription notification occurs, the item is in the Sent Items folder. The following responses were from queries using the different immutable id's but identify the same message - the myId GUID is a custom property attached to the message and used to correlate the notification with the message info stored in a local database.
\"id\":\"AAkALgAAAAAAHYQDEapmEc2byACqAC-EWg0AQ-irLc2NFESKcGAhz1k_GAADB4INPAAA\",...,\"myId\":\"8baa904f-cf64-437c-878c-be4f71714aee\"
\"id\":\"AAkALgAAAAAAHYQDEapmEc2byACqAC-EWg0AQ-irLc2NFESKcGAhz1k_GAADB4INLwAA\",...,\"myId\":\"8baa904f-cf64-437c-878c-be4f71714aee\"
We fixed this and now you should see the same ImmutableId for draft and sent messages. Can you try and let us know if this is working as expected?

Calendar ID in create response differs from what Graph stores

We are experiencing inconsistencies with calendar ID's.
When sending a POST to https://graph.mircrosoft.com/v1.0/me/calendars with the following payload
{ name: 'Calendar' }
We receive this reponse from which we store the id
{
:"#odata.context"=>"https://graph.microsoft.com/v1.0/$metadata#users('user%40outlook.com')/calendars/$entity",
:id=>"AQMkADAwATMwMAItMjE5ZC01YjYyLTAwAi0wMAoARgAAA1D6u4KwtRdMm1rAZoOEKvAHAMf0BP7S_89KmnrxCgze9tcAAAIBBgAAAMf0BP7S_89KmnrxCgze9tcAAAEBKdoAAAA=",
:name=>"Calendar",
:color=>"auto",
:changeKey=>"x/QE/tL7z0qaevEKDN721wAAAAAOFQ==",
:canShare=>true,
:canViewPrivateItems=>true,
:canEdit=>true,
:owner=>{:name=>"User", :address=>"user#outlook.com"}
}
When we attempt to create events into this calendar errors are being thrown as that ID does not exist. Looking into it further and making a GET request to https://graph.mircrosoft.com/v1.0/me/calendars we receive this payload (truncated for brevity)
{
:id=>"AQMkADAwATMwMAItMjE5ZC01YjYyLTAwAi0wMAoARgAAA1D6u4KwtRdMm1rAZoOEKvAHAMf0BP7S_89KmnrxCgze9tcAAAIBBgAAAMf0BP7S_89KmnrxCgze9tcAAAIjxAAAAA==",
:name=>"Calendar",
:color=>"auto",
:changeKey=>"I8E7t/aNjEqDHtJJL1UC6AAADFI=",
:canShare=>true,
:canViewPrivateItems=>true,
:canEdit=>true,
:owner=>{:name=>"User", :address=>"user#outlook.com"}}]
}
After diffing both ID's, we notice they differ. The interesting part of this is that this only happens with a handful of users and isn't an issue with most accounts. Is there a better way to keep track of specific calendars that we can continue to sync into? I'd hate to have to ping for calendars every time we'd like to fire off a CRUD action.

Does Firebase always guarantee added events in order?

I am developing messenger IOS app based on Firebase Realtime Database.
I want that all messages to be ordered based on timestamp.
There is a scenario as like below.
There are 3 clients. A, B and C.
1)
All clients register 'figure-1' listener to receive messages from others.
<figure-1>
ref.queryOrdered(byChild: "timestamp").queryStarting(atValue: startTime).observe(.childAdded, with:
{
....
// do work for the messages, print, save to storage, etc.
....
// save startTime to storage for next open.
startTime = max(timeOfSnapshot, startTime)
saveToStorage(startTime)
}
2)
Client A write message 1 to server with ServerValue.timestamp().
Client B write message 2 to server with ServerValue.timestamp().
Client C write message 3 to server with ServerValue.timestamp().
They sent messages extremely the same moment.
All clients have good speed wifi.
So, finally. Server data saved like 'figure-2'
<figure-2>
text : "Message 1", timestamp : 100000001
text : "Message 2", timestamp : 100000002
text : "Message 3", timestamp : 100000003
As my listener's code, i keep messages on storage and next listening timestamp for preventing downloading duplicated messages.
In this case.
Does Firebase always guarantee to trigger callback in order as like below?
Message 1
Message 2
Message 3
If it is not guaranteed, my strategy is absolutely wrong.
For example, some client received messages as like below.
Message 3 // the highest timestamp.
// app crash or out of storage
Message 1
Message 2
The client do not have chance to get message 1, 2 anymore.
I think if there are some nodes already, Firebase might trigger in order for those. Because, that is role of 'queryOrdered' functionality.
However, there are no node before register the listener and added new nodes additionally after then. What is will happen?
I suppose Firebase might send 3 packets to clients. (No matter how quickly the message arrives, Firebase has to send it out as soon as it arrives.)
Packet1 for message1
Packet2 for message2
Packet3 for message3
ClientA fail to receive for packet 1,2
ClientA success to receive for packet 3
Firebase re-send packet 1,2 again.
ClientA success to receive for packet 1,2
Eventually, all datas are consistent. But ordering is corrupted.
Does Firebase guarantee to occur events in order?
I have searched stack overflow and google and read official documents many times. However, i could not find the clear answer.
I have almost spent one week for this. Please give me piece of advice.
The order in which the data for a query is returns is consistent, and determined by the server. So all clients are guaranteed to get the results in the same order.
For new data that is sent to the database after the listeners are attached, all remote clients will receive it in the same order. The local client will see events for it's write operation right away though, before the data even reaches the database server.
In figure 2, it is actually quite simple: since each node has a unique timestamp, and they will be returned in the order of that timestamp. But even if they'd have the same timestamp, they'd be returned in the same order (timestamp first, then key) for each client.

Resources