1

I'm trying to send an email using mailgun on an iOS app with Swift. Lack of security aside, I always get a 400 Error. If I change a bit the key, I get a 401 so authentication works.

Whether I use Alamofire:

let parameters = ["Authorization" : "api:key-...",
                  "from": "from@email.com",
                  "to": "to@email.com",
                  "subject": "Test",
                  "text": "Testing email"]

alamofireManager.request("https://api.mailgun.net/v3/sandbox...mailgun.org/messages", method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: nil)
    .authenticate(user: "api", password: "key-...")
    .validate(statusCode: 200 ..< 300)
    .validate(contentType: ["application/json"])
    .responseJSON { response in
        print(response)
        print("Response : \(response.error)")
}

Or NSMutableURLRequest:

let session = URLSession.shared
let request = NSMutableURLRequest(url: URL(string: "https://api.mailgun.net/v3/sandbox...mailgun.org/messages")!)

request.httpMethod = "POST"
let credentials = "api:key-..."
request.setValue("Basic \(Data(credentials.utf8).base64EncodedString())", forHTTPHeaderField: "Authorization")

let data = "from:Test<(test@test.com)>&to:[my_email_address@gmail.com,(my_email_address@gmail.com)]&subject:Hello&text:Testing_email"
request.httpBody = data.data(using: String.Encoding.ascii)

let task = session.dataTask(with: request as URLRequest, 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! HTTPURLResponse
        print("response code = \(httpResponse.statusCode)")
    }
})
task.resume()

I always get a 400. I don't see what's wrong in my parameters. Any idea?

Nico
  • 6,269
  • 9
  • 45
  • 85

1 Answers1

0

Selecting a HTTP response code is quite an easy task and can be described by simple rules. The only tricky part which is often forgotten is paragraph 6.5 from RFC 7231:

Except when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition.

Rules are as following:

1- If request was successful, then return 2xx code (3xx for redirect). If there was an internal logic error on a server, then return 5xx. If there is anything wrong in client request, then return 4xx code.

2- Look through available response code from selected category. If one of them has a name which matches well to your situation, you can use it. Otherwise just fallback to x00 code (200, 400, 500). If you doubt, fallback to x00 code.

5- Return error description in response body. For 4xx codes it must contain enough information for client developer to understand the reason and fix the client. For 5xx because of security reasons no details must be revealed.

4- If client needs to distinguish different errors and have different reaction depending on it, define a machine readable and extendible error format and use it everywhere in your API. It is good practice to make that from very beginning.

5- Keep in mind that client developer may do strange things and try to parse strings which you return as human readable description. And by changing the strings you will break such badly written clients. So always provide machine readable description and try to avoid reporting additional information in text.

bsm-2000
  • 265
  • 2
  • 13