mail.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. use std::result::Result as RResult;
  2. use std::path::Path;
  3. use std::path::PathBuf;
  4. use std::fs::File;
  5. use std::io::Read;
  6. use libimagstore::store::{FileLockEntry, Store};
  7. use libimagref::reference::Ref;
  8. use libimagref::flags::RefFlags;
  9. use mailparse::{MailParseError, ParsedMail, parse_mail};
  10. use hasher::MailHasher;
  11. use result::Result;
  12. use error::{MapErrInto, MailErrorKind as MEK};
  13. struct Buffer(String);
  14. impl Buffer {
  15. pub fn parsed<'a>(&'a self) -> RResult<ParsedMail<'a>, MailParseError> {
  16. parse_mail(self.0.as_bytes())
  17. }
  18. }
  19. impl From<String> for Buffer {
  20. fn from(data: String) -> Buffer {
  21. Buffer(data)
  22. }
  23. }
  24. pub struct Mail<'a>(Ref<'a>, Buffer);
  25. impl<'a> Mail<'a> {
  26. /// Imports a mail from the Path passed
  27. pub fn import_from_path<P: AsRef<Path>>(store: &Store, p: P) -> Result<Mail> {
  28. let h = MailHasher::new();
  29. let f = RefFlags::default().with_content_hashing(true).with_permission_tracking(false);
  30. let p = PathBuf::from(p.as_ref());
  31. Ref::create_with_hasher(store, p, f, h)
  32. .map_err_into(MEK::RefCreationError)
  33. .and_then(|reference| {
  34. reference.fs_file()
  35. .map_err_into(MEK::RefHandlingError)
  36. .and_then(|path| File::open(path).map_err_into(MEK::IOError))
  37. .and_then(|mut file| {
  38. let mut s = String::new();
  39. file.read_to_string(&mut s)
  40. .map(|_| s)
  41. .map_err_into(MEK::IOError)
  42. })
  43. .map(Buffer::from)
  44. .map(|buffer| Mail(reference, buffer))
  45. })
  46. }
  47. /// Opens a mail by the passed hash
  48. pub fn open<S: AsRef<str>>(store: &Store, hash: S) -> Result<Option<Mail>> {
  49. Ref::get_by_hash(store, String::from(hash.as_ref()))
  50. .map_err_into(MEK::FetchByHashError)
  51. .map_err_into(MEK::FetchError)
  52. .and_then(|o| match o {
  53. Some(r) => Mail::from_ref(r).map(Some),
  54. None => Ok(None),
  55. })
  56. }
  57. /// Implement me as TryFrom as soon as it is stable
  58. pub fn from_ref(r: Ref<'a>) -> Result<Mail> {
  59. r.fs_file()
  60. .map_err_into(MEK::RefHandlingError)
  61. .and_then(|path| File::open(path).map_err_into(MEK::IOError))
  62. .and_then(|mut file| {
  63. let mut s = String::new();
  64. file.read_to_string(&mut s)
  65. .map(|_| s)
  66. .map_err_into(MEK::IOError)
  67. })
  68. .map(Buffer::from)
  69. .map(|buffer| Mail(r, buffer))
  70. }
  71. pub fn get_field(&self, field: &str) -> Result<Option<String>> {
  72. use mailparse::MailHeader;
  73. self.1
  74. .parsed()
  75. .map_err_into(MEK::MailParsingError)
  76. .map(|parsed| {
  77. parsed.headers
  78. .iter()
  79. .filter(|hdr| hdr.get_key().map(|n| n == field).unwrap_or(false))
  80. .next()
  81. .and_then(|field| field.get_value().ok())
  82. })
  83. }
  84. pub fn get_from(&self) -> Result<Option<String>> {
  85. self.get_field("From")
  86. }
  87. pub fn get_to(&self) -> Result<Option<String>> {
  88. self.get_field("To")
  89. }
  90. pub fn get_subject(&self) -> Result<Option<String>> {
  91. self.get_field("Subject")
  92. }
  93. pub fn get_message_id(&self) -> Result<Option<String>> {
  94. self.get_field("Message-ID")
  95. }
  96. pub fn get_in_reply_to(&self) -> Result<Option<String>> {
  97. self.get_field("In-Reply-To")
  98. }
  99. }