Skip to main content

email/
lib.rs

1use core::fmt;
2use file::File;
3use itertools::Itertools;
4use serde::{Deserialize, Serialize};
5use std::fmt::Display;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct EmailAddress {
9    #[serde(default, skip_serializing_if = "Option::is_none")]
10    pub name: Option<String>,
11    pub address: String,
12}
13
14impl<T: Into<String>> From<T> for EmailAddress {
15    fn from(value: T) -> Self {
16        EmailAddress {
17            name: None,
18            address: value.into(),
19        }
20    }
21}
22
23impl Display for EmailAddress {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        if let Some(name) = &self.name {
26            write!(f, "{} <{}>", name, self.address)
27        } else {
28            write!(f, "{}", self.address)
29        }
30    }
31}
32
33pub enum Body {
34    Text(String),
35    Html(String),
36    Combined { text: String, html: String },
37}
38
39impl Default for Body {
40    fn default() -> Self {
41        Body::Text("".to_string())
42    }
43}
44
45impl fmt::Display for Body {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        match self {
48            Body::Text(text) => write!(f, "{}", text),
49            Body::Html(html) => write!(f, "{}", html),
50            Body::Combined { text, .. } => write!(f, "{text}"),
51        }
52    }
53}
54
55pub struct Email {
56    pub from: EmailAddress,
57    pub to: Vec<EmailAddress>,
58    pub cc: Vec<EmailAddress>,
59    pub bcc: Vec<EmailAddress>,
60    pub subject: String,
61    pub body: Body,
62    pub attachments: Vec<File>,
63    /// Header message id to reply to
64    pub reply_to_message_id: Option<String>,
65    pub thread_id: Option<String>,
66}
67
68impl Email {
69    pub fn to_header(&self) -> String {
70        self.to
71            .iter()
72            .map(|x| x.to_string())
73            .collect_vec()
74            .join(", ")
75    }
76    pub fn cc_header(&self) -> String {
77        self.cc
78            .iter()
79            .map(|x| x.to_string())
80            .collect_vec()
81            .join(", ")
82    }
83    pub fn bcc_header(&self) -> String {
84        self.bcc
85            .iter()
86            .map(|x| x.to_string())
87            .collect_vec()
88            .join(", ")
89    }
90}