make one cargo feature per backend (#318)

This commit is contained in:
Clément DOUIN 2022-03-04 14:19:54 +01:00
parent c40dde6e9a
commit f06beb61ae
No known key found for this signature in database
GPG key ID: 353E4A18EE0FAB72
14 changed files with 103 additions and 110 deletions

View file

@ -33,3 +33,4 @@ jobs:
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: test command: test
args: --all-features

View file

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Flowed format support [#206] - Flowed format support [#206]
- List accounts command [#244] - List accounts command [#244]
- One cargo feature per backend [#318]
### Changed ### Changed
@ -474,4 +475,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#305]: https://github.com/soywod/himalaya/issues/305 [#305]: https://github.com/soywod/himalaya/issues/305
[#308]: https://github.com/soywod/himalaya/issues/308 [#308]: https://github.com/soywod/himalaya/issues/308
[#309]: https://github.com/soywod/himalaya/issues/309 [#309]: https://github.com/soywod/himalaya/issues/309
[#318]: https://github.com/soywod/himalaya/issues/318
[#321]: https://github.com/soywod/himalaya/issues/321 [#321]: https://github.com/soywod/himalaya/issues/321

10
Cargo.lock generated
View file

@ -602,7 +602,7 @@ dependencies = [
"idna", "idna",
"mime", "mime",
"native-tls", "native-tls",
"nom 7.0.0", "nom 7.1.0",
"once_cell", "once_cell",
"quoted_printable", "quoted_printable",
"regex", "regex",
@ -742,9 +742,9 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]] [[package]]
name = "minimal-lexical" name = "minimal-lexical"
version = "0.1.4" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c64630dcdd71f1a64c435f54885086a0de5d6a12d104d69b165fb7d5286d677" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]] [[package]]
name = "native-tls" name = "native-tls"
@ -793,9 +793,9 @@ dependencies = [
[[package]] [[package]]
name = "nom" name = "nom"
version = "7.0.0" version = "7.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffd9d26838a953b4af82cbeb9f1592c6798916983959be223a7124e992742c1" checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
dependencies = [ dependencies = [
"memchr 2.4.1", "memchr 2.4.1",
"minimal-lexical", "minimal-lexical",

View file

@ -16,6 +16,12 @@ repository = "https://github.com/soywod/himalaya"
priority = "optional" priority = "optional"
section = "mail" section = "mail"
[features]
imap-backend = ["imap", "imap-proto"]
maildir-backend = ["maildir", "md5"]
notmuch-backend = ["notmuch", "maildir-backend"]
default = ["imap-backend", "maildir-backend"]
[dependencies] [dependencies]
ammonia = "3.1.2" ammonia = "3.1.2"
anyhow = "1.0.44" anyhow = "1.0.44"
@ -25,15 +31,10 @@ clap = { version = "2.33.3", default-features = false, features = ["suggestions"
env_logger = "0.8.3" env_logger = "0.8.3"
erased-serde = "0.3.18" erased-serde = "0.3.18"
html-escape = "0.2.9" html-escape = "0.2.9"
imap = "=3.0.0-alpha.4"
imap-proto = "0.14.3"
lettre = { version = "0.10.0-rc.1", features = ["serde"] } lettre = { version = "0.10.0-rc.1", features = ["serde"] }
log = "0.4.14" log = "0.4.14"
maildir = "0.6.0"
mailparse = "0.13.6" mailparse = "0.13.6"
md5 = "0.7.0"
native-tls = "0.2.8" native-tls = "0.2.8"
notmuch = { version = "0.7.1", optional = true }
regex = "1.5.4" regex = "1.5.4"
rfc2047-decoder = "0.1.2" rfc2047-decoder = "0.1.2"
serde = { version = "1.0.118", features = ["derive"] } serde = { version = "1.0.118", features = ["derive"] }
@ -46,3 +47,11 @@ tree_magic = "0.2.3"
unicode-width = "0.1.7" unicode-width = "0.1.7"
url = "2.2.2" url = "2.2.2"
uuid = { version = "0.8", features = ["v4"] } uuid = { version = "0.8", features = ["v4"] }
# Optional dependencies:
imap = { version = "=3.0.0-alpha.4", optional = true }
imap-proto = { version = "0.14.3", optional = true }
maildir = { version = "0.6.0", optional = true }
md5 = { version = "0.7.0", optional = true }
notmuch = { version = "0.7.1", optional = true }

View file

@ -80,6 +80,7 @@
rustfmt rustfmt
rnix-lsp rnix-lsp
nixpkgs-fmt nixpkgs-fmt
notmuch
]; ];
}; };
} }

View file

@ -89,14 +89,16 @@ impl From<Iter<'_, String, DeserializedAccountConfig>> for Accounts {
fn from(map: Iter<'_, String, DeserializedAccountConfig>) -> Self { fn from(map: Iter<'_, String, DeserializedAccountConfig>) -> Self {
let mut accounts: Vec<_> = map let mut accounts: Vec<_> = map
.map(|(name, config)| match config { .map(|(name, config)| match config {
#[cfg(feature = "imap-backend")]
DeserializedAccountConfig::Imap(config) => { DeserializedAccountConfig::Imap(config) => {
Account::new(name, "imap", config.default.unwrap_or_default()) Account::new(name, "imap", config.default.unwrap_or_default())
} }
#[cfg(feature = "maildir-backend")]
DeserializedAccountConfig::Maildir(config) => { DeserializedAccountConfig::Maildir(config) => {
Account::new(name, "maildir", config.default.unwrap_or_default()) Account::new(name, "maildir", config.default.unwrap_or_default())
} }
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
DeserializedAccountConfig::Maildir(config) => { DeserializedAccountConfig::Notmuch(config) => {
Account::new(name, "notmuch", config.default.unwrap_or_default()) Account::new(name, "notmuch", config.default.unwrap_or_default())
} }
}) })

View file

@ -69,11 +69,13 @@ impl<'a> AccountConfig {
.accounts .accounts
.iter() .iter()
.find(|(_, account)| match account { .find(|(_, account)| match account {
#[cfg(feature = "imap-backend")]
DeserializedAccountConfig::Imap(account) => account.default.unwrap_or_default(), DeserializedAccountConfig::Imap(account) => account.default.unwrap_or_default(),
#[cfg(feature = "maildir-backend")]
DeserializedAccountConfig::Maildir(account) => { DeserializedAccountConfig::Maildir(account) => {
account.default.unwrap_or_default() account.default.unwrap_or_default()
} }
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
DeserializedAccountConfig::Notmuch(account) => { DeserializedAccountConfig::Notmuch(account) => {
account.default.unwrap_or_default() account.default.unwrap_or_default()
} }
@ -169,6 +171,7 @@ impl<'a> AccountConfig {
trace!("account config: {:?}", account_config); trace!("account config: {:?}", account_config);
let backend_config = match account { let backend_config = match account {
#[cfg(feature = "imap-backend")]
DeserializedAccountConfig::Imap(config) => BackendConfig::Imap(ImapBackendConfig { DeserializedAccountConfig::Imap(config) => BackendConfig::Imap(ImapBackendConfig {
imap_host: config.imap_host.clone(), imap_host: config.imap_host.clone(),
imap_port: config.imap_port.clone(), imap_port: config.imap_port.clone(),
@ -177,12 +180,13 @@ impl<'a> AccountConfig {
imap_login: config.imap_login.clone(), imap_login: config.imap_login.clone(),
imap_passwd_cmd: config.imap_passwd_cmd.clone(), imap_passwd_cmd: config.imap_passwd_cmd.clone(),
}), }),
#[cfg(feature = "maildir-backend")]
DeserializedAccountConfig::Maildir(config) => { DeserializedAccountConfig::Maildir(config) => {
BackendConfig::Maildir(MaildirBackendConfig { BackendConfig::Maildir(MaildirBackendConfig {
maildir_dir: shellexpand::full(&config.maildir_dir)?.to_string().into(), maildir_dir: shellexpand::full(&config.maildir_dir)?.to_string().into(),
}) })
} }
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
DeserializedAccountConfig::Notmuch(config) => { DeserializedAccountConfig::Notmuch(config) => {
BackendConfig::Notmuch(NotmuchBackendConfig { BackendConfig::Notmuch(NotmuchBackendConfig {
notmuch_database_dir: shellexpand::full(&config.notmuch_database_dir)? notmuch_database_dir: shellexpand::full(&config.notmuch_database_dir)?
@ -315,13 +319,16 @@ impl<'a> AccountConfig {
/// Represents all existing kind of account (backend). /// Represents all existing kind of account (backend).
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum BackendConfig { pub enum BackendConfig {
#[cfg(feature = "imap-backend")]
Imap(ImapBackendConfig), Imap(ImapBackendConfig),
#[cfg(feature = "maildir-backend")]
Maildir(MaildirBackendConfig), Maildir(MaildirBackendConfig),
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
Notmuch(NotmuchBackendConfig), Notmuch(NotmuchBackendConfig),
} }
/// Represents the IMAP backend. /// Represents the IMAP backend.
#[cfg(feature = "imap-backend")]
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct ImapBackendConfig { pub struct ImapBackendConfig {
/// Represents the IMAP host. /// Represents the IMAP host.
@ -338,6 +345,7 @@ pub struct ImapBackendConfig {
pub imap_passwd_cmd: String, pub imap_passwd_cmd: String,
} }
#[cfg(feature = "imap-backend")]
impl ImapBackendConfig { impl ImapBackendConfig {
/// Gets the IMAP password of the user account. /// Gets the IMAP password of the user account.
pub fn imap_passwd(&self) -> Result<String> { pub fn imap_passwd(&self) -> Result<String> {
@ -350,6 +358,7 @@ impl ImapBackendConfig {
} }
/// Represents the Maildir backend. /// Represents the Maildir backend.
#[cfg(feature = "maildir-backend")]
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct MaildirBackendConfig { pub struct MaildirBackendConfig {
/// Represents the Maildir directory path. /// Represents the Maildir directory path.
@ -357,7 +366,7 @@ pub struct MaildirBackendConfig {
} }
/// Represents the Notmuch backend. /// Represents the Notmuch backend.
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct NotmuchBackendConfig { pub struct NotmuchBackendConfig {
/// Represents the Notmuch database path. /// Represents the Notmuch database path.

View file

@ -104,8 +104,6 @@ mod tests {
} }
} }
struct TestBackend;
let config = DeserializedConfig { let config = DeserializedConfig {
accounts: HashMap::from_iter([( accounts: HashMap::from_iter([(
"account-1".into(), "account-1".into(),
@ -119,14 +117,13 @@ mod tests {
let account_config = AccountConfig::default(); let account_config = AccountConfig::default();
let mut printer = PrinterServiceTest::default(); let mut printer = PrinterServiceTest::default();
let mut backend = TestBackend {};
assert!(list(None, &config, &account_config, &mut printer).is_ok()); assert!(list(None, &config, &account_config, &mut printer).is_ok());
assert_eq!( assert_eq!(
concat![ concat![
"\n", "\n",
"NAME │BACKEND │DEFAULT \n", "NAME │BACKEND │DEFAULT \n",
"account-1 │imap │true \n", "account-1 │imap │yes \n",
"\n" "\n"
], ],
printer.writter.content printer.writter.content

View file

@ -11,18 +11,22 @@ pub trait ToDeserializedBaseAccountConfig {
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
pub enum DeserializedAccountConfig { pub enum DeserializedAccountConfig {
#[cfg(feature = "imap-backend")]
Imap(DeserializedImapAccountConfig), Imap(DeserializedImapAccountConfig),
#[cfg(feature = "maildir-backend")]
Maildir(DeserializedMaildirAccountConfig), Maildir(DeserializedMaildirAccountConfig),
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
Notmuch(DeserializedNotmuchAccountConfig), Notmuch(DeserializedNotmuchAccountConfig),
} }
impl ToDeserializedBaseAccountConfig for DeserializedAccountConfig { impl ToDeserializedBaseAccountConfig for DeserializedAccountConfig {
fn to_base(&self) -> DeserializedBaseAccountConfig { fn to_base(&self) -> DeserializedBaseAccountConfig {
match self { match self {
#[cfg(feature = "imap-backend")]
Self::Imap(config) => config.to_base(), Self::Imap(config) => config.to_base(),
#[cfg(feature = "maildir-backend")]
Self::Maildir(config) => config.to_base(), Self::Maildir(config) => config.to_base(),
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
Self::Notmuch(config) => config.to_base(), Self::Notmuch(config) => config.to_base(),
} }
} }
@ -118,6 +122,7 @@ macro_rules! make_account_config {
make_account_config!(DeserializedBaseAccountConfig,); make_account_config!(DeserializedBaseAccountConfig,);
#[cfg(feature = "imap-backend")]
make_account_config!( make_account_config!(
DeserializedImapAccountConfig, DeserializedImapAccountConfig,
imap_host: String, imap_host: String,
@ -128,9 +133,10 @@ make_account_config!(
imap_passwd_cmd: String imap_passwd_cmd: String
); );
#[cfg(feature = "maildir-backend")]
make_account_config!(DeserializedMaildirAccountConfig, maildir_dir: String); make_account_config!(DeserializedMaildirAccountConfig, maildir_dir: String);
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
make_account_config!( make_account_config!(
DeserializedNotmuchAccountConfig, DeserializedNotmuchAccountConfig,
notmuch_database_dir: String notmuch_database_dir: String

View file

@ -40,6 +40,7 @@ pub mod backends {
pub mod id_mapper; pub mod id_mapper;
pub use id_mapper::*; pub use id_mapper::*;
#[cfg(feature = "imap-backend")]
pub mod imap { pub mod imap {
pub mod imap_args; pub mod imap_args;
@ -62,8 +63,11 @@ pub mod backends {
pub mod msg_sort_criterion; pub mod msg_sort_criterion;
} }
#[cfg(feature = "imap-backend")]
pub use self::imap::*; pub use self::imap::*;
#[cfg(feature = "maildir-backend")]
pub mod maildir { pub mod maildir {
pub mod maildir_backend; pub mod maildir_backend;
pub use maildir_backend::*; pub use maildir_backend::*;
@ -77,11 +81,11 @@ pub mod backends {
pub mod maildir_flag; pub mod maildir_flag;
pub use maildir_flag::*; pub use maildir_flag::*;
} }
#[cfg(feature = "maildir-backend")]
pub use self::maildir::*; pub use self::maildir::*;
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
pub use self::notmuch::*;
#[cfg(feature = "notmuch")]
pub mod notmuch { pub mod notmuch {
pub mod notmuch_backend; pub mod notmuch_backend;
pub use notmuch_backend::*; pub use notmuch_backend::*;
@ -92,6 +96,9 @@ pub mod backends {
pub mod notmuch_envelope; pub mod notmuch_envelope;
pub use notmuch_envelope::*; pub use notmuch_envelope::*;
} }
#[cfg(feature = "notmuch-backend")]
pub use self::notmuch::*;
} }
pub mod smtp { pub mod smtp {

View file

@ -3,7 +3,7 @@ use std::{convert::TryFrom, env};
use url::Url; use url::Url;
use himalaya::{ use himalaya::{
backends::{imap_args, imap_handlers, Backend, ImapBackend, MaildirBackend}, backends::Backend,
compl::{compl_args, compl_handlers}, compl::{compl_args, compl_handlers},
config::{ config::{
account_args, account_handlers, config_args, AccountConfig, BackendConfig, account_args, account_handlers, config_args, AccountConfig, BackendConfig,
@ -15,11 +15,17 @@ use himalaya::{
smtp::LettreService, smtp::LettreService,
}; };
#[cfg(feature = "notmuch")] #[cfg(feature = "imap-backend")]
use himalaya::backends::{imap_args, imap_handlers, ImapBackend};
#[cfg(feature = "maildir-backend")]
use himalaya::backends::MaildirBackend;
#[cfg(feature = "notmuch-backend")]
use himalaya::{backends::NotmuchBackend, config::MaildirBackendConfig}; use himalaya::{backends::NotmuchBackend, config::MaildirBackendConfig};
fn create_app<'a>() -> clap::App<'a, 'a> { fn create_app<'a>() -> clap::App<'a, 'a> {
clap::App::new(env!("CARGO_PKG_NAME")) let app = clap::App::new(env!("CARGO_PKG_NAME"))
.version(env!("CARGO_PKG_VERSION")) .version(env!("CARGO_PKG_VERSION"))
.about(env!("CARGO_PKG_DESCRIPTION")) .about(env!("CARGO_PKG_DESCRIPTION"))
.author(env!("CARGO_PKG_AUTHORS")) .author(env!("CARGO_PKG_AUTHORS"))
@ -29,10 +35,14 @@ fn create_app<'a>() -> clap::App<'a, 'a> {
.args(&output_args::args()) .args(&output_args::args())
.arg(mbox_args::source_arg()) .arg(mbox_args::source_arg())
.subcommands(compl_args::subcmds()) .subcommands(compl_args::subcmds())
.subcommands(imap_args::subcmds())
.subcommands(account_args::subcmds()) .subcommands(account_args::subcmds())
.subcommands(mbox_args::subcmds()) .subcommands(mbox_args::subcmds())
.subcommands(msg_args::subcmds()) .subcommands(msg_args::subcmds());
#[cfg(feature = "imap-backend")]
let app = app.subcommands(imap_args::subcmds());
app
} }
#[allow(clippy::single_match)] #[allow(clippy::single_match)]
@ -50,22 +60,29 @@ fn main() -> Result<()> {
let url = Url::parse(&raw_args[1])?; let url = Url::parse(&raw_args[1])?;
let mut smtp = LettreService::from(&account_config); let mut smtp = LettreService::from(&account_config);
#[cfg(feature = "imap-backend")]
let mut imap; let mut imap;
#[cfg(feature = "maildir-backend")]
let mut maildir; let mut maildir;
#[cfg(feature = "notmuch")]
#[cfg(feature = "notmuch-backend")]
let maildir_config: MaildirBackendConfig; let maildir_config: MaildirBackendConfig;
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
let mut notmuch; let mut notmuch;
let backend: Box<&mut dyn Backend> = match backend_config { let backend: Box<&mut dyn Backend> = match backend_config {
#[cfg(feature = "imap-backend")]
BackendConfig::Imap(ref imap_config) => { BackendConfig::Imap(ref imap_config) => {
imap = ImapBackend::new(&account_config, imap_config); imap = ImapBackend::new(&account_config, imap_config);
Box::new(&mut imap) Box::new(&mut imap)
} }
#[cfg(feature = "maildir-backend")]
BackendConfig::Maildir(ref maildir_config) => { BackendConfig::Maildir(ref maildir_config) => {
maildir = MaildirBackend::new(&account_config, maildir_config); maildir = MaildirBackend::new(&account_config, maildir_config);
Box::new(&mut maildir) Box::new(&mut maildir)
} }
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
BackendConfig::Notmuch(ref notmuch_config) => { BackendConfig::Notmuch(ref notmuch_config) => {
maildir_config = MaildirBackendConfig { maildir_config = MaildirBackendConfig {
maildir_dir: notmuch_config.notmuch_database_dir.clone(), maildir_dir: notmuch_config.notmuch_database_dir.clone(),
@ -100,22 +117,29 @@ fn main() -> Result<()> {
.or_else(|| account_config.mailboxes.get("inbox").map(|s| s.as_str())) .or_else(|| account_config.mailboxes.get("inbox").map(|s| s.as_str()))
.unwrap_or(DEFAULT_INBOX_FOLDER); .unwrap_or(DEFAULT_INBOX_FOLDER);
let mut printer = StdoutPrinter::try_from(m.value_of("output"))?; let mut printer = StdoutPrinter::try_from(m.value_of("output"))?;
#[cfg(feature = "imap-backend")]
let mut imap; let mut imap;
#[cfg(feature = "maildir-backend")]
let mut maildir; let mut maildir;
#[cfg(feature = "notmuch")]
#[cfg(feature = "notmuch-backend")]
let maildir_config: MaildirBackendConfig; let maildir_config: MaildirBackendConfig;
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
let mut notmuch; let mut notmuch;
let backend: Box<&mut dyn Backend> = match backend_config { let backend: Box<&mut dyn Backend> = match backend_config {
#[cfg(feature = "imap-backend")]
BackendConfig::Imap(ref imap_config) => { BackendConfig::Imap(ref imap_config) => {
imap = ImapBackend::new(&account_config, imap_config); imap = ImapBackend::new(&account_config, imap_config);
Box::new(&mut imap) Box::new(&mut imap)
} }
#[cfg(feature = "maildir-backend")]
BackendConfig::Maildir(ref maildir_config) => { BackendConfig::Maildir(ref maildir_config) => {
maildir = MaildirBackend::new(&account_config, maildir_config); maildir = MaildirBackend::new(&account_config, maildir_config);
Box::new(&mut maildir) Box::new(&mut maildir)
} }
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
BackendConfig::Notmuch(ref notmuch_config) => { BackendConfig::Notmuch(ref notmuch_config) => {
maildir_config = MaildirBackendConfig { maildir_config = MaildirBackendConfig {
maildir_dir: notmuch_config.notmuch_database_dir.clone(), maildir_dir: notmuch_config.notmuch_database_dir.clone(),
@ -129,6 +153,8 @@ fn main() -> Result<()> {
let mut smtp = LettreService::from(&account_config); let mut smtp = LettreService::from(&account_config);
// Check IMAP commands. // Check IMAP commands.
#[allow(irrefutable_let_patterns)]
#[cfg(feature = "imap-backend")]
if let BackendConfig::Imap(ref imap_config) = backend_config { if let BackendConfig::Imap(ref imap_config) = backend_config {
let mut imap = ImapBackend::new(&account_config, imap_config); let mut imap = ImapBackend::new(&account_config, imap_config);
match imap_args::matches(&m)? { match imap_args::matches(&m)? {

View file

@ -2,8 +2,7 @@
//! //!
//! This module regroups email address entities and converters. //! This module regroups email address entities and converters.
use anyhow::{Context, Result}; use anyhow::Result;
use log::trace;
use mailparse; use mailparse;
use std::fmt::Debug; use std::fmt::Debug;
@ -63,71 +62,3 @@ pub fn from_addrs_to_sendable_addrs(addrs: &Addrs) -> Result<Vec<lettre::Address
} }
Ok(sendable_addrs) Ok(sendable_addrs)
} }
/// Converts a [`imap_proto::Address`] into an address.
pub fn from_imap_addr_to_addr(addr: &imap_proto::Address) -> Result<Addr> {
let name = addr
.name
.as_ref()
.map(|name| {
rfc2047_decoder::decode(&name.to_vec())
.context("cannot decode address name")
.map(Some)
})
.unwrap_or(Ok(None))?;
let mbox = addr
.mailbox
.as_ref()
.map(|mbox| {
rfc2047_decoder::decode(&mbox.to_vec())
.context("cannot decode address mailbox")
.map(Some)
})
.unwrap_or(Ok(None))?;
let host = addr
.host
.as_ref()
.map(|host| {
rfc2047_decoder::decode(&host.to_vec())
.context("cannot decode address host")
.map(Some)
})
.unwrap_or(Ok(None))?;
trace!("parsing address from imap address");
trace!("name: {:?}", name);
trace!("mbox: {:?}", mbox);
trace!("host: {:?}", host);
Ok(Addr::Single(mailparse::SingleInfo {
display_name: name,
addr: match host {
Some(host) => format!("{}@{}", mbox.unwrap_or_default(), host),
None => mbox.unwrap_or_default(),
},
}))
}
/// Converts a list of [`imap_proto::Address`] into a list of addresses.
pub fn from_imap_addrs_to_addrs(proto_addrs: &[imap_proto::Address]) -> Result<Addrs> {
let mut addrs = vec![];
for addr in proto_addrs {
addrs.push(
from_imap_addr_to_addr(addr).context(format!("cannot parse address {:?}", addr))?,
);
}
Ok(addrs.into())
}
/// Converts an optional list of [`imap_proto::Address`] into an optional list of addresses.
pub fn from_imap_addrs_to_some_addrs(
addrs: &Option<Vec<imap_proto::Address>>,
) -> Result<Option<Addrs>> {
Ok(
if let Some(addrs) = addrs.as_deref().map(from_imap_addrs_to_addrs) {
Some(addrs?)
} else {
None
},
)
}

View file

@ -1,8 +1,10 @@
#[cfg(feature = "imap-backend")]
use himalaya::{ use himalaya::{
backends::{Backend, ImapBackend, ImapEnvelopes}, backends::{Backend, ImapBackend, ImapEnvelopes},
config::{AccountConfig, ImapBackendConfig}, config::{AccountConfig, ImapBackendConfig},
}; };
#[cfg(feature = "imap-backend")]
#[test] #[test]
fn test_imap_backend() { fn test_imap_backend() {
// configure accounts // configure accounts

View file

@ -1,13 +1,13 @@
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
use std::{collections::HashMap, env, fs, iter::FromIterator}; use std::{collections::HashMap, env, fs, iter::FromIterator};
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
use himalaya::{ use himalaya::{
backends::{Backend, MaildirBackend, NotmuchBackend, NotmuchEnvelopes}, backends::{Backend, MaildirBackend, NotmuchBackend, NotmuchEnvelopes},
config::{AccountConfig, MaildirBackendConfig, NotmuchBackendConfig}, config::{AccountConfig, MaildirBackendConfig, NotmuchBackendConfig},
}; };
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch-backend")]
#[test] #[test]
fn test_notmuch_backend() { fn test_notmuch_backend() {
// set up maildir folders and notmuch database // set up maildir folders and notmuch database