Skip to main content

email_clients/clients/
memory.rs

1use crate::configuration::EmailConfiguration;
2use async_trait::async_trait;
3use std::sync::mpsc;
4use std::sync::mpsc::SyncSender;
5
6use crate::email::{EmailAddress, EmailObject};
7use crate::errors::EmailError;
8use crate::traits::EmailTrait;
9
10#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, Default, PartialOrd, PartialEq)]
11pub struct MemoryConfig {
12    pub sender: EmailAddress,
13}
14
15impl MemoryConfig {
16    /// Generates a new `MemoryConfig`.
17    ///
18    /// # Parameters
19    /// - `sender`: A `String` that will be used as the sender of the `MemoryConfig`.
20    ///
21    /// # Returns
22    /// A new instance of `MemoryConfig` with the `sender` property set to the provided `String`.
23    ///
24    /// # Examples
25    /// ```rust
26    /// use email_clients::clients::memory::MemoryConfig;
27    ///
28    /// let config = MemoryConfig::new("sender@example.com");
29    /// assert_eq!(config.sender.to_string(), "sender@example.com");
30    /// ```
31    pub fn new(sender: impl Into<EmailAddress>) -> Self {
32        Self {
33            sender: sender.into(),
34        }
35    }
36}
37
38impl From<String> for MemoryConfig {
39    /// Converts a `String` into a `MemoryConfig`.
40    ///
41    /// # Parameters
42    /// - `value`: A `String` value which will be used to initialize a `MemoryConfig` instance.
43    ///
44    /// # Returns
45    /// A new instance of `MemoryConfig` with the `sender` property set to the provided `String`.
46    ///
47    /// # Examples
48    /// ```rust
49    /// use email_clients::clients::memory::MemoryConfig;
50    /// let value = String::from("sender@example.com");
51    /// let config = MemoryConfig::from(value);
52    /// assert_eq!(config.sender.to_string(), "sender@example.com");
53    /// ```
54    fn from(value: String) -> Self {
55        Self::new(value.as_str())
56    }
57}
58
59impl From<MemoryConfig> for EmailConfiguration {
60    /// Implementation of From trait to convert MemoryConfig into EmailConfiguration
61    ///
62    /// # Example
63    ///
64    /// ```rust
65    /// # use email_clients::configuration::EmailConfiguration;
66    /// # use email_clients::clients::memory::MemoryConfig;
67    /// #
68    /// let memory_config = MemoryConfig::new("sender@example.com");
69    /// let email_config: EmailConfiguration = memory_config.into();
70    /// #
71    /// # match email_config {
72    /// #    EmailConfiguration::Memory(mc) => {
73    /// #       assert_eq!(mc.sender.to_string(), "sender@example.com");
74    /// #   },
75    /// #    _ => panic!("Invalid conversion"),
76    /// # }
77    /// ```
78    fn from(value: MemoryConfig) -> Self {
79        EmailConfiguration::Memory(value)
80    }
81}
82
83#[derive(Clone, Debug)]
84pub struct MemoryClient {
85    sender: EmailAddress,
86    tx: SyncSender<EmailObject>,
87}
88
89impl Default for MemoryClient {
90    /// `Default` implementation for `MemoryClient`.
91    ///
92    /// This method will return a `MemoryClient` instance with an empty sender and a `SyncSender<EmailObject>`
93    /// with a channel buffer size of 5.
94    ///
95    /// # Returns
96    /// A `MemoryClient` instance with the default configuration.
97    ///
98    /// # Examples
99    ///
100    /// ```rust
101    /// use email_clients::clients::memory::MemoryClient;
102    /// use email_clients::traits::EmailTrait;
103    ///
104    /// let default_client = MemoryClient::default();
105    /// // Gets the default sender which is an empty string
106    /// assert_eq!(default_client.get_sender().to_string(), "");
107    /// ```
108    fn default() -> Self {
109        let (tx, _) = mpsc::sync_channel(5 /* usize */);
110        Self {
111            sender: "".into(),
112            tx,
113        }
114    }
115}
116
117impl MemoryClient {
118    /// Initializes a new `MemoryClient` with the provided `MemoryConfig`.
119    ///
120    /// # Parameters
121    /// - `config`: A `MemoryConfig` instance that will be used to initialize the `MemoryClient`.
122    ///
123    /// # Returns
124    /// A new instance of `MemoryClient` with the `sender` and `SyncSender<EmailObject>` set per the provided `MemoryConfig`.
125    ///
126    /// # Examples
127    /// ```rust
128    /// # use email_clients::clients::memory::{MemoryConfig, MemoryClient};
129    /// # use email_clients::traits::EmailTrait;
130    ///
131    /// let config = MemoryConfig::new("sender@example.com");
132    /// let client = MemoryClient::new(config);
133    /// assert_eq!(client.get_sender().to_string(), "sender@example.com");
134    /// ```
135    pub fn new(config: MemoryConfig) -> Self {
136        let (tx, _) = mpsc::sync_channel(5 /* usize */);
137
138        Self {
139            sender: config.sender,
140            tx,
141        }
142    }
143
144    /// Initializes a new `MemoryClient` with the provided `MemoryConfig` and `SyncSender<EmailObject>`.
145    ///
146    /// # Parameters
147    /// - `config`: A `MemoryConfig` instance that will be used to initialize the `MemoryClient`.
148    /// - `tx`: A `SyncSender<EmailObject>` instance that will be used for sending emails.
149    ///
150    /// # Returns
151    /// A new instance of `MemoryClient` with the `sender` and `SyncSender<EmailObject>` set per the provided parameters.
152    ///
153    /// # Examples
154    /// ```rust
155    /// # use std::sync::mpsc::sync_channel;
156    /// # use email_clients::clients::memory::{MemoryConfig, MemoryClient};
157    /// # use email_clients::email::EmailObject;
158    /// # use email_clients::traits::EmailTrait;
159    ///
160    /// let config = MemoryConfig::new("sender@example.com");
161    /// let (tx, rx) = sync_channel(2);
162    /// let client = MemoryClient::with_tx(config, tx.clone());
163    /// assert_eq!(client.get_sender().to_string(), "sender@example.com");
164    /// ```
165    pub fn with_tx(config: MemoryConfig, tx: SyncSender<EmailObject>) -> Self {
166        Self {
167            sender: config.sender,
168            tx,
169        }
170    }
171}
172
173#[async_trait]
174impl EmailTrait for MemoryClient {
175    /// Returns the sender email address used for the `MemoryClient`.
176    ///
177    /// # Returns
178    /// An `EmailAddress` that is used as the sender's email in the `MemoryClient`.
179    ///
180    /// # Examples
181    ///
182    /// ```rust
183    /// # use email_clients::clients::memory::{MemoryConfig, MemoryClient};
184    /// # use email_clients::traits::EmailTrait;
185    ///
186    /// let config = MemoryConfig::new("sender@example.com");  
187    /// let client = MemoryClient::new(config);
188    /// assert_eq!(client.get_sender().to_string(), "sender@example.com");
189    /// ```
190    fn get_sender(&self) -> EmailAddress {
191        self.sender.clone()
192    }
193
194    /// Sends email from memory client.
195    async fn send_emails(&self, email: EmailObject) -> crate::Result<()> {
196        self.tx
197            .send(email)
198            .map_err(|_| EmailError::UnexpectedError("Cannot send email in memory".to_string()))?;
199        Ok(())
200    }
201}