Browse Source

changes for review

pull/5620/head
Guilhem Zeitoun 1 week ago
parent
commit
eac74fa0d1
Failed to extract signature
  1. 9
      .env.template
  2. 13
      src/config.rs
  3. 51
      src/mail.rs

9
.env.template

@ -640,6 +640,15 @@
## Embed images as email attachments ## Embed images as email attachments
# SMTP_EMBED_IMAGES=true # SMTP_EMBED_IMAGES=true
## Dkim signature (type:privatekey). |> Private must be base64-encoded ed key or PKCS#1 format RSA key.
# dkim_signing_key=rsa_key.pem
## Dkim algo (true if RSA else ed25519)
# dkim_use_rsa=true
## Dkim selector
# dkim_selector="dkim_key"
## Dkim domain
#dkim_domain="example.com"
## SMTP debugging ## SMTP debugging
## When set to true this will output very detailed SMTP messages. ## When set to true this will output very detailed SMTP messages.
## WARNING: This could contain sensitive information like passwords and usernames! Only enable this during troubleshooting! ## WARNING: This could contain sensitive information like passwords and usernames! Only enable this during troubleshooting!

13
src/config.rs

@ -15,6 +15,7 @@ use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor};
use crate::{ use crate::{
error::Error, error::Error,
mail::check_dkim, mail::check_dkim,
storage,
util::{ util::{
FeatureFlagFilter, get_active_web_release, get_env, get_env_bool, is_valid_email, FeatureFlagFilter, get_active_web_release, get_env, get_env_bool, is_valid_email,
parse_experimental_client_feature_flags, parse_experimental_client_feature_flags,
@ -885,12 +886,14 @@ make_config! {
smtp_username: String, true, option; smtp_username: String, true, option;
/// Password /// Password
smtp_password: Pass, true, option; smtp_password: Pass, true, option;
/// Dkim signature (type:privatekey). Private must be base64-encoded ed key or PKCS#1 format RSA key. /// Dkim signature (private key). |> Private must be base64-encoded ed key or PKCS#1 format RSA key. If set, dkim_selector and dkim_domain must be set as well.
dkim_signature: String, true, option; dkim_signing_key: String, true, option;
/// Dkim algo (true if RSA else ed25519) /// Dkim algorithm (true if RSA else ed25519)
dkim_use_rsa: bool, true, def, false; dkim_use_rsa: bool, true, def, false;
/// Dkim infos (selector:domain) /// Dkim selector
dkim_infos: String, true, option; dkim_selector: String, true, option;
/// Dkim domain
dkim_domain: String, true, option;
/// SMTP Auth mechanism |> Defaults for SSL is "Plain" and "Login" and nothing for Non-SSL connections. Possible values: ["Plain", "Login", "Xoauth2"]. Multiple options need to be separated by a comma ','. /// SMTP Auth mechanism |> Defaults for SSL is "Plain" and "Login" and nothing for Non-SSL connections. Possible values: ["Plain", "Login", "Xoauth2"]. Multiple options need to be separated by a comma ','.
smtp_auth_mechanism: String, true, option; smtp_auth_mechanism: String, true, option;
/// SMTP connection timeout |> Number of seconds when to stop trying to connect to the SMTP server /// SMTP connection timeout |> Number of seconds when to stop trying to connect to the SMTP server

51
src/mail.rs

@ -2,15 +2,12 @@ use std::{env::consts::EXE_SUFFIX, str::FromStr};
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use lettre::{ use lettre::{
<<<<<<< HEAD
Address, AsyncSendmailTransport, AsyncSmtpTransport, AsyncTransport, Tokio1Executor, Address, AsyncSendmailTransport, AsyncSmtpTransport, AsyncTransport, Tokio1Executor,
message::{Attachment, Body, Mailbox, Message, MultiPart, SinglePart}, message::{Attachment, Body, Mailbox, Message, MultiPart, SinglePart},
=======
message::{ message::{
dkim::{DkimConfig, DkimSigningAlgorithm, DkimSigningKey}, dkim::{DkimConfig, DkimSigningAlgorithm, DkimSigningKey},
dkim_sign, Attachment, Body, Mailbox, Message, MultiPart, SinglePart, dkim_sign,
}, },
>>>>>>> daa9e075 (corrections on config parsing)
transport::smtp::authentication::{Credentials, Mechanism as SmtpAuthMechanism}, transport::smtp::authentication::{Credentials, Mechanism as SmtpAuthMechanism},
transport::smtp::client::{Tls, TlsParameters}, transport::smtp::client::{Tls, TlsParameters},
transport::smtp::extension::ClientId, transport::smtp::extension::ClientId,
@ -26,7 +23,7 @@ use crate::{
}, },
db::models::{Device, DeviceType, EmergencyAccessId, MembershipId, OrganizationId, User, UserId}, db::models::{Device, DeviceType, EmergencyAccessId, MembershipId, OrganizationId, User, UserId},
error::Error, error::Error,
util::upcase_first, util::{get_env_str_value, upcase_first},
}; };
fn sendmail_transport() -> AsyncSendmailTransport<Tokio1Executor> { fn sendmail_transport() -> AsyncSendmailTransport<Tokio1Executor> {
@ -707,38 +704,32 @@ async fn send_with_selected_transport(email: Message) -> EmptyResult {
} }
} }
pub fn check_dkim() -> Result<Option<DkimConfig>, String> { pub fn check_dkim() -> Result<Option<DkimConfig>, String> {
match (CONFIG.dkim_signature(), CONFIG.dkim_infos()) { match (
(Some(sig), Some(infos)) => { CONFIG.dkim_signing_key().and_then(|a| get_env_str_value(&a)),
CONFIG.dkim_domain().and_then(|a| get_env_str_value(&a)),
CONFIG.dkim_selector().and_then(|a| get_env_str_value(&a)), //get_env_str should return None only if variables are not set, which is already checked
) {
(Some(sig), Some(domain), Some(selector)) => {
let config = { let config = {
let algo = if CONFIG.dkim_use_rsa() {DkimSigningAlgorithm::Rsa } else { DkimSigningAlgorithm::Ed25519 }; let algo = if CONFIG.dkim_use_rsa() {
let sig = match std::fs::read_to_string(sig) { DkimSigningAlgorithm::Rsa
} else {
DkimSigningAlgorithm::Ed25519
};
let sig = match DkimSigningKey::new(&sig, algo) {
Ok(d) => d,
Err(e) => { Err(e) => {
return Err(format!("Cannot read DKIM key. Err is {:?}", e)); return Err(format!("DKIM key is invalid. Err is {e:?}"));
} }
Ok(key) => match DkimSigningKey::new(&key, algo) {
Ok(d) => d,
Err(e) => {
return Err(format!("DKIM key is invalid. Err is {:?}", e));
}
},
}; };
match (sig, infos.split(':').collect::<Vec<&str>>()) { (selector, domain, sig)
(sig, split2) if split2.len() == 2 => {
let (selector, domain, sig) =
(String::from(*split2.first().unwrap()), String::from(*split2.last().unwrap()), sig);
(selector, domain, sig)
}
_ => {
return Err("DKIM issue, invalid domain, selector.".to_string());
}
}
}; };
Ok(Some(DkimConfig::default_config(config.0, config.1, config.2))) Ok(Some(DkimConfig::default_config(config.0, config.1, config.2)))
} }
(None, None) => Ok(None), (None, None, None) => Ok(None),
_ => { _ => Err(
Err("DKIM setting is badly implemented. One config is missing (DKIM signature or DKIM infos).".to_string()) "DKIM setting is badly implemented. One config is missing or invalid (DKIM signature or DKIM infos or DKIM signing key).".to_owned(),
} ),
} }
} }
async fn send_email(address: &str, subject: &str, body_html: String, body_text: String) -> EmptyResult { async fn send_email(address: &str, subject: &str, body_html: String, body_text: String) -> EmptyResult {

Loading…
Cancel
Save