I'm trying to get sms from twilio service but keep getting this error.
Request:
func SMSRequest(countryCode:String, phoneNumber: String) {
let accountSid = "ACc4d9785419f144412823ff2034660c3d"
let authToken = "a2293a42841f8999caa237er363" // changed
let phoneNumber = "+14243960339"
let toNumber = "+37378847884"
let url = URL(string: "https://\(accountSid):\(authToken)#api.twilio.com/2010-04-01/Accounts/\(accountSid)/SMS/Messages")
print("url", url!)
let parameters = [
"From": phoneNumber,
"To": toNumber,
"Body":"Hi daddy"
]
Alamofire.request(url!, method: .post, parameters: parameters,
encoding: JSONEncoding.default, headers: [:]).responseJSON { response in
let response = String(describing: response.result.ifFailure({
print(response)
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {print("Data: \(utf8Text)")}
}))
}
}
Error:
<TwilioResponse><RestException><Code>21603</Code><Message>A 'From' phone number is required.</Message><MoreInfo>https://www.twilio.com/docs/errors/21603</MoreInfo><Status>400</Status></RestException></TwilioResponse>
All the credentials I get from here
Solution:
use utf8 encoding.
Twilio developer evangelist here.
It's important to note that, even though you have solved your problem, you are building a fundamentally insecure application. I left this comment on your other question, but I need to point it out here too.
We do not recommend that you make requests to the Twilio API directly from your native application. To do so, you would need to store or retrieve your account SID and auth token in the application somewhere. If you do this, then a malicious attacker could get access to your credentials and abuse your Twilio account.
This is actually known as the Eavesdropper vulnerability and was written about earlier this year.
Instead we recommend that you create a web application and send the API requests from there. There is a blog post on how to do that here: https://www.twilio.com/blog/2016/11/how-to-send-an-sms-from-ios-in-swift.html
Update for Swift 4 - you don't really need to specify encoding, just leave it as a default.
Regarding the Twilio answer, they shouldn't say that people "shouldn't" make requests to their API, but rather remove that functionality per se and make a proper authentication service on their SDK. For now this works as the best solution I found.
let accountSID = "BOB"
let authToken = "BOB'S PASSWORD"
let url = "https://api.twilio.com/2010-04-01/Accounts/\(accountSID)/Messages" as URLConvertible
let parameters = ["From": "SENDER", "To": "RECIPIENT", "Body": "Hello world!"]
Alamofire.request(url, method: .post, parameters: parameters)
.authenticate(user: accountSID, password: authToken)
.responseString { response in
debugPrint(response)
}
Related
I test this thing many time in many devices with different ios versions but always succeeded to make API call. Also test with testflight build and got success for same request params.
Only at the time of App store review I got the error "JSON could not be serialized because of error:\nThe data couldn’t be read because it isn’t in the correct format."
for a correct formatted "requestParameter": {"device_token": "cBXIAfxpEpk:APA91bH8AZYHqMniP5oGNuHT7czD-wHm_ioE-th1_LkN3_w5w_KUa5grT6Ff73D8j9Kn-xONeK4ytT8ZSfVssG9mf4KwJzhY7WdoSxUHxLKNxyGMI0g9ieyuyF25Pi3KwFXDIQmawmow", "time_zone": "America/Los_Angeles", "device_type": "ios", "username": "demo", "password": "password", "location": "37.452728,-121.940140"}
these are the information i got from firebase files
I am sure its not for response because I also verified with backend but there is no log fired at that time , So its unable to make request from mobile side.
here is my API method
func serviceCall(withPath path:String, withData param:[String:Any], withCompletionHandler completion:#escaping (AnyObject?) -> Void){
let requestURL = String(format: "%#%#", BaseURL, path)
let manager = Alamofire.SessionManager.default
manager.session.configuration.timeoutIntervalForRequest = 40
manager.request(requestURL, method: .post, parameters: param, encoding: URLEncoding.methodDependent, headers: nil).responseJSON { (responseJson) in
print("Response 10: \(responseJson)")
if ((responseJson.result.value != nil)){
// store details to firebase
} else {
// store details to firebase
}
}
}
please help me out already rejected by app store for many times :(
Thank you in advance !!
Hello I am trying to use Alamofire for my HTTP requests. It is working with parameters that are not included any nested parameter. Normally, my url is working with following on the Google Chrome.
http://111.222.33.4:12345/my_server/dispatch?cmd=ext_getReferanceData&jp=%7b%22rfName%22:%22RF_ABC%22%7d&token=123
and the decoded version of above url is
http://111.222.33.4:12345/my_server/dispatch?cmd=ext_getReferanceData&jp={"rfName":"RF_ABC"}&token=123
It works fine when I paste it into any browser. However when I try to send following post request with Alamofire
let parameters3: [String: Any] = [
"cmd": "ext_getReferanceData",
"jp": [
"rfName": "RF_ABC"
],
"token": "123"
]
Alamofire.request("http://111.222.33.4:12345/my_server/dispatch", method: .get, parameters: parameters3, encoding: JSONEncoding.default).responseJSON { (response) in
}
It is returning
FAILURE:
responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength)
What could be the reason of it am I sending parameters wrong or is there anything that I am missing?
Edit: I also checked other questions about the error but the problem is about parameters that I am trying to send because there is " and { in the parameters but I could not send in the request.
have you considered printing the response being sent and confirming it that it's indeed the stuff you're trying to send?
You can do a couple of things to improve
Make the method .post
Try to use .validate() for added reliability
The way I do it is something like:
let submissionURL = URL(string: "https://blablabla.com/script.php")
sendAlamofireRequest(submissionURL: submissionURL!, parameters: parameters, chosenTrackerStr: chosenTrackerString) //function call
//function declaration
func sendAlamofireRequest(submissionURL: URL, parameters: Parameters, chosenTrackerStr: String){
Alamofire.request(submissionURL, method: .post, parameters: parameters, encoding: JSONEncoding.default).validate().responseString() { (response) in
//actual code goes here
}
}
Maybe try to play around with the alamofire request and check its documentation to see the suggested approach :)
I'm trying to get an SMS from twilio.com but get nil in response. Can anyone say what I'm doing wrong?
class SMSVerificationService: NSObject {
static let sharedInstance = SMSVerificationService()
func SMSRequest(countryCode:String, phoneNumber: String) {
let accountSid = "ACc4d9785419f144412823ff20as34660c3d"
let authToken = "4wqecx41f8999caa23735da214" // changed :)
let url = URL(string: "https://\(accountSid):\(authToken)#api.twilio.com/2010-04-01/Accounts\(accountSid)/Messages")
print("url", url!)
let parameters = [
"To": "+37378847884",
"From" : "+14243960339",
"Body": "Hi daddy"
]
Alamofire.request(url!, method: .post, parameters: parameters,
encoding: JSONEncoding.default, headers: [:]).responseJSON { response in
let response = String(describing: response.result.value)
print(response)
}
}
}
Twilio developer evangelist here.
We do not recommend that you make requests to the Twilio API directly from your native application. To do so, you would need to store or retrieve your account SID and auth token in the application somewhere. If you do this, then a malicious attacker could get access to your credentials and abuse your Twilio account.
This is actually known as the Eavesdropper vulnerability and was written about earlier this year.
Instead we recommend that you create a web application and send the API requests from there. There is a blog post on how to do that here: https://www.twilio.com/blog/2016/11/how-to-send-an-sms-from-ios-in-swift.html
I notice that your class is called SMSVerificationService too. If you are looking to build phone verification, then I recommend you take a look at the Twilio Verify API that does a lot of the work for you.
I am trying to send Email using MailGun api with Swift. I created and activate free account with mailgun. Installed pod.
cocoapods mailgun pod
If I press button I am getting message "Email was sent" but I am not receiving this email, nor it is displays in mailgun "Logs" or "Reporting".
I have also added and verified my personal e-mail to "Authorized Recipients"
I tied to run on IOS simulator and actual devices no luck.
#IBAction func dddd(_ sender: Any) {
let mailgun = MailgunAPI(apiKey: "key-<my_key from mailgun>, clientDomain: "sandboxe437***********.mailgun.org")
mailgun.sendEmail(to: "me#mail.com", from: "Test User <myemail#mail.com", subject: "This is a test15", bodyHTML: "<b>test<b>") { mailgunResult in
if mailgunResult.success{
print("Email was sent")
}else{
print("error")
}
}
Any word of advise what did I missed?
Thank you,
Stalker
#Stalker, your from parameter does not have a closing >. I hope you have seen it.
If you are already using Alamofire for your network requests then no need for this extra dependency mailgun pod:
Swift 3.2
import Alamofire
let parameters = [
"from": "sender#whatyouwant.com",
"to": "anyRecipient#example.com",
"subject": "Subject of the email",
"text": "This is the body of the email."]
let header = [
"Authorization": "Basic YOUR-BASE64ENCODED-KEY",
"Content-Type" : "application/x-www-form-urlencoded"]
let url = "https://api.mailgun.net/v3/YOUR-DOMAIN/messages"
Alamofire.request(url,
method: .post,
parameters: parameters,
encoding: URLEncoding.default,
headers: header)
.responseJSON { response in
print("Response: \(response)")
}
In the header, you have to replace YOUR-BASE64ENCODED-KEY with the base64 encoded string of "API:YOUR-SECRET-API-KEY" where YOUR-SECRET-API-KEYis found on your Mailgun dashboard.
In the URL you also replace YOUR-DOMAIN with your Mailgun domain.
With that you should be good to go and send emails through Mailgun.
I am a .net developer but very new to iOS and swift development, just need help with consuming Web API using Swift2
The Asp.net Web API has been built with OAuth2 authentication, published to my Azure VM server with SSL certificate installed. The API site itself works properly, tested through Postman
However I got stuck when started writing first few lines of code in Swift trying to get Authentication token. After reading some online tutorials I decided to engage Alamofire, and produced below codes snippet:
func GetToken() {
let params = [
"grant_type" : "password",
"username" : "123456#qq.com",
"password" : "averygoodpassword"
]
let headers = [
"Content-Type" : "application/x-www-form-urlencoded"
]
request(.POST, "https://api.example.com/token",
parameters: params,
headers: headers,
encoding: .JSON)
.responseJSON { request, response, result in
print (request)
print (response?.description)
print (result)
switch result {
case .Success(let JSON):
print("Success with JSON: \(JSON)")
case .Failure(let data, let error):
print("Request failed with error: \(error)")
if let data = data {
print("Response data: \(NSString(data: data, encoding: NSUTF8StringEncoding)!)")
}
}
}
}
It ends up with below output in Xcode which didn't seem to be OK. The error = unsupported_grant_type told me that the request were sent to server but the parameters were not sent with request properly. I really cannot figure out the reason and solution, had been digging on Internet for a few days but still feeling desperate with it. Can anyone help please? Even if someone can provide a pure swift solution without any 3rd party library will be greatly helpful. Thanks!
Xcode output:
Optional( { URL: https://api.example.com/token })
Optional(" { URL: https://api.example.com/token } { status code: 400, headers {\n \"Access-Control-Allow-Headers\" = \"Content-Type\";\n \"Access-Control-Allow-Methods\" = \"GET, POST, PUT, DELETE, OPTIONS\";\n \"Access-Control-Allow-Origin\" = \"*\";\n \"Cache-Control\" = \"no-cache\";\n \"Content-Length\" = 34;\n \"Content-Type\" = \"application/json;charset=UTF-8\";\n Date = \"Fri, 30 Sep 2016 10:30:31 GMT\";\n Expires = \"-1\";\n Pragma = \"no-cache\";\n Server = \"Microsoft-IIS/8.5\";\n \"X-Powered-By\" = \"ASP.NET\";\n} }")
SUCCESS
Success with JSON: {
error = "unsupported_grant_type";
}
I had a similar problem trying to POST to MailGun for some automated emails I was implementing in an app.
I was able to get this working properly with a large HTTP response. I put the full path into Keys.plist so that I can upload my code to github and broke out some of the arguments into variables so I can have them programmatically set later down the road.
// Email the FBO with desired information
// Parse our Keys.plist so we can use our path
var keys: NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("Keys", ofType: "plist") {
keys = NSDictionary(contentsOfFile: path)
}
if let dict = keys {
// variablize our https path with API key, recipient and message text
let mailgunAPIPath = dict["mailgunAPIPath"] as? String
let emailRecipient = "bar#foo.com"
let emailMessage = "Testing%20email%20sender%20variables"
// Create a session and fill it with our request
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: mailgunAPIPath! + "from=FBOGo%20Reservation%20%3Cscheduler#<my domain>.com%3E&to=reservations#<my domain>.com&to=\(emailRecipient)&subject=A%20New%20Reservation%21&text=\(emailMessage)")!)
// POST and report back with any errors and response codes
request.HTTPMethod = "POST"
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = \(response.URL!)")
print("response = \(response)")
let httpResponse = response as! NSHTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
The Mailgun Path is in Keys.plist as a string called mailgunAPIPath with the value:
https://API:key-<my key>#api.mailgun.net/v3/<my domain>.com/messages?
I'm slightly opposed to using 3rd party libraries, especially for small things like a http POST and this seems like a much more maintainable solution to me. Anyways, hope this helps, let me know if you have any questions!