feat: introduce SMTP env configurations (#2810)

Addresses #2601.

`lettre` crate requires Rust `1.70+`. `ZO_SMTP_ENCRYPTION` env variable
offers two important encryption method - `starttls` and `ssltls`.
This commit is contained in:
Subhra264 2024-02-28 17:15:48 +05:30 committed by GitHub
parent b68ba66ea5
commit 8f1d5f7010
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 204 additions and 13 deletions

View File

@ -9,7 +9,7 @@ OpenObserve uses Rust & embdeds sled db (For server) & VueJS (For Web UI)
You must have follwing installed:
1. Git
2. Rust & Cargo 1.61.0 + (We recommend 1.66+),
2. Rust & Cargo 1.70+
3. nodejs v14+ and npm v6+
Alternatively you can use pre-configured devcontainer in VS code to get up and running quickly.

149
Cargo.lock generated
View File

@ -1181,7 +1181,7 @@ dependencies = [
"hyper-rustls",
"lazy_static",
"pin-project-lite",
"rustls",
"rustls 0.21.10",
"tokio",
"tower",
"tracing",
@ -1823,6 +1823,16 @@ dependencies = [
"phf_codegen",
]
[[package]]
name = "chumsky"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9"
dependencies = [
"hashbrown 0.14.3",
"stacker",
]
[[package]]
name = "ciborium"
version = "0.2.2"
@ -2072,6 +2082,7 @@ dependencies = [
"hex",
"indexmap 2.1.0",
"itertools 0.12.1",
"lettre",
"log",
"memchr",
"murmur3",
@ -2783,6 +2794,22 @@ dependencies = [
"serde",
]
[[package]]
name = "email-encoding"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbfb21b9878cf7a348dcb8559109aabc0ec40d69924bd706fa5149846c4fef75"
dependencies = [
"base64 0.21.7",
"memchr",
]
[[package]]
name = "email_address"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112"
[[package]]
name = "ena"
version = "0.14.2"
@ -3532,10 +3559,10 @@ dependencies = [
"http 0.2.11",
"hyper",
"log",
"rustls",
"rustls 0.21.10",
"rustls-native-certs",
"tokio",
"tokio-rustls",
"tokio-rustls 0.24.1",
]
[[package]]
@ -3894,6 +3921,36 @@ dependencies = [
"spin 0.5.2",
]
[[package]]
name = "lettre"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357ff5edb6d8326473a64c82cf41ddf78ab116f89668c50c4fac1b321e5e80f4"
dependencies = [
"async-trait",
"base64 0.21.7",
"chumsky",
"email-encoding",
"email_address",
"fastrand 2.0.1",
"futures-io",
"futures-util",
"hostname",
"httpdate",
"idna",
"mime",
"nom",
"percent-encoding",
"quoted_printable",
"rustls 0.22.2",
"rustls-pemfile 2.0.0",
"socket2",
"tokio",
"tokio-rustls 0.25.0",
"url",
"webpki-roots 0.26.1",
]
[[package]]
name = "lexical-core"
version = "0.8.5"
@ -4671,6 +4728,7 @@ dependencies = [
"ipnetwork 0.20.0",
"itertools 0.12.1",
"jsonwebtoken",
"lettre",
"log",
"maxminddb",
"memory-stats",
@ -5483,6 +5541,15 @@ version = "2.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
[[package]]
name = "psm"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874"
dependencies = [
"cc",
]
[[package]]
name = "ptr_meta"
version = "0.1.4"
@ -5756,7 +5823,7 @@ dependencies = [
"once_cell",
"percent-encoding",
"pin-project-lite",
"rustls",
"rustls 0.21.10",
"rustls-native-certs",
"rustls-pemfile 1.0.4",
"serde",
@ -5765,7 +5832,7 @@ dependencies = [
"sync_wrapper",
"system-configuration",
"tokio",
"tokio-rustls",
"tokio-rustls 0.24.1",
"tokio-util",
"tower-service",
"url",
@ -5773,7 +5840,7 @@ dependencies = [
"wasm-bindgen-futures",
"wasm-streams",
"web-sys",
"webpki-roots",
"webpki-roots 0.25.4",
"winreg",
]
@ -6013,10 +6080,24 @@ checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba"
dependencies = [
"log",
"ring 0.17.7",
"rustls-webpki",
"rustls-webpki 0.101.7",
"sct",
]
[[package]]
name = "rustls"
version = "0.22.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41"
dependencies = [
"log",
"ring 0.17.7",
"rustls-pki-types",
"rustls-webpki 0.102.2",
"subtle",
"zeroize",
]
[[package]]
name = "rustls-native-certs"
version = "0.6.3"
@ -6064,6 +6145,17 @@ dependencies = [
"untrusted 0.9.0",
]
[[package]]
name = "rustls-webpki"
version = "0.102.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610"
dependencies = [
"ring 0.17.7",
"rustls-pki-types",
"untrusted 0.9.0",
]
[[package]]
name = "rustversion"
version = "1.0.14"
@ -6590,7 +6682,7 @@ dependencies = [
"once_cell",
"paste",
"percent-encoding",
"rustls",
"rustls 0.21.10",
"rustls-pemfile 1.0.4",
"serde",
"serde_json",
@ -6602,7 +6694,7 @@ dependencies = [
"tokio-stream",
"tracing",
"url",
"webpki-roots",
"webpki-roots 0.25.4",
]
[[package]]
@ -6758,6 +6850,19 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "stacker"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce"
dependencies = [
"cc",
"cfg-if 1.0.0",
"libc",
"psm",
"winapi 0.3.9",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
@ -7191,7 +7296,18 @@ version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
dependencies = [
"rustls",
"rustls 0.21.10",
"tokio",
]
[[package]]
name = "tokio-rustls"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f"
dependencies = [
"rustls 0.22.2",
"rustls-pki-types",
"tokio",
]
@ -7296,10 +7412,10 @@ dependencies = [
"percent-encoding",
"pin-project",
"prost 0.12.3",
"rustls",
"rustls 0.21.10",
"rustls-pemfile 1.0.4",
"tokio",
"tokio-rustls",
"tokio-rustls 0.24.1",
"tokio-stream",
"tower",
"tower-layer",
@ -7999,6 +8115,15 @@ version = "0.25.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
[[package]]
name = "webpki-roots"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "which"
version = "4.4.2"

View File

@ -152,6 +152,7 @@ zstd.workspace = true
config.workspace = true
infra.workspace = true
ingester.workspace = true
lettre.workspace = true
[build-dependencies]
chrono = { version = "0.4", default-features = false, features = ["clock"] }
@ -217,6 +218,14 @@ hex = "0.4"
indexmap = { version = "2.0", features = ["serde"] }
ipnetwork = "0.20"
itertools = "0.12"
lettre = { version = "0.11", default-features = false, features = [
"builder",
"hostname",
"smtp-transport",
"pool",
"tokio1",
"tokio1-rustls-tls",
] }
log = "0.4"
memchr = "2.5"
murmur3 = "0.5"

View File

@ -47,3 +47,4 @@ tracing-log.workspace = true
tracing-subscriber.workspace = true
utoipa.workspace = true
walkdir.workspace = true
lettre.workspace = true

View File

@ -19,6 +19,13 @@ use dotenv_config::EnvConfig;
use dotenvy::dotenv;
use hashbrown::{HashMap, HashSet};
use itertools::chain;
use lettre::{
transport::smtp::{
authentication::Credentials,
client::{Tls, TlsParameters},
},
AsyncSmtpTransport, Tokio1Executor,
};
use once_cell::sync::Lazy;
use reqwest::Client;
use sysinfo::{DiskExt, SystemExt};
@ -139,6 +146,34 @@ pub static TELEMETRY_CLIENT: Lazy<segment::HttpClient> = Lazy::new(|| {
)
});
pub static SMTP_CLIENT: Lazy<Option<AsyncSmtpTransport<Tokio1Executor>>> = Lazy::new(|| {
if !CONFIG.smtp.smtp_enabled {
None
} else {
let tls_parameters = TlsParameters::new(CONFIG.smtp.smtp_host.clone()).unwrap();
let mut transport_builder =
AsyncSmtpTransport::<Tokio1Executor>::builder_dangerous(&CONFIG.smtp.smtp_host)
.port(CONFIG.smtp.smtp_port);
let option = &CONFIG.smtp.smtp_encryption;
transport_builder = if option == "starttls" {
transport_builder.tls(Tls::Required(tls_parameters))
} else if option == "ssltls" {
transport_builder.tls(Tls::Wrapper(tls_parameters))
} else {
transport_builder
};
if !CONFIG.smtp.smtp_username.is_empty() && !CONFIG.smtp.smtp_password.is_empty() {
transport_builder = transport_builder.credentials(Credentials::new(
CONFIG.smtp.smtp_username.clone(),
CONFIG.smtp.smtp_password.clone(),
));
}
Some(transport_builder.build())
}
});
#[derive(EnvConfig)]
pub struct Config {
pub auth: Auth,
@ -158,6 +193,27 @@ pub struct Config {
pub tcp: TCP,
pub prom: Prometheus,
pub profiling: Pyroscope,
pub smtp: Smtp,
}
#[derive(EnvConfig)]
pub struct Smtp {
#[env_config(name = "ZO_SMTP_ENABLED", default = false)]
pub smtp_enabled: bool,
#[env_config(name = "ZO_SMTP_HOST", default = "localhost")]
pub smtp_host: String,
#[env_config(name = "ZO_SMTP_PORT", default = 25)]
pub smtp_port: u16,
#[env_config(name = "ZO_SMTP_USER_NAME", default = "")]
pub smtp_username: String,
#[env_config(name = "ZO_SMTP_PASSWORD", default = "")]
pub smtp_password: String,
#[env_config(name = "ZO_SMTP_REPLY_TO", default = "")]
pub smtp_reply_to: String,
#[env_config(name = "ZO_SMTP_FROM_EMAIL", default = "")]
pub smtp_from_email: String,
#[env_config(name = "ZO_SMTP_ENCRYPTION", default = "")]
pub smtp_encryption: String,
}
#[derive(EnvConfig)]