mail: update to lettre-0.10.0-rc.5 and adapt
This commit is contained in:
parent
39fae28f53
commit
55ec155b30
|
@ -56,12 +56,6 @@ dependencies = [
|
||||||
"term",
|
"term",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ascii_utils"
|
|
||||||
version = "0.9.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-stream"
|
name = "async-stream"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
@ -166,12 +160,6 @@ dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "base64"
|
|
||||||
version = "0.11.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
|
@ -506,18 +494,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "email"
|
name = "email-encoding"
|
||||||
version = "0.0.20"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "91549a51bb0241165f13d57fc4c72cef063b4088fb078b019ecbf464a45f22e4"
|
checksum = "6690291166824e467790ac08ba42f241791567e8337bbf00c5a6e87889629f98"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.9.3",
|
"base64 0.13.0",
|
||||||
"chrono",
|
|
||||||
"encoding",
|
|
||||||
"lazy_static",
|
|
||||||
"rand 0.4.6",
|
|
||||||
"time 0.1.43",
|
|
||||||
"version_check 0.1.5",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -615,12 +597,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fast_chemail"
|
name = "fastrand"
|
||||||
version = "0.9.6"
|
version = "1.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "495a39d30d624c2caabe6312bfead73e7717692b44e0b32df168c275a2e8e9e4"
|
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ascii_utils",
|
"instant",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -944,7 +926,6 @@ dependencies = [
|
||||||
"multipart",
|
"multipart",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"regex",
|
"regex",
|
||||||
"rfc2047",
|
|
||||||
"ring",
|
"ring",
|
||||||
"rocket",
|
"rocket",
|
||||||
"rocket_codegen",
|
"rocket_codegen",
|
||||||
|
@ -1356,17 +1337,19 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lettre"
|
name = "lettre"
|
||||||
version = "0.10.0-pre"
|
version = "0.10.0-rc.5"
|
||||||
source = "git+https://github.com/lettre/lettre?rev=245c600c82ee18b766e8729f005ff453a55dce34#245c600c82ee18b766e8729f005ff453a55dce34"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5144148f337be14dabfc0f0d85b691a68ac6c77ef22a5c47c5504b70a7c9fcf3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.11.0",
|
"base64 0.13.0",
|
||||||
"email",
|
"email-encoding",
|
||||||
"fast_chemail",
|
"fastrand",
|
||||||
"log 0.4.14",
|
"httpdate",
|
||||||
|
"idna 0.2.3",
|
||||||
"mime 0.3.16",
|
"mime 0.3.16",
|
||||||
"serde",
|
"once_cell",
|
||||||
"serde_json",
|
"quoted_printable",
|
||||||
"time 0.2.27",
|
"regex",
|
||||||
"uuid 0.8.2",
|
"uuid 0.8.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2097,17 +2080,10 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "quoted_printable"
|
||||||
version = "0.4.6"
|
version = "0.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
checksum = "3fee2dce59f7a43418e3382c766554c614e06a552d53a8f07ef499ea4b332c0f"
|
||||||
dependencies = [
|
|
||||||
"fuchsia-cprng",
|
|
||||||
"libc",
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
"rdrand",
|
|
||||||
"winapi 0.3.9",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
|
@ -2379,12 +2355,6 @@ dependencies = [
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rfc2047"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6986b5de4fa30c92b50020fdedf45bf9296d9842df4355b62f92dcc18bcdee15"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.13.5"
|
version = "0.13.5"
|
||||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -39,8 +39,8 @@ gettext-macros = "0.6.1"
|
||||||
gettext-utils = "0.1"
|
gettext-utils = "0.1"
|
||||||
gettext = "0.4"
|
gettext = "0.4"
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
rfc2047 = "0.1"
|
|
||||||
hyperx = "1.4"
|
hyperx = "1.4"
|
||||||
|
lettre = { version = "0.10.0-rc.5", default-features = false, features = ["builder", "file-transport", "sendmail-transport"] }
|
||||||
|
|
||||||
[dependencies.rocket_i18n]
|
[dependencies.rocket_i18n]
|
||||||
git = "https://github.com/Plume-org/rocket_i18n"
|
git = "https://github.com/Plume-org/rocket_i18n"
|
||||||
|
@ -48,14 +48,6 @@ branch = "go-async"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["rocket"]
|
features = ["rocket"]
|
||||||
|
|
||||||
[dependencies.lettre]
|
|
||||||
version = "0.10.0-pre"
|
|
||||||
default-features = false
|
|
||||||
# smtp-transport doesn't build (openssl problem)
|
|
||||||
features = ["builder", "file-transport", "sendmail-transport"]
|
|
||||||
git = "https://github.com/lettre/lettre"
|
|
||||||
rev = "245c600c82ee18b766e8729f005ff453a55dce34"
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
vergen = "3"
|
vergen = "3"
|
||||||
|
|
||||||
|
|
94
src/mail.rs
94
src/mail.rs
|
@ -2,16 +2,14 @@ use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use crate::counters;
|
use crate::counters;
|
||||||
use handlebars::Handlebars;
|
use handlebars::Handlebars;
|
||||||
use lettre::builder::{EmailBuilder, Mailbox, MimeMultipartType, PartBuilder};
|
use lettre::message::{Mailbox, MultiPart, SinglePart, header};
|
||||||
use lettre::{file::FileTransport, SendmailTransport, Transport as LettreTransport};
|
use lettre::{FileTransport, SendmailTransport, Transport as LettreTransport};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use gettext_macros::i18n;
|
use gettext_macros::i18n;
|
||||||
use rocket_i18n::I18n;
|
use rocket_i18n::I18n;
|
||||||
|
|
||||||
use rfc2047::rfc2047_encode;
|
|
||||||
|
|
||||||
use crate::template_helpers;
|
use crate::template_helpers;
|
||||||
|
|
||||||
use crate::database::types::Email;
|
use crate::database::types::Email;
|
||||||
|
@ -81,8 +79,9 @@ impl Service {
|
||||||
.host_str()
|
.host_str()
|
||||||
.ok_or_else(|| anyhow!("No host in base-URI"))?
|
.ok_or_else(|| anyhow!("No host in base-URI"))?
|
||||||
.to_string();
|
.to_string();
|
||||||
|
let from = from.parse().map_err(|_| anyhow!("From must be valid email address"))?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
from: from.into(),
|
from,
|
||||||
domain,
|
domain,
|
||||||
templates,
|
templates,
|
||||||
transport,
|
transport,
|
||||||
|
@ -203,7 +202,7 @@ impl Service {
|
||||||
|
|
||||||
fn send(
|
fn send(
|
||||||
&self,
|
&self,
|
||||||
to: &[&Email],
|
tos: &[&Email],
|
||||||
subject: &str,
|
subject: &str,
|
||||||
template: &str,
|
template: &str,
|
||||||
locale: &str,
|
locale: &str,
|
||||||
|
@ -212,46 +211,44 @@ impl Service {
|
||||||
let (html, txt) = self.render_template(template, locale, ctx)?;
|
let (html, txt) = self.render_template(template, locale, ctx)?;
|
||||||
|
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
for recipient in to.iter() {
|
for recipient in tos.iter() {
|
||||||
println!("To: {}", recipient);
|
println!("To: {}", recipient);
|
||||||
}
|
}
|
||||||
println!("{}", &txt);
|
println!("{}", &txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build this ourselves, as a temporary workaround for https://github.com/lettre/lettre/issues/400
|
let mut email = lettre::Message::builder()
|
||||||
let text = PartBuilder::new()
|
|
||||||
.body(txt)
|
|
||||||
.header(("Content-Type", "text/plain; charset=utf-8"))
|
|
||||||
.header(("Content-Transfer-Encoding", "8bit"))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let html = PartBuilder::new()
|
|
||||||
.body(html)
|
|
||||||
.header(("Content-Type", "text/html; charset=utf-8"))
|
|
||||||
.header(("Content-Transfer-Encoding", "8bit"))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let email = EmailBuilder::new()
|
|
||||||
.from(self.from.clone())
|
.from(self.from.clone())
|
||||||
.subject(rfc2047_encode(subject))
|
.subject(subject)
|
||||||
.message_id(format!("<{}@{}>", Uuid::new_v4(), self.domain))
|
.message_id(Some(format!("<{}@{}>", Uuid::new_v4(), self.domain)))
|
||||||
.message_type(MimeMultipartType::Alternative)
|
.header(header::ContentTransferEncoding::EightBit);
|
||||||
.header(("Content-Transfer-Encoding", "8bit"))
|
|
||||||
.child(text)
|
|
||||||
.child(html);
|
|
||||||
|
|
||||||
let email = to.iter().fold(email, |email, to| email.to(to.to_string()));
|
for to in tos.iter() {
|
||||||
|
email = email.to(to.as_str().parse().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
let email = email.build()?;
|
let email = email.multipart(
|
||||||
|
MultiPart::alternative()
|
||||||
|
.singlepart(
|
||||||
|
SinglePart::builder()
|
||||||
|
.header(header::ContentTransferEncoding::EightBit)
|
||||||
|
.header(header::ContentType::TEXT_PLAIN)
|
||||||
|
.body(txt)
|
||||||
|
)
|
||||||
|
.singlepart(SinglePart::builder()
|
||||||
|
.header(header::ContentTransferEncoding::EightBit)
|
||||||
|
.header(header::ContentType::TEXT_HTML)
|
||||||
|
.body(html)),
|
||||||
|
)?;
|
||||||
|
|
||||||
match self.transport {
|
match self.transport {
|
||||||
Transport::Sendmail => {
|
Transport::Sendmail => {
|
||||||
let mut transport = SendmailTransport::new();
|
let transport = SendmailTransport::new();
|
||||||
transport.send(email)?;
|
transport.send(&email)?;
|
||||||
}
|
}
|
||||||
Transport::Filemail(ref path) => {
|
Transport::Filemail(ref path) => {
|
||||||
let mut transport = FileTransport::new(path);
|
let transport = FileTransport::new(path);
|
||||||
transport.send(email)?;
|
transport.send(&email)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,31 +256,17 @@ impl Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for some reason, this is no longer public in lettre itself
|
|
||||||
// FIXME replace with builtin struct on lettre update
|
|
||||||
// see https://github.com/lettre/lettre/blob/master/lettre/src/file/mod.rs#L41
|
|
||||||
#[cfg(test)]
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct SerializableEmail {
|
|
||||||
#[serde(alias = "envelope")]
|
|
||||||
_envelope: lettre::Envelope,
|
|
||||||
#[serde(alias = "message_id")]
|
|
||||||
_message_id: String,
|
|
||||||
message: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns and removes the first mail it finds from the given
|
/// Returns and removes the first mail it finds from the given
|
||||||
/// directory.
|
/// directory.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn pop_mail(dir: &Path) -> Result<Option<String>> {
|
pub fn pop_mail(dir: &Path) -> Result<Option<String>> {
|
||||||
use std::fs;
|
use std::{fs, fs::read_to_string};
|
||||||
for entry in fs::read_dir(dir)? {
|
for entry in fs::read_dir(dir)? {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
if entry.file_type()?.is_file() {
|
if entry.file_type()?.is_file() {
|
||||||
let fh = fs::File::open(entry.path())?;
|
let body = read_to_string(entry.path())?.replace("\r\n", "\n");
|
||||||
fs::remove_file(entry.path())?;
|
fs::remove_file(entry.path())?;
|
||||||
let mail: SerializableEmail = ::serde_json::from_reader(fh)?;
|
println!("{}", body);
|
||||||
let body = String::from_utf8_lossy(&mail.message).to_string();
|
|
||||||
return Ok(Some(body));
|
return Ok(Some(body));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,15 +329,14 @@ mod test {
|
||||||
(h, v)
|
(h, v)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
assert!(headers.contains(&("Content-Transfer-Encoding", "8bit")));
|
|
||||||
assert!(headers.contains(&("Content-Type", "text/plain; charset=utf-8")));
|
assert!(headers.contains(&("Content-Type", "text/plain; charset=utf-8")));
|
||||||
assert!(headers.contains(&("Content-Type", "text/html; charset=utf-8")));
|
assert!(headers.contains(&("Content-Type", "text/html; charset=utf-8")));
|
||||||
assert!(headers.contains(&("From", "<test@localhost>")));
|
assert!(headers.contains(&("From", "test@localhost")));
|
||||||
assert!(headers.contains(&("To", "<recipient@example.org>")));
|
assert!(headers.contains(&("To", "recipient@example.org")));
|
||||||
assert_header(&headers, "Content-Type", |v| {
|
assert_header(&headers, "Content-Type", |v| {
|
||||||
v.starts_with("multipart/alternative")
|
v.starts_with("multipart/alternative")
|
||||||
});
|
});
|
||||||
assert_header(&headers, "Date", |v| v.contains("+0000"));
|
assert_header(&headers, "Date", |v| v.contains("-0000"));
|
||||||
assert_header(&headers, "Message-ID", |v| v.contains("@localhost>"));
|
assert_header(&headers, "Message-ID", |v| v.contains("@localhost>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,7 +395,7 @@ mod test {
|
||||||
assert!(mail_content.contains("test/about"));
|
assert!(mail_content.contains("test/about"));
|
||||||
assert!(mail_content.contains("あなたのメールアド"));
|
assert!(mail_content.contains("あなたのメールアド"));
|
||||||
assert!(mail_content.contains(
|
assert!(mail_content.contains(
|
||||||
"Subject: =?utf-8?q?localhost=E3=81=AE=E3=81=82=E3=81=AA=E3=81=9F=E3=81=AE?="
|
"Subject: =?utf-8?b?bG9jYWxob3N044Gu44GC44Gq44Gf44Gu6Y2144Gu44Gf44KB44GrbG9jYWxob3N044KS5qSc6Ki844GZ44KL?="
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,7 +449,7 @@ mod test {
|
||||||
assert!(mail_content.contains("test/about"));
|
assert!(mail_content.contains("test/about"));
|
||||||
assert!(mail_content.contains("この鍵の掲示されたア"));
|
assert!(mail_content.contains("この鍵の掲示されたア"));
|
||||||
assert!(mail_content.contains(
|
assert!(mail_content.contains(
|
||||||
"Subject: =?utf-8?q?localhost=E3=81=AE=E9=8D=B5=E3=82=92=E7=AE=A1=E7=90=86?="
|
"Subject: =?utf-8?b?bG9jYWxob3N044Gu6Y2144KS566h55CG44GZ44KL?="
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -887,7 +887,7 @@ pub mod tests {
|
||||||
check_verify_link(&client, &token, "foo@invalid.example.com", "de");
|
check_verify_link(&client, &token, "foo@invalid.example.com", "de");
|
||||||
let mail_content = pop_mail(&filemail_into).unwrap().unwrap();
|
let mail_content = pop_mail(&filemail_into).unwrap().unwrap();
|
||||||
assert!(mail_content.contains("Dies ist eine automatisierte Nachricht"));
|
assert!(mail_content.contains("Dies ist eine automatisierte Nachricht"));
|
||||||
assert!(mail_content.contains("Subject: =?utf-8?q?Best=C3=A4tige?= foo@invalid.example.com\r\n\t=?utf-8?q?f=C3=BCr?= deinen =?utf-8?q?Schl=C3=BCssel?= auf local.connection"));
|
assert!(mail_content.contains("Subject: =?utf-8?b?QmVzdMOkdGlnZQ==?= foo@invalid.example.com \n =?utf-8?b?ZsO8cg==?= deinen =?utf-8?b?U2NobMO8c3NlbA==?= auf \n local.connection"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in New Issue