mirror of
https://github.com/pimalaya/himalaya.git
synced 2026-06-17 13:17:55 +08:00
426 lines
13 KiB
Rust
426 lines
13 KiB
Rust
#[cfg(feature = "notmuch-backend")]
|
|
use pimalaya_email::backend::NotmuchConfig;
|
|
#[cfg(feature = "imap-backend")]
|
|
use pimalaya_email::backend::{ImapAuthConfig, ImapConfig};
|
|
#[cfg(feature = "smtp-sender")]
|
|
use pimalaya_email::sender::{SmtpAuthConfig, SmtpConfig};
|
|
use pimalaya_email::{
|
|
account::{
|
|
OAuth2Config, OAuth2Method, OAuth2Scopes, PasswdConfig, PgpConfig, PgpKey, PgpNativeConfig,
|
|
},
|
|
backend::{BackendConfig, MaildirConfig},
|
|
email::{EmailHooks, EmailTextPlainFormat},
|
|
folder::sync::FolderSyncStrategy,
|
|
sender::{SenderConfig, SendmailConfig},
|
|
};
|
|
use pimalaya_keyring::Entry;
|
|
use pimalaya_process::{Cmd, Pipeline, SingleCmd};
|
|
use pimalaya_secret::Secret;
|
|
use serde::{ser::SerializeSeq, Deserialize, Serialize, Serializer};
|
|
use std::{collections::HashSet, ops::Deref, path::PathBuf};
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "Entry", from = "String")]
|
|
pub struct EntryDef(#[serde(getter = "Deref::deref")] String);
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "SingleCmd", from = "String")]
|
|
pub struct SingleCmdDef(#[serde(getter = "Deref::deref")] String);
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "Pipeline", from = "Vec<String>")]
|
|
pub struct PipelineDef(
|
|
#[serde(getter = "Deref::deref", serialize_with = "pipeline")] Vec<SingleCmd>,
|
|
);
|
|
|
|
// NOTE: did not find the way to do it with macros…
|
|
pub fn pipeline<S>(cmds: &Vec<SingleCmd>, s: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
let mut seq = s.serialize_seq(Some(cmds.len()))?;
|
|
for cmd in cmds {
|
|
seq.serialize_element(&cmd.to_string())?;
|
|
}
|
|
seq.end()
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "Cmd", untagged)]
|
|
pub enum CmdDef {
|
|
#[serde(with = "SingleCmdDef")]
|
|
SingleCmd(SingleCmd),
|
|
#[serde(with = "PipelineDef")]
|
|
Pipeline(Pipeline),
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "Option<Cmd>", from = "OptionCmd")]
|
|
pub struct OptionCmdDef;
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(untagged)]
|
|
pub enum OptionCmd {
|
|
#[default]
|
|
#[serde(skip_serializing)]
|
|
None,
|
|
#[serde(with = "SingleCmdDef")]
|
|
SingleCmd(SingleCmd),
|
|
#[serde(with = "PipelineDef")]
|
|
Pipeline(Pipeline),
|
|
}
|
|
|
|
impl From<OptionCmd> for Option<Cmd> {
|
|
fn from(cmd: OptionCmd) -> Option<Cmd> {
|
|
match cmd {
|
|
OptionCmd::None => None,
|
|
OptionCmd::SingleCmd(cmd) => Some(Cmd::SingleCmd(cmd)),
|
|
OptionCmd::Pipeline(pipeline) => Some(Cmd::Pipeline(pipeline)),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "Secret", rename_all = "kebab-case")]
|
|
pub enum SecretDef {
|
|
Raw(String),
|
|
#[serde(with = "CmdDef")]
|
|
Cmd(Cmd),
|
|
#[serde(with = "EntryDef", rename = "keyring")]
|
|
KeyringEntry(Entry),
|
|
#[default]
|
|
Undefined,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "OAuth2Method")]
|
|
pub enum OAuth2MethodDef {
|
|
#[serde(rename = "xoauth2", alias = "XOAUTH2")]
|
|
XOAuth2,
|
|
#[serde(rename = "oauthbearer", alias = "OAUTHBEARER")]
|
|
OAuthBearer,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "BackendConfig", tag = "backend", rename_all = "kebab-case")]
|
|
pub enum BackendConfigDef {
|
|
#[default]
|
|
None,
|
|
#[cfg(feature = "imap-backend")]
|
|
#[serde(with = "ImapConfigDef")]
|
|
Imap(ImapConfig),
|
|
#[serde(with = "MaildirConfigDef")]
|
|
Maildir(MaildirConfig),
|
|
#[cfg(feature = "notmuch-backend")]
|
|
#[serde(with = "NotmuchConfigDef")]
|
|
Notmuch(NotmuchConfig),
|
|
}
|
|
|
|
#[cfg(feature = "imap-backend")]
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "ImapConfig")]
|
|
pub struct ImapConfigDef {
|
|
#[serde(rename = "imap-host")]
|
|
pub host: String,
|
|
#[serde(rename = "imap-port")]
|
|
pub port: u16,
|
|
#[serde(rename = "imap-ssl")]
|
|
pub ssl: Option<bool>,
|
|
#[serde(rename = "imap-starttls")]
|
|
pub starttls: Option<bool>,
|
|
#[serde(rename = "imap-insecure")]
|
|
pub insecure: Option<bool>,
|
|
#[serde(rename = "imap-login")]
|
|
pub login: String,
|
|
#[serde(flatten, with = "ImapAuthConfigDef")]
|
|
pub auth: ImapAuthConfig,
|
|
#[serde(rename = "imap-notify-cmd")]
|
|
pub notify_cmd: Option<String>,
|
|
#[serde(rename = "imap-notify-query")]
|
|
pub notify_query: Option<String>,
|
|
#[serde(rename = "imap-watch-cmds")]
|
|
pub watch_cmds: Option<Vec<String>>,
|
|
}
|
|
|
|
#[cfg(feature = "imap-backend")]
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "ImapAuthConfig", tag = "imap-auth")]
|
|
pub enum ImapAuthConfigDef {
|
|
#[serde(rename = "passwd", alias = "password", with = "ImapPasswdConfigDef")]
|
|
Passwd(#[serde(default)] PasswdConfig),
|
|
#[serde(rename = "oauth2", with = "ImapOAuth2ConfigDef")]
|
|
OAuth2(OAuth2Config),
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "PasswdConfig")]
|
|
pub struct ImapPasswdConfigDef {
|
|
#[serde(
|
|
rename = "imap-passwd",
|
|
with = "SecretDef",
|
|
default,
|
|
skip_serializing_if = "Secret::is_undefined"
|
|
)]
|
|
pub passwd: Secret,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "OAuth2Config")]
|
|
pub struct ImapOAuth2ConfigDef {
|
|
#[serde(rename = "imap-oauth2-method", with = "OAuth2MethodDef", default)]
|
|
pub method: OAuth2Method,
|
|
#[serde(rename = "imap-oauth2-client-id")]
|
|
pub client_id: String,
|
|
#[serde(
|
|
rename = "imap-oauth2-client-secret",
|
|
with = "SecretDef",
|
|
default,
|
|
skip_serializing_if = "Secret::is_undefined"
|
|
)]
|
|
pub client_secret: Secret,
|
|
#[serde(rename = "imap-oauth2-auth-url")]
|
|
pub auth_url: String,
|
|
#[serde(rename = "imap-oauth2-token-url")]
|
|
pub token_url: String,
|
|
#[serde(
|
|
rename = "imap-oauth2-access-token",
|
|
with = "SecretDef",
|
|
default,
|
|
skip_serializing_if = "Secret::is_undefined"
|
|
)]
|
|
pub access_token: Secret,
|
|
#[serde(
|
|
rename = "imap-oauth2-refresh-token",
|
|
with = "SecretDef",
|
|
default,
|
|
skip_serializing_if = "Secret::is_undefined"
|
|
)]
|
|
pub refresh_token: Secret,
|
|
#[serde(flatten, with = "ImapOAuth2ScopesDef")]
|
|
pub scopes: OAuth2Scopes,
|
|
#[serde(rename = "imap-oauth2-pkce", default)]
|
|
pub pkce: bool,
|
|
#[serde(
|
|
rename = "imap-oauth2-redirect-host",
|
|
default = "OAuth2Config::default_redirect_host"
|
|
)]
|
|
pub redirect_host: String,
|
|
#[serde(
|
|
rename = "imap-oauth2-redirect-port",
|
|
default = "OAuth2Config::default_redirect_port"
|
|
)]
|
|
pub redirect_port: u16,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "OAuth2Scopes")]
|
|
pub enum ImapOAuth2ScopesDef {
|
|
#[serde(rename = "imap-oauth2-scope")]
|
|
Scope(String),
|
|
#[serde(rename = "imap-oauth2-scopes")]
|
|
Scopes(Vec<String>),
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "MaildirConfig", rename_all = "kebab-case")]
|
|
pub struct MaildirConfigDef {
|
|
#[serde(rename = "maildir-root-dir")]
|
|
pub root_dir: PathBuf,
|
|
}
|
|
|
|
#[cfg(feature = "notmuch-backend")]
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "NotmuchConfig", rename_all = "kebab-case")]
|
|
pub struct NotmuchConfigDef {
|
|
#[serde(rename = "notmuch-db-path")]
|
|
pub db_path: PathBuf,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(
|
|
remote = "EmailTextPlainFormat",
|
|
tag = "type",
|
|
content = "width",
|
|
rename_all = "kebab-case"
|
|
)]
|
|
pub enum EmailTextPlainFormatDef {
|
|
#[default]
|
|
Auto,
|
|
Flowed,
|
|
Fixed(usize),
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "SenderConfig", tag = "sender", rename_all = "kebab-case")]
|
|
pub enum SenderConfigDef {
|
|
#[default]
|
|
None,
|
|
#[cfg(feature = "smtp-sender")]
|
|
#[serde(with = "SmtpConfigDef")]
|
|
Smtp(SmtpConfig),
|
|
#[serde(with = "SendmailConfigDef")]
|
|
Sendmail(SendmailConfig),
|
|
}
|
|
|
|
#[cfg(feature = "smtp-sender")]
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "SmtpConfig")]
|
|
struct SmtpConfigDef {
|
|
#[serde(rename = "smtp-host")]
|
|
pub host: String,
|
|
#[serde(rename = "smtp-port")]
|
|
pub port: u16,
|
|
#[serde(rename = "smtp-ssl")]
|
|
pub ssl: Option<bool>,
|
|
#[serde(rename = "smtp-starttls")]
|
|
pub starttls: Option<bool>,
|
|
#[serde(rename = "smtp-insecure")]
|
|
pub insecure: Option<bool>,
|
|
#[serde(rename = "smtp-login")]
|
|
pub login: String,
|
|
#[serde(flatten, with = "SmtpAuthConfigDef")]
|
|
pub auth: SmtpAuthConfig,
|
|
}
|
|
|
|
#[cfg(feature = "smtp-sender")]
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "SmtpAuthConfig", tag = "smtp-auth")]
|
|
pub enum SmtpAuthConfigDef {
|
|
#[serde(rename = "passwd", alias = "password", with = "SmtpPasswdConfigDef")]
|
|
Passwd(#[serde(default)] PasswdConfig),
|
|
#[serde(rename = "oauth2", with = "SmtpOAuth2ConfigDef")]
|
|
OAuth2(OAuth2Config),
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "PasswdConfig", default)]
|
|
pub struct SmtpPasswdConfigDef {
|
|
#[serde(
|
|
rename = "smtp-passwd",
|
|
with = "SecretDef",
|
|
default,
|
|
skip_serializing_if = "Secret::is_undefined"
|
|
)]
|
|
pub passwd: Secret,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "OAuth2Config")]
|
|
pub struct SmtpOAuth2ConfigDef {
|
|
#[serde(rename = "smtp-oauth2-method", with = "OAuth2MethodDef", default)]
|
|
pub method: OAuth2Method,
|
|
#[serde(rename = "smtp-oauth2-client-id")]
|
|
pub client_id: String,
|
|
#[serde(
|
|
rename = "smtp-oauth2-client-secret",
|
|
with = "SecretDef",
|
|
default,
|
|
skip_serializing_if = "Secret::is_undefined"
|
|
)]
|
|
pub client_secret: Secret,
|
|
#[serde(rename = "smtp-oauth2-auth-url")]
|
|
pub auth_url: String,
|
|
#[serde(rename = "smtp-oauth2-token-url")]
|
|
pub token_url: String,
|
|
#[serde(
|
|
rename = "smtp-oauth2-access-token",
|
|
with = "SecretDef",
|
|
default,
|
|
skip_serializing_if = "Secret::is_undefined"
|
|
)]
|
|
pub access_token: Secret,
|
|
#[serde(
|
|
rename = "smtp-oauth2-refresh-token",
|
|
with = "SecretDef",
|
|
default,
|
|
skip_serializing_if = "Secret::is_undefined"
|
|
)]
|
|
pub refresh_token: Secret,
|
|
#[serde(flatten, with = "SmtpOAuth2ScopesDef")]
|
|
pub scopes: OAuth2Scopes,
|
|
#[serde(rename = "smtp-oauth2-pkce", default)]
|
|
pub pkce: bool,
|
|
#[serde(
|
|
rename = "imap-oauth2-redirect-host",
|
|
default = "OAuth2Config::default_redirect_host"
|
|
)]
|
|
pub redirect_host: String,
|
|
#[serde(
|
|
rename = "imap-oauth2-redirect-port",
|
|
default = "OAuth2Config::default_redirect_port"
|
|
)]
|
|
pub redirect_port: u16,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "OAuth2Scopes")]
|
|
pub enum SmtpOAuth2ScopesDef {
|
|
#[serde(rename = "smtp-oauth2-scope")]
|
|
Scope(String),
|
|
#[serde(rename = "smtp-oauth2-scopes")]
|
|
Scopes(Vec<String>),
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "SendmailConfig", rename_all = "kebab-case")]
|
|
pub struct SendmailConfigDef {
|
|
#[serde(rename = "sendmail-cmd", with = "CmdDef")]
|
|
cmd: Cmd,
|
|
}
|
|
|
|
/// Represents the email hooks. Useful for doing extra email
|
|
/// processing before or after sending it.
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "EmailHooks", rename_all = "kebab-case")]
|
|
pub struct EmailHooksDef {
|
|
/// Represents the hook called just before sending an email.
|
|
#[serde(default, with = "OptionCmdDef")]
|
|
pub pre_send: Option<Cmd>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "FolderSyncStrategy", rename_all = "kebab-case")]
|
|
pub enum FolderSyncStrategyDef {
|
|
#[default]
|
|
All,
|
|
#[serde(alias = "only")]
|
|
Include(HashSet<String>),
|
|
#[serde(alias = "except")]
|
|
#[serde(alias = "ignore")]
|
|
Exclude(HashSet<String>),
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "PgpConfig", tag = "backend", rename_all = "kebab-case")]
|
|
pub enum PgpConfigDef {
|
|
#[default]
|
|
None,
|
|
#[serde(with = "PgpNativeConfigDef")]
|
|
Native(PgpNativeConfig),
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "PgpNativeConfig", rename_all = "kebab-case")]
|
|
pub struct PgpNativeConfigDef {
|
|
#[serde(default, with = "PgpKeyDef")]
|
|
secret_key: PgpKey,
|
|
#[serde(default, with = "SecretDef")]
|
|
secret_key_passwd: Secret,
|
|
#[serde(default, with = "PgpKeyDef")]
|
|
public_key: PgpKey,
|
|
#[serde(default = "PgpNativeConfig::default_wkd")]
|
|
wkd: bool,
|
|
#[serde(default = "PgpNativeConfig::default_key_servers")]
|
|
key_servers: Vec<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
|
#[serde(remote = "PgpKey", rename_all = "kebab-case")]
|
|
pub enum PgpKeyDef {
|
|
#[default]
|
|
None,
|
|
Path(PathBuf),
|
|
#[serde(with = "EntryDef")]
|
|
Keyring(Entry),
|
|
}
|