mirror of
https://github.com/soywod/himalaya.git
synced 2024-07-08 18:45:13 +00:00
parent
811ea45610
commit
6b042f5e6a
|
@ -20,6 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- `In-Reply-To` not set properly when replying to a message [#323]
|
- `In-Reply-To` not set properly when replying to a message [#323]
|
||||||
- `Cc` missing or invalid when replying to a message [#324]
|
- `Cc` missing or invalid when replying to a message [#324]
|
||||||
- Notmuch backend hangs [#329]
|
- Notmuch backend hangs [#329]
|
||||||
|
- Maildir e2e tests [#335]
|
||||||
|
- JSON API for listings [#331]
|
||||||
|
|
||||||
## [0.5.8] - 2022-03-04
|
## [0.5.8] - 2022-03-04
|
||||||
|
|
||||||
|
@ -499,3 +501,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
[#323]: https://github.com/soywod/himalaya/issues/323
|
[#323]: https://github.com/soywod/himalaya/issues/323
|
||||||
[#324]: https://github.com/soywod/himalaya/issues/324
|
[#324]: https://github.com/soywod/himalaya/issues/324
|
||||||
[#329]: https://github.com/soywod/himalaya/issues/329
|
[#329]: https://github.com/soywod/himalaya/issues/329
|
||||||
|
[#331]: https://github.com/soywod/himalaya/issues/331
|
||||||
|
[#335]: https://github.com/soywod/himalaya/issues/335
|
||||||
|
|
|
@ -15,13 +15,16 @@ use super::{ImapFlag, ImapFlags};
|
||||||
|
|
||||||
/// Represents a list of IMAP envelopes.
|
/// Represents a list of IMAP envelopes.
|
||||||
#[derive(Debug, Default, serde::Serialize)]
|
#[derive(Debug, Default, serde::Serialize)]
|
||||||
pub struct ImapEnvelopes(pub Vec<ImapEnvelope>);
|
pub struct ImapEnvelopes {
|
||||||
|
#[serde(rename = "response")]
|
||||||
|
pub envelopes: Vec<ImapEnvelope>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Deref for ImapEnvelopes {
|
impl Deref for ImapEnvelopes {
|
||||||
type Target = Vec<ImapEnvelope>;
|
type Target = Vec<ImapEnvelope>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.envelopes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +102,7 @@ impl TryFrom<RawImapEnvelopes> for ImapEnvelopes {
|
||||||
for raw_envelope in raw_envelopes.iter().rev() {
|
for raw_envelope in raw_envelopes.iter().rev() {
|
||||||
envelopes.push(ImapEnvelope::try_from(raw_envelope).context("cannot parse envelope")?);
|
envelopes.push(ImapEnvelope::try_from(raw_envelope).context("cannot parse envelope")?);
|
||||||
}
|
}
|
||||||
Ok(Self(envelopes))
|
Ok(Self { envelopes })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
//! to the mailbox.
|
//! to the mailbox.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use serde::Serialize;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
@ -16,14 +17,17 @@ use crate::{
|
||||||
use super::ImapMboxAttrs;
|
use super::ImapMboxAttrs;
|
||||||
|
|
||||||
/// Represents a list of IMAP mailboxes.
|
/// Represents a list of IMAP mailboxes.
|
||||||
#[derive(Debug, Default, serde::Serialize)]
|
#[derive(Debug, Default, Serialize)]
|
||||||
pub struct ImapMboxes(pub Vec<ImapMbox>);
|
pub struct ImapMboxes {
|
||||||
|
#[serde(rename = "response")]
|
||||||
|
pub mboxes: Vec<ImapMbox>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Deref for ImapMboxes {
|
impl Deref for ImapMboxes {
|
||||||
type Target = Vec<ImapMbox>;
|
type Target = Vec<ImapMbox>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.mboxes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +134,9 @@ pub type RawImapMboxes = imap::types::ZeroCopy<Vec<RawImapMbox>>;
|
||||||
|
|
||||||
impl<'a> From<RawImapMboxes> for ImapMboxes {
|
impl<'a> From<RawImapMboxes> for ImapMboxes {
|
||||||
fn from(raw_mboxes: RawImapMboxes) -> Self {
|
fn from(raw_mboxes: RawImapMboxes) -> Self {
|
||||||
Self(raw_mboxes.iter().map(ImapMbox::from).collect())
|
Self {
|
||||||
|
mboxes: raw_mboxes.iter().map(ImapMbox::from).collect(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ impl<'a> Backend<'a> for MaildirBackend<'a> {
|
||||||
envelopes.sort_by(|a, b| b.date.partial_cmp(&a.date).unwrap());
|
envelopes.sort_by(|a, b| b.date.partial_cmp(&a.date).unwrap());
|
||||||
|
|
||||||
// Applies pagination boundaries.
|
// Applies pagination boundaries.
|
||||||
envelopes.0 = envelopes[page_begin..page_end].to_owned();
|
envelopes.envelopes = envelopes[page_begin..page_end].to_owned();
|
||||||
|
|
||||||
// Appends envelopes hash to the id mapper cache file and
|
// Appends envelopes hash to the id mapper cache file and
|
||||||
// calculates the new short hash length. The short hash length
|
// calculates the new short hash length. The short hash length
|
||||||
|
|
|
@ -20,19 +20,22 @@ use crate::{
|
||||||
|
|
||||||
/// Represents a list of envelopes.
|
/// Represents a list of envelopes.
|
||||||
#[derive(Debug, Default, serde::Serialize)]
|
#[derive(Debug, Default, serde::Serialize)]
|
||||||
pub struct MaildirEnvelopes(pub Vec<MaildirEnvelope>);
|
pub struct MaildirEnvelopes {
|
||||||
|
#[serde(rename = "response")]
|
||||||
|
pub envelopes: Vec<MaildirEnvelope>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Deref for MaildirEnvelopes {
|
impl Deref for MaildirEnvelopes {
|
||||||
type Target = Vec<MaildirEnvelope>;
|
type Target = Vec<MaildirEnvelope>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.envelopes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DerefMut for MaildirEnvelopes {
|
impl DerefMut for MaildirEnvelopes {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.0
|
&mut self.envelopes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +117,7 @@ impl<'a> TryFrom<RawMaildirEnvelopes> for MaildirEnvelopes {
|
||||||
envelopes.push(envelope);
|
envelopes.push(envelope);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(MaildirEnvelopes(envelopes))
|
Ok(MaildirEnvelopes { envelopes })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,13 +19,16 @@ use crate::{
|
||||||
|
|
||||||
/// Represents a list of Maildir mailboxes.
|
/// Represents a list of Maildir mailboxes.
|
||||||
#[derive(Debug, Default, serde::Serialize)]
|
#[derive(Debug, Default, serde::Serialize)]
|
||||||
pub struct MaildirMboxes(pub Vec<MaildirMbox>);
|
pub struct MaildirMboxes {
|
||||||
|
#[serde(rename = "response")]
|
||||||
|
pub mboxes: Vec<MaildirMbox>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Deref for MaildirMboxes {
|
impl Deref for MaildirMboxes {
|
||||||
type Target = Vec<MaildirMbox>;
|
type Target = Vec<MaildirMbox>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.mboxes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +116,7 @@ impl TryFrom<RawMaildirMboxes> for MaildirMboxes {
|
||||||
for entry in mail_entries {
|
for entry in mail_entries {
|
||||||
mboxes.push(entry?.try_into()?);
|
mboxes.push(entry?.try_into()?);
|
||||||
}
|
}
|
||||||
Ok(MaildirMboxes(mboxes))
|
Ok(MaildirMboxes { mboxes })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ impl<'a> NotmuchBackend<'a> {
|
||||||
envelopes.sort_by(|a, b| b.date.partial_cmp(&a.date).unwrap());
|
envelopes.sort_by(|a, b| b.date.partial_cmp(&a.date).unwrap());
|
||||||
|
|
||||||
// Applies pagination boundaries.
|
// Applies pagination boundaries.
|
||||||
envelopes.0 = envelopes[page_begin..page_end].to_owned();
|
envelopes.envelopes = envelopes[page_begin..page_end].to_owned();
|
||||||
|
|
||||||
// Appends envelopes hash to the id mapper cache file and
|
// Appends envelopes hash to the id mapper cache file and
|
||||||
// calculates the new short hash length. The short hash length
|
// calculates the new short hash length. The short hash length
|
||||||
|
@ -118,17 +118,17 @@ impl<'a> Backend<'a> for NotmuchBackend<'a> {
|
||||||
fn get_mboxes(&mut self) -> Result<Box<dyn Mboxes>> {
|
fn get_mboxes(&mut self) -> Result<Box<dyn Mboxes>> {
|
||||||
info!(">> get notmuch virtual mailboxes");
|
info!(">> get notmuch virtual mailboxes");
|
||||||
|
|
||||||
let mut virt_mboxes: Vec<_> = self
|
let mut mboxes: Vec<_> = self
|
||||||
.account_config
|
.account_config
|
||||||
.mailboxes
|
.mailboxes
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, v)| NotmuchMbox::new(k, v))
|
.map(|(k, v)| NotmuchMbox::new(k, v))
|
||||||
.collect();
|
.collect();
|
||||||
trace!("virtual mailboxes: {:?}", virt_mboxes);
|
trace!("virtual mailboxes: {:?}", mboxes);
|
||||||
virt_mboxes.sort_by(|a, b| b.name.partial_cmp(&a.name).unwrap());
|
mboxes.sort_by(|a, b| b.name.partial_cmp(&a.name).unwrap());
|
||||||
|
|
||||||
info!("<< get notmuch virtual mailboxes");
|
info!("<< get notmuch virtual mailboxes");
|
||||||
Ok(Box::new(NotmuchMboxes(virt_mboxes)))
|
Ok(Box::new(NotmuchMboxes { mboxes }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn del_mbox(&mut self, _mbox: &str) -> Result<()> {
|
fn del_mbox(&mut self, _mbox: &str) -> Result<()> {
|
||||||
|
@ -202,7 +202,7 @@ impl<'a> Backend<'a> for NotmuchBackend<'a> {
|
||||||
// Adds the message to the maildir folder and gets its hash.
|
// Adds the message to the maildir folder and gets its hash.
|
||||||
let hash = self
|
let hash = self
|
||||||
.mdir
|
.mdir
|
||||||
.add_msg("inbox", msg, "seen")
|
.add_msg("", msg, "seen")
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
"cannot add notmuch message to maildir {:?}",
|
"cannot add notmuch message to maildir {:?}",
|
||||||
|
|
|
@ -19,19 +19,22 @@ use crate::{
|
||||||
|
|
||||||
/// Represents a list of envelopes.
|
/// Represents a list of envelopes.
|
||||||
#[derive(Debug, Default, serde::Serialize)]
|
#[derive(Debug, Default, serde::Serialize)]
|
||||||
pub struct NotmuchEnvelopes(pub Vec<NotmuchEnvelope>);
|
pub struct NotmuchEnvelopes {
|
||||||
|
#[serde(rename = "response")]
|
||||||
|
pub envelopes: Vec<NotmuchEnvelope>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Deref for NotmuchEnvelopes {
|
impl Deref for NotmuchEnvelopes {
|
||||||
type Target = Vec<NotmuchEnvelope>;
|
type Target = Vec<NotmuchEnvelope>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.envelopes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DerefMut for NotmuchEnvelopes {
|
impl DerefMut for NotmuchEnvelopes {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.0
|
&mut self.envelopes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +110,7 @@ impl<'a> TryFrom<RawNotmuchEnvelopes> for NotmuchEnvelopes {
|
||||||
.context("cannot parse notmuch mail entry")?;
|
.context("cannot parse notmuch mail entry")?;
|
||||||
envelopes.push(envelope);
|
envelopes.push(envelope);
|
||||||
}
|
}
|
||||||
Ok(NotmuchEnvelopes(envelopes))
|
Ok(NotmuchEnvelopes { envelopes })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,13 +17,16 @@ use crate::{
|
||||||
|
|
||||||
/// Represents a list of Notmuch mailboxes.
|
/// Represents a list of Notmuch mailboxes.
|
||||||
#[derive(Debug, Default, serde::Serialize)]
|
#[derive(Debug, Default, serde::Serialize)]
|
||||||
pub struct NotmuchMboxes(pub Vec<NotmuchMbox>);
|
pub struct NotmuchMboxes {
|
||||||
|
#[serde(rename = "response")]
|
||||||
|
pub mboxes: Vec<NotmuchMbox>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Deref for NotmuchMboxes {
|
impl Deref for NotmuchMboxes {
|
||||||
type Target = Vec<NotmuchMbox>;
|
type Target = Vec<NotmuchMbox>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.mboxes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,21 +115,23 @@ mod tests {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
fn get_mboxes(&mut self) -> Result<Box<dyn Mboxes>> {
|
fn get_mboxes(&mut self) -> Result<Box<dyn Mboxes>> {
|
||||||
Ok(Box::new(ImapMboxes(vec![
|
Ok(Box::new(ImapMboxes {
|
||||||
ImapMbox {
|
mboxes: vec![
|
||||||
delim: "/".into(),
|
ImapMbox {
|
||||||
name: "INBOX".into(),
|
delim: "/".into(),
|
||||||
attrs: ImapMboxAttrs(vec![ImapMboxAttr::NoSelect]),
|
name: "INBOX".into(),
|
||||||
},
|
attrs: ImapMboxAttrs(vec![ImapMboxAttr::NoSelect]),
|
||||||
ImapMbox {
|
},
|
||||||
delim: "/".into(),
|
ImapMbox {
|
||||||
name: "Sent".into(),
|
delim: "/".into(),
|
||||||
attrs: ImapMboxAttrs(vec![
|
name: "Sent".into(),
|
||||||
ImapMboxAttr::NoInferiors,
|
attrs: ImapMboxAttrs(vec![
|
||||||
ImapMboxAttr::Custom("HasNoChildren".into()),
|
ImapMboxAttr::NoInferiors,
|
||||||
]),
|
ImapMboxAttr::Custom("HasNoChildren".into()),
|
||||||
},
|
]),
|
||||||
])))
|
},
|
||||||
|
],
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
fn del_mbox(&mut self, _: &str) -> Result<()> {
|
fn del_mbox(&mut self, _: &str) -> Result<()> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
|
|
|
@ -19,10 +19,7 @@ fn test_maildir_backend() {
|
||||||
|
|
||||||
// configure accounts
|
// configure accounts
|
||||||
let account_config = AccountConfig {
|
let account_config = AccountConfig {
|
||||||
mailboxes: HashMap::from_iter([
|
mailboxes: HashMap::from_iter([("subdir".into(), "Subdir".into())]),
|
||||||
("inbox".into(), "INBOX".into()),
|
|
||||||
("subdir".into(), "Subdir".into()),
|
|
||||||
]),
|
|
||||||
..AccountConfig::default()
|
..AccountConfig::default()
|
||||||
};
|
};
|
||||||
let mdir_config = MaildirBackendConfig {
|
let mdir_config = MaildirBackendConfig {
|
||||||
|
|
Loading…
Reference in a new issue