SurveyMonkey v3 API: What gets put in the contacts/bulk "invalid" collection? - surveymonkey

What has to be wrong with a contact submitted to the contacts/bulk operation (described here) for it to be put in the invalids collection shown in the response?
When I exceed the field lengths cited here, SurveyMonkey just truncates the field and returns it in the successful collection. If I put an invalid character in the email address, it just returns a 500 error.

The invalids key is for invalid emails, basically emails that don't match some email validation regex.
So if you POST something like
{
"contacts": [{
"first_name": "Test",
"last_name": "Example",
"email": "notanemail"
}]
}
That should go into the invalids list. If invalid characters are causing a 500, that's something I would report as a bug to SurveyMonkey's API support.

Related

How do I get a usable email message reference id from headers to use in a Microsoft Graph query?

I am trying to use the references message ID in email headers of a forwarded email in Office 365 to then find the original email that has that message ID.
The references ID in the forwarded email's headers would show something like what's shown below. Note I'm obtaining these headers from Microsoft Graph by adding &$select=internetMessageHeaders to my query using sender/subject to find the forwarded email.
{
"name": "References",
"value": "<CAOLK2SAEzvs=-6Rs5cTbgORNivQVK2AvMJDJT8o+ghx-XhCn7w#mail.gmail.com>"
}
However, if I take this and use it in a query like https://graph.microsoft.com/v1.0/me/messages?$filter=internetMessageId eq '<CAOLK2SAEzvs=-6Rs5cTbgORNivQVK2AvMJDJT8o+ghx-XhCn7w#mail.gmail.com>'
I do not receive any results.
If I hunt down the original email in Microsoft Graph using sender and subject, I see the following for the internetMessageId field for the original email:
{
"name": "Message-ID",
"value": "<CAOLK2SC6s9Me05kYRqeuEHKK8DrQbXx34ScT0AzGOFFLMdRapg#mail.gmail.com>"
}
Does anyone have any ideas on what Office 365 or Microsoft Graph is doing to change CAOLK2SAEzvs=-6Rs5cTbgORNivQVK2AvMJDJT8o+ghx-XhCn7w into CAOLK2SC6s9Me05kYRqeuEHKK8DrQbXx34ScT0AzGOFFLMdRapg? It looks like some sort of encoding, but I haven't been able to reproduce it.
Ultimately I would like to be able to transform what I'm getting in the references ID header such that I can turn around and use that ID to find the original email using Microsoft Graph.
The id is a hashed value that, among other things, includes the path/folder that the message resides in. So if you, for example, move a message (say from Inbox to Archive) then you should expect the id to change.
For tracking a message, regardless of its location, you should use the internetMessageId ($select=internetMessageId) property instead.
I discovered the issue. In my test message-ID I have the characters = and +
These characters must be URL encoded to %3D and %2B before being used in the $filter query. When they are URL encoded, I am able to find the original email using MS Graph.
In Microsoft Graph v1.0 and beta, you can obtain "immutable ids" by sending an additional HTTP header in your API requests:
Prefer: IdType="ImmutableId"
I've put immutable in italics as this is the term Microsoft uses. Be aware of the following caveats, the ID will change if:
The user moves the item to an archive mailbox;
The user exports the item (to a PST, as an MSG file, etc.) and re-imports it into their mailbox;
The user creates a draft which they later send;
You can also convert existing ids to immutable ones by the following request:
POST https://graph.microsoft.com/beta/me/translateExchangeIds
{
"inputIds" :
[
"AQMkAGM2…"
],
"targetIdType" : "restImmutableEntryId",
"sourceIdType" : "restId"
}
Which will give you the response:
HTTP 200 OK
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#Collection(microsoft.graph.convertIdResult)",
"value": [
{
"targetId": "AAkALgAA...",
"sourceId": "AQMkAGM2..."
}
]
}

Microsoft Graph - Retrieving invalid contact email address

