use std::collections::HashMap;
use std::fs;
use json::{JsonValue, object};
use lazy_static::lazy_static;
use crate::imap::Imap;
use crate::pop3::Pop3;
use crate::smtp::Smtp;
#[cfg(any(feature = "default", feature = "pop"))]
pub mod pop3;
#[cfg(any(feature = "default", feature = "imaps"))]
mod imap;
#[cfg(any(feature = "default", feature = "smtp"))]
mod smtp;
pub mod analysis;
use std::sync::Mutex;
lazy_static! {
pub static ref MAIL_DATA : Mutex<HashMap<String,Mail>> = Mutex::new(HashMap::new());
pub static ref MAIL_CONN : Mutex<HashMap<String,Connection>> = Mutex::new(HashMap::new());
}
#[derive(Clone)]
pub enum Mail {
#[cfg(any(feature = "pop"))]
Pop3(Pop3),
#[cfg(any(feature = "imaps"))]
Imap(Imap),
#[cfg(any(feature = "smtp"))]
Smtp(Smtp),
None,
}
impl Mail {
pub fn load(path: &str) -> Self {
let config = match fs::read_to_string(path)
{
Ok(e) => {
match json::parse(&*e.clone()) {
Ok(e) => e,
Err(_) => {
let mut def = Config::default();
def.json()
}
}
}
Err(_) => {
let mut def = Config::default();
def.json()
}
};
Mail::new(config)
}
pub fn new(conf: JsonValue) -> Self {
let config = Config::from(conf);
for (key, value) in config.connections.clone() {
MAIL_CONN.lock().unwrap().insert(key.clone(), value.clone());
}
if MAIL_DATA.lock().unwrap().get(&*config.default.clone()).is_none() {
let mail = Mail::get_mode(config.connections.get(&*config.default.clone()).unwrap().clone());
MAIL_DATA.lock().unwrap().insert(config.default.clone(), mail.clone());
}
MAIL_DATA.lock().unwrap().get(&*config.default.clone()).unwrap().clone()
}
pub fn del(conf: JsonValue) {
let config = Config::from(conf);
for (key, _value) in config.connections.clone() {
MAIL_CONN.lock().unwrap().remove(key.as_str());
}
if !MAIL_DATA.lock().unwrap().get(&*config.default.clone()).is_none() {
MAIL_DATA.lock().unwrap().remove(config.default.as_str());
}
}
fn get_mode(mut connection: Connection) -> Self {
match connection.protocol.str() {
#[cfg(any(feature = "pop"))]
"pop3" => {
Mail::Pop3(Pop3 {
connection: connection.clone()
})
}
#[cfg(any(feature = "imaps"))]
"imap" => {
Mail::Imap(Imap {
connection,
})
}
#[cfg(any(feature = "smtp"))]
"smtp" => {
Mail::Smtp(Smtp {
connection: connection.clone(),
from_name: connection.name.to_string(),
from_mail: connection.mail.to_string(),
to_vec: vec![],
cc_vec: vec![],
body_text: "".to_string(),
body_html: "".to_string(),
subject: "".to_string(),
files: HashMap::new(),
})
}
_ => Mail::None
}
}
pub fn connection(&mut self, name: &str) -> Self {
if MAIL_DATA.lock().unwrap().get(&*name.clone()).is_none() {
let connection = MAIL_CONN.lock().unwrap().get(name.clone()).unwrap().clone();
let mail = Mail::get_mode(connection.clone());
MAIL_DATA.lock().unwrap().insert(name.to_string().clone(), mail.clone());
}
MAIL_DATA.lock().unwrap().get(&*name.clone()).unwrap().clone()
}
pub fn add_connection(&mut self, name: &str, connection: JsonValue) -> &mut Mail {
let conn = Connection::from(connection);
MAIL_CONN.lock().unwrap().insert(name.to_string(), conn).unwrap();
self
}
}
#[derive(Clone)]
pub struct Config {
pub default: String,
pub connections: HashMap<String, Connection>,
}
impl Config {
pub fn default() -> Config {
let mut connections = HashMap::new();
connections.insert("myname".to_string(), Connection::default());
Self {
default: "myname".to_string(),
connections,
}
}
pub fn json(&mut self) -> JsonValue {
let mut data = object! {};
data["default"] = self.default.clone().into();
let mut connections = object! {};
for (name, connection) in self.connections.iter_mut() {
connections[name.clone()] = connection.json().clone();
}
data["connections"] = connections;
data
}
pub fn from(data: JsonValue) -> Config {
let default = data["default"].to_string();
let mut connections = HashMap::new();
for (key, value) in data["connections"].entries() {
let connection = Connection::from(value.clone()).clone();
connections.insert(key.to_string(), connection.clone());
}
Self {
default,
connections,
}
}
}
impl Mode for Mail {
fn mail_id_max(&mut self) -> Result<u32, String> {
match self {
#[cfg(any(feature = "pop"))]
Mail::Pop3(e) => e.mail_id_max(),
#[cfg(any(feature = "imaps"))]
Mail::Imap(e) => e.mail_id_max(),
#[cfg(any(feature = "smtp"))]
Mail::Smtp(_) => Err("SMTP无此功能".to_string()),
Mail::None => Err("mail_id_max请求无效".to_string())
}
}
fn mail_id_list(&mut self) -> Result<Vec<String>, String> {
match self {
#[cfg(any(feature = "pop"))]
Mail::Pop3(e) => e.mail_id_list(),
#[cfg(any(feature = "imaps"))]
Mail::Imap(e) => e.mail_id_list(),
#[cfg(any(feature = "smtp"))]
Mail::Smtp(_) => Err("SMTP无此功能".to_string()),
Mail::None => Err("mail_id_list请求无效".to_string())
}
}
fn mail_id_get(&mut self, mail_id: u32) -> Result<Vec<u8>, String> {
match self {
#[cfg(any(feature = "pop"))]
Mail::Pop3(e) => e.mail_id_get(mail_id),
#[cfg(any(feature = "imaps"))]
Mail::Imap(e) => e.mail_id_get(mail_id),
#[cfg(any(feature = "smtp"))]
Mail::Smtp(_) => Err("SMTP无此功能".to_string()),
Mail::None => Err("mail_id_get请求无效".to_string())
}
}
fn mail_msg_size(&mut self, mail_id: u32) -> Result<u32, String> {
match self {
#[cfg(any(feature = "pop"))]
Mail::Pop3(e) => e.mail_msg_size(mail_id),
#[cfg(any(feature = "imaps"))]
Mail::Imap(e) => e.mail_msg_size(mail_id),
#[cfg(any(feature = "smtp"))]
Mail::Smtp(_) => Err("SMTP无此功能".to_string()),
Mail::None => Err("mail_msg_size请求无效".to_string())
}
}
fn mail_msg_uidl(&mut self, mail_id: u32) -> Result<String, String> {
match self {
#[cfg(any(feature = "pop"))]
Mail::Pop3(e) => e.mail_msg_uidl(mail_id),
#[cfg(any(feature = "imaps"))]
Mail::Imap(e) => e.mail_msg_uidl(mail_id),
#[cfg(any(feature = "smtp"))]
Mail::Smtp(_) => Err("SMTP无此功能".to_string()),
Mail::None => Err("mail_msg_uidl请求无效".to_string())
}
}
fn send(&mut self) -> Result<Vec<u8>, String> {
match self {
#[cfg(any(feature = "pop"))]
Mail::Pop3(_) => Err("Pop3请求无效".to_string()),
#[cfg(any(feature = "imaps"))]
Mail::Imap(_) => Err("Imap请求无效".to_string()),
#[cfg(any(feature = "smtp"))]
Mail::Smtp(e) => e.send(),
Mail::None => Err("send请求无效".to_string())
}
}
fn set_from(&mut self, name: &str, mail: &str) -> &mut Self {
match self {
#[cfg(any(feature = "pop"))]
Mail::Pop3(_) => {}
#[cfg(any(feature = "imaps"))]
Mail::Imap(_) => {}
Mail::None => {}
#[cfg(any(feature = "smtp"))]
Mail::Smtp(e) => {
e.set_from(name, mail);
}
}
self
}
fn set_to(&mut self, to_vec: Vec<String>) -> &mut Self {
match self {
#[cfg(any(feature = "pop"))]
Mail::Pop3(_) => {}
#[cfg(any(feature = "imaps"))]
Mail::Imap(_) => {}
Mail::None => {}
#[cfg(any(feature = "smtp"))]
Mail::Smtp(e) => {
e.set_to(to_vec);
}
}
self
}
fn set_cc(&mut self, cc_vec: Vec<String>) -> &mut Self {
match self {
#[cfg(any(feature = "pop"))]
Mail::Pop3(_) => {}
#[cfg(any(feature = "imaps"))]
Mail::Imap(_) => {}
Mail::None => {}
#[cfg(any(feature = "smtp"))]
Mail::Smtp(e) => {
e.set_cc(cc_vec);
}
}
self
}
fn set_subject(&mut self, subject: &str) -> &mut Self {
match self {
#[cfg(any(feature = "pop"))]
Mail::Pop3(_) => {}
#[cfg(any(feature = "imaps"))]
Mail::Imap(_) => {}
Mail::None => {}
#[cfg(any(feature = "smtp"))]
Mail::Smtp(e) =>
{
e.set_subject(subject);
}
}
self
}
fn set_body(&mut self, text: &str, html: &str) -> &mut Self {
match self {
#[cfg(any(feature = "pop"))]
Mail::Pop3(_) => {}
#[cfg(any(feature = "imaps"))]
Mail::Imap(_) => {}
Mail::None => {}
#[cfg(any(feature = "smtp"))]
Mail::Smtp(e) => {
e.set_body(text, html);
}
}
self
}
fn set_file(&mut self, name: &str, data: Vec<u8>, content_type: &str) -> &mut Self {
match self {
#[cfg(any(feature = "pop"))]
Mail::Pop3(_) => {}
#[cfg(any(feature = "imaps"))]
Mail::Imap(_) => {}
Mail::None => {}
#[cfg(any(feature = "smtp"))]
Mail::Smtp(e) => {
e.set_file(name, data, content_type);
}
}
self
}
}
pub trait Mode {
fn mail_id_max(&mut self) -> Result<u32, String>;
fn mail_id_list(&mut self) -> Result<Vec<String>, String>;
fn mail_id_get(&mut self, mail_id: u32) -> Result<Vec<u8>, String>;
fn mail_msg_size(&mut self, mail_id: u32) -> Result<u32, String>;
fn mail_msg_uidl(&mut self, mail_id: u32) -> Result<String, String>;
fn send(&mut self) -> Result<Vec<u8>, String>;
fn set_from(&mut self, name: &str, mail: &str) -> &mut Self;
fn set_to(&mut self, to_vec: Vec<String>) -> &mut Self;
fn set_cc(&mut self, cc_vec: Vec<String>) -> &mut Self;
fn set_subject(&mut self, subject: &str) -> &mut Self;
fn set_body(&mut self, text: &str, html: &str) -> &mut Self;
fn set_file(&mut self, name: &str, data: Vec<u8>, content_type: &str) -> &mut Self;
}
#[derive(Clone)]
pub enum Protocol {
Pop3,
Imap,
Smtp,
None,
}
impl Protocol {
pub fn str(&mut self) -> &'static str {
match self {
Protocol::Pop3 => "pop3",
Protocol::Imap => "imap",
Protocol::Smtp => "smtp",
Protocol::None => ""
}
}
pub fn from(name: &str) -> Self {
let name = name.to_lowercase();
match name.as_str() {
"pop3" => Protocol::Pop3,
"imap" => Protocol::Imap,
"smtp" => Protocol::Smtp,
_ => Protocol::None
}
}
}
#[derive(Clone)]
pub struct Connection {
pub host: String,
pub port: String,
pub name: String,
pub mail: String,
pub pass: String,
pub protocol: Protocol,
}
impl Connection {
pub fn default() -> Connection {
Self {
host: "".to_string(),
port: "".to_string(),
name: "".to_string(),
mail: "".to_string(),
pass: "".to_string(),
protocol: Protocol::Imap,
}
}
pub fn new_smtp() -> Connection {
Self {
host: "".to_string(),
port: "".to_string(),
name: "".to_string(),
mail: "".to_string(),
pass: "".to_string(),
protocol: Protocol::Smtp,
}
}
pub fn json(&mut self) -> JsonValue {
let mut data = object! {};
data["host"] = self.host.clone().into();
data["port"] = self.port.clone().into();
data["name"] = self.name.clone().into();
data["pass"] = self.pass.clone().into();
data["mail"] = self.mail.clone().into();
data["protocol"] = self.protocol.str().into();
data
}
pub fn from(data: JsonValue) -> Self {
let protocol = Protocol::from(data["protocol"].as_str().unwrap());
Self {
host: data["host"].to_string(),
port: data["port"].to_string(),
name: data["name"].to_string(),
mail: data["mail"].to_string(),
pass: data["pass"].to_string(),
protocol,
}
}
}