Spiegel von
https://github.com/dani-garcia/vaultwarden.git
synchronisiert 2024-11-26 05:50:29 +01:00
Update lettre to latest master
Dieser Commit ist enthalten in:
Ursprung
9cca64003a
Commit
63cbd9ef9c
4 geänderte Dateien mit 96 neuen und 173 gelöschten Zeilen
175
Cargo.lock
generiert
175
Cargo.lock
generiert
|
@ -27,12 +27,6 @@ dependencies = [
|
||||||
"nodrop",
|
"nodrop",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ascii_utils"
|
|
||||||
version = "0.9.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
@ -109,6 +103,12 @@ version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "binascii"
|
name = "binascii"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
@ -148,7 +148,6 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"openssl",
|
"openssl",
|
||||||
"percent-encoding 2.1.0",
|
"percent-encoding 2.1.0",
|
||||||
"quoted_printable",
|
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"ring",
|
"ring",
|
||||||
|
@ -482,85 +481,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 = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3"
|
checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "email"
|
|
||||||
version = "0.0.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "91549a51bb0241165f13d57fc4c72cef063b4088fb078b019ecbf464a45f22e4"
|
|
||||||
dependencies = [
|
|
||||||
"base64 0.9.3",
|
|
||||||
"chrono",
|
|
||||||
"encoding",
|
|
||||||
"lazy_static",
|
|
||||||
"rand 0.4.6",
|
|
||||||
"time 0.1.43",
|
|
||||||
"version_check 0.1.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "encoding"
|
|
||||||
version = "0.2.33"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
|
|
||||||
dependencies = [
|
|
||||||
"encoding-index-japanese",
|
|
||||||
"encoding-index-korean",
|
|
||||||
"encoding-index-simpchinese",
|
|
||||||
"encoding-index-singlebyte",
|
|
||||||
"encoding-index-tradchinese",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "encoding-index-japanese"
|
|
||||||
version = "1.20141219.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
|
|
||||||
dependencies = [
|
|
||||||
"encoding_index_tests",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "encoding-index-korean"
|
|
||||||
version = "1.20141219.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
|
|
||||||
dependencies = [
|
|
||||||
"encoding_index_tests",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "encoding-index-simpchinese"
|
|
||||||
version = "1.20141219.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
|
|
||||||
dependencies = [
|
|
||||||
"encoding_index_tests",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "encoding-index-singlebyte"
|
|
||||||
version = "1.20141219.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
|
|
||||||
dependencies = [
|
|
||||||
"encoding_index_tests",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "encoding-index-tradchinese"
|
|
||||||
version = "1.20141219.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
|
|
||||||
dependencies = [
|
|
||||||
"encoding_index_tests",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "encoding_index_tests"
|
|
||||||
version = "0.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.22"
|
version = "0.8.22"
|
||||||
|
@ -585,15 +505,6 @@ version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fast_chemail"
|
|
||||||
version = "0.9.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "495a39d30d624c2caabe6312bfead73e7717692b44e0b32df168c275a2e8e9e4"
|
|
||||||
dependencies = [
|
|
||||||
"ascii_utils",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fern"
|
name = "fern"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
@ -888,17 +799,6 @@ dependencies = [
|
||||||
"digest 0.8.1",
|
"digest 0.8.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hostname"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"match_cfg",
|
|
||||||
"winapi 0.3.8",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "html5ever"
|
name = "html5ever"
|
||||||
version = "0.22.5"
|
version = "0.22.5"
|
||||||
|
@ -1008,6 +908,24 @@ dependencies = [
|
||||||
"tokio-tls",
|
"tokio-tls",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyperx"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81d7ed6ec7d25c4de28b999a5693f14609a8b756137b1b4cb4927d119f59ef25"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.11.0",
|
||||||
|
"bytes 0.5.4",
|
||||||
|
"http",
|
||||||
|
"httparse",
|
||||||
|
"language-tags",
|
||||||
|
"log 0.4.8",
|
||||||
|
"mime 0.3.16",
|
||||||
|
"percent-encoding 2.1.0",
|
||||||
|
"time 0.1.43",
|
||||||
|
"unicase 2.6.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
|
@ -1128,20 +1046,21 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lettre"
|
name = "lettre"
|
||||||
version = "0.10.0-pre"
|
version = "0.10.0-pre"
|
||||||
source = "git+https://github.com/lettre/lettre?rev=245c600c82ee18b766e8729f005ff453a55dce34#245c600c82ee18b766e8729f005ff453a55dce34"
|
source = "git+https://github.com/lettre/lettre?rev=88df2a502d537ebfdd4218fb6b9f4168fb0f7943#88df2a502d537ebfdd4218fb6b9f4168fb0f7943"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.11.0",
|
"base64 0.12.0",
|
||||||
"bufstream",
|
"bufstream",
|
||||||
"email",
|
"hyperx",
|
||||||
"fast_chemail",
|
"idna 0.2.0",
|
||||||
"hostname",
|
"line-wrap",
|
||||||
"log 0.4.8",
|
|
||||||
"mime 0.3.16",
|
"mime 0.3.16",
|
||||||
"native-tls",
|
"native-tls",
|
||||||
"nom",
|
"nom",
|
||||||
|
"once_cell",
|
||||||
|
"quoted_printable",
|
||||||
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"textnonce",
|
||||||
"time 0.2.14",
|
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1175,6 +1094,15 @@ dependencies = [
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "line-wrap"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9"
|
||||||
|
dependencies = [
|
||||||
|
"safemem",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
|
@ -1230,12 +1158,6 @@ dependencies = [
|
||||||
"tendril",
|
"tendril",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "match_cfg"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matches"
|
name = "matches"
|
||||||
version = "0.1.8"
|
version = "0.1.8"
|
||||||
|
@ -2725,6 +2647,19 @@ dependencies = [
|
||||||
"utf-8",
|
"utf-8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textnonce"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acc659075a12c12c07bbb384862c352506707f6597f5b495f65427d08519b617"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.12.0",
|
||||||
|
"byteorder",
|
||||||
|
"chrono",
|
||||||
|
"rand 0.7.3",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textwrap"
|
name = "textwrap"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
|
|
|
@ -92,9 +92,8 @@ num-traits = "0.2.11"
|
||||||
num-derive = "0.3.0"
|
num-derive = "0.3.0"
|
||||||
|
|
||||||
# Email libraries
|
# Email libraries
|
||||||
lettre = "0.10.0-pre"
|
lettre = { version = "0.10.0-pre", features = ["smtp-transport", "builder", "serde", "native-tls"], default-features = false }
|
||||||
native-tls = "0.2.4"
|
native-tls = "0.2.4"
|
||||||
quoted_printable = "0.4.2"
|
|
||||||
|
|
||||||
# Template library
|
# Template library
|
||||||
handlebars = { version = "3.0.1", features = ["dir_source"] }
|
handlebars = { version = "3.0.1", features = ["dir_source"] }
|
||||||
|
@ -124,7 +123,7 @@ rocket = { git = 'https://github.com/SergioBenitez/Rocket', rev = '1010f6a2a88fa
|
||||||
rocket_contrib = { git = 'https://github.com/SergioBenitez/Rocket', rev = '1010f6a2a88fac899dec0cd2f642156908038a53' }
|
rocket_contrib = { git = 'https://github.com/SergioBenitez/Rocket', rev = '1010f6a2a88fac899dec0cd2f642156908038a53' }
|
||||||
|
|
||||||
# Use git version for timeout fix #706
|
# Use git version for timeout fix #706
|
||||||
lettre = { git = 'https://github.com/lettre/lettre', rev = '245c600c82ee18b766e8729f005ff453a55dce34' }
|
lettre = { git = 'https://github.com/lettre/lettre', rev = '88df2a502d537ebfdd4218fb6b9f4168fb0f7943' }
|
||||||
|
|
||||||
# For favicon extraction from main website
|
# For favicon extraction from main website
|
||||||
data-url = { git = 'https://github.com/servo/rust-url', package="data-url", rev = '7f1bd6ce1c2fde599a757302a843a60e714c5f72' }
|
data-url = { git = 'https://github.com/servo/rust-url', package="data-url", rev = '7f1bd6ce1c2fde599a757302a843a60e714c5f72' }
|
||||||
|
|
|
@ -45,7 +45,9 @@ use std::option::NoneError as NoneErr;
|
||||||
use std::time::SystemTimeError as TimeErr;
|
use std::time::SystemTimeError as TimeErr;
|
||||||
use u2f::u2ferror::U2fError as U2fErr;
|
use u2f::u2ferror::U2fError as U2fErr;
|
||||||
use yubico::yubicoerror::YubicoError as YubiErr;
|
use yubico::yubicoerror::YubicoError as YubiErr;
|
||||||
use lettre::smtp::error::Error as LettreErr;
|
use lettre::error::Error as LettreErr;
|
||||||
|
use lettre::address::AddressError as AddrErr;
|
||||||
|
use lettre::transport::smtp::error::Error as SmtpErr;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Empty {}
|
pub struct Empty {}
|
||||||
|
@ -73,7 +75,9 @@ make_error! {
|
||||||
ReqError(ReqErr): _has_source, _api_error,
|
ReqError(ReqErr): _has_source, _api_error,
|
||||||
RegexError(RegexErr): _has_source, _api_error,
|
RegexError(RegexErr): _has_source, _api_error,
|
||||||
YubiError(YubiErr): _has_source, _api_error,
|
YubiError(YubiErr): _has_source, _api_error,
|
||||||
LetreErr(LettreErr): _has_source, _api_error,
|
LetreError(LettreErr):_has_source, _api_error,
|
||||||
|
AddressError(AddrErr):_has_source, _api_error,
|
||||||
|
SmtpError(SmtpErr): _has_source, _api_error,
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is implemented by hand because NoneError doesn't implement neither Display nor Error
|
// This is implemented by hand because NoneError doesn't implement neither Display nor Error
|
||||||
|
|
81
src/mail.rs
81
src/mail.rs
|
@ -1,13 +1,11 @@
|
||||||
use lettre::smtp::authentication::Credentials;
|
use std::str::FromStr;
|
||||||
use lettre::smtp::authentication::Mechanism as SmtpAuthMechanism;
|
|
||||||
use lettre::smtp::ConnectionReuseParameters;
|
use lettre::message::{header, Mailbox, Message, MultiPart, SinglePart};
|
||||||
use lettre::{
|
use lettre::transport::smtp::authentication::{Credentials, Mechanism as SmtpAuthMechanism};
|
||||||
builder::{EmailBuilder, MimeMultipartType, PartBuilder},
|
use lettre::{Address, SmtpTransport, Tls, TlsParameters, Transport};
|
||||||
ClientSecurity, ClientTlsParameters, SmtpClient, SmtpTransport, Transport,
|
|
||||||
};
|
|
||||||
use native_tls::{Protocol, TlsConnector};
|
use native_tls::{Protocol, TlsConnector};
|
||||||
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
||||||
use quoted_printable::encode_to_str;
|
|
||||||
|
|
||||||
use crate::api::EmptyResult;
|
use crate::api::EmptyResult;
|
||||||
use crate::auth::{encode_jwt, generate_delete_claims, generate_invite_claims, generate_verify_email_claims};
|
use crate::auth::{encode_jwt, generate_delete_claims, generate_invite_claims, generate_verify_email_claims};
|
||||||
|
@ -24,23 +22,23 @@ fn mailer() -> SmtpTransport {
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let params = ClientTlsParameters::new(host.clone(), tls);
|
let params = TlsParameters::new(host.clone(), tls);
|
||||||
|
|
||||||
if CONFIG.smtp_explicit_tls() {
|
if CONFIG.smtp_explicit_tls() {
|
||||||
ClientSecurity::Wrapper(params)
|
Tls::Wrapper(params)
|
||||||
} else {
|
} else {
|
||||||
ClientSecurity::Required(params)
|
Tls::Required(params)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ClientSecurity::None
|
Tls::None
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
let smtp_client = SmtpClient::new((host.as_str(), CONFIG.smtp_port()), client_security).unwrap();
|
let smtp_client = SmtpTransport::new(host).port(CONFIG.smtp_port()).tls(client_security);
|
||||||
|
|
||||||
let smtp_client = match (&CONFIG.smtp_username(), &CONFIG.smtp_password()) {
|
let smtp_client = match (CONFIG.smtp_username(), CONFIG.smtp_password()) {
|
||||||
(Some(user), Some(pass)) => smtp_client.credentials(Credentials::new(user.clone(), pass.clone())),
|
(Some(user), Some(pass)) => smtp_client.credentials(Credentials::new(user, pass)),
|
||||||
_ => smtp_client,
|
_ => smtp_client,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,19 +46,16 @@ fn mailer() -> SmtpTransport {
|
||||||
Some(mechanism) => {
|
Some(mechanism) => {
|
||||||
let correct_mechanism = format!("\"{}\"", crate::util::upcase_first(mechanism.trim_matches('"')));
|
let correct_mechanism = format!("\"{}\"", crate::util::upcase_first(mechanism.trim_matches('"')));
|
||||||
|
|
||||||
|
// TODO: Allow more than one mechanism
|
||||||
match serde_json::from_str::<SmtpAuthMechanism>(&correct_mechanism) {
|
match serde_json::from_str::<SmtpAuthMechanism>(&correct_mechanism) {
|
||||||
Ok(auth_mechanism) => smtp_client.authentication_mechanism(auth_mechanism),
|
Ok(auth_mechanism) => smtp_client.authentication(vec![auth_mechanism]),
|
||||||
_ => panic!("Failure to parse mechanism. Is it proper Json? Eg. `\"Plain\"` not `Plain`"),
|
_ => panic!("Failure to parse mechanism. Is it proper Json? Eg. `\"Plain\"` not `Plain`"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => smtp_client,
|
_ => smtp_client,
|
||||||
};
|
};
|
||||||
|
|
||||||
smtp_client
|
smtp_client.timeout(Some(Duration::from_secs(CONFIG.smtp_timeout())))
|
||||||
.smtp_utf8(true)
|
|
||||||
.timeout(Some(Duration::from_secs(CONFIG.smtp_timeout())))
|
|
||||||
.connection_reuse(ConnectionReuseParameters::NoReuse)
|
|
||||||
.transport()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_text(template_name: &'static str, data: serde_json::Value) -> Result<(String, String, String), Error> {
|
fn get_text(template_name: &'static str, data: serde_json::Value) -> Result<(String, String, String), Error> {
|
||||||
|
@ -283,38 +278,28 @@ fn send_email(address: &str, subject: &str, body_html: &str, body_text: &str) ->
|
||||||
|
|
||||||
let address = format!("{}@{}", address_split[1], domain_puny);
|
let address = format!("{}@{}", address_split[1], domain_puny);
|
||||||
|
|
||||||
let html = PartBuilder::new()
|
let html = SinglePart::builder()
|
||||||
.body(encode_to_str(body_html))
|
.header(header::ContentType("text/html; charset=utf-8".parse().unwrap()))
|
||||||
.header(("Content-Type", "text/html; charset=utf-8"))
|
.header(header::ContentTransferEncoding::QuotedPrintable)
|
||||||
.header(("Content-Transfer-Encoding", "quoted-printable"))
|
.body(body_html);
|
||||||
.build();
|
|
||||||
|
|
||||||
let text = PartBuilder::new()
|
let text = SinglePart::builder()
|
||||||
.body(encode_to_str(body_text))
|
.header(header::ContentType("text/plain; charset=utf-8".parse().unwrap()))
|
||||||
.header(("Content-Type", "text/plain; charset=utf-8"))
|
.header(header::ContentTransferEncoding::QuotedPrintable)
|
||||||
.header(("Content-Transfer-Encoding", "quoted-printable"))
|
.body(body_text);
|
||||||
.build();
|
|
||||||
|
|
||||||
let alternative = PartBuilder::new()
|
let alternative = MultiPart::alternative().singlepart(text).singlepart(html);
|
||||||
.message_type(MimeMultipartType::Alternative)
|
|
||||||
.child(text)
|
|
||||||
.child(html);
|
|
||||||
|
|
||||||
let email = EmailBuilder::new()
|
let email = Message::builder()
|
||||||
.to(address)
|
.to(Mailbox::new(None, Address::from_str(&address)?))
|
||||||
.from((CONFIG.smtp_from().as_str(), CONFIG.smtp_from_name().as_str()))
|
.from(Mailbox::new(
|
||||||
|
Some(CONFIG.smtp_from_name()),
|
||||||
|
Address::from_str(&CONFIG.smtp_from())?,
|
||||||
|
))
|
||||||
.subject(subject)
|
.subject(subject)
|
||||||
.child(alternative.build())
|
.multipart(alternative)
|
||||||
.build()
|
|
||||||
.map_err(|e| Error::new("Error building email", e.to_string()))?;
|
.map_err(|e| Error::new("Error building email", e.to_string()))?;
|
||||||
|
|
||||||
let mut transport = mailer();
|
let _ = mailer().send(&email)?;
|
||||||
|
|
||||||
let result = transport.send(email);
|
|
||||||
|
|
||||||
// Explicitly close the connection, in case of error
|
|
||||||
transport.close();
|
|
||||||
|
|
||||||
result?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Laden …
In neuem Issue referenzieren