private GMime.Message GetGMimeMessage(string file, int offset, int size) { GMime.Message msg = null; if (!File.Exists(file)) { return(null); } StreamFs stream = null; Parser parser = null; try { int fd = Syscall.open(file, OpenFlags.O_RDONLY); stream = new StreamFs(fd, offset, offset + size); parser = new Parser(stream); msg = parser.ConstructMessage(); } catch { } finally { if (stream != null) { stream.Dispose(); } if (parser != null) { parser.Dispose(); } } return(msg); }
private GMime.Message FullMessage() { int fd; string file = Thunderbird.GetFullyIndexableFile(workfile); GMime.Message message = null; // gmime will go nuts and make the daemon "segmentation fault" in case the file doesn't exist! if (!File.Exists(file)) { return(message); } try { fd = Mono.Unix.Native.Syscall.open(file, Mono.Unix.Native.OpenFlags.O_RDONLY); StreamFs stream = new StreamFs(fd, Offset, Offset + Size); Parser parser = new Parser(stream); message = parser.ConstructMessage(); stream.Dispose(); parser.Dispose(); } catch {} return(message); }
public void Dispose() { if (this.handler != null && this.handler.Reader != null) { this.handler.Reader.Close(); } this.handler = null; if (this.message != null) { this.message.Dispose(); this.message = null; } }
private GMime.Message GetStubMessage(XmlDocument document) { GMime.Message message = new GMime.Message(true); message.Subject = Mime.HeaderDecodeText(GetText(document, "Subject")); message.Sender = Mime.HeaderDecodePhrase(GetText(document, "Author")); message.MessageId = GetText(document, "MessageId"); message.Date = DateTimeUtil.UnixToDateTimeUtc(Convert.ToInt64(GetText(document, "Date"))); string str = GetText(document, "Recipients"); GMime.InternetAddressList recipients = GMime.InternetAddressList.Parse(str); foreach (GMime.InternetAddress ia in recipients) { message.To.Add(ia); } recipients.Dispose(); return(message); }
private Indexable ToAddMailMessageIndexable(XmlDocument document) { GMime.Message message = null; // Check if the entire message is available if (ToBool(GetText(document, "HasOffline"))) { // We must make sure we don't get an exception here since we can fallback to // other information try { int offset = Convert.ToInt32(GetText(document, "MessageOffset")), size = Convert.ToInt32(GetText(document, "OfflineSize")); message = GetGMimeMessage(GetText(document, "FolderFile"), offset, size); } catch (Exception e) { Logger.Log.Debug(e, "Failed to parse GMime message"); } } if (message == null) { message = GetStubMessage(document); } Indexable indexable = new Indexable(GenerateUniqueUri(document)); indexable.HitType = "MailMessage"; indexable.MimeType = "message/rfc822"; indexable.Timestamp = DateTimeUtil.UnixToDateTimeUtc(Convert.ToInt64(GetText(document, "Date"))); indexable.CacheContent = true; indexable.FlushBufferCache = true; indexable.SetBinaryStream(message.Stream); indexable.AddProperty(Property.NewKeyword("fixme:client", "thunderbird")); indexable.AddProperty(Property.NewKeyword("fixme:folder", GetText(document, "Folder"))); indexable.AddProperty(Property.NewUnsearched("ParentUri", GetText(document, "FolderFile"))); indexable.AddProperty(Property.NewUnsearched("fixme:uri", GetText(document, "Uri"))); message.Dispose(); return(indexable); }
protected override void DoOpen(FileInfo info) { if (!gmime_initialized) { gmime_initialized = true; // Only try initialization once; if it fails, it'll never work. try { GMime.Global.Init(); } catch (Exception e) { Log.Error(e, "Unable to initialize GMime"); gmime_broken = true; Error(); return; } } if (gmime_broken) { Error(); return; } int mail_fd = Mono.Unix.Native.Syscall.open(info.FullName, Mono.Unix.Native.OpenFlags.O_RDONLY); if (mail_fd == -1) { throw new IOException(String.Format("Unable to read {0} for parsing mail", info.FullName)); } GMime.StreamFs stream = new GMime.StreamFs(mail_fd); GMime.Parser parser = new GMime.Parser(stream); this.message = parser.ConstructMessage(); stream.Dispose(); parser.Dispose(); if (this.message == null) { Error(); } }
private GMime.Message ConstructMessage() { GMime.Message message = null; // Try to fully index this mail by loading the entire mail into memory if (GetBool("FullIndex")) { message = FullMessage(); } // Make sure we have the correct status set on this message, in case something went wrong if (message == null || (message != null && message.Stream.Length <= 1)) { SetObject("FullIndex", (object)false); return(PartialMessage()); } else { return(message); } }
private GMime.Message PartialMessage() { string date = GetString("date"); GMime.Message message = new GMime.Message(true); message.Subject = GetString("subject"); message.Sender = GetString("sender"); message.MessageId = GetString("message-id"); message.SetDate((date != string.Empty ? DateTime.Parse(date) : DateTimeUtil.UnixToDateTimeUtc(0)), 0); // Add references if (data.ContainsKey("references")) { foreach (Match m in Regex.Matches((data ["references"] as string), @"\<(?>[^\<\>]+)\>")) { message.AddHeader("References", m.Value); } } return(message); }
private Indexable MailToIndexable(TB.Mail mail) { Indexable indexable; GMime.Message message = mail.Message; FullIndex = mail.GetBool("FullIndex"); // Make sure this is up to date string mailbox = (MailboxName != null ? MailboxName : (string)mail.GetString("mailbox")); indexable = NewIndexable(mail.Uri, message.Date.ToUniversalTime(), "MailMessage"); indexable.MimeType = "message/rfc822"; indexable.CacheContent = true; indexable.AddProperty(Property.NewKeyword("fixme:folder", mailbox)); indexable.SetBinaryStream(message.Stream); if (mail.GetBool("FullIndex")) { indexable.ContentUri = UriFu.PathToFileUri(Thunderbird.GetFullyIndexableFile(DbFile)); } message.Dispose(); return(indexable); }
protected override void DoOpen (FileInfo info) { if (!gmime_initialized) { gmime_initialized = true; // Only try initialization once; if it fails, it'll never work. try { GMime.Global.Init (); } catch (Exception e) { Log.Error (e, "Unable to initialize GMime"); gmime_broken = true; Error (); return; } } if (gmime_broken) { Error (); return; } int mail_fd = Mono.Unix.Native.Syscall.open (info.FullName, Mono.Unix.Native.OpenFlags.O_RDONLY); if (mail_fd == -1) throw new IOException (String.Format ("Unable to read {0} for parsing mail", info.FullName)); GMime.StreamFs stream = new GMime.StreamFs (mail_fd); GMime.Parser parser = new GMime.Parser (stream); this.message = parser.ConstructMessage (); stream.Dispose (); parser.Dispose (); if (this.message == null) Error (); }
public void Dispose () { if (this.handler != null && this.handler.Reader != null) this.handler.Reader.Close (); this.handler = null; if (this.message != null) { this.message.Dispose (); this.message = null; } }
private GMime.Message GetStubMessage (XmlDocument document) { GMime.Message message = new GMime.Message (true); message.Subject = Mime.HeaderDecodeText (GetText (document, "Subject")); message.Sender = Mime.HeaderDecodePhrase (GetText (document, "Author")); message.MessageId = GetText (document, "MessageId"); message.Date = DateTimeUtil.UnixToDateTimeUtc (Convert.ToInt64 (GetText (document, "Date"))); string str = GetText (document, "Recipients"); GMime.InternetAddressList recipients = GMime.InternetAddressList.Parse (str); foreach (GMime.InternetAddress ia in recipients) message.To.Add (ia); recipients.Dispose (); return message; }
public void OnEachPart(GMime.Object mime_part) { GMime.Object part = null; bool part_needs_dispose = false; //for (int i = 0; i < this.depth; i++) // Console.Write (" "); //Console.WriteLine ("Content-Type: {0}", mime_part.ContentType); ++depth; if (mime_part is GMime.MessagePart) { GMime.MessagePart msg_part = (GMime.MessagePart)mime_part; using (GMime.Message message = msg_part.Message) { using (GMime.Object subpart = message.MimePart) this.OnEachPart(subpart); } } else if (mime_part is GMime.Multipart) { GMime.Multipart multipart = (GMime.Multipart)mime_part; int num_parts = multipart.Count; // If the mimetype is multipart/alternative, we only want to index // one part -- the richest one we can filter. if (mime_part.ContentType.MediaSubtype.ToLower() == "alternative") { // The richest formats are at the end, so work from there // backward. for (int i = num_parts - 1; i >= 0; i--) { GMime.Object subpart = multipart[i]; if (IsMimeTypeHandled(subpart.ContentType.ToString())) { part = subpart; part_needs_dispose = true; break; } else { subpart.Dispose(); } } } // If it's not alternative, or we don't know how to filter any of // the parts, treat them like a bunch of attachments. if (part == null) { for (int i = 0; i < num_parts; i++) { using (GMime.Object subpart = multipart[i]) this.OnEachPart(subpart); } } } else if (mime_part is GMime.Part) { part = mime_part; } else { throw new Exception(String.Format("Unknown part type: {0}", part.GetType())); } if (part != null) { System.IO.Stream stream = null; using (GMime.DataWrapper content_obj = ((GMime.Part)part).ContentObject) stream = content_obj.Stream; // If this is the only part and it's plain text, we // want to just attach it to our filter instead of // creating a child indexable for it. bool no_child_needed = false; string mime_type = part.ContentType.ToString().ToLower(); if (this.depth == 1 && this.count == 0) { if (mime_type == "text/plain") { no_child_needed = true; this.reader = new StreamReader(stream); } else if (mime_type == "text/html") { no_child_needed = true; html_part = true; string enc = part.ContentType.GetParameter("charset"); // DataWrapper.Stream is a very limited stream // and does not allow Seek or Tell // HtmlFilter requires Stream.Position=0. // Play safe and create a memorystream // for HTML parsing. GMime.StreamMem mem_stream; mem_stream = new GMime.StreamMem(); GMime.Stream data_stream; data_stream = ((StreamWrapper)stream).GMimeStream; data_stream.WriteToStream(mem_stream); data_stream.Flush(); // The StreamWrapper and hence the memory_stream // will be closed when the reader is closed // after Pull()-ing is done. System.IO.Stream html_stream; html_stream = new StreamWrapper(mem_stream); html_stream.Seek(0, SeekOrigin.Begin); stream.Close(); try { this.reader = FilterHtml.GetHtmlReader(html_stream, enc, link_handler); } catch (Exception e) { Log.Debug(e, "Exception while filtering HTML email {0}", this.indexable.Uri); this.reader = null; html_stream.Close(); html_part = false; } } } if (!no_child_needed) { // Check the mime type against the blacklist and don't index any // parts that are contained within. That way the user doesn't // get flooded with pointless signatures and vcard and ical // attachments along with (real) attachments. if (Array.IndexOf(blacklisted_mime_types, mime_type) == -1) { string sub_uri = "#" + this.count; Indexable child; child = new Indexable(UriFu.AddFragment(this.indexable.Uri, sub_uri, true)); child.DisplayUri = new Uri(this.indexable.DisplayUri.ToString() + "#" + this.count); // This is a special case. // Even for mails found on disk, MailMessage hitype is set child.HitType = "MailMessage"; child.MimeType = mime_type; // If this is the richest part we found for multipart emails, add its content to textcache if (snippet_attachment || (this.depth == 1 && this.count == 0)) { child.CacheContent = true; } else { child.CacheContent = false; } string filename = ((GMime.Part)part).Filename; if (!String.IsNullOrEmpty(filename)) { child.AddProperty(Property.NewKeyword("fixme:attachment_title", filename)); foreach (Property prop in Property.StandardFileProperties(filename, false)) { child.AddProperty(prop); } } // Store length of attachment long length = stream.Length; if (length != -1) { child.AddProperty(Property.NewUnsearched("fixme:filesize", length)); } if (part.ContentType.MediaType.ToLower() == "text") { child.SetTextReader(new StreamReader(stream)); } else { child.SetBinaryStream(stream); } child.SetChildOf(this.indexable); child.StoreStream(); child.CloseStreams(); this.child_indexables.Add(child); } else { Log.Debug("Skipping attachment {0}#{1} with blacklisted mime type {2}", this.indexable.Uri, this.count, mime_type); } } this.count++; } if (part_needs_dispose) { part.Dispose(); } --depth; }
private GMime.Message PartialMessage () { string date = GetString ("date"); GMime.Message message = new GMime.Message (true); message.Subject = GetString ("subject"); message.Sender = GetString ("sender"); message.MessageId = GetString ("message-id"); message.SetDate ((date != string.Empty ? DateTime.Parse (date) : DateTimeUtil.UnixToDateTimeUtc (0)), 0); // Add references if (data.ContainsKey ("references")) { foreach (Match m in Regex.Matches ((data ["references"] as string), @"\<(?>[^\<\>]+)\>")) message.AddHeader ("References", m.Value); } return message; }