maik 0.2.0

A mock SMTP server library
Documentation
use fake::{
    faker::internet::en::{Password, SafeEmail},
    Fake,
};
use lazy_static::lazy_static;
use lettre::{
    message::{header, Mailboxes},
    transport::smtp::{
        authentication::{Credentials, Mechanism},
        client::{Certificate, TlsParameters, TlsParametersBuilder},
        PoolConfig, SmtpTransport, SmtpTransportBuilder,
    },
    Message,
};
use maik::{MockServer, MockServerBuilder};
use std::collections::HashSet;
use std::time::Duration;

pub struct TestInfo {
    pub mailer_builder: SmtpTransportBuilder,
    pub tls_params: TlsParameters,
    pub server: MockServer,
}

pub struct TestInfoBuilder {
    server_builder: MockServerBuilder,
    auth_user: Option<String>,
    auth_password: Option<String>,
    use_pool: bool,
}

pub const DEFAULT_SENDER: &str = "sender@domain1.com";
pub const DEFAULT_RECIPIENT: &str = "recipient@domain2.com";
pub const DEFAULT_BODY: &str = "Here is your verification code: 123456";
pub const DNE_USER: &str = "user_dne@xxx.com";

const DEFAULT_RECIPIENTS: &str = "r1@d.com, r2@d.com";

lazy_static! {
    pub static ref DEFAULT_MESSAGE: Message = new_message(DEFAULT_RECIPIENT, DEFAULT_BODY);
    pub static ref DEFAULT_MESSAGES: Message = new_message(DEFAULT_RECIPIENTS, DEFAULT_BODY);
    pub static ref EMPTY_MESSAGE: Message = new_message(DEFAULT_RECIPIENT, "");
    pub static ref EMPTY_MESSAGES: Message = new_message(DEFAULT_RECIPIENTS, "");
    pub static ref DEFAULT_RECIPIENTS_SET: HashSet<&'static str> =
        DEFAULT_RECIPIENTS.split(',').map(|s| s.trim()).collect();
}

impl TestInfoBuilder {
    pub fn new() -> Self {
        Self {
            server_builder: MockServer::builder(),
            auth_user: None,
            auth_password: None,
            use_pool: false,
        }
    }

    pub fn set_require_tls(mut self) -> Self {
        self.server_builder = self.server_builder.require_tls();
        self
    }

    pub fn close_after_n(mut self, n: u8) -> Self {
        self.server_builder = self.server_builder.assert_after_n_emails(n);
        self.use_pool = true;
        self
    }

    pub fn add_mailbox(mut self, smtp_user: &str, password: &str) -> Self {
        self.server_builder = self.server_builder.add_mailbox(smtp_user, password);
        self
    }

    pub fn auth_as(mut self, smtp_user: &str, password: &str) -> Self {
        self.auth_user = Some(smtp_user.to_string());
        self.auth_password = Some(password.to_string());
        self
    }

    pub fn default_auth_user(mut self) -> Self {
        self.server_builder = self.server_builder.no_verify_credentials();
        self.auth_as(
            &SafeEmail().fake::<String>(),
            &Password(8..16).fake::<String>(),
        )
    }

    pub fn build(self) -> TestInfo {
        let server = self.server_builder.build();
        let certificate = Certificate::from_pem(server.cert_pem()).unwrap();
        server.start();

        let mut mailer_builder = SmtpTransport::relay(&server.host().to_string())
            .unwrap()
            .port(server.port())
            .timeout(Some(Duration::from_millis(200)));
        if self.auth_user.is_some() && self.auth_user.is_some() {
            let creds = Credentials::new(
                self.auth_user.as_ref().unwrap().clone(),
                self.auth_password.as_ref().unwrap().clone(),
            );
            mailer_builder = mailer_builder
                .credentials(creds)
                .authentication(vec![Mechanism::Plain]);
        }
        if !self.use_pool {
            mailer_builder = mailer_builder.pool_config(PoolConfig::new().max_size(0));
        }

        TestInfo {
            mailer_builder,
            tls_params: TlsParametersBuilder::new(server.host().to_string())
                .add_root_certificate(certificate)
                .build()
                .unwrap(),
            server,
        }
    }
}

pub fn new_message(recipients: &str, body: &str) -> Message {
    let mailboxes: Mailboxes = recipients.parse().unwrap();
    let to_header: header::To = mailboxes.into();

    Message::builder()
        .from(DEFAULT_SENDER.parse().unwrap())
        .mailbox(to_header)
        .body(body.to_string())
        .unwrap()
}