Unsollicited responses on APPEND
This commit is contained in:
parent
4aa31ba8b5
commit
28b1f4f14d
3 changed files with 14 additions and 9 deletions
|
@ -14,13 +14,13 @@ use imap_codec::imap_types::mailbox::{ListMailbox, Mailbox as MailboxCodec};
|
||||||
use imap_codec::imap_types::response::{Code, CodeOther, Data};
|
use imap_codec::imap_types::response::{Code, CodeOther, Data};
|
||||||
use imap_codec::imap_types::status::{StatusDataItem, StatusDataItemName};
|
use imap_codec::imap_types::status::{StatusDataItem, StatusDataItemName};
|
||||||
|
|
||||||
|
use crate::imap::Body;
|
||||||
use crate::imap::capability::{ClientCapability, ServerCapability};
|
use crate::imap::capability::{ClientCapability, ServerCapability};
|
||||||
use crate::imap::command::{anystate, MailboxName};
|
use crate::imap::command::{anystate, MailboxName};
|
||||||
use crate::imap::flow;
|
use crate::imap::flow;
|
||||||
use crate::imap::mailbox_view::MailboxView;
|
use crate::imap::mailbox_view::{MailboxView, UpdateParameters};
|
||||||
use crate::imap::response::Response;
|
use crate::imap::response::Response;
|
||||||
|
|
||||||
use crate::mail::mailbox::Mailbox;
|
|
||||||
use crate::mail::uidindex::*;
|
use crate::mail::uidindex::*;
|
||||||
use crate::mail::user::{User, MAILBOX_HIERARCHY_DELIMITER as MBX_HIER_DELIM_RAW};
|
use crate::mail::user::{User, MAILBOX_HIERARCHY_DELIMITER as MBX_HIER_DELIM_RAW};
|
||||||
use crate::mail::IMF;
|
use crate::mail::IMF;
|
||||||
|
@ -558,9 +558,12 @@ impl<'a> AuthenticatedContext<'a> {
|
||||||
) -> Result<(Response<'static>, flow::Transition)> {
|
) -> Result<(Response<'static>, flow::Transition)> {
|
||||||
let append_tag = self.req.tag.clone();
|
let append_tag = self.req.tag.clone();
|
||||||
match self.append_internal(mailbox, flags, date, message).await {
|
match self.append_internal(mailbox, flags, date, message).await {
|
||||||
Ok((_mb, uidvalidity, uid, _modseq)) => Ok((
|
|
||||||
|
|
||||||
|
Ok((_mb_view, unsollicited, uidvalidity, uid, _modseq)) => Ok((
|
||||||
Response::build()
|
Response::build()
|
||||||
.tag(append_tag)
|
.tag(append_tag)
|
||||||
|
.set_body(unsollicited)
|
||||||
.message("APPEND completed")
|
.message("APPEND completed")
|
||||||
.code(Code::Other(CodeOther::unvalidated(
|
.code(Code::Other(CodeOther::unvalidated(
|
||||||
format!("APPENDUID {} {}", uidvalidity, uid).into_bytes(),
|
format!("APPENDUID {} {}", uidvalidity, uid).into_bytes(),
|
||||||
|
@ -593,13 +596,14 @@ impl<'a> AuthenticatedContext<'a> {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//@FIXME should be refactored and integrated to the mailbox view
|
||||||
pub(crate) async fn append_internal(
|
pub(crate) async fn append_internal(
|
||||||
self,
|
self,
|
||||||
mailbox: &MailboxCodec<'a>,
|
mailbox: &MailboxCodec<'a>,
|
||||||
flags: &[Flag<'a>],
|
flags: &[Flag<'a>],
|
||||||
date: &Option<DateTime>,
|
date: &Option<DateTime>,
|
||||||
message: &Literal<'a>,
|
message: &Literal<'a>,
|
||||||
) -> Result<(Arc<Mailbox>, ImapUidvalidity, ImapUid, ModSeq)> {
|
) -> Result<(MailboxView, Vec<Body<'static>>, ImapUidvalidity, ImapUid, ModSeq)> {
|
||||||
let name: &str = MailboxName(mailbox).try_into()?;
|
let name: &str = MailboxName(mailbox).try_into()?;
|
||||||
|
|
||||||
let mb_opt = self.user.open_mailbox(&name).await?;
|
let mb_opt = self.user.open_mailbox(&name).await?;
|
||||||
|
@ -607,6 +611,7 @@ impl<'a> AuthenticatedContext<'a> {
|
||||||
Some(mb) => mb,
|
Some(mb) => mb,
|
||||||
None => bail!("Mailbox does not exist"),
|
None => bail!("Mailbox does not exist"),
|
||||||
};
|
};
|
||||||
|
let mut view = MailboxView::new(mb, self.client_capabilities.condstore.is_enabled()).await;
|
||||||
|
|
||||||
if date.is_some() {
|
if date.is_some() {
|
||||||
tracing::warn!("Cannot set date when appending message");
|
tracing::warn!("Cannot set date when appending message");
|
||||||
|
@ -617,9 +622,10 @@ impl<'a> AuthenticatedContext<'a> {
|
||||||
let flags = flags.iter().map(|x| x.to_string()).collect::<Vec<_>>();
|
let flags = flags.iter().map(|x| x.to_string()).collect::<Vec<_>>();
|
||||||
// TODO: filter allowed flags? ping @Quentin
|
// TODO: filter allowed flags? ping @Quentin
|
||||||
|
|
||||||
let (uidvalidity, uid, modseq) = mb.append(msg, None, &flags[..]).await?;
|
let (uidvalidity, uid, modseq) = view.internal.mailbox.append(msg, None, &flags[..]).await?;
|
||||||
|
let unsollicited = view.update(UpdateParameters::default()).await?;
|
||||||
|
|
||||||
Ok((mb, uidvalidity, uid, modseq))
|
Ok((view, unsollicited, uidvalidity, uid, modseq))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,7 @@ fn rfc4551_imapext_condstore() {
|
||||||
FetchKind::Rfc822Size,
|
FetchKind::Rfc822Size,
|
||||||
FetchMod::ChangedSince(2),
|
FetchMod::ChangedSince(2),
|
||||||
)?;
|
)?;
|
||||||
assert!(fetch_res.contains("* 1 FETCH (RFC822.SIZE 84 MODSEQ (3))"));
|
assert!(fetch_res.contains("* 1 FETCH (RFC822.SIZE 81 MODSEQ (3))"));
|
||||||
assert!(!fetch_res.contains("* 2 FETCH"));
|
assert!(!fetch_res.contains("* 2 FETCH"));
|
||||||
assert_eq!(store_res.lines().count(), 2);
|
assert_eq!(store_res.lines().count(), 2);
|
||||||
|
|
||||||
|
|
|
@ -384,8 +384,7 @@ pub fn append(imap: &mut TcpStream, content: Email) -> Result<String> {
|
||||||
// write our stuff
|
// write our stuff
|
||||||
imap.write(ref_mail)?;
|
imap.write(ref_mail)?;
|
||||||
imap.write(&b"\r\n"[..])?;
|
imap.write(&b"\r\n"[..])?;
|
||||||
let read = read_lines(imap, &mut buffer, None)?;
|
let read = read_lines(imap, &mut buffer, Some(&b"47 OK"[..]))?;
|
||||||
assert_eq!(&read[..5], &b"47 OK"[..]);
|
|
||||||
let srv_msg = std::str::from_utf8(read)?;
|
let srv_msg = std::str::from_utf8(read)?;
|
||||||
|
|
||||||
Ok(srv_msg.to_string())
|
Ok(srv_msg.to_string())
|
||||||
|
|
Loading…
Reference in a new issue