mirror of
https://github.com/soywod/himalaya.git
synced 2025-04-17 23:03:37 +00:00
init backend override with list envelopes and send message
This commit is contained in:
parent
cec658aff4
commit
1f88b27468
9 changed files with 154 additions and 77 deletions
|
@ -10,9 +10,26 @@ email = "example@localhost"
|
|||
# listing envelopes or copying messages.
|
||||
backend = "imap"
|
||||
|
||||
imap.host = "imap.gmail.com"
|
||||
imap.port = 993
|
||||
imap.login = "example@localhost"
|
||||
imap.auth = "passwd"
|
||||
# imap.Some.passwd.cmd = "pass show gmail"
|
||||
# Override the backend used for sending messages.
|
||||
message.send.backend = "smtp"
|
||||
|
||||
# IMAP config
|
||||
imap.host = "localhost"
|
||||
imap.port = 3143
|
||||
imap.login = "example@localhost"
|
||||
imap.ssl = false
|
||||
imap.starttls = false
|
||||
imap.insecure = true
|
||||
imap.auth = "passwd"
|
||||
imap.passwd.raw = "example"
|
||||
|
||||
# SMTP config
|
||||
smtp.host = "localhost"
|
||||
smtp.port = 3025
|
||||
smtp.login = "example@localhost"
|
||||
smtp.ssl = false
|
||||
smtp.starttls = false
|
||||
smtp.insecure = true
|
||||
smtp.auth = "passwd"
|
||||
smtp.passwd.raw = "example"
|
||||
|
||||
|
|
106
src/backend.rs
106
src/backend.rs
|
@ -10,7 +10,10 @@ use email::smtp::{SmtpClientBuilder, SmtpClientSync};
|
|||
use email::{
|
||||
account::AccountConfig,
|
||||
config::Config,
|
||||
folder::list::{imap::ListFoldersImap, maildir::ListFoldersMaildir},
|
||||
email::{
|
||||
envelope::list::{imap::ListEnvelopesImap, maildir::ListEnvelopesMaildir},
|
||||
message::send_raw::{sendmail::SendRawMessageSendmail, smtp::SendRawMessageSmtp},
|
||||
},
|
||||
maildir::{MaildirSessionBuilder, MaildirSessionSync},
|
||||
sendmail::SendmailContext,
|
||||
};
|
||||
|
@ -18,11 +21,9 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::config::DeserializedConfig;
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum BackendKind {
|
||||
#[default]
|
||||
None,
|
||||
Maildir,
|
||||
#[cfg(feature = "imap-backend")]
|
||||
Imap,
|
||||
|
@ -35,8 +36,6 @@ pub enum BackendKind {
|
|||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct BackendContextBuilder {
|
||||
account_config: AccountConfig,
|
||||
|
||||
#[cfg(feature = "imap-backend")]
|
||||
imap: Option<ImapSessionBuilder>,
|
||||
maildir: Option<MaildirSessionBuilder>,
|
||||
|
@ -93,7 +92,7 @@ pub struct BackendBuilder(pub email::backend::BackendBuilder<BackendContextBuild
|
|||
|
||||
impl BackendBuilder {
|
||||
pub async fn new(config: DeserializedConfig, account_name: Option<&str>) -> Result<Self> {
|
||||
let (account_name, deserialized_account_config) = match account_name {
|
||||
let (account_name, mut deserialized_account_config) = match account_name {
|
||||
Some("default") | Some("") | None => config
|
||||
.accounts
|
||||
.iter()
|
||||
|
@ -111,6 +110,25 @@ impl BackendBuilder {
|
|||
.ok_or_else(|| anyhow!("cannot find account {name}")),
|
||||
}?;
|
||||
|
||||
println!(
|
||||
"deserialized_account_config: {:#?}",
|
||||
deserialized_account_config
|
||||
);
|
||||
|
||||
#[cfg(feature = "imap-backend")]
|
||||
if let Some(imap_config) = deserialized_account_config.imap.as_mut() {
|
||||
imap_config
|
||||
.auth
|
||||
.replace_undefined_keyring_entries(&account_name);
|
||||
}
|
||||
|
||||
#[cfg(feature = "smtp-sender")]
|
||||
if let Some(smtp_config) = deserialized_account_config.smtp.as_mut() {
|
||||
smtp_config
|
||||
.auth
|
||||
.replace_undefined_keyring_entries(&account_name);
|
||||
}
|
||||
|
||||
let config = Config {
|
||||
display_name: config.display_name,
|
||||
signature_delim: config.signature_delim,
|
||||
|
@ -166,10 +184,9 @@ impl BackendBuilder {
|
|||
)),
|
||||
};
|
||||
|
||||
let account_config = config.account(account_name)?;
|
||||
let account_config = config.account(&account_name)?;
|
||||
|
||||
let backend_ctx_builder = BackendContextBuilder {
|
||||
account_config: account_config.clone(),
|
||||
maildir: deserialized_account_config
|
||||
.maildir
|
||||
.as_ref()
|
||||
|
@ -199,28 +216,57 @@ impl BackendBuilder {
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
let backend_builder =
|
||||
email::backend::BackendBuilder::new(account_config.clone(), backend_ctx_builder)
|
||||
.with_list_folders(move |ctx| {
|
||||
println!(
|
||||
"deserialized_account_config: {:#?}",
|
||||
deserialized_account_config
|
||||
);
|
||||
match deserialized_account_config.backend {
|
||||
BackendKind::Maildir if ctx.maildir.is_some() => {
|
||||
ListFoldersMaildir::new(ctx.maildir.as_ref().unwrap())
|
||||
}
|
||||
#[cfg(feature = "imap-backend")]
|
||||
BackendKind::Imap if ctx.imap.is_some() => {
|
||||
ListFoldersImap::new(ctx.imap.as_ref().unwrap())
|
||||
}
|
||||
#[cfg(feature = "notmuch-backend")]
|
||||
BackendKind::Notmuch if ctx.notmuch.is_some() => {
|
||||
ListFoldersNotmuch::new(ctx.notmuch.as_ref().unwrap())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
let mut backend_builder =
|
||||
email::backend::BackendBuilder::new(account_config.clone(), backend_ctx_builder);
|
||||
|
||||
let list_envelopes = deserialized_account_config
|
||||
.envelope
|
||||
.as_ref()
|
||||
.and_then(|envelope| envelope.list.as_ref())
|
||||
.and_then(|send| send.backend.as_ref())
|
||||
.or_else(|| deserialized_account_config.backend.as_ref());
|
||||
|
||||
match list_envelopes {
|
||||
Some(BackendKind::Maildir) => {
|
||||
backend_builder = backend_builder.with_list_envelopes(|ctx| {
|
||||
ctx.maildir.as_ref().and_then(ListEnvelopesMaildir::new)
|
||||
});
|
||||
}
|
||||
#[cfg(feature = "imap-backend")]
|
||||
Some(BackendKind::Imap) => {
|
||||
backend_builder = backend_builder
|
||||
.with_list_envelopes(|ctx| ctx.imap.as_ref().and_then(ListEnvelopesImap::new));
|
||||
}
|
||||
#[cfg(feature = "notmuch-backend")]
|
||||
Some(BackendKind::Notmuch) => {
|
||||
backend_builder = backend_builder.with_list_envelopes(|ctx| {
|
||||
ctx.notmuch.as_ref().and_then(ListEnvelopesNotmuch::new)
|
||||
});
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let send_msg = deserialized_account_config
|
||||
.message
|
||||
.as_ref()
|
||||
.and_then(|msg| msg.send.as_ref())
|
||||
.and_then(|send| send.backend.as_ref())
|
||||
.or_else(|| deserialized_account_config.backend.as_ref());
|
||||
|
||||
match send_msg {
|
||||
#[cfg(feature = "smtp-sender")]
|
||||
Some(BackendKind::Smtp) => {
|
||||
backend_builder = backend_builder.with_send_raw_message(|ctx| {
|
||||
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new)
|
||||
});
|
||||
}
|
||||
Some(BackendKind::Sendmail) => {
|
||||
backend_builder = backend_builder.with_send_raw_message(|ctx| {
|
||||
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new)
|
||||
});
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
Ok(Self(backend_builder))
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ pub enum ImapAuthConfigDef {
|
|||
#[serde(remote = "PasswdConfig")]
|
||||
pub struct ImapPasswdConfigDef {
|
||||
#[serde(
|
||||
rename = "imap-passwd",
|
||||
rename = "passwd",
|
||||
with = "SecretDef",
|
||||
default,
|
||||
skip_serializing_if = "Secret::is_undefined"
|
||||
|
@ -335,19 +335,19 @@ pub enum EmailTextPlainFormatDef {
|
|||
pub struct OptionSmtpConfigDef;
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum OptionSmtpConfig {
|
||||
#[default]
|
||||
#[serde(skip_serializing)]
|
||||
None,
|
||||
Some(#[serde(with = "SmtpConfigDef")] SmtpConfig),
|
||||
pub struct OptionSmtpConfig {
|
||||
#[serde(default, skip)]
|
||||
is_none: bool,
|
||||
#[serde(flatten, with = "SmtpConfigDef")]
|
||||
inner: SmtpConfig,
|
||||
}
|
||||
|
||||
impl From<OptionSmtpConfig> for Option<SmtpConfig> {
|
||||
fn from(config: OptionSmtpConfig) -> Option<SmtpConfig> {
|
||||
match config {
|
||||
OptionSmtpConfig::None => None,
|
||||
OptionSmtpConfig::Some(config) => Some(config),
|
||||
if config.is_none {
|
||||
None
|
||||
} else {
|
||||
Some(config.inner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -356,17 +356,11 @@ impl From<OptionSmtpConfig> for Option<SmtpConfig> {
|
|||
#[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,
|
||||
|
@ -374,7 +368,7 @@ struct SmtpConfigDef {
|
|||
|
||||
#[cfg(feature = "smtp-sender")]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(remote = "SmtpAuthConfig", tag = "smtp-auth")]
|
||||
#[serde(remote = "SmtpAuthConfig", tag = "auth")]
|
||||
pub enum SmtpAuthConfigDef {
|
||||
#[serde(rename = "passwd", alias = "password", with = "SmtpPasswdConfigDef")]
|
||||
Passwd(#[serde(default)] PasswdConfig),
|
||||
|
@ -386,7 +380,7 @@ pub enum SmtpAuthConfigDef {
|
|||
#[serde(remote = "PasswdConfig", default)]
|
||||
pub struct SmtpPasswdConfigDef {
|
||||
#[serde(
|
||||
rename = "smtp-passwd",
|
||||
rename = "passwd",
|
||||
with = "SecretDef",
|
||||
default,
|
||||
skip_serializing_if = "Secret::is_undefined"
|
||||
|
@ -395,32 +389,26 @@ pub struct SmtpPasswdConfigDef {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(remote = "OAuth2Config")]
|
||||
#[serde(remote = "OAuth2Config", rename_all = "kebab-case")]
|
||||
pub struct SmtpOAuth2ConfigDef {
|
||||
#[serde(rename = "smtp-oauth2-method", with = "OAuth2MethodDef", default)]
|
||||
#[serde(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"
|
||||
|
@ -428,17 +416,11 @@ pub struct SmtpOAuth2ConfigDef {
|
|||
pub refresh_token: Secret,
|
||||
#[serde(flatten, with = "SmtpOAuth2ScopesDef")]
|
||||
pub scopes: OAuth2Scopes,
|
||||
#[serde(rename = "smtp-oauth2-pkce", default)]
|
||||
#[serde(default)]
|
||||
pub pkce: bool,
|
||||
#[serde(
|
||||
rename = "imap-oauth2-redirect-host",
|
||||
default = "OAuth2Config::default_redirect_host"
|
||||
)]
|
||||
#[serde(default = "OAuth2Config::default_redirect_host")]
|
||||
pub redirect_host: String,
|
||||
#[serde(
|
||||
rename = "imap-oauth2-redirect-port",
|
||||
default = "OAuth2Config::default_redirect_port"
|
||||
)]
|
||||
#[serde(default = "OAuth2Config::default_redirect_port")]
|
||||
pub redirect_port: u16,
|
||||
}
|
||||
|
||||
|
@ -476,11 +458,7 @@ impl From<OptionSendmailConfig> for Option<SendmailConfig> {
|
|||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(remote = "SendmailConfig", rename_all = "kebab-case")]
|
||||
pub struct SendmailConfigDef {
|
||||
#[serde(
|
||||
rename = "sendmail-cmd",
|
||||
with = "CmdDef",
|
||||
default = "sendmail_default_cmd"
|
||||
)]
|
||||
#[serde(with = "CmdDef", default = "sendmail_default_cmd")]
|
||||
cmd: Cmd,
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,10 @@ use email::{
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use crate::{backend::BackendKind, config::prelude::*};
|
||||
use crate::{
|
||||
backend::BackendKind, config::prelude::*, email::envelope::config::EnvelopeConfig,
|
||||
message::config::MessageConfig,
|
||||
};
|
||||
|
||||
/// Represents all existing kind of account config.
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||
|
@ -51,7 +54,10 @@ pub struct DeserializedAccountConfig {
|
|||
#[serde(default, with = "OptionFolderSyncStrategyDef")]
|
||||
pub sync_folders_strategy: Option<FolderSyncStrategy>,
|
||||
|
||||
pub backend: BackendKind,
|
||||
pub backend: Option<BackendKind>,
|
||||
|
||||
pub envelope: Option<EnvelopeConfig>,
|
||||
pub message: Option<MessageConfig>,
|
||||
|
||||
#[cfg(feature = "imap-backend")]
|
||||
#[serde(default, with = "OptionImapConfigDef")]
|
||||
|
|
13
src/domain/email/envelope/config.rs
Normal file
13
src/domain/email/envelope/config.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use ::serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::backend::BackendKind;
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub struct EnvelopeConfig {
|
||||
pub list: Option<EnvelopeListConfig>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub struct EnvelopeListConfig {
|
||||
pub backend: Option<BackendKind>,
|
||||
}
|
1
src/domain/email/envelope/mod.rs
Normal file
1
src/domain/email/envelope/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod config;
|
13
src/domain/email/message/config.rs
Normal file
13
src/domain/email/message/config.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use ::serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::backend::BackendKind;
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub struct MessageConfig {
|
||||
pub send: Option<MessageSendConfig>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub struct MessageSendConfig {
|
||||
pub backend: Option<BackendKind>,
|
||||
}
|
1
src/domain/email/message/mod.rs
Normal file
1
src/domain/email/message/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod config;
|
|
@ -1,2 +1,4 @@
|
|||
pub mod args;
|
||||
pub mod envelope;
|
||||
pub mod handlers;
|
||||
pub mod message;
|
||||
|
|
Loading…
Add table
Reference in a new issue