Compare commits
8 Commits
v0.11.16
...
prepare-v0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
036062a084 | ||
|
|
8873153178 | ||
|
|
b073df7666 | ||
|
|
cf6b767a9c | ||
|
|
d3d8e24824 | ||
|
|
c4df9730aa | ||
|
|
bfed19e6ad | ||
|
|
629967ac98 |
32
CHANGELOG.md
32
CHANGELOG.md
@@ -1,3 +1,35 @@
|
||||
<a name="v0.11.18"></a>
|
||||
### v0.11.18 (2025-07-28)
|
||||
|
||||
#### Features
|
||||
|
||||
* Allow inline attachments to be named ([#1101])
|
||||
|
||||
#### Misc
|
||||
|
||||
* Upgrade `socket2` to v0.6 ([#1098])
|
||||
|
||||
[#1098]: https://github.com/lettre/lettre/pull/1098
|
||||
[#1101]: https://github.com/lettre/lettre/pull/1101
|
||||
|
||||
<a name="v0.11.17"></a>
|
||||
### v0.11.17 (2025-06-06)
|
||||
|
||||
#### Features
|
||||
|
||||
* Add support for `rustls-platform-verifier` ([#1081])
|
||||
|
||||
#### Misc
|
||||
|
||||
* Change readme example to use `Mailbox::new` instead of string parsing ([#1090])
|
||||
* Replace futures-util `Mutex` with std `Mutex` in `AsyncStubTransport` ([#1091])
|
||||
* Avoid duplicate `abort_concurrent` implementation ([#1092])
|
||||
|
||||
[#1081]: https://github.com/lettre/lettre/pull/1081
|
||||
[#1090]: https://github.com/lettre/lettre/pull/1090
|
||||
[#1091]: https://github.com/lettre/lettre/pull/1091
|
||||
[#1092]: https://github.com/lettre/lettre/pull/1092
|
||||
|
||||
<a name="v0.11.16"></a>
|
||||
### v0.11.16 (2025-05-12)
|
||||
|
||||
|
||||
217
Cargo.lock
generated
217
Cargo.lock
generated
@@ -291,7 +291,7 @@ dependencies = [
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -437,6 +437,12 @@ dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cesu8"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
@@ -534,6 +540,16 @@ dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
version = "4.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "2.5.0"
|
||||
@@ -1241,6 +1257,28 @@ version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "jni"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
|
||||
dependencies = [
|
||||
"cesu8",
|
||||
"cfg-if",
|
||||
"combine",
|
||||
"jni-sys",
|
||||
"log",
|
||||
"thiserror",
|
||||
"walkdir",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jni-sys"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.33"
|
||||
@@ -1287,7 +1325,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "lettre"
|
||||
version = "0.11.16"
|
||||
version = "0.11.18"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"async-trait",
|
||||
@@ -1316,10 +1354,11 @@ dependencies = [
|
||||
"rsa",
|
||||
"rustls",
|
||||
"rustls-native-certs",
|
||||
"rustls-platform-verifier",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"socket2",
|
||||
"socket2 0.6.0",
|
||||
"tokio",
|
||||
"tokio-boring",
|
||||
"tokio-native-tls",
|
||||
@@ -1335,9 +1374,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.171"
|
||||
version = "0.2.174"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
|
||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
@@ -1346,7 +1385,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1972,9 +2011,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.25"
|
||||
version = "0.23.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c"
|
||||
checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"log",
|
||||
@@ -2005,10 +2044,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.1"
|
||||
name = "rustls-platform-verifier"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03"
|
||||
checksum = "eda84358ed17f1f354cf4b1909ad346e6c7bc2513e8c40eb08e0157aa13a9070"
|
||||
dependencies = [
|
||||
"core-foundation 0.10.0",
|
||||
"core-foundation-sys",
|
||||
"jni",
|
||||
"log",
|
||||
"once_cell",
|
||||
"rustls",
|
||||
"rustls-native-certs",
|
||||
"rustls-platform-verifier-android",
|
||||
"rustls-webpki",
|
||||
"security-framework 3.2.0",
|
||||
"security-framework-sys",
|
||||
"webpki-root-certs",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-platform-verifier-android"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"ring",
|
||||
@@ -2190,6 +2256,16 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
@@ -2277,6 +2353,26 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.8"
|
||||
@@ -2319,7 +2415,7 @@ dependencies = [
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"socket2 0.5.9",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
@@ -2602,6 +2698,15 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-root-certs"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01a83f7e1a9f8712695c03eabe9ed3fbca0feff0152f33f12593e5a6303cb1a4"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "1.0.0"
|
||||
@@ -2661,7 +2766,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2670,7 +2775,16 @@ version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2679,7 +2793,7 @@ version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2688,7 +2802,22 @@ version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2697,28 +2826,46 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
@@ -2731,24 +2878,48 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "lettre"
|
||||
# remember to update html_root_url and README.md (Cargo.toml example and deps.rs badge)
|
||||
version = "0.11.16"
|
||||
version = "0.11.18"
|
||||
description = "Email client"
|
||||
readme = "README.md"
|
||||
homepage = "https://lettre.rs"
|
||||
@@ -42,13 +42,14 @@ serde_json = { version = "1", optional = true }
|
||||
# smtp-transport
|
||||
nom = { version = "8", optional = true }
|
||||
hostname = { version = "0.4", optional = true } # feature
|
||||
socket2 = { version = "0.5.1", optional = true }
|
||||
socket2 = { version = "0.6", optional = true }
|
||||
url = { version = "2.4", optional = true }
|
||||
percent-encoding = { version = "2.3", optional = true }
|
||||
|
||||
## tls
|
||||
native-tls = { version = "0.2.9", optional = true } # feature
|
||||
rustls = { version = "0.23.18", default-features = false, features = ["logging", "std", "tls12"], optional = true }
|
||||
rustls-platform-verifier = { version = "0.6.0", optional = true }
|
||||
rustls-native-certs = { version = "0.8", optional = true }
|
||||
webpki-roots = { version = "1.0.0", optional = true }
|
||||
boring = { version = "4", optional = true }
|
||||
|
||||
10
README.md
10
README.md
@@ -28,8 +28,8 @@
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
<a href="https://deps.rs/crate/lettre/0.11.16">
|
||||
<img src="https://deps.rs/crate/lettre/0.11.16/status.svg"
|
||||
<a href="https://deps.rs/crate/lettre/0.11.18">
|
||||
<img src="https://deps.rs/crate/lettre/0.11.18/status.svg"
|
||||
alt="dependency status" />
|
||||
</a>
|
||||
</div>
|
||||
@@ -73,9 +73,9 @@ use lettre::{Message, SmtpTransport, Transport};
|
||||
|
||||
fn main() {
|
||||
let email = Message::builder()
|
||||
.from("NoBody <nobody@domain.tld>".parse().unwrap())
|
||||
.reply_to("Yuin <yuin@domain.tld>".parse().unwrap())
|
||||
.to("Hei <hei@domain.tld>".parse().unwrap())
|
||||
.from(Mailbox::new("NoBody".to_owned(), "nobody@domain.tld".parse().unwrap()))
|
||||
.reply_to(Mailbox::new("Yuin".to_owned(), "yuin@domain.tld".parse().unwrap()))
|
||||
.to(Mailbox::new("Hei".to_owned(), "hei@domain.tld".parse().unwrap()))
|
||||
.subject("Happy new year")
|
||||
.header(ContentType::TEXT_PLAIN)
|
||||
.body(String::from("Be happy!"))
|
||||
|
||||
27
src/lib.rs
27
src/lib.rs
@@ -93,17 +93,20 @@
|
||||
//! When the `rustls` feature is enabled, one of the following verification backends
|
||||
//! MUST also be enabled.
|
||||
//!
|
||||
//! * **rustls-native-certs**: verify TLS certificates using the platform's native certificate store (see [`rustls-native-certs`])
|
||||
//! * **rustls-platform-verifier**: verify TLS certificate using the OS's native certificate store (see [`rustls-platform-verifier`])
|
||||
//! * **rustls-native-certs**: verify TLS certificates using the platform's native certificate store (see [`rustls-native-certs`]) - when in doubt use `rustls-platform-verifier`
|
||||
//! * **webpki-roots**: verify TLS certificates against Mozilla's root certificates (see [`webpki-roots`])
|
||||
//!
|
||||
//! For the `rustls-native-certs` backend to work correctly, the following packages
|
||||
//! will need to be installed in order for the build stage and the compiled program
|
||||
//! to run properly.
|
||||
//! The following packages will need to be installed in order for the build
|
||||
//! stage and the compiled program to run properly.
|
||||
//!
|
||||
//! | Distro | Build-time packages | Runtime packages |
|
||||
//! | ------------ | -------------------------- | ---------------------------- |
|
||||
//! | Debian | none | `ca-certificates` |
|
||||
//! | Alpine Linux | none | `ca-certificates` |
|
||||
//! | Verification backend | Distro | Build-time packages | Runtime packages |
|
||||
//! | --------------------- | ------------ | -------------------------- | ---------------------------- |
|
||||
//! | `rustls-platform-verifier` | Debian | none | `ca-certificates` |
|
||||
//! | `rustls-platform-verifier` | Alpine Linux | none | `ca-certificates` |
|
||||
//! | `rustls-native-certs` | Debian | none | `ca-certificates` |
|
||||
//! | `rustls-native-certs` | Alpine Linux | none | `ca-certificates` |
|
||||
//! | `webpki-roots` | any | none | none |
|
||||
//!
|
||||
//! ### Sendmail transport
|
||||
//!
|
||||
@@ -151,6 +154,7 @@
|
||||
//! [AWS-LC]: https://github.com/aws/aws-lc
|
||||
//! [`aws-lc-rs`]: https://crates.io/crates/aws-lc-rs
|
||||
//! [`ring`]: https://crates.io/crates/ring
|
||||
//! [`rustls-platform-verifier`]: https://crates.io/crates/rustls-platform-verifier
|
||||
//! [`rustls-native-certs`]: https://crates.io/crates/rustls-native-certs
|
||||
//! [`webpki-roots`]: https://crates.io/crates/webpki-roots
|
||||
//! [Tokio 1.x]: https://docs.rs/tokio/1
|
||||
@@ -158,7 +162,7 @@
|
||||
//! [mime 0.3]: https://docs.rs/mime/0.3
|
||||
//! [DKIM]: https://datatracker.ietf.org/doc/html/rfc6376
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/crate/lettre/0.11.16")]
|
||||
#![doc(html_root_url = "https://docs.rs/crate/lettre/0.11.18")]
|
||||
#![doc(html_favicon_url = "https://lettre.rs/favicon.ico")]
|
||||
#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/15113230?v=4")]
|
||||
#![forbid(unsafe_code)]
|
||||
@@ -208,12 +212,13 @@ mod compiletime_checks {
|
||||
|
||||
#[cfg(all(
|
||||
feature = "rustls",
|
||||
not(feature = "rustls-platform-verifier"),
|
||||
not(feature = "rustls-native-certs"),
|
||||
not(feature = "webpki-roots")
|
||||
))]
|
||||
compile_error!(
|
||||
"feature `rustls` also requires either the `rustls-native-certs` or the `webpki-roots` feature to
|
||||
be enabled"
|
||||
"feature `rustls` also requires either the `rustls-platform-verifier`, the `rustls-native-certs`
|
||||
or the `webpki-roots` feature to be enabled"
|
||||
);
|
||||
|
||||
#[cfg(all(feature = "native-tls", feature = "boring-tls"))]
|
||||
|
||||
@@ -16,7 +16,10 @@ enum Disposition {
|
||||
/// File name
|
||||
Attached(String),
|
||||
/// Content id
|
||||
Inline(String),
|
||||
Inline {
|
||||
content_id: String,
|
||||
name: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Attachment {
|
||||
@@ -81,7 +84,50 @@ impl Attachment {
|
||||
/// ```
|
||||
pub fn new_inline(content_id: String) -> Self {
|
||||
Attachment {
|
||||
disposition: Disposition::Inline(content_id),
|
||||
disposition: Disposition::Inline {
|
||||
content_id,
|
||||
name: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new inline attachment giving it a name
|
||||
///
|
||||
/// This attachment should be displayed inline into the message
|
||||
/// body:
|
||||
///
|
||||
/// ```html
|
||||
/// <img src="cid:123">
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::error::Error;
|
||||
/// use std::fs;
|
||||
///
|
||||
/// use lettre::message::{header::ContentType, Attachment};
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// let content_id = String::from("123");
|
||||
/// let file_name = String::from("image.jpg");
|
||||
/// # if false {
|
||||
/// let filebody = fs::read(&file_name)?;
|
||||
/// # }
|
||||
/// # let filebody = fs::read("docs/lettre.png")?;
|
||||
/// let content_type = ContentType::parse("image/jpeg").unwrap();
|
||||
/// let attachment =
|
||||
/// Attachment::new_inline_with_name(content_id, file_name).body(filebody, content_type);
|
||||
///
|
||||
/// // The image `attachment` will display inline into the email.
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn new_inline_with_name(content_id: String, name: String) -> Self {
|
||||
Attachment {
|
||||
disposition: Disposition::Inline {
|
||||
content_id,
|
||||
name: Some(name),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,9 +141,18 @@ impl Attachment {
|
||||
Disposition::Attached(filename) => {
|
||||
builder.header(header::ContentDisposition::attachment(&filename))
|
||||
}
|
||||
Disposition::Inline(content_id) => builder
|
||||
Disposition::Inline {
|
||||
content_id,
|
||||
name: None,
|
||||
} => builder
|
||||
.header(header::ContentId::from(format!("<{content_id}>")))
|
||||
.header(header::ContentDisposition::inline()),
|
||||
Disposition::Inline {
|
||||
content_id,
|
||||
name: Some(name),
|
||||
} => builder
|
||||
.header(header::ContentId::from(format!("<{content_id}>")))
|
||||
.header(header::ContentDisposition::inline_with_name(&name)),
|
||||
};
|
||||
builder = builder.header(content_type);
|
||||
builder.body(content)
|
||||
@@ -142,4 +197,24 @@ mod tests {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attachment_inline_with_name() {
|
||||
let id = String::from("id");
|
||||
let name = String::from("test");
|
||||
let part = super::Attachment::new_inline_with_name(id, name).body(
|
||||
String::from("Hello world!"),
|
||||
ContentType::parse("text/plain").unwrap(),
|
||||
);
|
||||
assert_eq!(
|
||||
&String::from_utf8_lossy(&part.formatted()),
|
||||
concat!(
|
||||
"Content-ID: <id>\r\n",
|
||||
"Content-Disposition: inline; filename=\"test\"\r\n",
|
||||
"Content-Type: text/plain\r\n",
|
||||
"Content-Transfer-Encoding: 7bit\r\n\r\n",
|
||||
"Hello world!\r\n"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,8 +164,9 @@ pub enum CertificateStore {
|
||||
/// For native-tls, this will use the system certificate store on Windows, the keychain on
|
||||
/// macOS, and OpenSSL directories on Linux (usually `/etc/ssl`).
|
||||
///
|
||||
/// For rustls, this will also use the system store if the `rustls-native-certs` feature is
|
||||
/// enabled, or will fall back to `webpki-roots`.
|
||||
/// For rustls, this will use the system certificate verifier if the `rustls-platform-verifier`
|
||||
/// feature is enabled. If the `rustls-native-certs` feature is enabled, system certificate
|
||||
/// store will be used. Otherwise, it will fall back to `webpki-roots`.
|
||||
///
|
||||
/// The boring-tls backend uses the same logic as OpenSSL on all platforms.
|
||||
#[default]
|
||||
@@ -259,6 +260,8 @@ impl TlsParametersBuilder {
|
||||
|
||||
/// Controls whether certificates with an invalid hostname are accepted
|
||||
///
|
||||
/// This option is silently disabled when using `rustls-platform-verifier`.
|
||||
///
|
||||
/// Defaults to `false`.
|
||||
///
|
||||
/// # Warning
|
||||
@@ -461,7 +464,10 @@ impl TlsParametersBuilder {
|
||||
// Build TLS config
|
||||
let mut root_cert_store = RootCertStore::empty();
|
||||
|
||||
#[cfg(feature = "rustls-native-certs")]
|
||||
#[cfg(all(
|
||||
not(feature = "rustls-platform-verifier"),
|
||||
feature = "rustls-native-certs"
|
||||
))]
|
||||
fn load_native_roots(store: &mut RootCertStore) {
|
||||
let rustls_native_certs::CertificateResult { certs, errors, .. } =
|
||||
rustls_native_certs::load_native_certs();
|
||||
@@ -481,11 +487,26 @@ impl TlsParametersBuilder {
|
||||
store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "rustls-platform-verifier"), allow(unused_mut))]
|
||||
let mut extra_roots = None::<Vec<CertificateDer<'static>>>;
|
||||
match self.cert_store {
|
||||
CertificateStore::Default => {
|
||||
#[cfg(feature = "rustls-native-certs")]
|
||||
#[cfg(feature = "rustls-platform-verifier")]
|
||||
{
|
||||
extra_roots = Some(Vec::new());
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "rustls-platform-verifier"),
|
||||
feature = "rustls-native-certs"
|
||||
))]
|
||||
load_native_roots(&mut root_cert_store);
|
||||
#[cfg(all(not(feature = "rustls-native-certs"), feature = "webpki-roots"))]
|
||||
|
||||
#[cfg(all(
|
||||
not(feature = "rustls-platform-verifier"),
|
||||
not(feature = "rustls-native-certs"),
|
||||
feature = "webpki-roots"
|
||||
))]
|
||||
load_webpki_roots(&mut root_cert_store);
|
||||
}
|
||||
#[cfg(all(feature = "rustls", feature = "webpki-roots"))]
|
||||
@@ -496,11 +517,17 @@ impl TlsParametersBuilder {
|
||||
}
|
||||
for cert in self.root_certs {
|
||||
for rustls_cert in cert.rustls {
|
||||
#[cfg(feature = "rustls-platform-verifier")]
|
||||
if let Some(extra_roots) = &mut extra_roots {
|
||||
extra_roots.push(rustls_cert.clone());
|
||||
}
|
||||
root_cert_store.add(rustls_cert).map_err(error::tls)?;
|
||||
}
|
||||
}
|
||||
|
||||
let tls = if self.accept_invalid_certs || self.accept_invalid_hostnames {
|
||||
let tls = if self.accept_invalid_certs
|
||||
|| (extra_roots.is_none() && self.accept_invalid_hostnames)
|
||||
{
|
||||
let verifier = InvalidCertsVerifier {
|
||||
ignore_invalid_hostnames: self.accept_invalid_hostnames,
|
||||
ignore_invalid_certs: self.accept_invalid_certs,
|
||||
@@ -510,7 +537,23 @@ impl TlsParametersBuilder {
|
||||
tls.dangerous()
|
||||
.with_custom_certificate_verifier(Arc::new(verifier))
|
||||
} else {
|
||||
tls.with_root_certificates(root_cert_store)
|
||||
#[cfg(feature = "rustls-platform-verifier")]
|
||||
if let Some(extra_roots) = extra_roots {
|
||||
tls.dangerous().with_custom_certificate_verifier(Arc::new(
|
||||
rustls_platform_verifier::Verifier::new_with_extra_roots(
|
||||
extra_roots,
|
||||
crypto_provider,
|
||||
)
|
||||
.map_err(error::tls)?,
|
||||
))
|
||||
} else {
|
||||
tls.with_root_certificates(root_cert_store)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "rustls-platform-verifier"))]
|
||||
{
|
||||
tls.with_root_certificates(root_cert_store)
|
||||
}
|
||||
};
|
||||
|
||||
let tls = if let Some(identity) = self.identity {
|
||||
|
||||
@@ -149,11 +149,7 @@ impl<E: Executor> Pool<E> {
|
||||
pub(crate) async fn shutdown(&self) {
|
||||
let connections = { self.connections.lock().await.take() };
|
||||
if let Some(connections) = connections {
|
||||
stream::iter(connections)
|
||||
.for_each_concurrent(8, |conn| async move {
|
||||
conn.unpark().abort().await;
|
||||
})
|
||||
.await;
|
||||
abort_concurrent(connections.into_iter().map(ParkedConnection::unpark)).await;
|
||||
}
|
||||
|
||||
if let Some(handle) = self.handle.get() {
|
||||
|
||||
@@ -43,13 +43,11 @@
|
||||
use std::{
|
||||
error::Error as StdError,
|
||||
fmt,
|
||||
sync::{Arc, Mutex as StdMutex},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "tokio1", feature = "async-std1"))]
|
||||
use async_trait::async_trait;
|
||||
#[cfg(any(feature = "tokio1", feature = "async-std1"))]
|
||||
use futures_util::lock::Mutex as FuturesMutex;
|
||||
|
||||
#[cfg(any(feature = "tokio1", feature = "async-std1"))]
|
||||
use crate::AsyncTransport;
|
||||
@@ -72,7 +70,7 @@ impl StdError for Error {}
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StubTransport {
|
||||
response: Result<(), Error>,
|
||||
message_log: Arc<StdMutex<Vec<(Envelope, String)>>>,
|
||||
message_log: Arc<Mutex<Vec<(Envelope, String)>>>,
|
||||
}
|
||||
|
||||
/// This transport logs messages and always returns the given response
|
||||
@@ -81,7 +79,7 @@ pub struct StubTransport {
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "tokio1", feature = "async-std1"))))]
|
||||
pub struct AsyncStubTransport {
|
||||
response: Result<(), Error>,
|
||||
message_log: Arc<FuturesMutex<Vec<(Envelope, String)>>>,
|
||||
message_log: Arc<Mutex<Vec<(Envelope, String)>>>,
|
||||
}
|
||||
|
||||
impl StubTransport {
|
||||
@@ -89,7 +87,7 @@ impl StubTransport {
|
||||
pub fn new(response: Result<(), Error>) -> Self {
|
||||
Self {
|
||||
response,
|
||||
message_log: Arc::new(StdMutex::new(vec![])),
|
||||
message_log: Arc::new(Mutex::new(vec![])),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +95,7 @@ impl StubTransport {
|
||||
pub fn new_ok() -> Self {
|
||||
Self {
|
||||
response: Ok(()),
|
||||
message_log: Arc::new(StdMutex::new(vec![])),
|
||||
message_log: Arc::new(Mutex::new(vec![])),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +103,7 @@ impl StubTransport {
|
||||
pub fn new_error() -> Self {
|
||||
Self {
|
||||
response: Err(Error),
|
||||
message_log: Arc::new(StdMutex::new(vec![])),
|
||||
message_log: Arc::new(Mutex::new(vec![])),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +122,7 @@ impl AsyncStubTransport {
|
||||
pub fn new(response: Result<(), Error>) -> Self {
|
||||
Self {
|
||||
response,
|
||||
message_log: Arc::new(FuturesMutex::new(vec![])),
|
||||
message_log: Arc::new(Mutex::new(vec![])),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +130,7 @@ impl AsyncStubTransport {
|
||||
pub fn new_ok() -> Self {
|
||||
Self {
|
||||
response: Ok(()),
|
||||
message_log: Arc::new(FuturesMutex::new(vec![])),
|
||||
message_log: Arc::new(Mutex::new(vec![])),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,14 +138,14 @@ impl AsyncStubTransport {
|
||||
pub fn new_error() -> Self {
|
||||
Self {
|
||||
response: Err(Error),
|
||||
message_log: Arc::new(FuturesMutex::new(vec![])),
|
||||
message_log: Arc::new(Mutex::new(vec![])),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return all logged messages sent using [`AsyncTransport::send_raw`]
|
||||
#[cfg(any(feature = "tokio1", feature = "async-std1"))]
|
||||
pub async fn messages(&self) -> Vec<(Envelope, String)> {
|
||||
self.message_log.lock().await.clone()
|
||||
self.message_log.lock().unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +171,7 @@ impl AsyncTransport for AsyncStubTransport {
|
||||
async fn send_raw(&self, envelope: &Envelope, email: &[u8]) -> Result<Self::Ok, Self::Error> {
|
||||
self.message_log
|
||||
.lock()
|
||||
.await
|
||||
.unwrap()
|
||||
.push((envelope.clone(), String::from_utf8_lossy(email).into()));
|
||||
self.response
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user