imap: get() ENVELOPE instead of RFC822.HEADER; it's faster
parent
335a1011de
commit
d1d11356db
|
@ -45,6 +45,8 @@ use crate::email::*;
|
||||||
use crate::error::{MeliError, Result};
|
use crate::error::{MeliError, Result};
|
||||||
use fnv::{FnvHashMap, FnvHashSet};
|
use fnv::{FnvHashMap, FnvHashSet};
|
||||||
use native_tls::TlsConnector;
|
use native_tls::TlsConnector;
|
||||||
|
use std::collections::hash_map::DefaultHasher;
|
||||||
|
use std::hash::Hasher;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
@ -116,7 +118,7 @@ impl MailBackend for ImapType {
|
||||||
while exists > 1 {
|
while exists > 1 {
|
||||||
let mut envelopes = vec![];
|
let mut envelopes = vec![];
|
||||||
exit_on_error!(&tx,
|
exit_on_error!(&tx,
|
||||||
conn.send_command(format!("UID FETCH {}:{} (FLAGS RFC822.HEADER)", std::cmp::max(exists.saturating_sub(20000), 1), exists).as_bytes())
|
conn.send_command(format!("UID FETCH {}:{} (FLAGS ENVELOPE)", std::cmp::max(exists.saturating_sub(20000), 1), exists).as_bytes())
|
||||||
conn.read_response(&mut response)
|
conn.read_response(&mut response)
|
||||||
);
|
);
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -124,21 +126,23 @@ impl MailBackend for ImapType {
|
||||||
response.len(),
|
response.len(),
|
||||||
response.lines().collect::<Vec<&str>>().len()
|
response.lines().collect::<Vec<&str>>().len()
|
||||||
);
|
);
|
||||||
match protocol_parser::uid_fetch_response(response.as_bytes())
|
match protocol_parser::uid_fetch_envelopes_response(response.as_bytes())
|
||||||
.to_full_result()
|
.to_full_result()
|
||||||
.map_err(MeliError::from)
|
.map_err(MeliError::from)
|
||||||
{
|
{
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
debug!("responses len is {}", v.len());
|
debug!("responses len is {}", v.len());
|
||||||
for (uid, flags, b) in v {
|
for (uid, flags, mut env) in v {
|
||||||
if let Ok(e) = Envelope::from_bytes(&b, flags) {
|
let mut h = DefaultHasher::new();
|
||||||
hash_index
|
h.write_usize(uid);
|
||||||
.lock()
|
h.write(folder_path.as_bytes());
|
||||||
.unwrap()
|
env.set_hash(h.finish());
|
||||||
.insert(e.hash(), (uid, folder_hash));
|
hash_index
|
||||||
uid_index.lock().unwrap().insert(uid, e.hash());
|
.lock()
|
||||||
envelopes.push(e);
|
.unwrap()
|
||||||
}
|
.insert(env.hash(), (uid, folder_hash));
|
||||||
|
uid_index.lock().unwrap().insert(uid, env.hash());
|
||||||
|
envelopes.push(env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -496,17 +500,12 @@ impl ImapType {
|
||||||
exit_on_error!(s,
|
exit_on_error!(s,
|
||||||
conn.send_command( format!( "LOGIN \"{}\" \"{}\"", get_conf_val!(s["server_username"]), get_conf_val!(s["server_password"])).as_bytes())
|
conn.send_command( format!( "LOGIN \"{}\" \"{}\"", get_conf_val!(s["server_username"]), get_conf_val!(s["server_password"])).as_bytes())
|
||||||
conn.read_lines(&mut res, String::new())
|
conn.read_lines(&mut res, String::new())
|
||||||
std::io::stderr().write(res.as_bytes())
|
|
||||||
);
|
);
|
||||||
m.capabilities = match protocol_parser::capabilities(res.as_bytes())
|
m.capabilities = match protocol_parser::capabilities(res.as_bytes())
|
||||||
.to_full_result()
|
.to_full_result()
|
||||||
.map_err(MeliError::from)
|
.map_err(MeliError::from)
|
||||||
{
|
{
|
||||||
Ok(c) => {
|
Ok(c) => FnvHashSet::from_iter(c.into_iter().map(|s| s.to_vec())),
|
||||||
eprintln!("cap len {}", c.len());
|
|
||||||
|
|
||||||
FnvHashSet::from_iter(c.into_iter().map(|s| s.to_vec()))
|
|
||||||
}
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Could not login in account `{}`: {}",
|
"Could not login in account `{}`: {}",
|
||||||
|
|
|
@ -4,6 +4,10 @@ use std::collections::hash_map::DefaultHasher;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
macro_rules! to_str (
|
||||||
|
($v:expr) => (unsafe{ std::str::from_utf8_unchecked($v) })
|
||||||
|
);
|
||||||
|
|
||||||
macro_rules! dbg_dmp (
|
macro_rules! dbg_dmp (
|
||||||
($i: expr, $submac:ident!( $($args:tt)* )) => (
|
($i: expr, $submac:ident!( $($args:tt)* )) => (
|
||||||
{
|
{
|
||||||
|
@ -371,9 +375,18 @@ pub fn flags(input: &str) -> IResult<&str, Flag> {
|
||||||
let mut ret = Flag::default();
|
let mut ret = Flag::default();
|
||||||
|
|
||||||
let mut input = input;
|
let mut input = input;
|
||||||
while input.starts_with("\\") {
|
while !input.starts_with(")") && !input.is_empty() {
|
||||||
input = &input[1..];
|
if input.starts_with("\\") {
|
||||||
let match_end = input.find(|c: char| !c.is_ascii_alphabetic()).or_else(|| input.find(" ")).unwrap_or(input.len());
|
input = &input[1..];
|
||||||
|
}
|
||||||
|
let mut match_end = 0;
|
||||||
|
while match_end < input.len() {
|
||||||
|
if input[match_end..].starts_with(" ") || input[match_end..].starts_with(")") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
match_end += 1;
|
||||||
|
}
|
||||||
|
|
||||||
match &input[..match_end] {
|
match &input[..match_end] {
|
||||||
"Answered" => {
|
"Answered" => {
|
||||||
ret.set(Flag::REPLIED, true);
|
ret.set(Flag::REPLIED, true);
|
||||||
|
@ -392,13 +405,10 @@ pub fn flags(input: &str) -> IResult<&str, Flag> {
|
||||||
}
|
}
|
||||||
f => {
|
f => {
|
||||||
debug!("unknown Flag token value: {}", f);
|
debug!("unknown Flag token value: {}", f);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
input = &input[match_end..];
|
input = &input[match_end..];
|
||||||
if input.starts_with(" \\") {
|
input = input.trim_start();
|
||||||
input = &input[1..];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
IResult::Done(input, ret)
|
IResult::Done(input, ret)
|
||||||
}
|
}
|
||||||
|
@ -412,3 +422,205 @@ pub fn byte_flags(input: &[u8]) -> IResult<&[u8], Flag> {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The fields of the envelope structure are in the following
|
||||||
|
* order: date, subject, from, sender, reply-to, to, cc, bcc,
|
||||||
|
* in-reply-to, and message-id. The date, subject, in-reply-to,
|
||||||
|
* and message-id fields are strings. The from, sender, reply-to,
|
||||||
|
* to, cc, and bcc fields are parenthesized lists of address
|
||||||
|
* structures.
|
||||||
|
* An address structure is a parenthesized list that describes an
|
||||||
|
* electronic mail address. The fields of an address structure
|
||||||
|
* are in the following order: personal name, [SMTP]
|
||||||
|
* at-domain-list (source route), mailbox name, and host name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* * 12 FETCH (FLAGS (\Seen) INTERNALDATE "17-Jul-1996 02:44:25 -0700"
|
||||||
|
* RFC822.SIZE 4286 ENVELOPE ("Wed, 17 Jul 1996 02:23:25 -0700 (PDT)"
|
||||||
|
* "IMAP4rev1 WG mtg summary and minutes"
|
||||||
|
* (("Terry Gray" NIL "gray" "cac.washington.edu"))
|
||||||
|
* (("Terry Gray" NIL "gray" "cac.washington.edu"))
|
||||||
|
* (("Terry Gray" NIL "gray" "cac.washington.edu"))
|
||||||
|
* ((NIL NIL "imap" "cac.washington.edu"))
|
||||||
|
* ((NIL NIL "minutes" "CNRI.Reston.VA.US")
|
||||||
|
* ("John Klensin" NIL "KLENSIN" "MIT.EDU")) NIL NIL
|
||||||
|
* "<B27397-0100000@cac.washington.edu>")
|
||||||
|
*/
|
||||||
|
|
||||||
|
named!(
|
||||||
|
pub envelope<Envelope>,
|
||||||
|
do_parse!(
|
||||||
|
tag!("(")
|
||||||
|
>> opt!(is_a!("\r\n\t "))
|
||||||
|
>> date: quoted_or_nil
|
||||||
|
>> opt!(is_a!("\r\n\t "))
|
||||||
|
>> subject: quoted_or_nil
|
||||||
|
>> opt!(is_a!("\r\n\t "))
|
||||||
|
>> from: envelope_addresses
|
||||||
|
>> opt!(is_a!("\r\n\t "))
|
||||||
|
>> sender: envelope_addresses
|
||||||
|
>> opt!(is_a!("\r\n\t "))
|
||||||
|
>> reply_to: envelope_addresses
|
||||||
|
>> opt!(is_a!("\r\n\t "))
|
||||||
|
>> to: envelope_addresses
|
||||||
|
>> opt!(is_a!("\r\n\t "))
|
||||||
|
>> cc: envelope_addresses
|
||||||
|
>> opt!(is_a!("\r\n\t "))
|
||||||
|
>> bcc: envelope_addresses
|
||||||
|
>> opt!(is_a!("\r\n\t "))
|
||||||
|
>> in_reply_to: quoted_or_nil
|
||||||
|
>> opt!(is_a!("\r\n\t "))
|
||||||
|
>> message_id: quoted_or_nil
|
||||||
|
>> opt!(is_a!("\r\n\t "))
|
||||||
|
>> tag!(")")
|
||||||
|
>> ({
|
||||||
|
let mut env = Envelope::new(0);
|
||||||
|
if let Some(date) = date {
|
||||||
|
env.set_date(&date);
|
||||||
|
if let Some(d) = crate::email::parser::date(env.date_as_str().as_bytes()) {
|
||||||
|
env.set_datetime(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(subject) = subject {
|
||||||
|
env.set_subject(subject.to_vec());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(from) = from {
|
||||||
|
env.set_from(from);
|
||||||
|
}
|
||||||
|
if let Some(to) = to {
|
||||||
|
env.set_to(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(cc) = cc {
|
||||||
|
env.set_cc(cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(bcc) = bcc {
|
||||||
|
env.set_bcc(bcc);
|
||||||
|
}
|
||||||
|
if let Some(in_reply_to) = in_reply_to {
|
||||||
|
env.set_in_reply_to(&in_reply_to);
|
||||||
|
env.push_references(&in_reply_to);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(message_id) = message_id {
|
||||||
|
env.set_message_id(&message_id);
|
||||||
|
}
|
||||||
|
env
|
||||||
|
})
|
||||||
|
));
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_envelope() {
|
||||||
|
// FIXME add a proper test
|
||||||
|
/*
|
||||||
|
use std::io::Read;
|
||||||
|
let mut buffer: Vec<u8> = Vec::new();
|
||||||
|
let _ = std::fs::File::open("/tmp/a").unwrap().read_to_end(&mut buffer);
|
||||||
|
debug!(envelope(&buffer));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper to build StrBuilder for Address structs */
|
||||||
|
macro_rules! str_builder {
|
||||||
|
($offset:expr, $length:expr) => {
|
||||||
|
StrBuilder {
|
||||||
|
offset: $offset,
|
||||||
|
length: $length,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse a list of addresses in the format of the ENVELOPE structure
|
||||||
|
named!(pub envelope_addresses<Option<Vec<Address>>>,
|
||||||
|
alt_complete!(map!(tag!("NIL"), |_| None) |
|
||||||
|
do_parse!(
|
||||||
|
tag!("(")
|
||||||
|
>> envelopes: many1!(delimited!(ws!(tag!("(")), envelope_address, tag!(")")))
|
||||||
|
>> tag!(")")
|
||||||
|
>> ({
|
||||||
|
Some(envelopes)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
// Parse an address in the format of the ENVELOPE structure eg
|
||||||
|
// ("Terry Gray" NIL "gray" "cac.washington.edu")
|
||||||
|
named!(
|
||||||
|
pub envelope_address<Address>,
|
||||||
|
do_parse!(
|
||||||
|
name: alt_complete!(quoted | map!(tag!("NIL"), |_| Vec::new()))
|
||||||
|
>> is_a!("\r\n\t ")
|
||||||
|
>> alt_complete!(quoted| map!(tag!("NIL"), |_| Vec::new()))
|
||||||
|
>> is_a!("\r\n\t ")
|
||||||
|
>> mailbox_name: dbg_dmp!(alt_complete!(quoted | map!(tag!("NIL"), |_| Vec::new())))
|
||||||
|
>> is_a!("\r\n\t ")
|
||||||
|
>> host_name: alt_complete!(quoted | map!(tag!("NIL"), |_| Vec::new()))
|
||||||
|
>> ({
|
||||||
|
Address::Mailbox(MailboxAddress {
|
||||||
|
raw: format!("{}{}<{}@{}>", to_str!(&name), if name.is_empty() { "" } else { " " }, to_str!(&mailbox_name), to_str!(&host_name)).into_bytes(),
|
||||||
|
display_name: str_builder!(0, name.len()),
|
||||||
|
address_spec: str_builder!(if name.is_empty() { 1 } else { name.len() + 2 }, mailbox_name.len() + host_name.len() + 1),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
));
|
||||||
|
|
||||||
|
// Read a literal ie a byte sequence prefixed with a tag containing its length delimited in {}s
|
||||||
|
named!(pub literal<&[u8]>,length_bytes!(delimited!(tag!("{"), map_res!(digit, |s| { usize::from_str(unsafe { std::str::from_utf8_unchecked(s) }) }), tag!("}\r\n"))));
|
||||||
|
|
||||||
|
// Return a byte sequence surrounded by "s and decoded if necessary
|
||||||
|
pub fn quoted(input: &[u8]) -> IResult<&[u8], Vec<u8>> {
|
||||||
|
if let IResult::Done(r, o) = literal(input) {
|
||||||
|
return match crate::email::parser::phrase(o) {
|
||||||
|
IResult::Done(_, out) => IResult::Done(r, out),
|
||||||
|
e => e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if input.is_empty() || input[0] != b'"' {
|
||||||
|
return IResult::Error(nom::ErrorKind::Custom(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut i = 1;
|
||||||
|
while i < input.len() {
|
||||||
|
if input[i] == b'\"' { //&& input[i - 1] != b'\\' {
|
||||||
|
return match crate::email::parser::phrase(&input[1..i]) {
|
||||||
|
IResult::Done(_, out) => IResult::Done(&input[i+1..], out),
|
||||||
|
e=> e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IResult::Error(nom::ErrorKind::Custom(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
named!(
|
||||||
|
pub quoted_or_nil<Option<Vec<u8>>>,
|
||||||
|
alt_complete!(map!(ws!(tag!("NIL")), |_| None) | map!(quoted, |v| Some(v))));
|
||||||
|
|
||||||
|
named!(
|
||||||
|
pub uid_fetch_envelopes_response<Vec<(usize, Option<Flag>, Envelope)>>,
|
||||||
|
many0!(
|
||||||
|
do_parse!(
|
||||||
|
tag!("* ")
|
||||||
|
>> take_while!(call!(is_digit))
|
||||||
|
>> tag!(" FETCH (")
|
||||||
|
>> uid_flags: permutation!(preceded!(ws!(tag!("UID ")), map_res!(digit, |s| { usize::from_str(unsafe { std::str::from_utf8_unchecked(s) }) })), opt!(preceded!(ws!(tag!("FLAGS ")), delimited!(tag!("("), byte_flags, tag!(")")))))
|
||||||
|
>> tag!(" ENVELOPE ")
|
||||||
|
>> env: ws!(envelope)
|
||||||
|
>> tag!(")\r\n")
|
||||||
|
>> ((uid_flags.0, uid_flags.1, env))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
|
@ -52,16 +52,16 @@ use chrono::TimeZone;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct GroupAddress {
|
pub struct GroupAddress {
|
||||||
raw: Vec<u8>,
|
pub raw: Vec<u8>,
|
||||||
display_name: StrBuilder,
|
pub display_name: StrBuilder,
|
||||||
mailbox_list: Vec<Address>,
|
pub mailbox_list: Vec<Address>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct MailboxAddress {
|
pub struct MailboxAddress {
|
||||||
raw: Vec<u8>,
|
pub raw: Vec<u8>,
|
||||||
display_name: StrBuilder,
|
pub display_name: StrBuilder,
|
||||||
address_spec: StrBuilder,
|
pub address_spec: StrBuilder,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
@ -149,9 +149,9 @@ impl fmt::Debug for Address {
|
||||||
|
|
||||||
/// Helper struct to return slices from a struct field on demand.
|
/// Helper struct to return slices from a struct field on demand.
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
||||||
struct StrBuilder {
|
pub struct StrBuilder {
|
||||||
offset: usize,
|
pub offset: usize,
|
||||||
length: usize,
|
pub length: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Structs implementing this trait must contain a `StrBuilder` field.
|
/// Structs implementing this trait must contain a `StrBuilder` field.
|
||||||
|
@ -177,7 +177,7 @@ impl StrBuilder {
|
||||||
|
|
||||||
/// `MessageID` is accessed through the `StrBuild` trait.
|
/// `MessageID` is accessed through the `StrBuild` trait.
|
||||||
#[derive(Clone, Serialize, Deserialize, Default)]
|
#[derive(Clone, Serialize, Deserialize, Default)]
|
||||||
pub struct MessageID(Vec<u8>, StrBuilder);
|
pub struct MessageID(pub Vec<u8>, pub StrBuilder);
|
||||||
|
|
||||||
impl StrBuild for MessageID {
|
impl StrBuild for MessageID {
|
||||||
fn new(string: &[u8], slice: &[u8]) -> Self {
|
fn new(string: &[u8], slice: &[u8]) -> Self {
|
||||||
|
@ -334,12 +334,13 @@ pub struct Envelope {
|
||||||
|
|
||||||
impl fmt::Debug for Envelope {
|
impl fmt::Debug for Envelope {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "Envelope {{\ndate: {}\n,from:{:#?}\nto {:#?}\nmessage_id: {},\n references: {:#?}\nhash: {}\n
|
write!(f, "Envelope {{\n\tsubject: {}\n\tdate: {},\n\tfrom:{:#?},\n\tto {:#?},\n\tmessage_id: {},\n\tin_reply_to: {:?}\n\treferences: {:#?},\n\thash: {}\n}}",
|
||||||
}}",
|
self.subject(),
|
||||||
self.date,
|
self.date,
|
||||||
self.from,
|
self.from,
|
||||||
self.to,
|
self.to,
|
||||||
self.message_id_display(),
|
self.message_id_display(),
|
||||||
|
self.in_reply_to_display(),
|
||||||
self.references,
|
self.references,
|
||||||
self.hash)
|
self.hash)
|
||||||
}
|
}
|
||||||
|
@ -667,22 +668,22 @@ impl Envelope {
|
||||||
pub fn message_id_raw(&self) -> Cow<str> {
|
pub fn message_id_raw(&self) -> Cow<str> {
|
||||||
String::from_utf8_lossy(self.message_id.raw())
|
String::from_utf8_lossy(self.message_id.raw())
|
||||||
}
|
}
|
||||||
fn set_date(&mut self, new_val: &[u8]) {
|
pub fn set_date(&mut self, new_val: &[u8]) {
|
||||||
self.date = String::from_utf8_lossy(new_val).into_owned();
|
self.date = String::from_utf8_lossy(new_val).into_owned();
|
||||||
}
|
}
|
||||||
fn set_bcc(&mut self, new_val: Vec<Address>) {
|
pub fn set_bcc(&mut self, new_val: Vec<Address>) {
|
||||||
self.bcc = new_val;
|
self.bcc = new_val;
|
||||||
}
|
}
|
||||||
fn set_cc(&mut self, new_val: Vec<Address>) {
|
pub fn set_cc(&mut self, new_val: Vec<Address>) {
|
||||||
self.cc = new_val;
|
self.cc = new_val;
|
||||||
}
|
}
|
||||||
fn set_from(&mut self, new_val: Vec<Address>) {
|
pub fn set_from(&mut self, new_val: Vec<Address>) {
|
||||||
self.from = new_val;
|
self.from = new_val;
|
||||||
}
|
}
|
||||||
fn set_to(&mut self, new_val: Vec<Address>) {
|
pub fn set_to(&mut self, new_val: Vec<Address>) {
|
||||||
self.to = new_val;
|
self.to = new_val;
|
||||||
}
|
}
|
||||||
fn set_in_reply_to(&mut self, new_val: &[u8]) {
|
pub fn set_in_reply_to(&mut self, new_val: &[u8]) {
|
||||||
let slice = match parser::message_id(new_val).to_full_result() {
|
let slice = match parser::message_id(new_val).to_full_result() {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
@ -692,22 +693,24 @@ impl Envelope {
|
||||||
};
|
};
|
||||||
self.in_reply_to = Some(MessageID::new(new_val, slice));
|
self.in_reply_to = Some(MessageID::new(new_val, slice));
|
||||||
}
|
}
|
||||||
fn set_subject(&mut self, new_val: Vec<u8>) {
|
pub fn set_subject(&mut self, new_val: Vec<u8>) {
|
||||||
self.subject = Some(new_val);
|
self.subject = Some(new_val);
|
||||||
}
|
}
|
||||||
fn set_message_id(&mut self, new_val: &[u8]) {
|
pub fn set_message_id(&mut self, new_val: &[u8]) {
|
||||||
let slice = match parser::message_id(new_val).to_full_result() {
|
let slice = match parser::message_id(new_val).to_full_result() {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(_) => {
|
Err(e) => {
|
||||||
|
debug!(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.message_id = MessageID::new(new_val, slice);
|
self.message_id = MessageID::new(new_val, slice);
|
||||||
}
|
}
|
||||||
fn push_references(&mut self, new_val: &[u8]) {
|
pub fn push_references(&mut self, new_val: &[u8]) {
|
||||||
let slice = match parser::message_id(new_val).to_full_result() {
|
let slice = match parser::message_id(new_val).to_full_result() {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(_) => {
|
Err(e) => {
|
||||||
|
debug!(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -736,7 +739,7 @@ impl Envelope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn set_references(&mut self, new_val: &[u8]) {
|
pub fn set_references(&mut self, new_val: &[u8]) {
|
||||||
match self.references {
|
match self.references {
|
||||||
Some(ref mut s) => {
|
Some(ref mut s) => {
|
||||||
s.raw = new_val.into();
|
s.raw = new_val.into();
|
||||||
|
@ -764,6 +767,11 @@ impl Envelope {
|
||||||
pub fn other_headers(&self) -> &FnvHashMap<String, String> {
|
pub fn other_headers(&self) -> &FnvHashMap<String, String> {
|
||||||
&self.other_headers
|
&self.other_headers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn other_headers_mut(&mut self) -> &mut FnvHashMap<String, String> {
|
||||||
|
&mut self.other_headers
|
||||||
|
}
|
||||||
|
|
||||||
pub fn thread(&self) -> ThreadHash {
|
pub fn thread(&self) -> ThreadHash {
|
||||||
self.thread
|
self.thread
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue