Twilio: Rest API - Send Message - How to get message sid? - twilio

I want to send MMS using Twilio REST API. The message was sent successfully However, I am not able to get the unique MessageSid of the sent message.
I have already tried with $result->sid and $result->messageSid.
Current Code
$result= $client->account->messages->create(
$to, array('from' => $from,
'body' => $message,
'mediaUrl' => $mediaurl
));
if (isset($result->messageSid))
return $result->messageSid;
else
return "";
Is there anything i am doing wrong ?

Twilio developer evangelist here.
If you check the output for the first code sample on the documentation page for sending messages with Twilio then you will see that the returned JSON should have a sid property. Like this:
{
"sid": "MMc781610ec0b3400c9e0cab8e757da937",
"date_created": "Mon, 19 Oct 2015 07:07:03 +0000",
"date_updated": "Mon, 19 Oct 2015 07:07:03 +0000",
"date_sent": null,
"account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"to": "+15558675309",
"from": "+15017250604",
"body": "This is the ship that made the Kessel Run in fourteen parsecs?",
"status": "queued",
"num_segments": "1",
"num_media": "1",
"direction": "outbound-api",
"api_version": "2010-04-01",
"price": null,
"price_unit": "USD",
"error_code": null,
"error_message": null,
"uri": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/MMc781610ec0b3400c9e0cab8e757da937.json",
"subresource_uris": {
"media": "/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages/MMc781610ec0b3400c9e0cab8e757da937/Media.json"
}
}
I just used similar code to you (I didn't send a media URL) and could echo $result->sid.
$result = $client->account->messages->create(
'MY_NUMBER',
array(
'from' => 'MY_TWILIO_NUMBER',
'body' => "Hey Jenny! Good luck on the bar exam!"
)
);
echo $result->sid;
Let me know if that helps.

Related

Filter email via headers information in M365 using Microsoft Graph API

I am trying to locate emails in mailboxes that contain certain email header information. Utilizing the Microsoft Graph Explorer I am able to extract all 'internetMessageHeaders' for emails:
https://graph.microsoft.com/v1.0/me/mailfolders('Inbox')/messages?$select=internetMessageHeaders
Which results in:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('xxxxxxx-ef44-425b-b7a5-xxxxxxxxxx')/mailFolders('Inbox')/messages(internetMessageHeaders)",
"value": [
{
"#odata.etag": "W/\"xxxxxxxxxxxZXLAAASEk7/\"",
"id": "kSlaEZXLAAASFWUWAAA="
},
{
"#odata.etag": "W/\"EZXLAAAKjXG0\"",
"id": "AKj3OcAAA=",
"internetMessageHeaders": [
{
"name": "Received",
"value": "from x.x.prod.outlook.com (x:x:x:x::x) by x.x.prod.outlook.com with HTTPS; Tue, 23 Nov 2021 22:13:31 +0000"
},
{
"name": "Received",
"value": "from x.x.prod.outlook.com (x:x:x:x::x) by x.x.prod.outlook.com (x:x:x:x::x) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id x; Tue, 23 Nov 2021 22:13:28 +0000"
},
{
"name": "Received",
"value": "from x.x.prod.protection.outlook.com (x:x:x:x::x) by x.outlook.office365.com (x:x:x:x::x) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id x via Frontend Transport; Tue, 23 Nov 2021 22:13:27 +0000"
},
{
"name": "Received",
"value": "from x (x.x.x.x) by x.mail.protection.outlook.com (x.x.x.x) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id x via Frontend Transport; Tue, 23 Nov 2021 22:13:26 +0000"
},
{
"name": "Authentication-Results",
"value": "spf=pass (sender IP is x.x.x.x) smtp.mailfrom=senderdomain.com; dkim=pass (signature was verified) header.d=senderdomain.com;dmarc=pass action=none header.from=senderdomain.com;compauth=pass reason=100"
},
{
"name": "Received-SPF",
"value": "Pass (protection.outlook.com: domain of senderdomain.com designates x.x.x.x as permitted sender) receiver=protection.outlook.com; client-ip=x.x.x.x; helo=senderdomain.com;"
},
{
"name": "Date",
"value": "Tue, 23 Nov 2021 22:13:24 +0000"
},
{
"name": "DKIM-Signature",
"value": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=senderdomain.com;s=senderdomain; t=1637705605;bh=xxxxxxx;h=Date:To:From:Reply-To:Subject:From;b=[redacted]="
},
{
"name": "Subject",
"value": "Test #3"
},....
With the JSON results available, is it possible to use the $filter operation to search any of the value fields for specific conditions?
For example:
how would I search/filter the Received-SPF field for a Pass or Fail condition?
how would I search/filter any of the Received fields for a specific string?
how would I combine #1 and #2 with an AND logic in a single filter?
I have looked at the Advanced Query references, yet I am not able to find any reference on how to filter for values inside the internetMessageHeaders JSON structure.
Any thoughts or pointers on how to search the header information fields would be much appreciated.
The end-goal is to only return emails where the $filter criteria on the email header fields is met.
You could filter on filter singleValueExtendedProperties of type 0x007D which returns all internetmessageheaders as one object:
"singleValueExtendedProperties": [
{
"id": "String 0x7d",
"value": "{headerName}: {headerValue}; {headerName}: {headerValue}; ....."
}
]
If you want to use this filter:
$filter=internetMessageHeaders/any(r:r/name eq 'Received-SPF')
use this instead
$filter=singleValueExtendedProperties/any(r:r/id eq 'String 0x007D' and contains(r/value,'Received-SPF'))
If you want to avoid parsing that one long string of headers, you can add
$select=internetMessageHeaders
and you get them as one long array of key/value objects
The property InternetMessageHeaders does not support filtering.
You can try this request
GET https://graph.microsoft.com/v1.0/me/mailfolders('Inbox')/messages?$select=internetMessageHeaders&$filter=internetMessageHeaders/any(r:r/name eq 'Received-SPF')
But it will return ErrorInvalidProperty

Azure Logic App: Read telemetry data as dynamic content from IoT hub message

I'm routing telemetry messages via IoT Events and event Grid to Logic Apps using a webhook. The logic app lets you input a sample JSON message and then use dynamic content to add information to an email alert I'm sending(O365: Send an Email V2)
I can include System Properties like "iothub-connection-device-id" But when I try to pick temeletry data I get the following error:
InvalidTemplate. Unable to process template language expressions in action 'Send_an_email_(V2)' inputs at line '1' and column '1680': 'The template language expression 'items('For_each')?['data']?['body']?['windingTemp1']' cannot be evaluated because property 'windingTemp1' cannot be selected. Property selection is not supported on values of type 'String'. Please see https://aka.ms/logicexpressions for usage details.'.
When I look at the raw output of the webhook connector it shows the following message but the telemetry points are cleary not there. I'd expect to see them in the "body" property but instead there is just the string: "eyJ3aW5kaW5nVGVtcDEiOjg2LjYzOTYxNzk4MjYxODMzLCJ3aW5kaW5nVGVtcDIiOjc4LjQ1MDc4NTgwMjQyMTUyLCJ3aW5kaW5nVGVtcDMiOjg1LjUzMDYxMDY5OTQ1MzY1LCJMb2FkQSI6MjAyOS44NDgyMTg4ODYxMTEsIkxvYWRCIjoyMDQwLjgxMDk4OTg0MDMzMzgsIkxvYWRWIjoyMDA0LjYxMTkzMjMyNTQ2MTgsIk9pbFRlbXAiOjk5LjA2MjMyNjU2MTY4ODU4fQ=="
Looking for help to determine what could be causing this and how to get the telemetry data passed through correctly so that I can inculde it dynamically in the email alert.
Thanks!
{
"headers": {
"Connection": "Keep-Alive",
"Accept-Encoding": "gzip,deflate",
"Host": "prod-24.northeurope.logic.azure.com",
"aeg-subscription-name": "TEMPALERT",
"aeg-delivery-count": "1",
"aeg-data-version": "",
"aeg-metadata-version": "1",
"aeg-event-type": "Notification",
"Content-Length": "1017",
"Content-Type": "application/json; charset=utf-8"
},
"body": [
{
"id": "c767fb91-3806-324c-ec3c-XXXXXXXXXX",
"topic": "/SUBSCRIPTIONS/XXXXXXXXXXXX",
"subject": "devices/Device-001",
"eventType": "Microsoft.Devices.DeviceTelemetry",
"data": {
"properties": {
"TempAlarm": "true"
},
"systemProperties": {
"iothub-connection-device-id": "Device-001",
"iothub-connection-auth-method": "{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}",
"iothub-connection-auth-generation-id": "637264713410XXXX",
"iothub-enqueuedtime": "2020-06-01T23:05:58.3130000Z",
"iothub-message-source": "Telemetry"
},
"body": "eyJ3aW5kaW5nVGVtcDEiOjg2LjYzOTYxNzk4MjYxODMzLCJ3aW5kaW5nVGVtcDIiOjc4LjQ1MDc4NTgwMjQyMTUyLCJ3aW5kaW5nVGVtcDMiOjg1LjUzMDYxMDY5OTQ1MzY1LCJMb2FkQSI6MjAyOS44NDgyMTg4ODYxMTEsIkxvYWRCIjoyMDQwLjgxMDk4OTg0MDMzMzgsIkxvYWRWIjoyMDA0LjYxMTkzMjMyNTQ2MTgsIk9pbFRlbXAiOjk5LjA2MjMyNjU2MTY4ODU4fQ=="
},
"dataVersion": "",
"metadataVersion": "1",
"eventTime": "2020-06-01T23:05:58.313Z"
}
]
}
Here is the sample input I am using with the trigger:
[{
"id": "9af86784-8d40-fe2g-8b2a-bab65e106785",
"topic": "/SUBSCRIPTIONS/<subscription ID>/RESOURCEGROUPS/<resource group name>/PROVIDERS/MICROSOFT.DEVICES/IOTHUBS/<hub name>",
"subject": "devices/LogicAppTestDevice",
"eventType": "Microsoft.Devices.DeviceTelemetry",
"eventTime": "2019-01-07T20:58:30.48Z",
"data": {
"body": {
"windingTemp1": 95.62818310718433
},
"properties": {
"Status": "Active"
},
"systemProperties": {
"iothub-content-type": "application/json",
"iothub-content-encoding": "utf-8",
"iothub-connection-device-id": "d1",
"iothub-connection-auth-method": "{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}",
"iothub-connection-auth-generation-id": "123455432199234570",
"iothub-enqueuedtime": "2019-01-07T20:58:30.48Z",
"iothub-message-source": "Telemetry"
}
},
"dataVersion": "",
"metadataVersion": "1"
}]
Summary comment to answer to help others who have same problem.
The body you provided is Base64 encoded, you can decode it with Convert.FromBase64String(String) Method.
byte[] newBytes = Convert.FromBase64String(body);
For more details, you could refer to this issue.
Update:
Add the following code in my application will solve the problem.
message.ContentEncoding = "utf-8";
message.ContentType = "application/json";

How to delete message replies using Slack API?

I'm getting an error when I try to use Slack API to remove the replies saying the channel doesn't exists.
To validate it, I'm calling the:
https://slack.com/api/channels.history?token={token}&channel={channel}&count=1&inclusive=true&latest={ts}&oldest={ts}
Then I get the message back.
The message I'm getting back is this one:
{
"ok": true,
"latest": "1540555927.024300",
"oldest": "1540555927.024300",
"messages": [
{
"text": "This message was deleted.",
"edited": {
"user": "UD6SLKGEP",
"ts": "1540555928.000000"
},
"type": "message",
"subtype": "tombstone",
"user": "USLACKBOT",
"hidden": true,
"thread_ts": "1540555927.024300",
"reply_count": 1,
"replies": [
{
"user": "UD6SLKGEP",
"ts": "1540555928.024401"
}
],
"subscribed": false,
"unread_count": 1,
"ts": "1540555927.024300"
}
],
"has_more": false,
"is_limited": true
}
As you can see, there is this "This message was deleted." that seems to be generated automatically and keep showing up because I still have replies associated to it.
If I call the same endpoint passing the reply ts (1540555928.024401), for the same channel I get this:
{
"ok": true,
"latest": "1540555928.024401",
"oldest": "1540555928.024401",
"messages": [
{
"type": "message",
"user": "UD6SLKGEP",
"text": "45d7bc14a6fa03 23456789 abcdefghijklmnop",
"bot_id": "BD6AJUY8G",
"thread_ts": "1540555927.024300",
"ts": "1540555928.024401"
}
],
"has_more": false,
"is_limited": true
}
Which means that there is a message there, which is a reply from another message.
The problem starts when I try to remove this reply message.
I call this endpoint:
https://slack.com/api/chat.delete?token={token}
Passing the channel and the reply ts as the payload:
{
"channel": "CD65XB2D7",
"message_ts": "1540555928.024401"
}
Now instead of having the message removed, I get this response:
{
"ok": false,
"error": "channel_not_found",
"warning": "missing_charset",
"response_metadata": {
"warnings": [
"missing_charset"
]
}
}
But the channel exists and I'm using it to remove other messages as well. That happens when I try to remove the reply from a message only.
Is there something special about removing reply messages?
I just found out the problem here:
https://api.slack.com/changelog/2017-10-keeping-up-with-the-jsons#methods
For some reason on my side it's working for messages, but not for replies. I had to move the token to the "Authorization" on header with the Bearer as suggested on this link.

Fetching caller location (city/country) from historical Twilio call logs

I currently receive data from each call to a Twilio number that contains info like this:
{
"Called": "+xxxxxxxx",
"ToState": "CA",
"CallerCountry": "US",
"Direction": "inbound",
"Timestamp": "Sat, 25 Aug 2018 00:01:46 +0000",
"CallbackSource": "call-progress-events",
"CallerState": "CA",
"ToZip": "92111",
"SequenceNumber": "0",
"To": "+1xxxxxx",
"CallSid": "xxxxxxxxxxxxx",
"ToCountry": "US",
"CallerZip": "92117",
"CalledZip": "92111",
"ApiVersion": "2010-04-01",
"CallStatus": "completed",
"CalledCity": "SAN DIEGO",
"Duration": "1",
"From": "+1xxxxxxxxxx",
"CallDuration": "10",
"AccountSid": "xxxxxxxxxxxxx",
"CalledCountry": "US",
"CallerCity": "POWAY",
"ToCity": "SAN DIEGO",
"FromCountry": "US",
"Caller": "+1xxxxxxxxxxx",
"FromCity": "POWAY",
"CalledState": "CA",
"FromZip": "92117",
"FromState": "CA",
}
This is provided at the end of each call to my server. However I need to fetch historical data to reconcile some missing info so I attempted to use the call log api as:
const calls = await twilio.calls.list()
This returns a different type of structure:
CallInstance {
accountSid: 'xxxxxxxxxx',
annotation: null,
answeredBy: null,
apiVersion: '2010-04-01',
callerName: null,
dateCreated: 2018-08-29T17:20:51.000Z,
dateUpdated: 2018-08-29T17:21:52.000Z,
direction: 'inbound',
duration: '61',
endTime: 2018-08-29T17:21:52.000Z,
forwardedFrom: '+xxxxxxxxxx',
from: '+xxxxxxxxxx',
fromFormatted: 'xxxxxxxxxx,
groupSid: null,
parentCallSid: null,
phoneNumberSid: 'xxxxxxxxxx',
price: -0.017,
priceUnit: 'USD',
sid: 'xxxxxxxxxx',
startTime: 2018-08-29T17:20:51.000Z,
status: 'completed',
subresourceUris:
{ notifications:
'/2010-04-01/Accounts/xxxxxxxxxx/Calls/xxxxxxxxxx/Notifications.json',
recordings:
'/2010-04-01/Accounts/xxxxxxxxxx/Calls/xxxxxxxxxx/Recordings.json' },
to: '+17603137608',
toFormatted: '(760) 313-7608',
uri:
'/2010-04-01/Accounts/xxxxxxxxxx/Calls/xxxxxxxxxx.json'
}
However this has no caller location data such as the city/country. Is there another API call to get the location data or am I left to my own devices by analyzing the phone number?
So after diving into it it doesn't appear to be possible. I ended up using something like the Google phone lib to analyze the number and return country.

Creating Group via Microsoft Graph returns Error "An unexpected PrimitiveValue node was found when reading from the JSON reader"

Am trying to create group using my admin account via Microsoft Graph. I have implemented all the required parameters/variables but when I tried making calls to the API, it displays error below:
{
"error": {
"code": "Request_BadRequest",
"message": "An unexpected 'PrimitiveValue' node was found when reading from the JSON reader. A 'StartArray' node was expected.",
"innerError": {
"request-id": "02bfcc43-5982-4c49-8484-da9d6cc61bab",
"date": "2017-12-05T17:53:57"
}
}
}
My code:
<?php
session_start();
echo $acc= $_SESSION['access_token'];
$data_string = array("description" => "An Awesome New Group", "displayName" => "Awesome Group", "groupTypes" => "Unified", "mailEnabled" => "true", "mailNickname" => "awesomeGroup", "securityEnabled" => "fasle");
$data = json_encode($data_string);
//$data = $data_string;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://graph.microsoft.com/v1.0/groups",
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "$data",
CURLOPT_HTTPHEADER => array(
"accept: application/json",
"authorization: Bearer $acc",
"content-type: application/json; charset=utf-8"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
print_r($response);
if ($err) {
echo "cURL Error #:" . $err;
} else {
//echo $response;
}
?>
Note that my real tenant id was replaced with admin#secx34fake.onmicrosoft.com so that its not displayed to public.
The error is telling you that the URL you're using is invalid.
This is accurate as /v1.0/admin#secx34fake.onmicrosoft.com/groups isn't a valid endpoint. Specifically it rejecting the userPrincipalName of admin#secx34fake.onmicrosoft.com. I'm not exactly sure where you were going with this but a Group is not a child of a User object. A User can be a member of a Group but they are both top-level elements within your Active Directory.
As an aside, a "segment" in the context of a URL is the elements separated by a /. You can think of a URL as a / delimited string with each column being a "segment". For example, /v1.0/me/events contains 3 segments: v1.0, me and events. The error you got is telling you one of these "segments" is either invalid or not in the proper order (i.e. /v1.0/events/me has the right segments in the wrong order).
For creating a Group, the proper URI looks like this:
POST https://graph.microsoft.com/v1.0/groups
Within the body of your POST you define the properties of the group. For example:
{
"description": "An Awesome New Group",
"displayName": "Awesome Group",
"groupTypes": ["Unified"],
"mailEnabled": true,
"mailNickname": "awesomeGroup",
"securityEnabled": false
}

Resources