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);
        }
Example #2
0
            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);
            }
Example #3
0
        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);
        }
Example #6
0
        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();
            }
        }
Example #7
0
            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);
                }
            }
Example #8
0
            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);
            }
Example #9
0
        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);
        }
Example #10
0
		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 ();
		}
Example #11
0
		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;
		}
Example #13
0
            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;
            }
Example #14
0
			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;
			}