Repository: TabbyML/tabby
File: ee/tabby-webserver/src/service/email/mod.rs (Rust)

Code before:

struct EmailServiceImpl {
    db: DbConn,
    setting: Arc<dyn SettingService>,
    smtp_server: Arc<RwLock<Option<AsyncSmtpTransport<Tokio1Executor>>>>,
    from: RwLock<String>,
}

fn auth_mechanism(auth_method: AuthMethod) -> Vec<Mechanism> {
    match auth_method {
        AuthMethod::Plain => vec![Mechanism::Plain],
        AuthMethod::Login => vec![Mechanism::Login],
        AuthMethod::None => vec![],
    }
}

fn make_smtp_builder(
    host: &str,
    port: u16,
    encryption: Encryption,
    cert_pem: Option<String>,
) -> Result<AsyncSmtpTransportBuilder> {
    let mut tls_parameters = TlsParameters::builder(host.into());

    if let Ok(cert_path) = std::env::var("TABBY_EMAIL_CERT_PATH") {
        let cert = Certificate::from_pem(&std::fs::read(cert_path)?)
            .map_err(|_| CoreError::EmailInvalidCert)?;
        tls_parameters = tls_parameters.add_root_certificate(cert);
    }

    let tls_parameters = tls_parameters
        .build()
        .map_err(|_| CoreError::EmailInvalidCert)?;

    let builder = match encryption {
        Encryption::StartTls => AsyncSmtpTransport::<Tokio1Executor>::builder_dangerous(host)
            .port(port)
            .tls(Tls::Required(tls_parameters)),
        Encryption::SslTls => AsyncSmtpTransport::<Tokio1Executor>::builder_dangerous(host)
            .port(port)
            .tls(Tls::Wrapper(tls_parameters)),
        Encryption::None => {
            AsyncSmtpTransport::<Tokio1Executor>::builder_dangerous(host).port(port)
        }
    };

    Ok(builder)
}

impl EmailServiceImpl {
    fn new(db: DbConn, setting: Arc<dyn SettingService>) -> Self {

Review comment (suggestion):
```suggestion
        let cert = Certificate::from_pem(&cert_string)
```

Code after:

struct EmailServiceImpl {
    db: DbConn,
    setting: Arc<dyn SettingService>,
    smtp_server: Arc<RwLock<Option<AsyncSmtpTransport<Tokio1Executor>>>>,
    from: RwLock<String>,
}

fn auth_mechanism(auth_method: AuthMethod) -> Vec<Mechanism> {
    match auth_method {
        AuthMethod::Plain => vec![Mechanism::Plain],
        AuthMethod::Login => vec![Mechanism::Login],
        AuthMethod::None => vec![],
    }
}

fn make_smtp_builder(
    host: &str,
    port: u16,
    encryption: Encryption,
    cert_pem: Option<String>,
) -> Result<AsyncSmtpTransportBuilder> {
    let mut tls_parameters = TlsParameters::builder(host.into());

    if let Ok(cert_string) = std::env::var("TABBY_WEBSERVER_EMAIL_CERT") {
        let cert = Certificate::from_pem(cert_string.as_bytes())
            .map_err(|e| CoreError::Other(e.into()))?;
        tls_parameters = tls_parameters.add_root_certificate(cert);
    }

    let tls_parameters = tls_parameters
        .build()
        .map_err(|e| CoreError::Other(e.into()))?;

    let builder = match encryption {
        Encryption::StartTls => AsyncSmtpTransport::<Tokio1Executor>::builder_dangerous(host)
            .port(port)
            .tls(Tls::Required(tls_parameters)),
        Encryption::SslTls => AsyncSmtpTransport::<Tokio1Executor>::builder_dangerous(host)
            .port(port)
            .tls(Tls::Wrapper(tls_parameters)),
        Encryption::None => {
            AsyncSmtpTransport::<Tokio1Executor>::builder_dangerous(host).port(port)
        }
    };

    Ok(builder)
}

impl EmailServiceImpl {
    fn new(db: DbConn, setting: Arc<dyn SettingService>) -> Self {