Files
windmill/backend/windmill-common/src/server.rs
T
Ruben Fiszel 1a39bd538d add opt-in SMTP click tracking disable for email links (#8665)
* feat: add opt-in SMTP click tracking disable for email links

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref.txt for email clicktracking branch

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref.txt after simplification

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: exclude trailing commas from URL regex in clicktracking

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref to 57dd88faa3b0b354f813385cf3f6a34eca54a4a1

This commit updates the EE repository reference after PR #504 was merged in windmill-ee-private.

Previous ee-repo-ref: 5cf901db7fb0ea169b09564372e444f28e23ac3a

New ee-repo-ref: 57dd88faa3b0b354f813385cf3f6a34eca54a4a1

Automated by sync-ee-ref workflow.

* chore: update ee-repo-ref.txt to include dedicated worker fixes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
2026-04-02 20:44:08 +00:00

107 lines
3.2 KiB
Rust

use serde::{Deserialize, Serialize};
use crate::{error, DB};
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
pub struct Smtp {
pub host: String,
pub username: Option<String>,
pub password: Option<String>,
pub port: u16,
pub from: String,
pub tls_implicit: Option<bool>,
pub disable_tls: Option<bool>,
pub clicktracking_off: Option<bool>,
}
#[derive(Serialize, Deserialize, PartialEq)]
pub struct SmtpConfigOpt {
pub smtp_host: Option<String>,
pub smtp_username: Option<String>,
pub smtp_password: Option<String>,
pub smtp_port: Option<u16>,
pub smtp_from: Option<String>,
pub smtp_tls_implicit: Option<bool>,
pub smtp_disable_tls: Option<bool>,
pub smtp_clicktracking_off: Option<bool>,
}
pub async fn load_smtp_config(db: &DB) -> error::Result<Option<Smtp>> {
let config: SmtpConfigOpt =
sqlx::query_scalar!("SELECT value FROM global_settings WHERE name = 'smtp_settings'",)
.fetch_optional(db)
.await?
.map(|x| serde_json::from_value(x).ok())
.flatten()
.unwrap_or_default();
let config_smtp = if let (Some(host), username, password) =
(config.smtp_host, config.smtp_username, config.smtp_password)
{
Some(Smtp {
host,
username,
password,
tls_implicit: config.smtp_tls_implicit,
disable_tls: config.smtp_disable_tls,
port: config.smtp_port.unwrap_or(587),
from: config
.smtp_from
.unwrap_or_else(|| "noreply@getwindmill.com".to_string()),
clicktracking_off: config.smtp_clicktracking_off,
})
} else {
None
};
let smtp = config_smtp.or(
if let (Some(host), username, password) = (
std::env::var("SMTP_HOST").ok(),
std::env::var("SMTP_USERNAME").ok(),
std::env::var("SMTP_PASSWORD").ok(),
) {
Some(Smtp {
host,
username,
password,
tls_implicit: std::env::var("SMTP_TLS_IMPLICIT")
.ok()
.and_then(|p| p.parse().ok()),
disable_tls: std::env::var("SMTP_DISABLE_TLS")
.ok()
.and_then(|p| p.parse().ok()),
port: std::env::var("SMTP_PORT")
.ok()
.and_then(|p| p.parse().ok())
.unwrap_or(587),
from: std::env::var("SMTP_FROM")
.unwrap_or_else(|_| "noreply@getwindmill.com".to_string()),
clicktracking_off: std::env::var("SMTP_CLICKTRACKING_OFF")
.ok()
.and_then(|p| p.parse().ok()),
})
} else {
None
},
);
if smtp.is_none() {
tracing::warn!("SMTP not configured");
}
Ok(smtp)
}
impl Default for SmtpConfigOpt {
fn default() -> Self {
Self {
smtp_from: None,
smtp_host: None,
smtp_password: None,
smtp_port: None,
smtp_tls_implicit: None,
smtp_username: None,
smtp_disable_tls: None,
smtp_clicktracking_off: None,
}
}
}