I'm working on implementing MFA in my pet-project. As I understand from Twilio Verify docs (https://www.twilio.com/docs/verify/api/rate-limits-and-timeouts#code-validity-period) it has some limitations: the code is valid for 10 minutes and I can only send 5 messages in this 10 minute time span (https://www.twilio.com/docs/api/errors/60203). Also, I found a way to avoid this restriction by updating verification status to "cancelled". The code in C# looks like this:
static async Task TestingTwilioLimitations()
{
VerificationResource verification = null;
for (int i = 0; i < 3; i++)
{
verification = await VerificationResource.CreateAsync(
to: "phone number",
channel: "sms",
pathServiceSid: serviceSid
);
Thread.Sleep(TimeSpan.FromSeconds(10));
}
await VerificationResource.UpdateAsync(new UpdateVerificationOptions(serviceSid, verification.Sid, VerificationResource.StatusEnum.Canceled));
for (int i = 0; i < 3; i++)
{
verification = await VerificationResource.CreateAsync(
to: "phone number",
channel: "sms",
pathServiceSid: serviceSid
);
Thread.Sleep(TimeSpan.FromSeconds(10));
}
}
This code allows me to receive 6 messages with codes, despite the limitations of 10 minutes and 5 attempts to send the code. So, the question is, can I use this trick? It allows to spam people (I'm not going to do that, just wanted to be able to configure max send attempts and code validation time from my side), and I'm afraid of being banned by Twilio Verify for using this API calls.
This blog may help you.
How to test Twilio Verify without getting rate limited
Otherwise, no way to change the behavior.
Related
This seems like a really simple issue, but I've searched the web and can't find an answer, unfortunately.
We're trying to setup a basic forwarding/voicemail service on Twilio. Our expected behavior is that a caller will call in and be forwarded to 3 different numbers. If none of the numbers answer, the caller is directed to the company voicemail.
Our issue comes in when any of the numbers reject the call (by pressing the red button on their phone) or are set to Do Not Disturb (which seems to act like a rejection). When this happens, the caller is sent directly to the callee's personal voicemail, instead of the company voicemail. I believe this is because Twilio is passed a "in-progress" status even though the call was rejected.
Is there a way to detect when the call is rejected and continue to the "action" part of our Dial? We looked into the Automatic Machine Detection, but am not sure that is the correct route to take, since it would still reveal the callee's personal voicemail until it determined it was a machine.
Thanks for any help! Our simple code is below.
<Response>
<Dial callerId="+1xxx-xxx-xxxx" timeout="15" action="http://twimlets.com/voicemail?Email=email#email.com&Message=https://website.com/Audio.mp3">
<Number>xxx-xxx-xxxx</Number>
<Number>xxx-xxx-xxxx</Number>
<Number>xxx-xxx-xxxx</Number>
</Dial>
</Response> ```
You can take a look at the blog below, which uses Human Detection (alternatives to AMD) to intelligently handle the dialed party's voicemail.
Outsmart Voice Mail with Human Detection Using Keypress Prompts
You cannot use your current approach with parallel forking, since it cannot account for Voicemail.
You will need to build the sequential dialing logic. Below is some Twilio Function code that may be useful, but you will need to adapt it to meet your needs
Main Function (where you point your Twilio Telephone Number to) is shown first:
Replace:
let phoneTreeUrl = "https://YOUR_FUNTION/PATH";
With your unique Function URL and path (this varies for each Twilio customer). Also update the phoneNumbers to be the phone numbers you want to call. You can pass the Timeout as a variable when you call the function from your Twilio phone number or change it in the code below (it defaults to 30 seconds).
Update the PLACE_HOLDER URL with the other Function you will create in the next step further below.
/*
* Example: Strictly Linear Phone Tree
* This example shows how you might iterate through a list of numbers.
* Each will be tried for 10 seconds before moving on to the next.
*/
exports.handler = function(context, event, callback) {
// REQUIRED - URL to this Function
let phoneTreeUrl = "https://YOUR_FUNTION/PATH";
// Timeout - The amount of time we want to dial before giving up
let timeout = event.Timeout || 30;
// Attempt - The position in the list we are currently at
let attempt = parseInt(event.Attempt) || 0;
console.log(attempt);
// DialCallStatus - Returned by <Dial> action
let DialCallStatus = event.DialCallStatus || null;
console.log(DialCallStatus);
// Phone Numbers - The list of numbers to cycle through
let phoneNumbers = [
"+14073601234", "+16787851234"
];
// generate the TwiML to tell Twilio how to forward this call
let twiml = new Twilio.twiml.VoiceResponse();
// If we have successfully contacted a number, then exit Function
if (DialCallStatus === "completed" || DialCallStatus === "answered") {
twiml.hangup();
callback(null, twiml);
}
// If we have exhausted all numbers end the attempts
if (attempt >= phoneNumbers.length) {
twiml.say("Sorry, we could not find someone to take your call. Please try again later");
callback(null, twiml);
}
// Build the state for our Twiml response
let target = phoneNumbers[attempt];
let nextAttempt = attempt + 1;
let nextAttemptUrl = phoneTreeUrl + "?Attempt=" + nextAttempt;
twiml.dial({ timeout: timeout, action: nextAttemptUrl})
.number({url: "https://PLACE_HOLDER/humandetect?Detection=required"}, target);
callback(null, twiml);
};
Human Detection Function:
Give this new function the path /humandetect
Update the code below, THIS_FUNCTION, to the unique URL for this FUNCTION (with the path of /humandetect)
exports.handler = function(context, event, callback) {
let twiml = new Twilio.twiml.VoiceResponse();
// REQUIRED - URL to this Function
let phoneTreeUrl = "https://THIS_FUNCTION/humandetect";
let detection = event.Detection || null;
if (detection === "required") {
twiml.gather({timeout: 5, numDigits: 1, action: phoneTreeUrl})
.say("Press any key to hear an important message about your appointment.");
twiml.hangup();
}
callback(null, twiml);
};
Okay so I got approval from WhatsApp and Twilio (after Facebook Business verification) to use the WhatsApp API for sending out appointment reminders to my clients. I configured the message templates and they got approved too. Check the image below:
I have written a code in Python where I pick my data from a PostgreSQL server hosted on cloud (using psycopg2) and then it sends out messages to the phone numbers fetched using a query. Here is the code:
from twilio.rest import Client
import psycopg2
import time
account_sid = 'AC54xxxxxxxxxxxxxxxxxxxxxxxxxxx'
auth_token = 'f1384yyyyyyyyyyyyyyyyyyyyyyyyyyy'
connection_string = ""
conn = psycopg2.connect(user = "xxxx",
password = "yyyyyy",
host = "zzzzzzzzzzzzzzz.zzzzzzzzzzzz",
port = "ABCD",
database = "some_db")
cur = conn.cursor()
cur.execute("""query to pick data""")
rows = cur.fetchall()
client_phone_list = []
phone_list_not_received = []
session_date_list = []
session_time_list = []
client_first_name_list = []
for row in rows:
session_date_list.append(row[0])
session_time_list.append(row[1])
client_first_name_list.append(row[2])
client_phone_list.append(row[3])
cur.close()
conn.close()
client = Client(account_sid, auth_token)
message_reminder_template = """Hello {},
This is a reminder about your session today at {}. Please be on time to utilize the full length of
the session and avoid distress :)
We look forward to taking care of you!"""
for i in range(len(client_phone_list)):
first_name = client_first_name_list[i]
appointment_time = session_time_list[i]
message_body = message_reminder_template.format(first_name, appointment_time)
print(message_body)
message = client.messages.create(body = str(message_body),
from_ = 'whatsapp:+1(mytwilionumber)',
to = 'whatsapp:+91'+client_phone_list[i])
time.sleep(10)
text_status = message.status
print(text_status)
Whenever I run this code the message status returned is always 'queued'. I have checked that I am not using the 'Test Credentials' but the 'Live Credentials'.
I have also checked the error_code and error_message which returns as NULL. So there is no error but the messages are not getting sent. How can I change that?
Any help would be hugely appreciated.
Also note that the message body used in the code above is approved as a template from WhatsApp.
Twilio developer evangelist here.
At the point that you make the API request to send the message the status will be returned to code as "queued". That's this point in your code here:
message = client.messages.create(body = str(message_body),
from_ = 'whatsapp:+1(mytwilionumber)',
to = 'whatsapp:+91'+client_phone_list[i])
What you do next will not work though:
time.sleep(10)
text_status = message.status
print(text_status)
Waiting 10 seconds and then reading the status from the message object that was returned when you created the message will still return "queued".
If you want to fetch the message status after 10 seconds to see if it has been sent then you will need to make a second call to the messages API, like so:
time.sleep(10)
latest_message = client.messages(message.sid).fetch()
print(latest_message.status)
For a more efficient method of keeping track of the status of your messages, check out this tutorial on receiving webhooks for message status updates.
Let me know if that helped at all.
I tried to make multiple subscriptions to a single user, to test out how many subscription requests i can send until throttling occurs. I used the following code:
for (int i = 0; i < 10000; i++)
{
try
{
var request = graphClient.Subscriptions.Request();
var result = await request.AddAsync(
new Subscription
{
ChangeType = "created,updated,deleted",
NotificationUrl = notificationUrl,
Resource = "/users/" + userId + "/" + resource,
ExpirationDateTime = DateTimeOffset.UtcNow.AddMinutes(4230),
ClientState = "my-subscription-identifier"
}
);
AddOutputMessage((i + 1) + " Created Webhook", Color.Blue);
}
catch (ServiceException serviceException)
{
AddOutputErrorMessage(serviceException);
}
}
The throttling limit per user per app is 10000 in 10 minutes (as described in another stackoverflow post). I already tested this limit by making some requests to a single users calendar and contacts where it seems to work.
I was able to make 220 subscriptions until throttling occured (tested it three times). Even though that seems to be a little low, my end goal is to make multiple subscription requests for multiple users (for example 1000 subscriptions to a 1000 users), so it wouldn't be a problem if this throttling limit is for a single user only.
The throttling (HttpStatusCode 429) service exception for the subscriptions request also contained the error code 'ExtensionError' which i couldn't really find in the doc.
What i want to know is:
What are the throttling limits for the '/subscription endpoint'?
Especially after how many requests does throttling occur? (per user and overall per app) e.g. if i want to make subscriptions to 1000 users will i be throttled after 220?
What is an 'ExtensionError'?
ExtensionError is actually an OAuth error category. Expand the Message string to see if it has more info.
I'm checking with the code owners to see what the subscription limits for REST are.
I am sending messages in using Twilio using this code:
string channelId = <channelId>;
string serviceSid = <servicesid>;
IpMessagingClient ipMessagingClient = new IpMessagingClient(<accountid>, <token>);
var msgResult = ipMessagingClient.CreateMessage(serviceSid, channelId, "sender", "message");
msg.Body = "body"
msg.DateSent = DateTime.Now;
msg.Sender = "sender"
return Json(new
{
Success = msgResult.Sid != null,
NewMessage = msg
});
Message is sent just fine and I can retrieve the messages of the channel. What I am trying to achieve now is other open browser and in the channel gets notified of new messages sent so I can update the UI to display the new messages without manual refreshing the browser.
Twilio developer evangelist here.
It looks like you are using the REST API to send messages to the Programmable Chat API.
To get using the client versions, the JS client in particular, I would take a read through the Programmable Chat documentation, go download the JS SDK and take a look at the code for the reference chat demo. All of those bits should give you a good grounding in building chat for the client side.
Let me know if that helps at all.
To address the Rate Limit Exceeding issue in code, I am just wondering, can I do this?
do
{
Log.Info(this, string.Format("Fetching user timeline statuses for {0}", screenName));
var twitterService = new TwitterService(_consumerKey, _consumerSecret);
twitterService.AuthenticateWith(_accessToken, _accessTokenSecret);
ListTweetsOnUserTimelineOptions listTweetsOnUserTimelineOptions =
new ListTweetsOnUserTimelineOptions();
listTweetsOnUserTimelineOptions.ScreenName = screenName;
listTweetsOnUserTimelineOptions.IncludeRts = true;
Thread.sleep(50000);
catch (Exception e)
{
Log.Error(this, string.Format("exception happened whille calling Twitter Service{0}", e.StackTrace));
}
} while (result.Count < count);
According to the API, the time is divided in to 15 minutes window now. So, by putting in a Thread.sleep() would that be OK? because Twitter documentation doesn't really provide any code example.
All help is greatly appreciated.
Yes you can, but I'd look for a more sophisticated task scheduling, like this one: https://stackoverflow.com/a/14945407/253468
Also revisit the Twitter API docs, I think it's not one request you can send every 15 minutes. Divide the number of times you can request over 15 minutes to know how often you can run your scheduled task.