diff --git a/Cargo.lock b/Cargo.lock index dd675ce..8463f2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1233,6 +1233,7 @@ dependencies = [ "url", "uuid", "walkdir", + "web-time", "webpki-roots", ] @@ -2442,6 +2443,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.26.7" diff --git a/Cargo.toml b/Cargo.toml index 26ab7c4..0eb3ab4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,6 +75,9 @@ ed25519-dalek = { version = "2", optional = true } # email formats email_address = { version = "0.2.1", default-features = false } +# webtime for wasm support +web-time = { version = "1.1.0", optional = true } + [dev-dependencies] pretty_assertions = "1" criterion = "0.5" @@ -122,6 +125,9 @@ tokio1-boring-tls = ["tokio1", "boring-tls", "dep:tokio1_boring"] dkim = ["dep:base64", "dep:sha2", "dep:rsa", "dep:ed25519-dalek"] +# wasm support +web = ["dep:web-time"] + [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(lettre_ignore_tls_mismatch)'] } diff --git a/src/lib.rs b/src/lib.rs index 9e66337..8f9dfe9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -107,6 +107,7 @@ //! * **tracing**: Logging using the `tracing` crate //! * **mime03**: Allow creating a [`ContentType`] from an existing [mime 0.3] `Mime` struct //! * **dkim**: Add support for signing email with DKIM +//! * **web**: WebAssembly support using the `web-time` crate for time operations //! //! [`SMTP`]: crate::transport::smtp //! [`sendmail`]: crate::transport::sendmail diff --git a/src/message/dkim.rs b/src/message/dkim.rs index 3a3b3eb..4ee56c2 100644 --- a/src/message/dkim.rs +++ b/src/message/dkim.rs @@ -346,6 +346,13 @@ 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) { + #[cfg(feature = "web")] + dkim_sign_fixed_time( + message, + dkim_config, + crate::message::to_std_systemtime(web_time::SystemTime::now()), + ); + #[cfg(not(feature = "web"))] dkim_sign_fixed_time(message, dkim_config, SystemTime::now()); } diff --git a/src/message/header/date.rs b/src/message/header/date.rs index 6512002..36b8185 100644 --- a/src/message/header/date.rs +++ b/src/message/header/date.rs @@ -21,7 +21,12 @@ impl Date { /// /// Shortcut for `Date::new(SystemTime::now())` pub fn now() -> Self { - Self::new(SystemTime::now()) + #[cfg(not(feature = "web"))] + return Self::new(SystemTime::now()); + #[cfg(feature = "web")] + return Self::new(crate::message::to_std_systemtime( + web_time::SystemTime::now(), + )); } } diff --git a/src/message/mod.rs b/src/message/mod.rs index 442160d..3650862 100644 --- a/src/message/mod.rs +++ b/src/message/mod.rs @@ -277,7 +277,10 @@ impl MessageBuilder { /// Shortcut for `self.date(SystemTime::now())`, it is automatically inserted /// if no date has been provided. pub fn date_now(self) -> Self { - self.date(SystemTime::now()) + #[cfg(not(feature = "web"))] + return self.date(SystemTime::now()); + #[cfg(feature = "web")] + return self.date(to_std_systemtime(web_time::SystemTime::now())); } /// Set or add mailbox to `ReplyTo` header @@ -623,8 +626,17 @@ fn make_message_id() -> String { iter::repeat_with(fastrand::alphanumeric).take(36).collect() } +#[cfg(feature = "web")] +pub(crate) fn to_std_systemtime(time: web_time::SystemTime) -> std::time::SystemTime { + let duration = time + .duration_since(web_time::SystemTime::UNIX_EPOCH) + .unwrap(); + std::time::SystemTime::UNIX_EPOCH + duration +} + #[cfg(test)] mod test { + use std::time::{Duration, SystemTime}; use pretty_assertions::assert_eq;