]>
Commit | Line | Data |
---|---|---|
1 | //! # Configuration | |
2 | //! | |
3 | //! This module defines the configuration used to initialize both proxies. | |
4 | ||
5 | use log::error; | |
6 | use std::env; | |
7 | use std::fmt::Debug; | |
8 | use std::sync::Arc; | |
9 | use thiserror::Error; | |
10 | ||
11 | #[derive(Error, Debug)] | |
12 | pub enum Error { | |
13 | #[error("Environment variable {0} not set.")] | |
14 | MissingEnvVar(String), | |
15 | #[error("Failed to parse {0}.")] | |
16 | ParseError(String), | |
17 | } | |
18 | ||
19 | /// Configuration for any proxy | |
20 | #[derive(Debug)] | |
21 | pub struct Proxy { | |
22 | pub local_port: u16, | |
23 | pub bind_address: String, | |
24 | pub remote_host: String, | |
25 | pub remote_port: u16, | |
26 | pub protocol: &'static str, | |
27 | } | |
28 | ||
29 | /// Aggregated configuration for both proxies, already in a reference counter. | |
30 | pub struct Configuration { | |
31 | pub imap_configuration: Arc<Proxy>, | |
32 | pub smtp_configuration: Arc<Proxy>, | |
33 | } | |
34 | ||
35 | impl Configuration { | |
36 | /// Creates a new configuration object by reading the environment | |
37 | /// variables. Exits if the right ones aren't found. | |
38 | pub fn new() -> Result<Self, Error> { | |
39 | Ok(Configuration { | |
40 | imap_configuration: Arc::new(Proxy { | |
41 | local_port: get_env_number("LOCAL_IMAP_PORT", 143)?, | |
42 | bind_address: get_env_var("LOCAL_IMAP_BIND_ADDRESS", Some("0.0.0.0".to_string()))?, | |
43 | remote_host: get_env_var("REMOTE_IMAP_DOMAIN", None)?, | |
44 | remote_port: get_env_number("REMOTE_IMAP_PORT", 993)?, | |
45 | protocol: "IMAP", | |
46 | }), | |
47 | smtp_configuration: Arc::new(Proxy { | |
48 | local_port: get_env_number("LOCAL_SMTP_PORT", 25)?, | |
49 | bind_address: get_env_var("LOCAL_SMTP_BIND_ADDRESS", Some("0.0.0.0".to_string()))?, | |
50 | remote_host: get_env_var("REMOTE_SMTP_DOMAIN", None)?, | |
51 | remote_port: get_env_number("REMOTE_SMTP_PORT", 993)?, | |
52 | protocol: "SMTP", | |
53 | }), | |
54 | }) | |
55 | } | |
56 | } | |
57 | ||
58 | /// Get an environment variable or return an error. | |
59 | fn get_env_var(name: &str, default: Option<String>) -> Result<String, Error> { | |
60 | match env::var(name) { | |
61 | Ok(value) => Ok(value), | |
62 | Err(_) => match default { | |
63 | Some(default_value) => Ok(default_value), | |
64 | None => Err(Error::MissingEnvVar(name.to_string())), | |
65 | }, | |
66 | } | |
67 | } | |
68 | ||
69 | /// Get an environment variable and parse it as a number. Return a default | |
70 | /// if not set. | |
71 | fn get_env_number(name: &str, default: u16) -> Result<u16, Error> { | |
72 | match env::var(name) { | |
73 | Ok(value) => value | |
74 | .parse() | |
75 | .map_err(|_| Error::ParseError(name.to_string())), | |
76 | Err(_) => Ok(default), | |
77 | } | |
78 | } |