Compare commits

...

4 Commits

Author SHA1 Message Date
Paolo Barbolini
036062a084 Prepare v0.11.18 2025-07-28 09:38:52 +02:00
Francesco Luzzi
8873153178 feat: add ability to give a name to an inline attachment (#1101) 2025-07-21 08:19:31 +02:00
Paolo Barbolini
b073df7666 build(deps): upgrade socket2 to v0.6 (#1098) 2025-07-05 12:09:17 +02:00
Paolo Barbolini
cf6b767a9c Prepare v0.11.17 (#1093) 2025-06-05 21:41:17 +02:00
6 changed files with 130 additions and 13 deletions

View File

@@ -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)

20
Cargo.lock generated
View File

@@ -1325,7 +1325,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "lettre"
version = "0.11.16"
version = "0.11.18"
dependencies = [
"async-std",
"async-trait",
@@ -1358,7 +1358,7 @@ dependencies = [
"serde",
"serde_json",
"sha2",
"socket2",
"socket2 0.6.0",
"tokio",
"tokio-boring",
"tokio-native-tls",
@@ -1374,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"
@@ -2256,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"
@@ -2405,7 +2415,7 @@ dependencies = [
"mio",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"socket2 0.5.9",
"tokio-macros",
"windows-sys 0.52.0",
]

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.16"
version = "0.11.18"
description = "Email client"
readme = "README.md"
homepage = "https://lettre.rs"
@@ -42,7 +42,7 @@ 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 }

View File

@@ -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>

View File

@@ -162,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)]

View File

@@ -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"
)
);
}
}