If an Office 365 contact's email address is invalid (ex: user#example?com), how do I retrieve the the email address with Microsoft Graph?
I've tried /contacts and /contacts/{id}. The first returns an empty address:
"emailAddresses": [
{
"name": "name",
"address": ""
}
]
and the second simply omits it:
"emailAddresses": [
{
"name": "name"
}
]
Edit: By "contact" I mean Outlook contacts accessible in the Office 365 People app, not regular Office 365 users. Sorry if my question was unclear.
I'm not sure if this would work, but perhaps give it a try.
string email = await graphClient.Users[your_users_id].Request().Select("Mail").GetAsync().Mail;
To get the answer above, I used this Get User documentation which briefly talks about Select statements. And this documentation has a list of the properties which are available to the Select statement.
Found an issue on Github that solved my problem.
Turns out an Exchange contact's (first) EmailAddress has an hidden PidLidEmail1OriginalDisplayName in addition to its address.
When you set the email address to an invalid one, the invalid address is stored in the OriginalDisplayName and its address is cleared, which is the reason the contact's email address is (Empty) in Office 365 People's contact list but the invalid address seems to still be there when you edit the contact.
PidLidEmail1OriginalDisplayName is an MAPI property. In order to obtain it, we need to use extended properties. The request should look like below but with the spaces URL-encoded to %20:
GET /me/contacts/{id}?$expand=singleValueExtendedProperties($filter=id eq 'String {00062004-0000-0000-C000-000000000046} Id 0x8084')
The response should include an additional field containing the invalid address:
"singleValueExtendedProperties": [
{
"id": "String {00062004-0000-0000-c000-000000000046} Id 0x8084",
"value": "user#example?com"
}
If the contact has multiple email addresses, use PidLidEmail2OriginalDisplayName/PidLidEmail3OriginalDisplayName for the contact's second or third email address.

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.

How to add bulk email ID's using surveymonkey api v3

In case of surveymonkey api's of version v2, 'https://api.surveymonkey.net/v2/batch/send_flow' with the body containing recepients list in an array will add all the recipients emailID's to the message simply.
But in case of version v3, is there a simple method to add all the recipients on a bulk and send the emails for all those recipients? The below flow to send the message will add only one recipients emailID or else we have to do several POST calls of "POST /collectors/{id}/messages/{id}/recipients" eachtime with a new emailID. How can we add all the emailID's into the recepients list with one api call and send message to that recipients list?
POST /surveys/{id}/collectors -> POST /collectors/{id}/messages -> POST /collectors/{id}/messages/{id}/recipients -> POST /collectors/{id}/messages/{id}/send
The only way to do it is the way you suggested in V3 right now. The only thing I will add is that there is a bulk recipient endpoint.
So you would
POST /surveys/{id}/collectors
POST /collectors/{id}/messages
POST /collectors/{id}/messages/{id}/recipients/bulk
POST /collectors/{id}/messages/{id}/send
Part of the reason for preferring to split these up is for better transaction management. For example if you call send_flow and you create a collector and a message, then error trying to add recipients for whatever reason, you'll be left with lingering collector/messages. This way you can handle what happens on each error case yourself.
SurveyMonkey is considering releasing some SDKs that have functionality like that encapsulated, as well as potentially a batch request endpoint, but as of right now that is the process for sending a message in the API.
Example use of bulk recipient endpoint:
You can add a list of contacts to your message all at once like this:
POST /collectors/{id}/messages/{id}/recipients/bulk
{
"contact_ids": ["1000", "10001"]
}
You can add all contacts from a list of Contact Lists all at once like this:
POST /collectors/{id}/messages/{id}/recipients/bulk
{
"contact_list_ids": ["2000", "20001"]
}
Or you can manually add any number of contacts by email like this:
POST /collectors/{id}/messages/{id}/recipients/bulk
{
"contacts": [{
"email": "user1#example.com",
"first_name": "User 1",
"last_name": "Testing"
},{
"email": "user2#example.com",
"first_name": "User 2",
"last_name": "Testing"
}]
}
I believe you can add from all three of those methods from one request.

"additional properties" error in Survey Monkey API call

I'm trying to use the create_flow endpoint to the Survey Monkey API. It is sending back a status 3 message with the following error:
additional properties not defined by 'properties' are not allowed in field '_data'
I'm able to do successfully use all other API endpoints and have a valid API key and durable OAuth token.
Here's an example JSON body that I'm sending to: https://api.surveymonkey.net/v2/batch/create_flow?api_key=apikeyhere
{
"survey": {
"template_id": "566",
"survey_title": "test1",
"collector": {
"type": "email",
"name": "collector1",
"recipients": [
{
"email": "email#example.com"
}
]
},
"email_message": {
"reply_email": "myemail#example.com",
"subject": "this is a test"
}
}
Note: JSON formatting here is being generated automatically using RJSONIO
Any ideas what might be causing the error? It seems like all fields are correctly named and where they're supposed to be, so I'm not sure what the problem is.
It's a bad error message unfortunately - it's a known issue. It means you are providing extra keys that are not part of the create_flow schema.
The issue here is that the "email_message" and "collector" keys have been nested inside of "survey", instead of being in the main JSON body like the "survey" key. Move them out a level and it should work.

Resources