parent
8be583a9f7
commit
ee56c8e42b
2 changed files with 86 additions and 1 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
use base64;
|
use base64;
|
||||||
use bufstream::BufStream;
|
use bufstream::BufStream;
|
||||||
|
use chrono::{DateTime, FixedOffset};
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
use native_tls::{TlsConnector, TlsStream};
|
use native_tls::{TlsConnector, TlsStream};
|
||||||
use nom;
|
use nom;
|
||||||
|
|
@ -1096,6 +1097,32 @@ impl<T: Read + Write> Session<T> {
|
||||||
mailbox: S,
|
mailbox: S,
|
||||||
content: B,
|
content: B,
|
||||||
flags: &[Flag<'_>],
|
flags: &[Flag<'_>],
|
||||||
|
) -> Result<()> {
|
||||||
|
self.append_with_flags_and_date(mailbox, content, flags, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The [`APPEND` command](https://tools.ietf.org/html/rfc3501#section-6.3.11) can take
|
||||||
|
/// an optional FLAGS parameter to set the flags on the new message.
|
||||||
|
///
|
||||||
|
/// > If a flag parenthesized list is specified, the flags SHOULD be set
|
||||||
|
/// > in the resulting message; otherwise, the flag list of the
|
||||||
|
/// > resulting message is set to empty by default. In either case, the
|
||||||
|
/// > Recent flag is also set.
|
||||||
|
///
|
||||||
|
/// The [`\Recent` flag](https://tools.ietf.org/html/rfc3501#section-2.3.2) is not
|
||||||
|
/// allowed as an argument to `APPEND` and will be filtered out if present in `flags`.
|
||||||
|
///
|
||||||
|
/// Pass a date in order to set the date that the message was originally sent.
|
||||||
|
///
|
||||||
|
/// > If a date-time is specified, the internal date SHOULD be set in
|
||||||
|
/// > the resulting message; otherwise, the internal date of the
|
||||||
|
/// > resulting message is set to the current date and time by default.
|
||||||
|
pub fn append_with_flags_and_date<S: AsRef<str>, B: AsRef<[u8]>>(
|
||||||
|
&mut self,
|
||||||
|
mailbox: S,
|
||||||
|
content: B,
|
||||||
|
flags: &[Flag<'_>],
|
||||||
|
date: impl Into<Option<DateTime<FixedOffset>>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let content = content.as_ref();
|
let content = content.as_ref();
|
||||||
let flagstr = flags
|
let flagstr = flags
|
||||||
|
|
@ -1104,11 +1131,16 @@ impl<T: Read + Write> Session<T> {
|
||||||
.map(|f| f.to_string())
|
.map(|f| f.to_string())
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(" ");
|
.join(" ");
|
||||||
|
let datestr = match date.into() {
|
||||||
|
Some(date) => format!(" \"{}\"", date.format("%d-%h-%Y %T %z")),
|
||||||
|
None => "".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
self.run_command(&format!(
|
self.run_command(&format!(
|
||||||
"APPEND \"{}\" ({}) {{{}}}",
|
"APPEND \"{}\" ({}){} {{{}}}",
|
||||||
mailbox.as_ref(),
|
mailbox.as_ref(),
|
||||||
flagstr,
|
flagstr,
|
||||||
|
datestr,
|
||||||
content.len()
|
content.len()
|
||||||
))?;
|
))?;
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
|
extern crate chrono;
|
||||||
extern crate imap;
|
extern crate imap;
|
||||||
extern crate lettre;
|
extern crate lettre;
|
||||||
extern crate lettre_email;
|
extern crate lettre_email;
|
||||||
extern crate native_tls;
|
extern crate native_tls;
|
||||||
|
|
||||||
|
use chrono::{FixedOffset, TimeZone};
|
||||||
use lettre::Transport;
|
use lettre::Transport;
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
|
|
||||||
|
|
@ -330,3 +332,54 @@ fn append_with_flags() {
|
||||||
let inbox = c.search("ALL").unwrap();
|
let inbox = c.search("ALL").unwrap();
|
||||||
assert_eq!(inbox.len(), 0);
|
assert_eq!(inbox.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn append_with_flags_and_date() {
|
||||||
|
use imap::types::Flag;
|
||||||
|
|
||||||
|
let to = "inbox-append3@localhost";
|
||||||
|
|
||||||
|
// make a message to append
|
||||||
|
let e: lettre::SendableEmail = lettre_email::Email::builder()
|
||||||
|
.from("sender@localhost")
|
||||||
|
.to(to)
|
||||||
|
.subject("My third e-mail")
|
||||||
|
.text("Hello world")
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.into();
|
||||||
|
|
||||||
|
// connect
|
||||||
|
let mut c = session(to);
|
||||||
|
let mbox = "INBOX";
|
||||||
|
c.select(mbox).unwrap();
|
||||||
|
// append
|
||||||
|
let flags: &[Flag] = &[Flag::Seen, Flag::Flagged];
|
||||||
|
let date = FixedOffset::east(8 * 3600)
|
||||||
|
.ymd(2020, 12, 13)
|
||||||
|
.and_hms(13, 36, 36);
|
||||||
|
c.append_with_flags_and_date(mbox, e.message_to_string().unwrap(), flags, Some(date))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// now we should see the e-mail!
|
||||||
|
let inbox = c.uid_search("ALL").unwrap();
|
||||||
|
// and the one message should have the first message sequence number
|
||||||
|
assert_eq!(inbox.len(), 1);
|
||||||
|
let uid = inbox.into_iter().next().unwrap();
|
||||||
|
|
||||||
|
// fetch the e-mail
|
||||||
|
let fetch = c.uid_fetch(format!("{}", uid), "(ALL UID)").unwrap();
|
||||||
|
assert_eq!(fetch.len(), 1);
|
||||||
|
let fetch = &fetch[0];
|
||||||
|
assert_eq!(fetch.uid, Some(uid));
|
||||||
|
assert_eq!(fetch.internal_date(), Some(date));
|
||||||
|
|
||||||
|
// and let's delete it to clean up
|
||||||
|
c.uid_store(format!("{}", uid), "+FLAGS (\\Deleted)")
|
||||||
|
.unwrap();
|
||||||
|
c.expunge().unwrap();
|
||||||
|
|
||||||
|
// the e-mail should be gone now
|
||||||
|
let inbox = c.search("ALL").unwrap();
|
||||||
|
assert_eq!(inbox.len(), 0);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue