Can Microsoft Graph filter out Junk Email? - microsoft-graph-api

I am using https://graph.microsoft.com/v1.0/me/messages?$filter=isRead eq false in Microsoft Graph Explorer to return a list of my unread emails. My goal is to have a simple HUD on my website that shows a notification to any logged-in user how many unread messages they have waiting for them in Outlook.
The problem is this returns all unread emails in my Junk Email folder in addition to my legitimate unread emails. I would like to filter out Junk Email, but graph doesn't give me a way to systemically accomplish this for all users.
All emails have a parentFolderID, and Graph says the email in my Junk email folder has "parentFolderId": "AQMkAGFjOGFkNWM2LTcxMjQtND...". This means I could filter out my own Junk Email, but that doesn't help the rest of my users since they would each have a unique parentFolderID for their Junk Email.
I could create a rule for myself that marks Junk Email as read, but I can't expect my users to do something like that.
Any thoughts on how I can filter out Junk Email for all users?

I do not think a single query to the Graph API will solve this problem, but you can do multiple calls with a little bit of logic to solve this.
List all mailFolders
https://graph.microsoft.com/v1.0/me/mailFolders
Find the 'Junk Email' folder
var json = `
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('48d31887-5fad-4d73-a9f5-3c356e68a038')/mailFolders",
"value": [
{
"id": "AAMkAGVmMDEzMTM4LTZmYWUtNDdkNC1hMDZiLTU1OGY5OTZhYmY4OAAuAAAAAAAiQ8W967B7TKBjgx9rVEURAQAiIsqMbYjsT5e-T7KzowPTAAAAAAEkAAA=",
"displayName": "Junk Email",
"parentFolderId": "AAMkAGVmMDEzMTM4LTZmYWUtNDdkNC1hMDZiLTU1OGY5OTZhYmY4OAAuAAAAAAAiQ8W967B7TKBjgx9rVEURAQAiIsqMbYjsT5e-T7KzowPTAAAAAAEIAAA=",
"childFolderCount": 0,
"unreadItemCount": 0,
"totalItemCount": 0
}
]
}`
var obj = JSON.parse(json)
for(var folder in obj.value)
{
if (obj.value[folder].displayName == 'Junk Email')
{
document.write(obj.value[folder].id)
break
}
}
Filter out messages from that folder as you described, uniquely per user.

To get a count of unread mail from ONLY my inbox, I ended up using:
https://graph.microsoft.com/v1.0/me/mailFolders?$filter=displayName eq 'Inbox'
which returns:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('ed313cf6-f369-45c6-94b2-48bbb3589788')/mailFolders",
"value": [
{
"id": "AAMkAGFjOGFkNWM2LTcxMjQtNDQ4My1iNjBlLTVhZmNiNTA3ZTcwNQAuAAAAAAAcAJPfHQ_aQputXsbIt-bZAQC5oqQhrW6CRI4cZpo9l5YaAA7BDDZpAAA=",
"displayName": "Inbox",
"parentFolderId": "AAMkAGFjOGFkNWM2LTcxMjQtNDQ4My1iNjBlLTVhZmNiNTA3ZTcwNQAuAAAAAAAcAJPfHQ_aQputXsbIt-bZAQC5oqQhrW6CRI4cZpo9l5YaAA7BDDZmAAA=",
"childFolderCount": 14,
"unreadItemCount": 1,
"totalItemCount": 25
}
]
}
The data I'm after is in "unreadItemCount". Thanks for Shawn Tabrizi for setting me on the correct path with /me/mailFolders.
Please note that you currently cannot filter /me/messages by parentFolderId, so you would need to run custom filtering code like Shawn Tabrizi had suggested if you want to get any mail content from /me/messages.
{
"error": {
"code": "ErrorInvalidProperty",
"message": "The property 'ParentFolderId' does not support filtering.",
"innerError": {
"request-id": "526bafdd-d8ac-47f2-be1f-656b3b93da35",
"date": "2017-10-11T15:45:33"
}
}
}

