Compare commits

...

9 Commits

Author SHA1 Message Date
Paolo Barbolini
de075153b0 Prepare v0.11.11 (#1013) 2024-12-05 20:48:10 +01:00
Paolo Barbolini
02dfc7dd4a fix: off-by-one error reaching the min number of pooled connections (#1012) 2024-12-05 19:19:54 +01:00
Paolo Barbolini
83ce5872d7 Fix some clippy warnings (#1009) 2024-11-28 15:48:08 +00:00
Paolo Barbolini
272efeca74 build(deps): bump locked dependencies (#1006) 2024-11-27 10:21:13 +01:00
Paolo Barbolini
ec6f5f3920 build: bump MSRV to 1.71 (#1008) 2024-11-27 10:15:59 +01:00
Paolo Barbolini
b62d23bd87 build: fix -Zminimal-versions build (#1007) 2024-11-27 10:11:49 +01:00
Paolo Barbolini
51794aa912 Prepare v0.11.10 (#1002) 2024-10-23 23:04:45 +02:00
Paolo Barbolini
eb42651401 Use case insensitive comparisons for login challenge requests (#1000) 2024-10-23 20:01:00 +02:00
Paolo Barbolini
99c6dc2a87 Replace quit with abort in transport connection drop code (#999) 2024-10-23 20:00:31 +02:00
20 changed files with 314 additions and 267 deletions

View File

@@ -75,8 +75,8 @@ jobs:
rust: stable
- name: beta
rust: beta
- name: '1.70'
rust: '1.70'
- name: '1.71'
rust: '1.71'
steps:
- name: Checkout

View File

@@ -1,3 +1,35 @@
<a name="v0.11.11"></a>
### v0.11.11 (2024-12-05)
#### Upgrade notes
* MSRV is now 1.71 ([#1008])
#### Bug fixes
* Fix off-by-one error reaching the minimum number of configured pooled connections ([#1012])
#### Misc
* Fix clippy warnings ([#1009])
* Fix `-Zminimal-versions` build ([#1007])
[#1007]: https://github.com/lettre/lettre/pull/1007
[#1008]: https://github.com/lettre/lettre/pull/1008
[#1009]: https://github.com/lettre/lettre/pull/1009
[#1012]: https://github.com/lettre/lettre/pull/1012
<a name="v0.11.10"></a>
### v0.11.10 (2024-10-23)
#### Bug fixes
* Ignore disconnect errors when `pool` feature of SMTP transport is disabled ([#999])
* Use case insensitive comparisons for matching login challenge requests ([#1000])
[#999]: https://github.com/lettre/lettre/pull/999
[#1000]: https://github.com/lettre/lettre/pull/1000
<a name="v0.11.9"></a>
### v0.11.9 (2024-09-13)

460
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -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.9"
version = "0.11.11"
description = "Email client"
readme = "README.md"
homepage = "https://lettre.rs"
@@ -11,7 +11,7 @@ authors = ["Alexis Mousset <contact@amousset.me>", "Paolo Barbolini <paolo@paolo
categories = ["email", "network-programming"]
keywords = ["email", "smtp", "mailer", "message", "sendmail"]
edition = "2021"
rust-version = "1.70"
rust-version = "1.71"
[badges]
is-it-maintained-issue-resolution = { repository = "lettre/lettre" }
@@ -44,7 +44,7 @@ url = { version = "2.4", optional = true }
percent-encoding = { version = "2.3", optional = true }
## tls
native-tls = { version = "0.2.5", optional = true } # feature
native-tls = { version = "0.2.9", optional = true } # feature
rustls = { version = "0.23.5", default-features = false, features = ["ring", "logging", "std", "tls12"], optional = true }
rustls-pemfile = { version = "2", optional = true }
rustls-native-certs = { version = "0.8", optional = true }

View File

@@ -28,8 +28,8 @@
</div>
<div align="center">
<a href="https://deps.rs/crate/lettre/0.11.9">
<img src="https://deps.rs/crate/lettre/0.11.9/status.svg"
<a href="https://deps.rs/crate/lettre/0.11.11">
<img src="https://deps.rs/crate/lettre/0.11.11/status.svg"
alt="dependency status" />
</a>
</div>
@@ -53,12 +53,12 @@ Lettre does not provide (for now):
## Supported Rust Versions
Lettre supports all Rust versions released in the last 6 months. At the time of writing
the minimum supported Rust version is 1.70, but this could change at any time either from
the minimum supported Rust version is 1.71, but this could change at any time either from
one of our dependencies bumping their MSRV or by a new patch release of lettre.
## Example
This library requires Rust 1.70 or newer.
This library requires Rust 1.71 or newer.
To use this library, add the following to your `Cargo.toml`:
```toml

View File

@@ -36,7 +36,7 @@ impl<'de> Deserialize<'de> for Address {
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
impl Visitor<'_> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut Formatter<'_>) -> FmtResult {

View File

@@ -6,7 +6,7 @@
//! * Secure defaults
//! * Async support
//!
//! Lettre requires Rust 1.70 or newer.
//! Lettre requires Rust 1.71 or newer.
//!
//! ## Features
//!
@@ -109,7 +109,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.9")]
#![doc(html_root_url = "https://docs.rs/crate/lettre/0.11.11")]
#![doc(html_favicon_url = "https://lettre.rs/favicon.ico")]
#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/15113230?v=4")]
#![forbid(unsafe_code)]

View File

@@ -345,7 +345,6 @@ fn dkim_canonicalize_headers<'a>(
/// Sign with Dkim a message by adding Dkim-Signature header created with configuration expressed by
/// dkim_config
pub fn dkim_sign(message: &mut Message, dkim_config: &DkimConfig) {
dkim_sign_fixed_time(message, dkim_config, SystemTime::now())
}

View File

@@ -119,7 +119,7 @@ mod serde {
{
struct ContentTypeVisitor;
impl<'de> Visitor<'de> for ContentTypeVisitor {
impl Visitor<'_> for ContentTypeVisitor {
type Value = ContentType;
// The error message which states what the Visitor expects to

View File

@@ -36,7 +36,7 @@ impl<'de> Deserialize<'de> for Mailbox {
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
impl Visitor<'_> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut Formatter<'_>) -> FmtResult {

View File

@@ -174,7 +174,7 @@ impl Mailboxes {
self
}
/// Adds a new [`Mailbox`] to the list, in a Vec::push style pattern.
/// Adds a new [`Mailbox`] to the list, in a `Vec::push` style pattern.
///
/// # Examples
///

View File

@@ -345,7 +345,7 @@ impl MessageBuilder {
let hostname = hostname::get()
.map_err(|_| ())
.and_then(|s| s.into_string().map_err(|_| ()))
.unwrap_or_else(|_| DEFAULT_MESSAGE_ID_DOMAIN.to_owned());
.unwrap_or_else(|()| DEFAULT_MESSAGE_ID_DOMAIN.to_owned());
#[cfg(not(feature = "hostname"))]
let hostname = DEFAULT_MESSAGE_ID_DOMAIN.to_owned();

View File

@@ -45,7 +45,7 @@ impl AsyncTransport for AsyncSmtpTransport<Tokio1Executor> {
let result = conn.send(envelope, email).await?;
#[cfg(not(feature = "pool"))]
conn.quit().await?;
conn.abort().await;
Ok(result)
}

View File

@@ -98,13 +98,17 @@ impl Mechanism {
let decoded_challenge = challenge
.ok_or_else(|| error::client("This mechanism does expect a challenge"))?;
if ["User Name", "Username:", "Username", "User Name\0"]
.contains(&decoded_challenge)
{
if contains_ignore_ascii_case(
decoded_challenge,
["User Name", "Username:", "Username", "User Name\0"],
) {
return Ok(credentials.authentication_identity.clone());
}
if ["Password", "Password:", "Password\0"].contains(&decoded_challenge) {
if contains_ignore_ascii_case(
decoded_challenge,
["Password", "Password:", "Password\0"],
) {
return Ok(credentials.secret.clone());
}
@@ -121,6 +125,15 @@ impl Mechanism {
}
}
fn contains_ignore_ascii_case<'a>(
haystack: &str,
needles: impl IntoIterator<Item = &'a str>,
) -> bool {
needles
.into_iter()
.any(|item| item.eq_ignore_ascii_case(haystack))
}
#[cfg(test)]
mod test {
use super::{Credentials, Mechanism};
@@ -155,6 +168,23 @@ mod test {
assert!(mechanism.response(&credentials, None).is_err());
}
#[test]
fn test_login_case_insensitive() {
let mechanism = Mechanism::Login;
let credentials = Credentials::new("alice".to_owned(), "wonderland".to_owned());
assert_eq!(
mechanism.response(&credentials, Some("username")).unwrap(),
"alice"
);
assert_eq!(
mechanism.response(&credentials, Some("password")).unwrap(),
"wonderland"
);
assert!(mechanism.response(&credentials, None).is_err());
}
#[test]
fn test_xoauth2() {
let mechanism = Mechanism::Xoauth2;

View File

@@ -119,12 +119,12 @@ impl NetworkStream {
if let Some(timeout) = timeout {
match socket.connect_timeout(&addr.into(), timeout) {
Ok(_) => return Ok(socket.into()),
Ok(()) => return Ok(socket.into()),
Err(err) => last_err = Some(err),
}
} else {
match socket.connect(&addr.into()) {
Ok(_) => return Ok(socket.into()),
Ok(()) => return Ok(socket.into()),
Err(err) => last_err = Some(err),
}
}
@@ -369,7 +369,7 @@ impl Write for NetworkStream {
/// If the local address is set, binds the socket to this address.
/// If local address is not set, then destination address is required to determine the default
/// local address on some platforms.
/// See: https://github.com/hyperium/hyper/blob/faf24c6ad8eee1c3d5ccc9a4d4835717b8e2903f/src/client/connect/http.rs#L560
/// See: <https://github.com/hyperium/hyper/blob/faf24c6ad8eee1c3d5ccc9a4d4835717b8e2903f/src/client/connect/http.rs#L560>
fn bind_local_address(
socket: &socket2::Socket,
dst_addr: &SocketAddr,

View File

@@ -62,7 +62,7 @@ impl TransportBuilder for AsyncSmtpTransportBuilder {
}
}
/// Create a new SmtpTransportBuilder or AsyncSmtpTransportBuilder from a connection URL
/// Create a new `SmtpTransportBuilder` or `AsyncSmtpTransportBuilder` from a connection URL
pub(crate) fn from_connection_url<B: TransportBuilder>(connection_url: &str) -> Result<B, Error> {
let connection_url = Url::parse(connection_url).map_err(error::connection)?;
let tls: Option<String> = connection_url

View File

@@ -78,7 +78,7 @@ impl<E: Executor> Pool<E> {
#[cfg(feature = "tracing")]
let mut created = 0;
for _ in count..=(min_idle as usize) {
for _ in count..(min_idle as usize) {
let conn = match pool.client.connection().await {
Ok(conn) => conn,
Err(err) => {

View File

@@ -72,7 +72,7 @@ impl Pool {
#[cfg(feature = "tracing")]
let mut created = 0;
for _ in count..=(min_idle as usize) {
for _ in count..(min_idle as usize) {
let conn = match pool.client.connection() {
Ok(conn) => conn,
Err(err) => {

View File

@@ -32,7 +32,7 @@ impl Transport for SmtpTransport {
let result = conn.send(envelope, email)?;
#[cfg(not(feature = "pool"))]
conn.quit()?;
conn.abort();
Ok(result)
}

View File

@@ -6,7 +6,7 @@ use std::fmt::{Display, Formatter, Result as FmtResult};
#[derive(Debug)]
pub struct XText<'a>(pub &'a str);
impl<'a> Display for XText<'a> {
impl Display for XText<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
let mut rest = self.0;
while let Some(idx) = rest.find(|c| c < '!' || c == '+' || c == '=') {