Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d16344d53 | ||
|
|
8873153178 | ||
|
|
b073df7666 |
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,3 +1,17 @@
|
|||||||
|
<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>
|
<a name="v0.11.17"></a>
|
||||||
### v0.11.17 (2025-06-06)
|
### v0.11.17 (2025-06-06)
|
||||||
|
|
||||||
|
|||||||
20
Cargo.lock
generated
20
Cargo.lock
generated
@@ -1325,7 +1325,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lettre"
|
name = "lettre"
|
||||||
version = "0.11.17"
|
version = "0.11.18"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-std",
|
"async-std",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -1358,7 +1358,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"socket2",
|
"socket2 0.6.0",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-boring",
|
"tokio-boring",
|
||||||
"tokio-native-tls",
|
"tokio-native-tls",
|
||||||
@@ -1374,9 +1374,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.171"
|
version = "0.2.174"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
|
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libloading"
|
name = "libloading"
|
||||||
@@ -2256,6 +2256,16 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"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]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.9.8"
|
version = "0.9.8"
|
||||||
@@ -2405,7 +2415,7 @@ dependencies = [
|
|||||||
"mio",
|
"mio",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2 0.5.9",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lettre"
|
name = "lettre"
|
||||||
# remember to update html_root_url and README.md (Cargo.toml example and deps.rs badge)
|
# remember to update html_root_url and README.md (Cargo.toml example and deps.rs badge)
|
||||||
version = "0.11.17"
|
version = "0.11.18"
|
||||||
description = "Email client"
|
description = "Email client"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
homepage = "https://lettre.rs"
|
homepage = "https://lettre.rs"
|
||||||
@@ -42,7 +42,7 @@ serde_json = { version = "1", optional = true }
|
|||||||
# smtp-transport
|
# smtp-transport
|
||||||
nom = { version = "8", optional = true }
|
nom = { version = "8", optional = true }
|
||||||
hostname = { version = "0.4", optional = true } # feature
|
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 }
|
url = { version = "2.4", optional = true }
|
||||||
percent-encoding = { version = "2.3", optional = true }
|
percent-encoding = { version = "2.3", optional = true }
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://deps.rs/crate/lettre/0.11.17">
|
<a href="https://deps.rs/crate/lettre/0.11.18">
|
||||||
<img src="https://deps.rs/crate/lettre/0.11.17/status.svg"
|
<img src="https://deps.rs/crate/lettre/0.11.18/status.svg"
|
||||||
alt="dependency status" />
|
alt="dependency status" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -162,7 +162,7 @@
|
|||||||
//! [mime 0.3]: https://docs.rs/mime/0.3
|
//! [mime 0.3]: https://docs.rs/mime/0.3
|
||||||
//! [DKIM]: https://datatracker.ietf.org/doc/html/rfc6376
|
//! [DKIM]: https://datatracker.ietf.org/doc/html/rfc6376
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/crate/lettre/0.11.17")]
|
#![doc(html_root_url = "https://docs.rs/crate/lettre/0.11.18")]
|
||||||
#![doc(html_favicon_url = "https://lettre.rs/favicon.ico")]
|
#![doc(html_favicon_url = "https://lettre.rs/favicon.ico")]
|
||||||
#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/15113230?v=4")]
|
#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/15113230?v=4")]
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
|||||||
@@ -16,7 +16,10 @@ enum Disposition {
|
|||||||
/// File name
|
/// File name
|
||||||
Attached(String),
|
Attached(String),
|
||||||
/// Content id
|
/// Content id
|
||||||
Inline(String),
|
Inline {
|
||||||
|
content_id: String,
|
||||||
|
name: Option<String>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attachment {
|
impl Attachment {
|
||||||
@@ -81,7 +84,50 @@ impl Attachment {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn new_inline(content_id: String) -> Self {
|
pub fn new_inline(content_id: String) -> Self {
|
||||||
Attachment {
|
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) => {
|
Disposition::Attached(filename) => {
|
||||||
builder.header(header::ContentDisposition::attachment(&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::ContentId::from(format!("<{content_id}>")))
|
||||||
.header(header::ContentDisposition::inline()),
|
.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 = builder.header(content_type);
|
||||||
builder.body(content)
|
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"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user