Merge pull request #260 from mozilla/pb/248
https://github.com/mozilla/fxa-email-service/pull/260 r=vladikoff
This commit is contained in:
Коммит
5eeb3b3a6b
|
@ -622,6 +622,7 @@ dependencies = [
|
|||
"rocket 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rocket_codegen 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rocket_contrib 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"roxmltree 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rusoto_core 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rusoto_credential 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rusoto_mock 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1597,6 +1598,14 @@ dependencies = [
|
|||
"serde_json 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roxmltree"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"xmlparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusoto_core"
|
||||
version = "0.34.0"
|
||||
|
@ -2526,6 +2535,11 @@ dependencies = [
|
|||
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xmlparser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.0"
|
||||
|
@ -2712,6 +2726,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum rocket 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "a61d746c68f1d357f6e011985570474c4af368aa81900320074098d34ed0c64e"
|
||||
"checksum rocket_codegen 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7873d65adfa3e440ac373a28240341853da170913aad7e4207c0198389e5d0e9"
|
||||
"checksum rocket_contrib 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2348e3b2458e173203f1e51f3b2e00495a092b70bd9506d2ce2ac64e129d14"
|
||||
"checksum roxmltree 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad070c83663f89f74524e296935fc4b2479a111c0ac57098effcba59c6a76b69"
|
||||
"checksum rusoto_core 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dac3a75644426c7d4116e85dd314d5be26400f06d40d5673511d69a1168101f6"
|
||||
"checksum rusoto_credential 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6b31eb8789afa4e601fa4677cab6886cbf8830b765f4da5cff2ba24ab485bfe"
|
||||
"checksum rusoto_mock 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab5c74050e9b4d7deb4ebebba181d76bd04c74d7fb52a47da72758b8e688679b"
|
||||
|
@ -2817,5 +2832,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e"
|
||||
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
||||
"checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2"
|
||||
"checksum xmlparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41e9a53f10a83f2d007556b671737aee4d4820d64f3f1b98e1ca27f31a81ddb4"
|
||||
"checksum yaml-rust 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57ab38ee1a4a266ed033496cf9af1828d8d6e6c1cfa5f643a2809effcae4d628"
|
||||
"checksum yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d60c3b48c9cdec42fb06b3b84b5b087405e1fa1c644a1af3930e4dfafe93de48"
|
||||
|
|
|
@ -39,6 +39,7 @@ reqwest = ">=0.8.5"
|
|||
rocket = ">=0.3.17"
|
||||
rocket_codegen = ">=0.3.17"
|
||||
rocket_contrib = ">=0.3.17"
|
||||
roxmltree = ">=0.3.0"
|
||||
rusoto_core = ">=0.34.0"
|
||||
rusoto_credential = ">=0.13.0"
|
||||
rusoto_mock = ">=0.28.0"
|
||||
|
|
|
@ -54,6 +54,7 @@ extern crate reqwest;
|
|||
extern crate rocket;
|
||||
#[macro_use]
|
||||
extern crate rocket_contrib;
|
||||
extern crate roxmltree;
|
||||
extern crate rusoto_core;
|
||||
extern crate rusoto_credential;
|
||||
extern crate rusoto_ses;
|
||||
|
|
|
@ -5,12 +5,16 @@
|
|||
use std::boxed::Box;
|
||||
|
||||
use base64;
|
||||
use roxmltree::Document as XmlDocument;
|
||||
use rusoto_core::{request::HttpClient, Region};
|
||||
use rusoto_credential::StaticProvider;
|
||||
use rusoto_ses::{RawMessage, SendRawEmailRequest, Ses, SesClient};
|
||||
use rusoto_ses::{RawMessage, SendRawEmailError, SendRawEmailRequest, Ses, SesClient};
|
||||
|
||||
use super::{build_multipart_mime, Headers, Provider};
|
||||
use crate::{settings::Settings, types::error::AppResult};
|
||||
use crate::{
|
||||
settings::Settings,
|
||||
types::error::{AppError, AppErrorKind, AppResult},
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
@ -77,3 +81,53 @@ impl Provider for SesProvider {
|
|||
.map_err(From::from)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SendRawEmailError> for AppError {
|
||||
fn from(error: SendRawEmailError) -> Self {
|
||||
if let SendRawEmailError::Unknown(ref body) = error {
|
||||
if let Ok(xml) = XmlDocument::parse(body) {
|
||||
for child in xml.root_element().children() {
|
||||
if child.is_element() && child.tag_name().name() == "Error" {
|
||||
let mut is_invalid_payload = false;
|
||||
let mut error_message = None;
|
||||
let mut error_property = None;
|
||||
|
||||
for grandchild in child.children() {
|
||||
if grandchild.is_element() {
|
||||
match grandchild.tag_name().name() {
|
||||
"Code" => {
|
||||
is_invalid_payload =
|
||||
grandchild.text() == Some("InvalidParameterValue")
|
||||
}
|
||||
"Message" => {
|
||||
error_message =
|
||||
grandchild.text().map(|message| message.to_owned())
|
||||
}
|
||||
"Type" => {
|
||||
error_property =
|
||||
grandchild.text().map(|property| property.to_owned())
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if is_invalid_payload {
|
||||
return AppErrorKind::InvalidPayload(error_message.unwrap_or_else(
|
||||
|| {
|
||||
format!(
|
||||
"Invalid {}",
|
||||
error_property.unwrap_or_else(|| "parameter".to_owned())
|
||||
)
|
||||
},
|
||||
))
|
||||
.into();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AppErrorKind::Internal(format!("{:?}", error)).into()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,3 +91,36 @@ fn ses_send_handles_error_response() {
|
|||
assert_eq!(error.error(), "Internal Server Error");
|
||||
assert_eq!(error.to_string(), "Unknown(\"FREAKOUT\")");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ses_send_handles_invalid_domain_response() {
|
||||
let body = r#"
|
||||
<ErrorResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
|
||||
<Error>
|
||||
<Type>Sender</Type>
|
||||
<Code>InvalidParameterValue</Code>
|
||||
<Message>Invalid domain name: gmail.com.com</Message>
|
||||
</Error>
|
||||
<RequestId>f972bc68-f90c-11e8-90d8-9f9fb80f3486</RequestId>
|
||||
</ErrorResponse>
|
||||
"#;
|
||||
let mock_dispatcher = MockRequestDispatcher::with_status(500).with_body(&body);
|
||||
let mock_ses = SesProvider {
|
||||
client: Box::new(SesClient::new_with(
|
||||
mock_dispatcher,
|
||||
MockCredentialsProvider,
|
||||
Region::SaEast1,
|
||||
)),
|
||||
sender: "Wibble <blee@example.com>".to_string(),
|
||||
};
|
||||
let result = mock_ses.send("blee@gmail.com.com", &[], None, "subject", "body", None);
|
||||
assert!(result.is_err());
|
||||
let error = result.unwrap_err();
|
||||
assert_eq!(error.code(), 400);
|
||||
assert_eq!(error.errno().unwrap(), 102);
|
||||
assert_eq!(error.error(), "Bad Request");
|
||||
assert_eq!(
|
||||
error.to_string(),
|
||||
"Invalid payload: Invalid domain name: gmail.com.com"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ use rocket::{
|
|||
Outcome, Request, State,
|
||||
};
|
||||
use rocket_contrib::Json;
|
||||
use rusoto_ses::SendRawEmailError;
|
||||
use sendgrid::errors::SendgridError;
|
||||
use serde::ser::{Serialize, SerializeMap, Serializer};
|
||||
use serde_json::{map::Map, ser::to_string, Error as JsonError, Value};
|
||||
|
@ -277,7 +276,6 @@ to_internal_error!(JsonError);
|
|||
to_internal_error!(RedisError);
|
||||
to_internal_error!(RequestError);
|
||||
to_internal_error!(SendgridError);
|
||||
to_internal_error!(SendRawEmailError);
|
||||
to_internal_error!(SmtpError);
|
||||
to_internal_error!(SocketLabsError);
|
||||
to_internal_error!(ToStrError);
|
||||
|
|
Загрузка…
Ссылка в новой задаче