You can run two separate queries to get all new emails in the inbox folder and their content data.
First run:
https://graph.microsoft.com/v1.0/me/mailFolders?$filter=displayName eq 'Inbox'
to get details on the Inbox folder only.
$filter=displayName eq 'Inbox' filters folders with displayName equal to (eq) 'Inbox'
This returns:
`{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('9285d2c9-f210-45e1-b78e-d74ba3d5e186')/mailFolders",
"value": [
{
"id": "AAMkADRlM2I0YmM5LWI2MTUtNDgzZC04N2M0LWJmMWU1MTFjMDBiYwAuAAAAAAB1tij3RiDhRab9QpP_GQhpAQCTj9cyjezTSYJYfMfg3p5fAAAAAAEMAAA=",
"displayName": "Inbox",
"parentFolderId": "AAMkADRlM2I0YmM5LWI2MTUtNDgzZC04N2M0LWJmMWU1MTFjMDBiYwAuAAAAAAB1tij3RiDhRab9QpP_GQhpAQCTj9cyjezTSYJYfMfg3p5fAAAAAAEIAAA=",
"childFolderCount": 0,
"unreadItemCount": 1,
"totalItemCount": 0
}
]
}`
To get the content data you need the id value to form part of the second query.
Add &$count=true to the end to get the count of unread emails in Inbox:
Second query:
https://graph.microsoft.com/v1.0/me/mailFolders/{ Inbox id goes here }/messages?$filter=isRead eq false&$count=true
This filters the unread (isRead eq false) from the Inbox folder and returns something like:
`{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('9285d2c9-f210-45e1-b78e-d74ba3d5e186')/mailFolders('AAMkADRlM2I0YmM5LWI2MTUtNDgzZC04N2M0LWJmMWU1MTFjMDBiYwAuAAAAAAB1tij3RiDhRab9QpP_GQhpAQCTj9cyjezTSYJYfMfg3p5fAAAAAAEMAAA%3D')/messages",
"#odata.count": 1,
"value": [
{
"#odata.etag": "W/\"CQAAABYAAACTj9cyjezTSYJYfMfg3p5fAACWjeF5\"",
"receivedDateTime": "2018-01-29T11:32:40Z",
"sentDateTime": "2018-01-29T11:32:37Z",
"subject": "New Mail",
"bodyPreview": "New email body for email preview",
"isRead": false,
"isDraft": false,
-- More properties are returned. Shortened response for brevity --
`
Email content data are acceessed via value.
Count of unread emails in Inbox folder is accessed via odata.count.
See Microsof Graph - List messages in a specified folder in the mailbox

Related

Experiencing "404-unknown error" when attempting to lis team channel tabs with Graph

For a given team I want to choose a specific channel and list the tabs for the channel.
Using x to censor IDs:
I am able to use the following HTTP GET call to view the group:
https://graph.microsoft.com/v1.0/groups/193cexxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
And the following allows me to view the specific channel:
https://graph.microsoft.com/v1.0/groups/193cexxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
/team/channels/19:xxxxxxxxxxxxxxxxxxxxx#thread.skype/
The result looks like this:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#groups('193cee12-xxxx-xxxx-xxxx-a8022fe6754c')/team/channels/$entity",
"id": "19:xxxxxxxxxxxxxxxxxx#thread.skype",
"displayName": "General",
"description": "Test ",
"email": "",
"webUrl": "https://teams.microsoft.com/l/channel/19%xxxxxxxxxxxxxxxxxxx%40thread.skype/General?groupId=193cee12-xxxx-xxxx-xxxx-a8022fe6754c&tenantId=d02b4c26-xxxx-xxxx-xxxx-0e19a90257d6"
}
The error occurs when I try to access any properties of the channel:
https://graph.microsoft.com/v1.0/groups/193cexxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
/team/channels/19:xxxxxxxxxxxxxxxxxxxxx#thread.skype/tabs
The error looks like this:
{
"error": {
"code": "UnknownError",
"message": "",
"innerError": {
"request-id": "1b1040df-xxxx-xxxx-xxxx-04c7952674ba",
"date": "2019-11-04T11:xx:xx"
}
}
}
I am a group Owner.
There is no error message so it's hard to figure out what goes wrong. Has anybody else experienced this?
To get the information about the channels, you need to use the teams segment instead of the groups segment.
\/ -- 'teams' here, not 'groups'
/v1.0/teams/193cexxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/channels/19:xxxxxxxxxxxxxxxxxxxxx#thread.skype/tabs
https://learn.microsoft.com/en-us/graph/api/teamstab-list?view=graph-rest-1.0

