1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//! Copyright 2021 Nyah Check crate.
//!
//! Application-specific configuration for PrivatEmail

#![allow(clippy::style)]
use serde::{Deserialize, Serialize};
use std::env;

/**
 * Config object for PrivatEmail.
 *
 * Implements [`serde::Deserialize`] and [`serde::Serialize`] and
 * can be composed with other consumer configs.
 * PrivatEmailConfig:
 *  from_email: Forwarded emails will be received from this SES verified email address.
 *              To match all email addresses on a domain, use a key without the name part of the email(`example.com`)
 *  to_email: Recipient email address. Example: jon@doe.example
 *  subject_prefix: Forwarded emails subject will contain this prefix.
 *  email_bucket: S3 bucket to store raw SES emails.
 *  email_key_prefix: S3 key prefix where SES stores emails.
 */
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(default)]
pub struct PrivatEmailConfig {
    /** Forwarded emails will be received from this SES verified email address */
    #[serde(default, skip_serializing_if = "String::is_empty")]
    pub from_email: String,
    /** Recipient email address that receives the forwarded SES email */
    #[serde(default, skip_serializing_if = "String::is_empty")]
    pub to_email: String,
    /** Forwarded emails subject will contain this prefix */
    #[serde(skip_serializing_if = "Option::is_none")]
    pub subject_prefix: Option<String>,
    /** S3 bucket to store raw SES emails */
    #[serde(skip_serializing_if = "Option::is_none")]
    pub email_bucket: Option<String>,
    /** S3 key prefix where SES stores emails */
    #[serde(skip_serializing_if = "Option::is_none")]
    pub email_key_prefix: Option<String>,
}

/// Create default method for PrivatEmailConfig struct
impl Default for PrivatEmailConfig {
    fn default() -> Self {
        PrivatEmailConfig {
            from_email: String::from("hello@nyah.dev"),
            to_email: String::from("nyah@hey.com"),
            subject_prefix: None, // not currently used
            email_bucket: None,
            email_key_prefix: None,
        }
    }
}

/// Create a new PrivatEmailConfig client struct from environment variables.
impl PrivatEmailConfig {
    /// Create new PrivatEmailConfig struct from environment variables.
    /// As long as you have the `from_email` and `to_email` environment setup; this should work
    pub fn new_from_env() -> Self {
        PrivatEmailConfig {
            from_email: env::var("FROM_EMAIL").unwrap_or_default(),
            to_email: env::var("TO_EMAIL").unwrap_or_default(),
            subject_prefix: None, // not currently used
            email_bucket: None,
            email_key_prefix: None,
        }
    }

    /// Create a new PrivatEmailConfig struct.PrivatEmailConfig
    /// You can leave the s3 bucket related fields empty since it's not currently being used
    #[allow(dead_code)]
    pub fn new<F, T, S>(from_email: F, to_email: T, subject_prefix: S) -> Self
    where
        F: ToString,
        T: ToString,
        S: ToString,
    {
        PrivatEmailConfig {
            from_email: from_email.to_string(),
            to_email: to_email.to_string(),
            subject_prefix: Some(subject_prefix.to_string()),
            email_bucket: None,
            email_key_prefix: None,
        }
    }
}

/** Test module for PrivatEmailConfig struct */
#[cfg(test)]
mod tests {
    use super::*;
    use std::env;

    #[test]
    fn test_new_privatemail_config() {
        let new_config = PrivatEmailConfig::new(
            String::from("test_from"),
            String::from("test_to"),
            String::from("test_subject"),
        );
        assert_eq!(new_config.from_email.contains("test_from"), true);
        assert_eq!(new_config.to_email.contains("test_to"), true);
        assert_eq!(new_config.subject_prefix.unwrap(), "test_subject");
        assert_eq!(new_config.email_bucket.is_none(), true);
        assert_eq!(new_config.email_key_prefix.is_none(), true);
    }

    #[test]
    fn test_default_privatemail_config() {
        let new_config = PrivatEmailConfig::default();
        assert_eq!(new_config.from_email.contains("hello@nyah.dev"), true);
        assert_eq!(new_config.to_email.contains("nyah@hey.com"), true);
        assert_eq!(new_config.subject_prefix.is_none(), true);
        assert_eq!(new_config.email_bucket.is_none(), true);
        assert_eq!(new_config.email_key_prefix.is_none(), true);
    }

    #[test]
    fn test_new_from_env_privatemail_config() {
        env::set_var("FROM_EMAIL", "test_from");
        env::set_var("TO_EMAIL", "test_to");

        let new_config = PrivatEmailConfig::new_from_env();
        assert_eq!(new_config.from_email.contains("test_from"), true);
        assert_eq!(new_config.to_email.contains("test_to"), true);
        assert_eq!(new_config.subject_prefix.is_none(), true);
        assert_eq!(new_config.email_bucket.is_none(), true);
        assert_eq!(new_config.email_key_prefix.is_none(), true);
    }
}