Skip to content
This repository was archived by the owner on Apr 3, 2019. It is now read-only.

Commit 5926a06

Browse files
committed
fix(errors): convert ses invalid domain error into a 400
1 parent b8c65bd commit 5926a06

File tree

6 files changed

+107
-4
lines changed

6 files changed

+107
-4
lines changed

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ reqwest = ">=0.8.5"
3939
rocket = ">=0.3.17"
4040
rocket_codegen = ">=0.3.17"
4141
rocket_contrib = ">=0.3.17"
42+
roxmltree = ">=0.3.0"
4243
rusoto_core = ">=0.34.0"
4344
rusoto_credential = ">=0.13.0"
4445
rusoto_mock = ">=0.28.0"

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ extern crate reqwest;
5454
extern crate rocket;
5555
#[macro_use]
5656
extern crate rocket_contrib;
57+
extern crate roxmltree;
5758
extern crate rusoto_core;
5859
extern crate rusoto_credential;
5960
extern crate rusoto_ses;

src/providers/ses/mod.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@
55
use std::boxed::Box;
66

77
use base64;
8+
use roxmltree::Document as XmlDocument;
89
use rusoto_core::{request::HttpClient, Region};
910
use rusoto_credential::StaticProvider;
10-
use rusoto_ses::{RawMessage, SendRawEmailRequest, Ses, SesClient};
11+
use rusoto_ses::{RawMessage, SendRawEmailError, SendRawEmailRequest, Ses, SesClient};
1112

1213
use super::{build_multipart_mime, Headers, Provider};
13-
use crate::{settings::Settings, types::error::AppResult};
14+
use crate::{
15+
settings::Settings,
16+
types::error::{AppError, AppErrorKind, AppResult},
17+
};
1418

1519
#[cfg(test)]
1620
mod test;
@@ -77,3 +81,53 @@ impl Provider for SesProvider {
7781
.map_err(From::from)
7882
}
7983
}
84+
85+
impl From<SendRawEmailError> for AppError {
86+
fn from(error: SendRawEmailError) -> Self {
87+
if let SendRawEmailError::Unknown(ref body) = error {
88+
if let Ok(xml) = XmlDocument::parse(body) {
89+
for child in xml.root_element().children() {
90+
if child.is_element() && child.tag_name().name() == "Error" {
91+
let mut is_invalid_payload = false;
92+
let mut error_message = None;
93+
let mut error_property = None;
94+
95+
for grandchild in child.children() {
96+
if grandchild.is_element() {
97+
match grandchild.tag_name().name() {
98+
"Code" => {
99+
is_invalid_payload =
100+
grandchild.text() == Some("InvalidParameterValue")
101+
}
102+
"Message" => {
103+
error_message =
104+
grandchild.text().map(|message| message.to_owned())
105+
}
106+
"Type" => {
107+
error_property =
108+
grandchild.text().map(|property| property.to_owned())
109+
}
110+
_ => {}
111+
}
112+
}
113+
}
114+
115+
if is_invalid_payload {
116+
return AppErrorKind::InvalidPayload(error_message.unwrap_or_else(
117+
|| {
118+
format!(
119+
"Invalid {}",
120+
error_property.unwrap_or_else(|| "parameter".to_owned())
121+
)
122+
},
123+
))
124+
.into();
125+
}
126+
}
127+
}
128+
}
129+
}
130+
131+
AppErrorKind::Internal(format!("{:?}", error)).into()
132+
}
133+
}

src/providers/ses/test.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,36 @@ fn ses_send_handles_error_response() {
9191
assert_eq!(error.error(), "Internal Server Error");
9292
assert_eq!(error.to_string(), "Unknown(\"FREAKOUT\")");
9393
}
94+
95+
#[test]
96+
fn ses_send_handles_invalid_domain_response() {
97+
let body = r#"
98+
<ErrorResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
99+
<Error>
100+
<Type>Sender</Type>
101+
<Code>InvalidParameterValue</Code>
102+
<Message>Invalid domain name: gmail.com.com</Message>
103+
</Error>
104+
<RequestId>f972bc68-f90c-11e8-90d8-9f9fb80f3486</RequestId>
105+
</ErrorResponse>
106+
"#;
107+
let mock_dispatcher = MockRequestDispatcher::with_status(500).with_body(&body);
108+
let mock_ses = SesProvider {
109+
client: Box::new(SesClient::new_with(
110+
mock_dispatcher,
111+
MockCredentialsProvider,
112+
Region::SaEast1,
113+
)),
114+
sender: "Wibble <blee@example.com>".to_string(),
115+
};
116+
let result = mock_ses.send("blee@gmail.com.com", &[], None, "subject", "body", None);
117+
assert!(result.is_err());
118+
let error = result.unwrap_err();
119+
assert_eq!(error.code(), 400);
120+
assert_eq!(error.errno().unwrap(), 102);
121+
assert_eq!(error.error(), "Bad Request");
122+
assert_eq!(
123+
error.to_string(),
124+
"Invalid payload: Invalid domain name: gmail.com.com"
125+
);
126+
}

src/types/error/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ use rocket::{
2424
Outcome, Request, State,
2525
};
2626
use rocket_contrib::Json;
27-
use rusoto_ses::SendRawEmailError;
2827
use sendgrid::errors::SendgridError;
2928
use serde::ser::{Serialize, SerializeMap, Serializer};
3029
use serde_json::{map::Map, ser::to_string, Error as JsonError, Value};
@@ -277,7 +276,6 @@ to_internal_error!(JsonError);
277276
to_internal_error!(RedisError);
278277
to_internal_error!(RequestError);
279278
to_internal_error!(SendgridError);
280-
to_internal_error!(SendRawEmailError);
281279
to_internal_error!(SmtpError);
282280
to_internal_error!(SocketLabsError);
283281
to_internal_error!(ToStrError);

0 commit comments

Comments
 (0)