Microsoft Graph: insert a message (mail) to user inbox

I have a Microsoft application (with Mail.Read/Write permissions) and I need to insert a mail (.eml extension file) to a user inbox.
Is that possible? I know that with Gsuite that can be done using the 'insert' API and was wondering if something similar exist with Graph API.
I'm not talking about sending new mail to the user or about inserting an attachment to existing message in the user inbox, but to insert completely new email to his inbox (without having to go through SPF or whatever checks that take place before mails usually get into end users inboxes).
Looking into Mail section under Graph API documentation wasn't so helpful.
If that not possible, perhaps there is a workaround?
EDIT: seems like the best option is to use "send mail" API and specify "saveToSentItems": False.. the only issue here as that my application will need to request the Mail.Send permission as well..
Thanks
You don't need to use the send mail api as all your doing is creating an Item in the Mailbox. If you want it to appear as a Sent Mail (rather then a draft) you do need to set the PidTagMessageFlags extended property (the same as you would in EWS https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-import-items-by-using-ews-in-exchange). Also if you want it to appear if its been sent in the past there are few additional extended properties you need to set. eg
{
"Subject": "test1234",
"Sender": {
"EmailAddress": {
"Name": "blah",
"Address": "blah#blah.com"
}
},
"Body": {
"ContentType": "HTML",
"Content": "123Body"
},
"SingleValueExtendedProperties": [
{
"PropertyId": "Integer 0x0E07",
"Value": "1"
},
{
"PropertyId": "SystemTime 0x0039",
"Value": "2019-06-12T10:10:47.2048+10:00"
},
{
"PropertyId": "SystemTime 0x0E06",
"Value": "2019-06-12T10:10:47.2048+10:00"
}
]
}

Get the message ID in the survey monkey response

I am using survey monkey v3 API's to send survey emails. While sending a survey email from one collector, I am sending two different survey messages for the same recipient. However, while collecting the survey responses from survey monkey using the api "/surveys/{id}/responses/bulk", I couldn't find the messageID in it. So I how can I find which response belong to which message of the collector then? Is there a different API that I have to use?
What's the use case for tracking the specific message? You have the recipient_id, and first/last/email fields.
You can get recipient details at /collectors/{collector_id}/recipients/{recipient_id}. There's no way (as far as I can tell) to query for this other than searching your messages with /collectors/{collector_id}/messages/{message_id}/recipients
Generally speaking, when you add recipients to a message, they are shared with the collector. Which specific message was responded to is not really tracked, the tracking ID is the recipient_id with respect to the collector.
If you are interested in message stats (ex. which message gets a better response rate) you can use the message stats endpoint.
With regards to having a different message for say different products, unfortunately the message ID is not tied to a response, but two options are:
1) Use a different collector for each product (not ideal if there is a lot)
2) Use extra fields on the recipient (see example):
Example:
POST /v3/collectors/<collector_id>/messages/<message_id1>/recipients
{
"first_name": "Test",
"last_name": "Tester",
"email": "test#example.com",
"extra_fields": {
"product": "shoes"
}
}
POST /v3/collectors/<collector_id>/messages/<message_id2>/recipients
{
"first_name": "Test",
"last_name": "Tester",
"email": "test#example.com",
"extra_fields": {
"product": "shirts"
}
}
Then when you fetch the responses, you'll get that information in metadata, example:
{
"id": "<response_id>",
"recipient_id": "<recipient_id>",
"collector_id": "<collector_id>",
...
"metadata": {
"contact": {
"product": {
"type": "string",
"value": "shoes"
},
"email": {
"type": "string",
"value": "test#example.com"
}
}
}
}
One thing to watch out for is that the extra fields from the contact do not currently show up in the /responses/bulk endpoint, only individual responses/<id> endpoint. Also with extra fields you can't filter responses where product=shoes or whatnot. Those are some limitations with the current API - but hopefully it can at least be helpful for now.

