append ignore dates instead of failing
This commit is contained in:
parent
b91c64920d
commit
74686ebb77
5 changed files with 89 additions and 12 deletions
|
@ -58,7 +58,7 @@ aws-sdk-s3 = "1.9.0"
|
|||
eml-codec = { git = "https://git.deuxfleurs.fr/Deuxfleurs/eml-codec.git", branch = "main" }
|
||||
smtp-message = { git = "http://github.com/Alexis211/kannader", branch = "feature/lmtp" }
|
||||
smtp-server = { git = "http://github.com/Alexis211/kannader", branch = "feature/lmtp" }
|
||||
imap-codec = { version = "1.0.0", features = ["quirk_crlf_relaxed", "bounded-static"] }
|
||||
imap-codec = { version = "1.0.0", features = ["quirk_crlf_relaxed", "bounded-static", "ext_condstore_qresync"] }
|
||||
imap-flow = { git = "https://github.com/duesee/imap-flow.git", rev = "e45ce7bb6ab6bda3c71a0c7b05e9b558a5902e90" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -1,10 +1,24 @@
|
|||
use imap_codec::imap_types::core::NonEmptyVec;
|
||||
use imap_codec::imap_types::response::Capability;
|
||||
|
||||
fn capability_unselect() -> Capability<'static> {
|
||||
Capability::try_from("UNSELECT").unwrap()
|
||||
}
|
||||
|
||||
fn capability_condstore() -> Capability<'static> {
|
||||
Capability::try_from("CONDSTORE").unwrap()
|
||||
}
|
||||
|
||||
fn capability_qresync() -> Capability<'static> {
|
||||
Capability::try_from("QRESYNC").unwrap()
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ServerCapability {
|
||||
r#move: bool,
|
||||
unselect: bool,
|
||||
condstore: bool,
|
||||
qresync: bool,
|
||||
}
|
||||
|
||||
impl Default for ServerCapability {
|
||||
|
@ -12,6 +26,8 @@ impl Default for ServerCapability {
|
|||
Self {
|
||||
r#move: true,
|
||||
unselect: true,
|
||||
condstore: false,
|
||||
qresync: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +39,64 @@ impl ServerCapability {
|
|||
acc.push(Capability::Move);
|
||||
}
|
||||
if self.unselect {
|
||||
acc.push(Capability::try_from("UNSELECT").unwrap());
|
||||
acc.push(capability_unselect());
|
||||
}
|
||||
if self.condstore {
|
||||
acc.push(capability_condstore());
|
||||
}
|
||||
if self.qresync {
|
||||
acc.push(capability_qresync());
|
||||
}
|
||||
acc.try_into().unwrap()
|
||||
}
|
||||
|
||||
pub fn support(&self, cap: &Capability<'static>) -> bool {
|
||||
match cap {
|
||||
Capability::Imap4Rev1 => true,
|
||||
Capability::Move => self.r#move,
|
||||
x if *x == capability_condstore() => self.condstore,
|
||||
x if *x == capability_qresync() => self.qresync,
|
||||
x if *x == capability_unselect() => self.unselect,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientCapability {
|
||||
condstore: bool,
|
||||
qresync: bool,
|
||||
}
|
||||
|
||||
impl Default for ClientCapability {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
condstore: false,
|
||||
qresync: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientCapability {
|
||||
pub fn try_enable(
|
||||
&mut self,
|
||||
srv: &ServerCapability,
|
||||
caps: &[Capability<'static>],
|
||||
) -> Vec<Capability<'static>> {
|
||||
let mut enabled = vec![];
|
||||
for cap in caps {
|
||||
match cap {
|
||||
x if *x == capability_condstore() && srv.condstore && !self.condstore => {
|
||||
self.condstore = true;
|
||||
enabled.push(x.clone());
|
||||
}
|
||||
x if *x == capability_qresync() && srv.qresync && !self.qresync => {
|
||||
self.qresync = true;
|
||||
enabled.push(x.clone());
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
enabled
|
||||
}
|
||||
}
|
||||
|
|
|
@ -305,6 +305,9 @@ impl<'a> AuthenticatedContext<'a> {
|
|||
StatusDataItemName::DeletedStorage => {
|
||||
bail!("quota not implemented, can't return freed storage after EXPUNGE will be run");
|
||||
},
|
||||
StatusDataItemName::HighestModSeq => {
|
||||
bail!("highestmodseq not yet implemented");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -524,7 +527,7 @@ impl<'a> AuthenticatedContext<'a> {
|
|||
};
|
||||
|
||||
if date.is_some() {
|
||||
bail!("Cannot set date when appending message");
|
||||
tracing::warn!("Cannot set date when appending message");
|
||||
}
|
||||
|
||||
let msg =
|
||||
|
|
|
@ -89,7 +89,7 @@ async fn client_wrapper(ctx: ClientContext) {
|
|||
let addr = ctx.addr.clone();
|
||||
match client(ctx).await {
|
||||
Ok(()) => {
|
||||
tracing::info!("closing successful session for {:?}", addr);
|
||||
tracing::debug!("closing successful session for {:?}", addr);
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("closing errored session for {:?}: {}", addr, e);
|
||||
|
@ -127,7 +127,9 @@ async fn client(mut ctx: ClientContext) -> Result<()> {
|
|||
Some(cmd_recv) => cmd_recv,
|
||||
};
|
||||
|
||||
tracing::debug!(cmd=?cmd, sock=%ctx.addr, "command");
|
||||
let maybe_response = session.command(cmd).await;
|
||||
tracing::debug!(cmd=?maybe_response.completion, sock=%ctx.addr, "response");
|
||||
|
||||
match resp_tx.send(maybe_response) {
|
||||
Err(_) => break,
|
||||
|
|
|
@ -9,7 +9,7 @@ use base64::Engine;
|
|||
use futures::{future::BoxFuture, FutureExt};
|
||||
//use tokio::io::AsyncReadExt;
|
||||
use tokio::sync::watch;
|
||||
use tracing::{error, info, warn};
|
||||
use tracing::{debug, error, info, warn};
|
||||
|
||||
use crate::cryptoblob;
|
||||
use crate::login::{Credentials, PublicCredentials};
|
||||
|
@ -62,7 +62,7 @@ async fn incoming_mail_watch_process_internal(
|
|||
|
||||
loop {
|
||||
let maybe_updated_incoming_key = if *lock_held.borrow() {
|
||||
info!("incoming lock held");
|
||||
debug!("incoming lock held");
|
||||
|
||||
let wait_new_mail = async {
|
||||
loop {
|
||||
|
@ -83,7 +83,7 @@ async fn incoming_mail_watch_process_internal(
|
|||
_ = rx_inbox_id.changed() => None,
|
||||
}
|
||||
} else {
|
||||
info!("incoming lock not held");
|
||||
debug!("incoming lock not held");
|
||||
tokio::select! {
|
||||
_ = lock_held.changed() => None,
|
||||
_ = rx_inbox_id.changed() => None,
|
||||
|
@ -93,11 +93,11 @@ async fn incoming_mail_watch_process_internal(
|
|||
let user = match Weak::upgrade(&user) {
|
||||
Some(user) => user,
|
||||
None => {
|
||||
info!("User no longer available, exiting incoming loop.");
|
||||
debug!("User no longer available, exiting incoming loop.");
|
||||
break;
|
||||
}
|
||||
};
|
||||
info!("User still available");
|
||||
debug!("User still available");
|
||||
|
||||
// If INBOX no longer is same mailbox, open new mailbox
|
||||
let inbox_id = *rx_inbox_id.borrow();
|
||||
|
@ -235,7 +235,7 @@ async fn k2v_lock_loop_internal(
|
|||
let watch_lock_loop: BoxFuture<Result<()>> = async {
|
||||
let mut ct = row_ref.clone();
|
||||
loop {
|
||||
info!("k2v watch lock loop iter: ct = {:?}", ct);
|
||||
debug!("k2v watch lock loop iter: ct = {:?}", ct);
|
||||
match storage.row_poll(&ct).await {
|
||||
Err(e) => {
|
||||
error!(
|
||||
|
@ -263,7 +263,7 @@ async fn k2v_lock_loop_internal(
|
|||
}
|
||||
let new_ct = cv.row_ref;
|
||||
|
||||
info!(
|
||||
debug!(
|
||||
"k2v watch lock loop: changed, old ct = {:?}, new ct = {:?}, v = {:?}",
|
||||
ct, new_ct, lock_state
|
||||
);
|
||||
|
@ -378,7 +378,7 @@ async fn k2v_lock_loop_internal(
|
|||
|
||||
let _ = futures::try_join!(watch_lock_loop, lock_notify_loop, take_lock_loop);
|
||||
|
||||
info!("lock loop exited, releasing");
|
||||
debug!("lock loop exited, releasing");
|
||||
|
||||
if !held_tx.is_closed() {
|
||||
warn!("weird...");
|
||||
|
|
Loading…
Reference in a new issue