Repository: gsquire/sendgrid-rs (language: rust)

Issue:
when SG returns error, library happily returns success
Hey @gsquire, I've tried to send message and it returned Ok with the following error:
```
{"errors":[{"message":"If present, text/plain must be first, followed by text/html, followed by any other content.","field":"content","help":null}]}
```

I wonder if SG returns successful status code in this case?


Discussion / hints:
Did a quick check and SG does return 400. I think it would make sense to check if response anything else than 200 and return an error instead.
Let me know how you want to approach this and I might provide a PR.
Hey, Kane. I didn't do any status checking so I would be happy to integrate that in.
@gsquire main question do we return response text verbatim or try to decode json?
Perhaps we can make a new error type for unsuccessful responses and return that? So you could parse the JSON and return the actual status.

Fix patch:
diff --git a/Cargo.toml b/Cargo.toml
index 4b7b87a..8367bcf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sendgrid"
-version = "0.10.1"
+version = "0.10.2"
 edition = "2018"
 authors = ["Garrett Squire <garrettsquire@gmail.com>"]
 description = "An unofficial client library for the SendGrid API"
diff --git a/src/errors.rs b/src/errors.rs
index dcb5941..366533b 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -16,6 +16,8 @@ pub enum SendgridError {
     InvalidHeader(#[cause] InvalidHeaderValue),
     #[fail(display = "could not UTF-8 decode this filename")]
     InvalidFilename,
+    #[fail(display = "Request failed with StatusCode: {}", _0)]
+    RequestNotSuccessful(reqwest::StatusCode),
 }
 
 impl From<reqwest::Error> for SendgridError {
diff --git a/src/sg_client.rs b/src/sg_client.rs
index 6456592..f05bc66 100644
--- a/src/sg_client.rs
+++ b/src/sg_client.rs
@@ -1,7 +1,7 @@
 use reqwest::header::{self, HeaderMap, HeaderValue};
 use url::form_urlencoded::Serializer;
 
-use crate::errors::SendgridResult;
+use crate::errors::{SendgridError, SendgridResult};
 use crate::mail::Mail;
 
 static API_URL: &str = "https://api.sendgrid.com/api/mail.send.json?";
@@ -94,7 +94,11 @@ impl SGClient {
             .body(post_body)
             .send()?;
 
-        res.text().map_err(|e| e.into())
+        if !res.status().is_success() {
+            Err(SendgridError::RequestNotSuccessful(res.status()))
+        } else {
+            Ok(res.text()?)
+        }
     }
 }
 
diff --git a/src/v3.rs b/src/v3.rs
index 9d27831..02b7afe 100644
--- a/src/v3.rs
+++ b/src/v3.rs
@@ -7,7 +7,6 @@ use reqwest::header::{self, HeaderMap, HeaderValue, InvalidHeaderValue};
 use serde::Serialize;
 use serde_json;
 
-#[cfg(feature = "async")]
 use crate::errors::SendgridError;
 
 use crate::errors::SendgridResult;
@@ -133,18 +132,19 @@ impl Sender {
     pub async fn send(&self, mail: &Message) -> SendgridResult<reqwest::Response> {
         use reqwest::Client;
 
-        let headers_res = self.get_headers();
+        let headers = self.get_headers()?;
 
-        if let Ok(headers) = headers_res {
-            Client::new()
-                .post(V3_API_URL)
-                .headers(headers)
-                .body(mail.gen_json())
-                .send()
-                .await
-                .map_err(|err| SendgridError::from(err))
+        let res = Client::new()
+            .post(V3_API_URL)
+            .headers(headers)
+            .body(mail.gen_json())
+            .send()
+            .await
+            .map_err(|err| SendgridError::from(err))?;
+        if !res.status().is_success() {
+            Err(SendgridError::RequestNotSuccessful(res.status()))
         } else {
-            Err(SendgridError::from(headers_res.unwrap_err()))
+            Ok(res)
         }
     }
 
@@ -155,7 +155,11 @@ impl Sender {
         let headers = self.get_headers()?;
         let body = mail.gen_json();
         let res = client.post(V3_API_URL).headers(headers).body(body).send()?;
-        Ok(res)
+        if !res.status().is_success() {
+            Err(SendgridError::RequestNotSuccessful(res.status()))
+        } else {
+            Ok(res)
+        }
     }
 }
 


Test patch: