You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

797 lines
24KB

  1. /*
  2. * meli - email module
  3. *
  4. * Copyright 2017 Manos Pitsidianakis
  5. *
  6. * This file is part of meli.
  7. *
  8. * meli is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * meli is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with meli. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. /*!
  22. * Email parsing, handling, sending etc.
  23. */
  24. mod compose;
  25. pub use self::compose::*;
  26. mod attachment_types;
  27. pub mod attachments;
  28. pub use crate::attachments::*;
  29. pub mod parser;
  30. use crate::parser::BytesExt;
  31. use crate::backends::BackendOp;
  32. use crate::error::{MeliError, Result};
  33. use crate::thread::ThreadHash;
  34. use std::borrow::Cow;
  35. use std::cmp::Ordering;
  36. use std::collections::hash_map::DefaultHasher;
  37. use std::fmt;
  38. use std::hash::Hasher;
  39. use std::option::Option;
  40. use std::str;
  41. use std::string::String;
  42. use chrono;
  43. use chrono::TimeZone;
  44. #[derive(Clone, Debug, Serialize, Deserialize)]
  45. pub struct GroupAddress {
  46. raw: Vec<u8>,
  47. display_name: StrBuilder,
  48. mailbox_list: Vec<Address>,
  49. }
  50. #[derive(Clone, Debug, Serialize, Deserialize)]
  51. pub struct MailboxAddress {
  52. raw: Vec<u8>,
  53. display_name: StrBuilder,
  54. address_spec: StrBuilder,
  55. }
  56. #[derive(Clone, Serialize, Deserialize)]
  57. pub enum Address {
  58. Mailbox(MailboxAddress),
  59. Group(GroupAddress),
  60. }
  61. impl Address {
  62. pub fn get_display_name(&self) -> String {
  63. match self {
  64. Address::Mailbox(m) => m.display_name.display(&m.raw),
  65. Address::Group(g) => g.display_name.display(&g.raw),
  66. }
  67. }
  68. pub fn get_email(&self) -> String {
  69. match self {
  70. Address::Mailbox(m) => m.address_spec.display(&m.raw),
  71. Address::Group(_) => String::new(),
  72. }
  73. }
  74. pub fn get_fqdn(&self) -> Option<String> {
  75. match self {
  76. Address::Mailbox(m) => {
  77. let raw_address = m.address_spec.display_bytes(&m.raw);
  78. let fqdn_pos = raw_address.iter().position(|&b| b == b'@')? + 1;
  79. Some(String::from_utf8_lossy(&raw_address[fqdn_pos..]).into())
  80. }
  81. Address::Group(_) => None,
  82. }
  83. }
  84. }
  85. impl Eq for Address {}
  86. impl PartialEq for Address {
  87. fn eq(&self, other: &Address) -> bool {
  88. match (self, other) {
  89. (Address::Mailbox(_), Address::Group(_)) | (Address::Group(_), Address::Mailbox(_)) => {
  90. false
  91. }
  92. (Address::Mailbox(s), Address::Mailbox(o)) => {
  93. s.address_spec.display_bytes(&s.raw) == o.address_spec.display_bytes(&o.raw)
  94. }
  95. (Address::Group(s), Address::Group(o)) => {
  96. s.display_name.display_bytes(&s.raw) == o.display_name.display_bytes(&o.raw)
  97. && s.mailbox_list
  98. .iter()
  99. .zip(o.mailbox_list.iter())
  100. .fold(true, |b, (s, o)| b && (s == o))
  101. }
  102. }
  103. }
  104. }
  105. impl fmt::Display for Address {
  106. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  107. match self {
  108. Address::Mailbox(m) if m.display_name.length > 0 => write!(
  109. f,
  110. "{} <{}>",
  111. m.display_name.display(&m.raw),
  112. m.address_spec.display(&m.raw)
  113. ),
  114. Address::Group(g) => {
  115. let attachment_strings: Vec<String> =
  116. g.mailbox_list.iter().map(|a| format!("{}", a)).collect();
  117. write!(
  118. f,
  119. "{}: {}",
  120. g.display_name.display(&g.raw),
  121. attachment_strings.join(", ")
  122. )
  123. }
  124. Address::Mailbox(m) => write!(f, "{}", m.address_spec.display(&m.raw)),
  125. }
  126. }
  127. }
  128. impl fmt::Debug for Address {
  129. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  130. fmt::Display::fmt(self, f)
  131. }
  132. }
  133. /// Helper struct to return slices from a struct field on demand.
  134. #[derive(Clone, Debug, Serialize, Deserialize, Default)]
  135. struct StrBuilder {
  136. offset: usize,
  137. length: usize,
  138. }
  139. /// Structs implementing this trait must contain a `StrBuilder` field.
  140. pub trait StrBuild {
  141. /// Create a new `Self` out of a string and a slice
  142. fn new(string: &[u8], slice: &[u8]) -> Self;
  143. /// Get the slice part of the string
  144. fn raw(&self) -> &[u8];
  145. /// Get the entire string as a slice
  146. fn val(&self) -> &[u8];
  147. }
  148. impl StrBuilder {
  149. fn display<'a>(&self, s: &'a [u8]) -> String {
  150. let offset = self.offset;
  151. let length = self.length;
  152. String::from_utf8(s[offset..offset + length].to_vec()).unwrap()
  153. }
  154. fn display_bytes<'a>(&self, b: &'a [u8]) -> &'a [u8] {
  155. &b[self.offset..(self.offset + self.length)]
  156. }
  157. }
  158. /// `MessageID` is accessed through the `StrBuild` trait.
  159. #[derive(Clone, Serialize, Deserialize, Default)]
  160. pub struct MessageID(Vec<u8>, StrBuilder);
  161. impl StrBuild for MessageID {
  162. fn new(string: &[u8], slice: &[u8]) -> Self {
  163. let offset = string.find(slice).unwrap();
  164. MessageID(
  165. string.to_owned(),
  166. StrBuilder {
  167. offset,
  168. length: slice.len() + 1,
  169. },
  170. )
  171. }
  172. fn raw(&self) -> &[u8] {
  173. let offset = self.1.offset;
  174. let length = self.1.length;
  175. &self.0[offset..offset + length.saturating_sub(1)]
  176. }
  177. fn val(&self) -> &[u8] {
  178. &self.0
  179. }
  180. }
  181. #[test]
  182. fn test_strbuilder() {
  183. let m_id = b"<20170825132332.6734-1@el13635@mail.ntua.gr>";
  184. let (_, slice) = parser::message_id(m_id).unwrap();
  185. assert_eq!(
  186. MessageID::new(m_id, slice),
  187. MessageID(
  188. m_id.to_vec(),
  189. StrBuilder {
  190. offset: 1,
  191. length: 43,
  192. }
  193. )
  194. );
  195. }
  196. impl fmt::Display for MessageID {
  197. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  198. if self.val().is_ascii() {
  199. write!(f, "{}", unsafe { str::from_utf8_unchecked(self.val()) })
  200. } else {
  201. write!(f, "{}", String::from_utf8_lossy(self.val()))
  202. }
  203. }
  204. }
  205. impl PartialEq for MessageID {
  206. fn eq(&self, other: &MessageID) -> bool {
  207. self.raw() == other.raw()
  208. }
  209. }
  210. impl fmt::Debug for MessageID {
  211. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  212. write!(f, "{}", String::from_utf8(self.raw().to_vec()).unwrap())
  213. }
  214. }
  215. #[derive(Clone, Serialize, Deserialize)]
  216. struct References {
  217. raw: Vec<u8>,
  218. refs: Vec<MessageID>,
  219. }
  220. impl fmt::Debug for References {
  221. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  222. write!(f, "{:#?}", self.refs)
  223. }
  224. }
  225. bitflags! {
  226. #[derive(Default, Serialize, Deserialize)]
  227. pub struct Flag: u8 {
  228. const PASSED = 0b0000_0001;
  229. const REPLIED = 0b0000_0010;
  230. const SEEN = 0b0000_0100;
  231. const TRASHED = 0b0000_1000;
  232. const DRAFT = 0b0001_0000;
  233. const FLAGGED = 0b0010_0000;
  234. }
  235. }
  236. #[derive(Debug, Clone, Default)]
  237. pub struct EnvelopeWrapper {
  238. envelope: Envelope,
  239. buffer: Vec<u8>,
  240. }
  241. use std::ops::Deref;
  242. impl Deref for EnvelopeWrapper {
  243. type Target = Envelope;
  244. fn deref(&self) -> &Envelope {
  245. &self.envelope
  246. }
  247. }
  248. impl EnvelopeWrapper {
  249. pub fn new(buffer: Vec<u8>) -> Result<Self> {
  250. Ok(EnvelopeWrapper {
  251. envelope: Envelope::from_bytes(&buffer)?,
  252. buffer,
  253. })
  254. }
  255. pub fn update(&mut self, new_buffer: Vec<u8>) {
  256. // TODO: Propagate error.
  257. if let Ok(e) = EnvelopeWrapper::new(new_buffer) {
  258. *self = e;
  259. }
  260. }
  261. pub fn envelope(&self) -> &Envelope {
  262. &self.envelope
  263. }
  264. pub fn buffer(&self) -> &[u8] {
  265. &self.buffer
  266. }
  267. }
  268. pub type UnixTimestamp = u64;
  269. pub type EnvelopeHash = u64;
  270. /// `Envelope` represents all the data of an email we need to know.
  271. ///
  272. /// Attachments (the email's body) is parsed on demand with `body`.
  273. ///
  274. /// Access to the underlying email object in the account's backend (for example the file or the
  275. /// entry in an IMAP server) is given through `operation_token`. For more information see
  276. /// `BackendOp`.
  277. #[derive(Clone, Default, Serialize, Deserialize)]
  278. pub struct Envelope {
  279. date: String,
  280. from: Vec<Address>,
  281. to: Vec<Address>,
  282. cc: Vec<Address>,
  283. bcc: Vec<Address>,
  284. subject: Option<Vec<u8>>,
  285. message_id: MessageID,
  286. in_reply_to: Option<MessageID>,
  287. references: Option<References>,
  288. timestamp: UnixTimestamp,
  289. thread: ThreadHash,
  290. hash: EnvelopeHash,
  291. flags: Flag,
  292. has_attachments: bool,
  293. }
  294. impl fmt::Debug for Envelope {
  295. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  296. write!(f, "Envelope {{\ndate: {}\n,from:{:#?}\nto {:#?}\nmessage_id: {},\n references: {:#?}\nhash: {}\n
  297. }}",
  298. self.date,
  299. self.from,
  300. self.to,
  301. self.message_id_display(),
  302. self.references,
  303. self.hash)
  304. }
  305. }
  306. impl Envelope {
  307. pub fn new(hash: EnvelopeHash) -> Self {
  308. Envelope {
  309. date: String::new(),
  310. from: Vec::new(),
  311. to: Vec::new(),
  312. cc: Vec::new(),
  313. bcc: Vec::new(),
  314. subject: None,
  315. message_id: MessageID::default(),
  316. in_reply_to: None,
  317. references: None,
  318. timestamp: 0,
  319. thread: ThreadHash::null(),
  320. hash,
  321. has_attachments: false,
  322. flags: Flag::default(),
  323. }
  324. }
  325. pub fn set_hash(&mut self, new_hash: EnvelopeHash) {
  326. self.hash = new_hash;
  327. }
  328. pub fn from_bytes(bytes: &[u8]) -> Result<Envelope> {
  329. let mut h = DefaultHasher::new();
  330. h.write(bytes);
  331. let mut e = Envelope::new(h.finish());
  332. let res = e.populate_headers(bytes).ok();
  333. if res.is_some() {
  334. return Ok(e);
  335. }
  336. Err(MeliError::new("Couldn't parse mail."))
  337. }
  338. pub fn from_token(mut operation: Box<BackendOp>, hash: EnvelopeHash) -> Option<Envelope> {
  339. let mut e = Envelope::new(hash);
  340. e.flags = operation.fetch_flags();
  341. if let Ok(bytes) = operation.as_bytes() {
  342. let res = e.populate_headers(bytes).ok();
  343. if res.is_some() {
  344. return Some(e);
  345. }
  346. }
  347. None
  348. }
  349. pub fn hash(&self) -> EnvelopeHash {
  350. self.hash
  351. }
  352. pub fn populate_headers(&mut self, bytes: &[u8]) -> Result<()> {
  353. let (headers, body) = match parser::mail(bytes).to_full_result() {
  354. Ok(v) => v,
  355. Err(e) => {
  356. debug!("error in parsing mail\n{:?}\n", e);
  357. let error_msg = String::from("Mail cannot be shown because of errors.");
  358. return Err(MeliError::new(error_msg));
  359. }
  360. };
  361. let mut in_reply_to = None;
  362. for (name, value) in headers {
  363. if value.len() == 1 && value.is_empty() {
  364. continue;
  365. }
  366. if name.eq_ignore_ascii_case(b"to") {
  367. let parse_result = parser::rfc2822address_list(value);
  368. if parse_result.is_done() {
  369. let value = parse_result.to_full_result().unwrap();
  370. self.set_to(value);
  371. };
  372. } else if name.eq_ignore_ascii_case(b"cc") {
  373. let parse_result = parser::rfc2822address_list(value);
  374. if parse_result.is_done() {
  375. let value = parse_result.to_full_result().unwrap();
  376. self.set_cc(value);
  377. };
  378. } else if name.eq_ignore_ascii_case(b"bcc") {
  379. let parse_result = parser::rfc2822address_list(value);
  380. if parse_result.is_done() {
  381. let value = parse_result.to_full_result().unwrap();
  382. self.set_bcc(value);
  383. };
  384. } else if name.eq_ignore_ascii_case(b"from") {
  385. let parse_result = parser::rfc2822address_list(value);
  386. if parse_result.is_done() {
  387. let value = parse_result.to_full_result().unwrap();
  388. self.set_from(value);
  389. }
  390. } else if name.eq_ignore_ascii_case(b"subject") {
  391. let parse_result = parser::phrase(value.trim());
  392. if parse_result.is_done() {
  393. let value = parse_result.to_full_result().unwrap();
  394. self.set_subject(value);
  395. };
  396. } else if name.eq_ignore_ascii_case(b"message-id") {
  397. self.set_message_id(value);
  398. } else if name.eq_ignore_ascii_case(b"references") {
  399. {
  400. let parse_result = parser::references(value);
  401. if parse_result.is_done() {
  402. for v in parse_result.to_full_result().unwrap() {
  403. self.push_references(v);
  404. }
  405. }
  406. }
  407. self.set_references(value);
  408. } else if name.eq_ignore_ascii_case(b"in-reply-to") {
  409. self.set_in_reply_to(value);
  410. in_reply_to = Some(value);
  411. } else if name.eq_ignore_ascii_case(b"date") {
  412. let parse_result = parser::phrase(value);
  413. if parse_result.is_done() {
  414. let value = parse_result.to_full_result().unwrap();
  415. self.set_date(value.as_slice());
  416. } else {
  417. self.set_date(value);
  418. }
  419. } else if name.eq_ignore_ascii_case(b"content-type") {
  420. match parser::content_type(value).to_full_result() {
  421. Ok((ct, cst, _))
  422. if ct.eq_ignore_ascii_case(b"multipart")
  423. && cst.eq_ignore_ascii_case(b"mixed") =>
  424. {
  425. let mut builder = AttachmentBuilder::new(body);
  426. builder.set_content_type(value);
  427. let b = builder.build();
  428. let subs = b.attachments();
  429. self.has_attachments = subs.iter().any(|sub| !sub.is_text());
  430. }
  431. _ => {}
  432. }
  433. }
  434. }
  435. /*
  436. * https://tools.ietf.org/html/rfc5322#section-3.6.4
  437. *
  438. * if self.message_id.is_none() ...
  439. */
  440. if let Some(ref mut x) = in_reply_to {
  441. self.push_references(x);
  442. }
  443. if let Some(d) = parser::date(&self.date.as_bytes()) {
  444. self.set_datetime(d);
  445. }
  446. if self.message_id.raw().is_empty() {
  447. let hash = self.hash;
  448. self.set_message_id(format!("<{:x}>", hash).as_bytes());
  449. }
  450. if self.references.is_some() {
  451. if let Some(pos) = self
  452. .references
  453. .as_ref()
  454. .map(|r| &r.refs)
  455. .unwrap()
  456. .iter()
  457. .position(|r| r == &self.message_id)
  458. {
  459. self.references.as_mut().unwrap().refs.remove(pos);
  460. }
  461. }
  462. Ok(())
  463. }
  464. pub fn populate_headers_from_token(&mut self, mut operation: Box<BackendOp>) -> Result<()> {
  465. let headers = operation.fetch_headers()?;
  466. self.populate_headers(headers)
  467. }
  468. pub fn date(&self) -> UnixTimestamp {
  469. self.timestamp
  470. }
  471. pub fn datetime(&self) -> chrono::DateTime<chrono::FixedOffset> {
  472. if let Some(d) = parser::date(&self.date.as_bytes()) {
  473. return d;
  474. }
  475. chrono::FixedOffset::west(0)
  476. .ymd(1970, 1, 1)
  477. .and_hms(0, 0, 0)
  478. }
  479. pub fn date_as_str(&self) -> &str {
  480. &self.date
  481. }
  482. pub fn from(&self) -> &Vec<Address> {
  483. &self.from
  484. }
  485. pub fn field_bcc_to_string(&self) -> String {
  486. let _strings: Vec<String> = self.bcc.iter().map(|a| format!("{}", a)).collect();
  487. _strings.join(", ")
  488. }
  489. pub fn field_cc_to_string(&self) -> String {
  490. let _strings: Vec<String> = self.cc.iter().map(|a| format!("{}", a)).collect();
  491. _strings.join(", ")
  492. }
  493. pub fn field_from_to_string(&self) -> String {
  494. let _strings: Vec<String> = self.from().iter().map(|a| format!("{}", a)).collect();
  495. _strings.join(", ")
  496. }
  497. pub fn to(&self) -> &Vec<Address> {
  498. &self.to
  499. }
  500. pub fn field_to_to_string(&self) -> String {
  501. let _strings: Vec<String> = self.to.iter().map(|a| format!("{}", a)).collect();
  502. _strings.join(", ")
  503. }
  504. pub fn bytes(&self, mut operation: Box<BackendOp>) -> Vec<u8> {
  505. operation
  506. .as_bytes()
  507. .map(|v| v.into())
  508. .unwrap_or_else(|_| Vec::new())
  509. }
  510. pub fn body_bytes(&self, bytes: &[u8]) -> Attachment {
  511. if bytes.is_empty() {
  512. let builder = AttachmentBuilder::new(bytes);
  513. return builder.build();
  514. }
  515. let (headers, body) = match parser::mail(bytes).to_full_result() {
  516. Ok(v) => v,
  517. Err(_) => {
  518. debug!("error in parsing mail\n");
  519. let error_msg = b"Mail cannot be shown because of errors.";
  520. let builder = AttachmentBuilder::new(error_msg);
  521. return builder.build();
  522. }
  523. };
  524. let mut builder = AttachmentBuilder::new(body);
  525. for (name, value) in headers {
  526. if value.len() == 1 && value.is_empty() {
  527. continue;
  528. }
  529. if name.eq_ignore_ascii_case(b"content-transfer-encoding") {
  530. builder.set_content_transfer_encoding(value);
  531. } else if name.eq_ignore_ascii_case(b"content-type") {
  532. builder.set_content_type(value);
  533. }
  534. }
  535. builder.build()
  536. }
  537. pub fn headers<'a>(&self, bytes: &'a [u8]) -> Result<Vec<(&'a str, &'a str)>> {
  538. let ret = parser::headers(bytes).to_full_result()?;
  539. let len = ret.len();
  540. ret.into_iter()
  541. .try_fold(Vec::with_capacity(len), |mut acc, (a, b)| {
  542. Ok({
  543. acc.push((std::str::from_utf8(a)?, std::str::from_utf8(b)?));
  544. acc
  545. })
  546. })
  547. }
  548. pub fn body(&self, mut operation: Box<BackendOp>) -> Attachment {
  549. debug!("searching body for {:?}", self.message_id_display());
  550. let file = operation.as_bytes();
  551. self.body_bytes(file.unwrap())
  552. /*
  553. let (headers, body) = match parser::mail(file.unwrap()).to_full_result() {
  554. Ok(v) => v,
  555. Err(_) => {
  556. debug!("2error in parsing mail\n");
  557. let error_msg = b"Mail cannot be shown because of errors.";
  558. let mut builder = AttachmentBuilder::new(error_msg);
  559. return builder.build();
  560. }
  561. };
  562. let mut builder = AttachmentBuilder::new(body);
  563. for (name, value) in headers {
  564. if value.len() == 1 && value.is_empty() {
  565. continue;
  566. }
  567. if name.eq_ignore_ascii_case(b"content-transfer-encoding") {
  568. builder.content_transfer_encoding(value);
  569. } else if name.eq_ignore_ascii_case(b"content-type") {
  570. builder.content_type(value);
  571. }
  572. }
  573. builder.build()
  574. */
  575. }
  576. pub fn subject(&self) -> Cow<str> {
  577. match self.subject {
  578. Some(ref s) => String::from_utf8_lossy(s),
  579. _ => Cow::from(String::new()),
  580. }
  581. }
  582. pub fn in_reply_to(&self) -> Option<&MessageID> {
  583. self.in_reply_to.as_ref()
  584. }
  585. pub fn in_reply_to_display(&self) -> Option<Cow<str>> {
  586. if let Some(ref m) = self.in_reply_to {
  587. Some(String::from_utf8_lossy(m.val()))
  588. } else {
  589. None
  590. }
  591. }
  592. pub fn in_reply_to_raw(&self) -> Option<Cow<str>> {
  593. if let Some(ref m) = self.in_reply_to {
  594. Some(String::from_utf8_lossy(m.raw()))
  595. } else {
  596. None
  597. }
  598. }
  599. pub fn message_id(&self) -> &MessageID {
  600. &self.message_id
  601. }
  602. pub fn message_id_display(&self) -> Cow<str> {
  603. String::from_utf8_lossy(self.message_id.val())
  604. }
  605. pub fn message_id_raw(&self) -> Cow<str> {
  606. String::from_utf8_lossy(self.message_id.raw())
  607. }
  608. fn set_date(&mut self, new_val: &[u8]) {
  609. self.date = String::from_utf8_lossy(new_val).into_owned();
  610. }
  611. fn set_bcc(&mut self, new_val: Vec<Address>) {
  612. self.bcc = new_val;
  613. }
  614. fn set_cc(&mut self, new_val: Vec<Address>) {
  615. self.cc = new_val;
  616. }
  617. fn set_from(&mut self, new_val: Vec<Address>) {
  618. self.from = new_val;
  619. }
  620. fn set_to(&mut self, new_val: Vec<Address>) {
  621. self.to = new_val;
  622. }
  623. fn set_in_reply_to(&mut self, new_val: &[u8]) {
  624. let slice = match parser::message_id(new_val).to_full_result() {
  625. Ok(v) => v,
  626. Err(_) => {
  627. self.in_reply_to = None;
  628. return;
  629. }
  630. };
  631. self.in_reply_to = Some(MessageID::new(new_val, slice));
  632. }
  633. fn set_subject(&mut self, new_val: Vec<u8>) {
  634. self.subject = Some(new_val);
  635. }
  636. fn set_message_id(&mut self, new_val: &[u8]) {
  637. let slice = match parser::message_id(new_val).to_full_result() {
  638. Ok(v) => v,
  639. Err(_) => {
  640. return;
  641. }
  642. };
  643. self.message_id = MessageID::new(new_val, slice);
  644. }
  645. fn push_references(&mut self, new_val: &[u8]) {
  646. let slice = match parser::message_id(new_val).to_full_result() {
  647. Ok(v) => v,
  648. Err(_) => {
  649. return;
  650. }
  651. };
  652. let new_ref = MessageID::new(new_val, slice);
  653. match self.references {
  654. Some(ref mut s) => {
  655. if s.refs.contains(&new_ref) {
  656. if s.refs[s.refs.len() - 1] != new_ref {
  657. if let Some(index) = s.refs.iter().position(|x| *x == new_ref) {
  658. s.refs.remove(index);
  659. } else {
  660. panic!();
  661. }
  662. } else {
  663. return;
  664. }
  665. }
  666. s.refs.push(new_ref);
  667. }
  668. None => {
  669. let v = vec![new_ref];
  670. self.references = Some(References {
  671. raw: "".into(),
  672. refs: v,
  673. });
  674. }
  675. }
  676. }
  677. fn set_references(&mut self, new_val: &[u8]) {
  678. match self.references {
  679. Some(ref mut s) => {
  680. s.raw = new_val.into();
  681. }
  682. None => {
  683. self.references = Some(References {
  684. raw: new_val.into(),
  685. refs: Vec::new(),
  686. });
  687. }
  688. }
  689. }
  690. pub fn references(&self) -> Vec<&MessageID> {
  691. match self.references {
  692. Some(ref s) => s
  693. .refs
  694. .iter()
  695. .fold(Vec::with_capacity(s.refs.len()), |mut acc, x| {
  696. acc.push(x);
  697. acc
  698. }),
  699. None => Vec::new(),
  700. }
  701. }
  702. pub fn thread(&self) -> ThreadHash {
  703. self.thread
  704. }
  705. pub fn set_thread(&mut self, new_val: ThreadHash) {
  706. self.thread = new_val;
  707. }
  708. pub fn set_datetime(&mut self, new_val: chrono::DateTime<chrono::FixedOffset>) {
  709. self.timestamp = new_val.timestamp() as UnixTimestamp;
  710. }
  711. pub fn set_flag(&mut self, f: Flag, mut operation: Box<BackendOp>) -> Result<()> {
  712. operation.set_flag(self, f)?;
  713. self.flags |= f;
  714. Ok(())
  715. }
  716. pub fn flags(&self) -> Flag {
  717. self.flags
  718. }
  719. pub fn set_seen(&mut self, operation: Box<BackendOp>) -> Result<()> {
  720. self.set_flag(Flag::SEEN, operation)
  721. }
  722. pub fn is_seen(&self) -> bool {
  723. self.flags.contains(Flag::SEEN)
  724. }
  725. pub fn has_attachments(&self) -> bool {
  726. self.has_attachments
  727. }
  728. }
  729. impl Eq for Envelope {}
  730. impl Ord for Envelope {
  731. fn cmp(&self, other: &Envelope) -> Ordering {
  732. self.datetime().cmp(&other.datetime())
  733. }
  734. }
  735. impl PartialOrd for Envelope {
  736. fn partial_cmp(&self, other: &Envelope) -> Option<Ordering> {
  737. Some(self.cmp(other))
  738. }
  739. }
  740. impl PartialEq for Envelope {
  741. fn eq(&self, other: &Envelope) -> bool {
  742. self.hash == other.hash
  743. }
  744. }