https://github.com/mozilla/fxa-email-service/pull/241
r=vladikoff
This commit is contained in:
Phil Booth 2018-11-15 14:33:58 +00:00 коммит произвёл GitHub
Родитель b74a56f0d9 3d73bee857
Коммит ecb7c38da0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 103 добавлений и 59 удалений

Просмотреть файл

@ -2,9 +2,6 @@ language: rust
services:
- redis-server
cache: cargo
branches:
only:
- master
before_script:
- rustup component add rustfmt-preview
script:

Просмотреть файл

@ -1,3 +1,17 @@
<a name="v1.125.1"></a>
## v1.125.1 (2018-11-15)
#### Bug Fixes
* **ci:** enable branch builds in travis ([14491612](14491612))
* **headers:** propagate the Content-Language header ([67ebf3fe](67ebf3fe))
* **ses:**
* add Sender header ([3e278667](3e278667))
* ensure html part gets charset=utf-8 content type ([67320d28](67320d28))
<a name="v1.125.0"></a>
## v1.125.0 (2018-11-14)

2
Cargo.lock сгенерированный
Просмотреть файл

@ -598,7 +598,7 @@ dependencies = [
[[package]]
name = "fxa_email_service"
version = "1.125.0"
version = "1.125.1"
dependencies = [
"base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",

Просмотреть файл

@ -1,6 +1,6 @@
[package]
name = "fxa_email_service"
version = "1.125.0"
version = "1.125.1"
publish = false
[[bin]]

Просмотреть файл

@ -6,7 +6,7 @@
use std::{boxed::Box, collections::HashMap, convert::TryFrom};
use emailmessage::{header::ContentType, Message, MessageBuilder, MultiPart, SinglePart};
use emailmessage::{header::ContentType, Mailbox, Message, MessageBuilder, MultiPart, SinglePart};
use self::{
mock::MockProvider as Mock, sendgrid::SendgridProvider as Sendgrid, ses::SesProvider as Ses,
@ -40,16 +40,17 @@ fn build_multipart_mime<'a>(
body_text: &'a str,
body_html: Option<&'a str>,
) -> AppResult<Message<MultiPart<&'a str>>> {
let mut message =
Message::builder()
.from(sender.parse().map_err(|_| {
AppErrorKind::InvalidPayload(format!("`from` address \"{}\"", sender))
})?)
.to(to
.parse()
.map_err(|_| AppErrorKind::InvalidPayload(format!("`to` address \"{}\"", to)))?)
.subject(subject)
.mime_1_0();
let sender: Mailbox = sender
.parse()
.map_err(|_| AppErrorKind::InvalidPayload(format!("`from` address \"{}\"", sender)))?;
let mut message = Message::builder()
.sender(sender.clone())
.from(sender)
.to(to
.parse()
.map_err(|_| AppErrorKind::InvalidPayload(format!("`to` address \"{}\"", to)))?)
.subject(subject)
.mime_1_0();
if cc.len() > 0 {
for address in cc.iter() {
@ -74,7 +75,7 @@ fn build_multipart_mime<'a>(
body = body.multipart(
MultiPart::related().singlepart(
SinglePart::base64()
.header(ContentType::html())
.header(ContentType("text/html; charset=utf-8".parse()?))
.body(body_html),
),
);
@ -86,6 +87,7 @@ fn build_multipart_mime<'a>(
fn set_custom_header(message: MessageBuilder, name: &str, value: &str) -> MessageBuilder {
let lowercase_name = name.to_lowercase();
match lowercase_name.as_str() {
"content-language" => message.header(ContentLanguage::new(value.to_owned())),
"x-device-id" => message.header(DeviceId::new(value.to_owned())),
"x-email-sender" => message.header(EmailSender::new(value.to_owned())),
"x-email-service" => message.header(EmailService::new(value.to_owned())),

Просмотреть файл

@ -8,27 +8,10 @@ use super::*;
#[test]
fn build_mime_without_optional_data() {
let message =
build_multipart_mime("a@a.com", "b@b.com", &[], None, "subject", "body", None).unwrap();
let message: Vec<String> = format!("{}", message)
.split("\r\n")
.map(|s| s.to_owned())
.collect();
assert_eq!("From: a@a.com", &message[0]);
assert_eq!("To: b@b.com", &message[1]);
assert_eq!("Subject: subject", &message[2]);
assert_eq!("MIME-Version: 1.0", &message[3]);
assert_eq!("Content-Transfer-Encoding: quoted-printable", &message[10]);
assert_eq!("Content-Type: text/plain; charset=utf-8", &message[11]);
assert_eq!("body", &message[13]);
}
#[test]
fn build_mime_with_cc_headers() {
let message = build_multipart_mime(
"a@a.com",
"Wibble Blee <a@a.com>",
"b@b.com",
&["c@c.com", "d@d.com"],
&[],
None,
"subject",
"body",
@ -39,16 +22,52 @@ fn build_mime_with_cc_headers() {
.split("\r\n")
.map(|s| s.to_owned())
.collect();
assert_eq!("From: a@a.com", &message[0]);
assert_eq!("To: b@b.com", &message[1]);
assert_eq!("Subject: subject", &message[2]);
assert_eq!("MIME-Version: 1.0", &message[3]);
assert_eq!("Cc: c@c.com, d@d.com", &message[4]);
assert_eq!("Sender: Wibble Blee <a@a.com>", &message[0]);
assert_eq!("From: Wibble Blee <a@a.com>", &message[1]);
assert_eq!("To: b@b.com", &message[2]);
assert_eq!("Subject: subject", &message[3]);
assert_eq!("MIME-Version: 1.0", &message[4]);
assert_eq!("Content-Transfer-Encoding: quoted-printable", &message[11]);
assert_eq!("Content-Type: text/plain; charset=utf-8", &message[12]);
assert_eq!("body", &message[14]);
}
#[test]
fn build_mime_with_cc_headers() {
let mut headers = HashMap::new();
headers.insert("Content-Language".to_owned(), "en-gb".to_owned());
headers.insert("x-verify-code".to_owned(), "wibble".to_owned());
let message = build_multipart_mime(
"a@a.com",
"b@b.com",
&["c@c.com", "d@d.com"],
Some(&headers),
"subject",
"body",
None,
)
.unwrap();
let message: Vec<String> = format!("{}", message)
.split("\r\n")
.map(|s| s.to_owned())
.collect();
assert_eq!("Sender: a@a.com", &message[0]);
assert_eq!("From: a@a.com", &message[1]);
assert_eq!("To: b@b.com", &message[2]);
assert_eq!("Subject: subject", &message[3]);
assert_eq!("MIME-Version: 1.0", &message[4]);
assert_eq!("Cc: c@c.com, d@d.com", &message[5]);
if message[6] == "Content-Language: en-gb" {
assert_eq!("X-Verify-Code: wibble", &message[7]);
} else {
assert_eq!("X-Verify-Code: wibble", &message[6]);
assert_eq!("Content-Language: en-gb", &message[7]);
}
assert_eq!("Content-Transfer-Encoding: quoted-printable", &message[14]);
assert_eq!("Content-Type: text/plain; charset=utf-8", &message[15]);
assert_eq!("body", &message[17]);
}
#[test]
fn build_mime_with_custom_headers() {
let mut custom_headers = HashMap::new();
@ -68,14 +87,15 @@ fn build_mime_with_custom_headers() {
.split("\r\n")
.map(|s| s.to_owned())
.collect();
assert_eq!("From: a@a.com", &message[0]);
assert_eq!("To: b@b.com", &message[1]);
assert_eq!("Subject: subject", &message[2]);
assert_eq!("MIME-Version: 1.0", &message[3]);
assert_eq!("X-Device-Id: baz", &message[4]);
assert_eq!("Content-Transfer-Encoding: quoted-printable", &message[11]);
assert_eq!("Content-Type: text/plain; charset=utf-8", &message[12]);
assert_eq!("body", &message[14]);
assert_eq!("Sender: a@a.com", &message[0]);
assert_eq!("From: a@a.com", &message[1]);
assert_eq!("To: b@b.com", &message[2]);
assert_eq!("Subject: subject", &message[3]);
assert_eq!("MIME-Version: 1.0", &message[4]);
assert_eq!("X-Device-Id: baz", &message[5]);
assert_eq!("Content-Transfer-Encoding: quoted-printable", &message[12]);
assert_eq!("Content-Type: text/plain; charset=utf-8", &message[13]);
assert_eq!("body", &message[15]);
}
#[test]
@ -94,16 +114,17 @@ fn build_mime_with_body_html() {
.split("\r\n")
.map(|s| s.to_owned())
.collect();
assert_eq!("From: a@a.com", &message[0]);
assert_eq!("To: b@b.com", &message[1]);
assert_eq!("Subject: subject", &message[2]);
assert_eq!("MIME-Version: 1.0", &message[3]);
assert_eq!("Content-Transfer-Encoding: quoted-printable", &message[10]);
assert_eq!("Content-Type: text/plain; charset=utf-8", &message[11]);
assert_eq!("body", &message[13]);
assert_eq!("Content-Transfer-Encoding: base64", &message[18]);
assert_eq!("Content-Type: text/html", &message[19]);
assert_eq!("PHA+Ym9keTwvcD4=", &message[21]);
assert_eq!("Sender: a@a.com", &message[0]);
assert_eq!("From: a@a.com", &message[1]);
assert_eq!("To: b@b.com", &message[2]);
assert_eq!("Subject: subject", &message[3]);
assert_eq!("MIME-Version: 1.0", &message[4]);
assert_eq!("Content-Transfer-Encoding: quoted-printable", &message[11]);
assert_eq!("Content-Type: text/plain; charset=utf-8", &message[12]);
assert_eq!("body", &message[14]);
assert_eq!("Content-Transfer-Encoding: base64", &message[19]);
assert_eq!("Content-Type: text/html; charset=utf-8", &message[20]);
assert_eq!("PHA+Ym9keTwvcD4=", &message[22]);
}
#[test]

Просмотреть файл

@ -12,6 +12,7 @@ use std::{
use failure::{Backtrace, Context, Fail};
use hmac::crypto_mac::InvalidKeyLength;
use hyperx::mime::FromStrError;
use lettre::smtp::error::Error as SmtpError;
use lettre_email::error::Error as EmailError;
use redis::RedisError;
@ -252,6 +253,7 @@ macro_rules! to_internal_error {
}
to_internal_error!(EmailError);
to_internal_error!(FromStrError);
to_internal_error!(InvalidKeyLength);
to_internal_error!(JsonError);
to_internal_error!(RedisError);

Просмотреть файл

@ -73,6 +73,7 @@ macro_rules! custom_header {
};
}
custom_header!(ContentLanguage, "Content-Language");
custom_header!(DeviceId, "X-Device-Id");
custom_header!(EmailSender, "X-Email-Sender");
custom_header!(EmailService, "X-Email-Service");

Просмотреть файл

@ -4,6 +4,13 @@
use super::*;
#[test]
fn content_language() {
let header = ContentLanguage::new("en-gb".to_owned());
assert_eq!(header.to_string(), "en-gb");
assert_eq!(ContentLanguage::header_name(), "Content-Language");
}
#[test]
fn device_id() {
let header = DeviceId::new("wibble".to_owned());