Unable to filter messages by recipient in Microsoft Graph Api. One or more invalid nodes

I am trying to get a list of messages that are filtered by recipient from Microsoft Graph API. The url I am using for the request is:
https://graph.microsoft.com/beta/me/messages?$filter=toRecipients/any(r: r/emailAddress/address eq '[Email Address]')
But I am getting this is the response:
{
"error": {
"code": "ErrorInvalidUrlQueryFilter",
"message": "The query filter contains one or more invalid nodes.",
"innerError": {
"request-id": "7db712c3-e337-49d9-aa8d-4a5d350d8480",
"date": "2016-09-28T16:58:34"
}
}
}
A successful request should look like this (with a lot more data that I have omitted).
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#users('99999999-9999-9999-9999-999999999999')/messages",
"#odata.nextLink": "https://graph.microsoft.com/beta/me/messages?$skip=10",
"value": [
{
"toRecipients": [
{
"emailAddress": {
"name": "[Name]",
"address": "[Email Address]"
}
}
],
}
]
}
The request works if I remove the filter, and I am able to perform requests with simpler filters.
Is there a problem with my URL, or is there another way to make the request?
Another way to make the request might be to not use filter and use search instead, depending on exactly what you want (and you may have already tried this):
https://graph.microsoft.com/beta/me/messages?$search="to:[Email Address]"
After several hours looking for the solution, I found in the office365 documentation that the property toRecipients is not filterable:
https://msdn.microsoft.com/en-us/office/office365/api/complex-types-for-mail-contacts-calendar#MessageResource
I guess that it's the same in the graph api. So the only solution is using search.

Set Message-Id with Mandrill for bulk emails

I am sending emails to lists of contacts based on templates using Mandrill. I would like to track if the contacts have replied to my email and, to do so, I would like to check whether the Message-Id of my sent emails appears in the In-Reply-To header field of new messages.
The problem is that I have to generate and set the Message-Id manually since Mandrill only gives me their internal _id. However, since I am sending emails to various contacts at the same time, I set preserve_recipients to false. But then I can only set one Message-Id, which will therefore become not globally unique.
Here is an example JSON that I'm sending:
{
"from_email": "itsme#email.com",
"from_name": "Its Me",
"headers": {"Message-Id": ["<20150528161426.4265.93582#email.com>"]},
"subject": "Thesubject",
"text": "Thebody",
"to": [
{
"email": "john#email.com",
"name": "John",
"type": "to"
},
{
"email": "patrick#email.com",
"name": "Patrick",
"type": "to"
}
],
"preserve_recipients": false
}
In this case, two messages will be sent, but they'll have the same Message-Id. If I don't set it, Mandrill will automatically assign one, but then I can't retrieve it.
Any idea what I could do ? Maybe my whole approach is incorrect...
I ended up looping over all the recipients and generating a new Message-Id at each iteration and send one email at a time. Probably not optimal since I'm not using Mandrill bulk capability, but at least now I can store the email id.
import email
import mandrill
mandrill_client = mandrill.Mandrill('YOUR_MANDRILL_KEY')
for recipient in recipients:
# Generate RFC 2822-compliant Message-ID header
message_id = email.Utils.make_msgid()
m = {
"headers": {"Message-Id": [message_id],
"from_email": "itsme#email.com",
"from_name": "Its Me",
"subject": "The subject",
"text": "The body",
"to": [{"email": recipient["email"],
"name": recipient["name"],
"type": "to"}],
"track_clicks": True,
"track_opens": True
}
result = mandrill_client.messages.send(message=m)
From mandrill documentation you can retrieve the _id from the return value of the message.

Resources