feat(server): basic server implementation in rust
continuous-integration/drone/push Build is passing Details

main
Guus van Meerveld 1 month ago
parent d3d781c765
commit e74cd0b800
Signed by: Guusvanmeerveld
GPG Key ID: 2BA7D7912771966E

455
Cargo.lock generated

@ -39,6 +39,17 @@ dependencies = [
"opaque-debug",
]
[[package]]
name = "aes"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241"
dependencies = [
"cfg-if",
"cipher 0.4.3",
"cpufeatures",
]
[[package]]
name = "aes-gcm"
version = "0.9.4"
@ -46,10 +57,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
dependencies = [
"aead 0.4.3",
"aes",
"aes 0.7.5",
"cipher 0.3.0",
"ctr",
"ghash",
"ctr 0.8.0",
"ghash 0.4.4",
"subtle",
]
[[package]]
name = "aes-gcm"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c"
dependencies = [
"aead 0.5.1",
"aes 0.8.2",
"cipher 0.4.3",
"ctr 0.9.2",
"ghash 0.5.0",
"subtle",
]
@ -111,6 +136,38 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "async-stream"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e"
dependencies = [
"async-stream-impl",
"futures-core",
]
[[package]]
name = "async-stream-impl"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "async-trait"
version = "0.1.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "atk"
version = "0.15.1"
@ -135,6 +192,26 @@ dependencies = [
"system-deps 6.0.3",
]
[[package]]
name = "atomic"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c"
dependencies = [
"autocfg",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi 0.1.19",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@ -157,12 +234,24 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5"
[[package]]
name = "base64"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
[[package]]
name = "binascii"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72"
[[package]]
name = "bitflags"
version = "1.3.2"
@ -457,6 +546,24 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
name = "cookie"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
dependencies = [
"aes-gcm 0.10.1",
"base64 0.20.0",
"hkdf",
"hmac",
"percent-encoding",
"rand 0.8.5",
"sha2",
"subtle",
"time 0.3.17",
"version_check",
]
[[package]]
name = "core-foundation"
version = "0.9.3"
@ -592,6 +699,15 @@ dependencies = [
"cipher 0.3.0",
]
[[package]]
name = "ctr"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
"cipher 0.4.3",
]
[[package]]
name = "cty"
version = "0.2.2"
@ -696,6 +812,39 @@ dependencies = [
"syn",
]
[[package]]
name = "devise"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50c7580b072f1c8476148f16e0a0d5dedddab787da98d86c5082c5e9ed8ab595"
dependencies = [
"devise_codegen",
"devise_core",
]
[[package]]
name = "devise_codegen"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "123c73e7a6e51b05c75fe1a1b2f4e241399ea5740ed810b0e3e6cacd9db5e7b2"
dependencies = [
"devise_core",
"quote",
]
[[package]]
name = "devise_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841ef46f4787d9097405cac4e70fb8644fc037b526e8c14054247c0263c400d0"
dependencies = [
"bitflags",
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
"syn",
]
[[package]]
name = "digest"
version = "0.10.6"
@ -704,6 +853,7 @@ checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
@ -796,6 +946,14 @@ dependencies = [
"tauri-build",
]
[[package]]
name = "dust-mail-server"
version = "0.1.0"
dependencies = [
"rocket",
"sdk",
]
[[package]]
name = "either"
version = "1.8.1"
@ -852,6 +1010,20 @@ dependencies = [
"rustc_version 0.3.3",
]
[[package]]
name = "figment"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e56602b469b2201400dec66a66aec5a9b8761ee97cd1b8c96ab2483fcc16cc9"
dependencies = [
"atomic",
"pear",
"serde",
"toml",
"uncased",
"version_check",
]
[[package]]
name = "filetime"
version = "0.2.20"
@ -1136,7 +1308,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
dependencies = [
"opaque-debug",
"polyval",
"polyval 0.5.3",
]
[[package]]
name = "ghash"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
dependencies = [
"opaque-debug",
"polyval 0.6.0",
]
[[package]]
@ -1339,6 +1521,15 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
@ -1348,6 +1539,24 @@ dependencies = [
"libc",
]
[[package]]
name = "hkdf"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
dependencies = [
"hmac",
]
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]]
name = "hostname"
version = "0.3.1"
@ -1587,6 +1796,7 @@ checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
"serde",
]
[[package]]
@ -1598,6 +1808,12 @@ dependencies = [
"cfb",
]
[[package]]
name = "inlinable_string"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
[[package]]
name = "inout"
version = "0.1.3"
@ -1972,6 +2188,26 @@ dependencies = [
"windows-sys 0.42.0",
]
[[package]]
name = "multer"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ed4198ce7a4cbd2a57af78d28c6fbb57d81ac5f1d6ad79ac6c5587419cbdf22"
dependencies = [
"bytes",
"encoding_rs",
"futures-util",
"http",
"httparse",
"log",
"memchr",
"mime",
"spin",
"tokio",
"tokio-util",
"version_check",
]
[[package]]
name = "native-tls"
version = "0.2.11"
@ -2106,7 +2342,7 @@ version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi",
"hermit-abi 0.2.6",
"libc",
]
@ -2292,6 +2528,29 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
[[package]]
name = "pear"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15e44241c5e4c868e3eaa78b7c1848cadd6344ed4f54d029832d32b415a58702"
dependencies = [
"inlinable_string",
"pear_codegen",
"yansi",
]
[[package]]
name = "pear_codegen"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82a5ca643c2303ecb740d506539deba189e16f2754040a42901cd8105d0282d0"
dependencies = [
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
"syn",
]
[[package]]
name = "percent-encoding"
version = "2.2.0"
@ -2483,6 +2742,18 @@ dependencies = [
"universal-hash 0.4.1",
]
[[package]]
name = "polyval"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6"
dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug",
"universal-hash 0.5.0",
]
[[package]]
name = "pop3"
version = "0.1.0"
@ -2556,6 +2827,19 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "proc-macro2-diagnostics"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada"
dependencies = [
"proc-macro2",
"quote",
"syn",
"version_check",
"yansi",
]
[[package]]
name = "quick-xml"
version = "0.26.0"
@ -2690,6 +2974,26 @@ dependencies = [
"thiserror",
]
[[package]]
name = "ref-cast"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c78fb8c9293bcd48ef6fce7b4ca950ceaf21210de6e105a883ee280c0f7b9ed"
dependencies = [
"ref-cast-impl",
]
[[package]]
name = "ref-cast-impl"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f9c0c92af03644e4806106281fe2e068ac5bc0ae74a707266d06ea27bccee5f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "regex"
version = "1.7.1"
@ -2762,6 +3066,88 @@ dependencies = [
"winreg",
]
[[package]]
name = "rocket"
version = "0.5.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98ead083fce4a405feb349cf09abdf64471c6077f14e0ce59364aa90d4b99317"
dependencies = [
"async-stream",
"async-trait",
"atomic",
"atty",
"binascii",
"bytes",
"either",
"figment",
"futures",
"indexmap",
"log",
"memchr",
"multer",
"num_cpus",
"parking_lot",
"pin-project-lite",
"rand 0.8.5",
"ref-cast",
"rocket_codegen",
"rocket_http",
"serde",
"serde_json",
"state",
"tempfile",
"time 0.3.17",
"tokio",
"tokio-stream",
"tokio-util",
"ubyte",
"version_check",
"yansi",
]
[[package]]
name = "rocket_codegen"
version = "0.5.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6aeb6bb9c61e9cd2c00d70ea267bf36f76a4cc615e5908b349c2f9d93999b47"
dependencies = [
"devise",
"glob",
"indexmap",
"proc-macro2",
"quote",
"rocket_http",
"syn",
"unicode-xid",
]
[[package]]
name = "rocket_http"
version = "0.5.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ded65d127954de3c12471630bf4b81a2792f065984461e65b91d0fdaafc17a2"
dependencies = [
"cookie",
"either",
"futures",
"http",
"hyper",
"indexmap",
"log",
"memchr",
"pear",
"percent-encoding",
"pin-project-lite",
"ref-cast",
"serde",
"smallvec",
"stable-pattern",
"state",
"time 0.3.17",
"tokio",
"uncased",
]
[[package]]
name = "rustc_version"
version = "0.3.3"
@ -3133,6 +3519,21 @@ dependencies = [
"system-deps 5.0.0",
]
[[package]]
name = "spin"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc"
[[package]]
name = "stable-pattern"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4564168c00635f88eaed410d5efa8131afa8d8699a612c80c455a0ba05c21045"
dependencies = [
"memchr",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
@ -3438,7 +3839,7 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5abbc109a6eb45127956ffcc26ef0e875d160150ac16cfa45d26a6b2871686f1"
dependencies = [
"aes-gcm",
"aes-gcm 0.9.4",
"brotli",
"ctor",
"getrandom 0.2.8",
@ -3627,6 +4028,17 @@ dependencies = [
"tokio",
]
[[package]]
name = "tokio-stream"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.7"
@ -3756,12 +4168,31 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
name = "ubyte"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c81f0dae7d286ad0d9366d7679a77934cfc3cf3a8d67e82669794412b2368fe6"
dependencies = [
"serde",
]
[[package]]
name = "ucd-trie"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
[[package]]
name = "uncased"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622"
dependencies = [
"serde",
"version_check",
]
[[package]]
name = "unicode-bidi"
version = "0.3.10"
@ -3795,6 +4226,12 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "universal-hash"
version = "0.4.1"
@ -4358,6 +4795,12 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
[[package]]
name = "yansi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
[[package]]
name = "zeroize"
version = "1.5.7"

@ -2,6 +2,7 @@
members = [
"apps/web/src-tauri",
"apps/server",
"packages/sdk",
"packages/autoconfig",
"packages/pop3"

@ -0,0 +1,10 @@
[package]
name = "dust-mail-server"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rocket = { version = "0.5.0-rc.2", features=["json"] }
sdk = { path = "../../packages/sdk", version = "0.1" }

@ -0,0 +1,58 @@
use std::{
collections::HashMap,
sync::Mutex,
time::{Duration, Instant},
};
use crate::{types::Result, utils::get_domain_from_email};
use sdk::detect::Config;
pub struct ConfigCache {
configs: Mutex<HashMap<String, (Instant, Config)>>,
}
const CACHE_TIMEOUT: Duration = Duration::from_secs(60 * 5);
impl ConfigCache {
pub fn new() -> Self {
Self {
configs: Mutex::new(HashMap::new()),
}
}
pub fn set(&self, email: &str, config: Config) -> Result<()> {
let domain = get_domain_from_email(email)?;
let mut config_write_lock = self.configs.lock().unwrap();
let now = Instant::now();
config_write_lock.insert(String::from(domain), (now, config));
Ok(())
}
pub fn get(&self, email: &str) -> Option<Config> {
let domain = get_domain_from_email(email).ok()?;
let config_read_lock = self.configs.lock().unwrap();
match config_read_lock.get(domain) {
Some((age, value)) => {
let now = Instant::now();
if !now
.duration_since(*age)
.saturating_sub(CACHE_TIMEOUT)
.is_zero()
{
return None;
}
Some(value.clone())
}
None => None,
}
}
}

@ -0,0 +1,3 @@
mod config;
pub use config::ConfigCache;

@ -0,0 +1,31 @@
mod cache;
mod routes;
mod types;
mod utils;
#[macro_use]
extern crate rocket;
use rocket::serde::json::Json;
use types::{ErrResponse, ErrorKind};
#[catch(404)]
fn not_found() -> Json<ErrResponse> {
ErrResponse::new(ErrorKind::NotFound, "Route could not be found")
}
#[catch(500)]
fn internal_error() -> Json<ErrResponse> {
ErrResponse::new(ErrorKind::InternalError, "Internal server error")
}
#[launch]
fn rocket() -> _ {
rocket::build()
.register("/", catchers![not_found, internal_error])
.manage(cache::ConfigCache::new())
.mount(
"/",
routes![routes::auto_detect_config_handler, routes::login_handler,],
)
}

@ -0,0 +1,30 @@
use crate::{
cache::ConfigCache,
types::{ErrResponse, ErrorKind, OkResponse, ResponseResult},
};
use rocket::{http::Status, State};
use sdk::detect::{self, Config};
#[get("/detect/<email>")]
pub async fn auto_detect_config(email: &str, cache: &State<ConfigCache>) -> ResponseResult<Config> {
match cache.get(email) {
Some(config) => Ok(OkResponse::new(config)),
None => match detect::from_email(email).await {
Ok(config) => {
cache
.set(email, config.clone())
.map_err(ErrResponse::from_err);
Ok(OkResponse::new(config))
}
Err(err) => Err((
Status::BadRequest,
ErrResponse::new(
ErrorKind::SdkError(err),
"Failed to detect config from email address",
),
)),
},
}
}

@ -0,0 +1,6 @@
use crate::types::{OkResponse, ResponseResult};
#[post("/login")]
pub fn login() -> ResponseResult<String> {
Ok(OkResponse::new("yeet".to_string()))
}

@ -0,0 +1,5 @@
mod detect;
mod login;
pub use detect::auto_detect_config as auto_detect_config_handler;
pub use login::login as login_handler;

@ -0,0 +1,28 @@
use rocket::serde::Serialize;
use sdk::types::Error as SdkError;
#[derive(Serialize)]
#[serde(crate = "rocket::serde")]
pub enum ErrorKind {
SdkError(SdkError),
NotFound,
Parse,
InternalError,
}
#[derive(Serialize)]
#[serde(crate = "rocket::serde")]
pub struct Error {
message: String,
kind: ErrorKind,
}
impl Error {
pub fn new<S: Into<String>>(kind: ErrorKind, message: S) -> Self {
Self {
kind,
message: message.into(),
}
}
}

@ -0,0 +1,13 @@
use rocket::{http::Status, serde::json::Json};
mod error;
mod response;
use std::result;
pub use error::{Error, ErrorKind};
pub use response::{ErrResponse, OkResponse};
pub type Result<T> = result::Result<T, Error>;
pub type ResponseResult<T> = result::Result<Json<OkResponse<T>>, (Status, Json<ErrResponse>)>;

@ -0,0 +1,36 @@
use rocket::serde::{json::Json, Serialize};
use super::{Error, ErrorKind};
#[derive(Serialize)]
#[serde(crate = "rocket::serde")]
pub struct OkResponse<T: Serialize> {
ok: bool,
data: T,
}
impl<T: Serialize> OkResponse<T> {
pub fn new(data: T) -> Json<Self> {
Json(Self { ok: true, data })
}
}
#[derive(Serialize)]
#[serde(crate = "rocket::serde")]
pub struct ErrResponse {
ok: bool,
error: Error,
}
impl ErrResponse {
pub fn from_err(error: Error) -> Json<Self> {
Json(Self { ok: false, error })
}
pub fn new<S: Into<String>>(kind: ErrorKind, msg: S) -> Json<Self> {
Json(Self {
ok: false,
error: Error::new(kind, msg),
})
}
}

@ -0,0 +1,19 @@
use crate::types::{Error, ErrorKind, Result};
pub fn create_mail_parse_error() -> Error {
Error::new(ErrorKind::Parse, "Failed to parse email address")
}
pub fn get_domain_from_email<'a>(email: &'a str) -> Result<&'a str> {
let mut email_split = email.split('@');
match email_split.next() {
Some(_) => {}
None => return Err(create_mail_parse_error()),
};
match email_split.next() {
Some(domain) => Ok(domain),
None => Err(create_mail_parse_error()),
}
}

@ -1,15 +1,14 @@
use http::Client;
use regex::Regex;
use types::config::Config;
mod http;
mod parse;
pub mod types;
mod utils;
const AT_SYMBOL: char = '@';
pub use utils::validate_email;
const EMAIL_REGEX: &str =
r"^([a-z0-9_+]([a-z0-9_+.]*[a-z0-9_+])?)@([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6})";
const AT_SYMBOL: char = '@';
/// Given an email providers domain, try to connect to autoconfig servers for that provider and return the config.
pub fn from_domain(domain: &str) -> types::Result<Option<Config>> {
@ -41,9 +40,7 @@ pub fn from_domain(domain: &str) -> types::Result<Option<Config>> {
/// Given an email address, try to connect to the email providers autoconfig servers and return the config that was found.
pub fn from_addr(email_address: &str) -> types::Result<Option<Config>> {
let email_regex = Regex::new(EMAIL_REGEX).unwrap();
if !email_regex.is_match(email_address) {
if !utils::validate_email(email_address) {
return Err(types::Error::new(
types::ErrorKind::BadInput,
"Given email address is invalid",

@ -0,0 +1,10 @@
use regex::Regex;
const EMAIL_REGEX: &str =
r"^([a-z0-9_+]([a-z0-9_+.]*[a-z0-9_+])?)@([a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6})";
pub fn validate_email(unknown_str: &str) -> bool {
let email_regex = Regex::new(EMAIL_REGEX).unwrap();
email_regex.is_match(unknown_str)
}

@ -52,6 +52,13 @@ async fn check_sockets<'a>(
/// Automatically detect an email providers config for a given email address
pub async fn from_email(email_address: &str) -> Result<Config> {
if !autoconfig::validate_email(email_address) {
return Err(Error::new(
ErrorKind::ParseAddress,
"Given email address is invalid",
));
};
let mut config: Option<Config> = None;
let mut split = email_address.split(AT_SYMBOL);

@ -13,7 +13,7 @@ pub enum ServerConfigType {
Exchange,
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct ServerConfig {
r#type: ServerConfigType,
@ -61,7 +61,7 @@ impl ServerConfig {
}
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
pub enum AuthenticationType {
ClearText,
Encrypted,
@ -70,7 +70,7 @@ pub enum AuthenticationType {
Unknown,
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub enum ConfigType {
MultiServer {
@ -85,7 +85,7 @@ impl ConfigType {
}
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Config {
r#type: ConfigType,

Loading…
Cancel
Save