Re: Mail reader app (Re: Is Beagle indexing my email?)
- From: Nat Friedman <nat novell com>
- To: Sigurd Gartmann <sigurd-beagle brogar org>
- Cc: dashboard-hackers gnome org
- Subject: Re: Mail reader app (Re: Is Beagle indexing my email?)
- Date: Wed, 18 May 2005 18:05:46 -0400
My *preference* would be if Evolution were modified to support reading
mails from non ~/.evolution locations, so that we can launch
evolution file:///home/nat/old-mail/Maildir/cur/09238u092384098
and Evolution would pop up a mail-viewer window, allowing me to respond,
forward, etc. This way I have one interface to mail on my system (as an
Evolution user).
It is a secondary option to create a standalone viewer. This will be
useful to people who aren't exposed to Evolution itself.
On Wed, 2005-05-18 at 11:50 +0200, Sigurd Gartmann wrote:
> Beagle will be a killer app. I saw your presentation at last
> year's GUADEC, and have done a presentation about "metadata
> search systems on the desktop" for the digital library group at
> the university.
Very cool!
> You probably want more than this. What do you want?
Well, we have the beagle-imlog-viewer in Beagle; I guess a
beagle-mail-viewer would run along similar lines.
The challenge is, once you can view mails, you suddenly want other
functionality, including
- replying to them,
- forwarding them,
- viewing or saving their attachments,
and so I think that this project is a bit of a slippery slope. That's
why I recommend making Evolution work as a mail viewer.
If you were going to write a mail viewer, it'd be nice if it were done
in Mono, in the Beagle tree. I started writing such a thing a while
ago, but didn't get very far (as you can see). Maybe someone can pick
it up.
Nat
//
// MailViewer.cs
//
// Nat Friedman <nat novell com>
//
// Copyright (C) 2005 Novell, Inc.
//
using System;
using System.Collections;
using System.IO;
using Gtk;
using Glade;
using System.Text;
using System.Xml;
using Mono.Posix;
using Beagle.Util;
namespace Beagle {
public class Driver {
static void Usage (string error)
{
if (error != null)
Console.WriteLine ("Error: " + error + "\n\n");
string usage =
"beagle-mailviewer: A simple tool to display a mail message.\n" +
"Web page: http://www.gnome.org/projects/beagle\n" +
"Copyright (C) 2004 Novell, Inc.\n\n";
usage +=
"Usage: beagle-mailviewer [OPTIONS] <mbox path> <byte offset to mail>\n\n" +
"Options:\n" +
" --help\t\t\tPrint this usage message.\n";
Console.WriteLine (usage);
System.Environment.Exit (0);
}
static string path;
static long offset;
public static void Main (string[] args)
{
if (args.Length < 2)
Usage ("Required arguments missing");
if (! File.Exists (args [0]))
Usage ("Mailbox file " + args [0] + " does not exist");
Application.Init ();
GeckoUtils.Init ();
GeckoUtils.SetSystemFonts ();
GMime.Global.Init ();
path = args [0];
offset = System.Convert.ToInt64 (args [1]);
GLib.Idle.Add (new GLib.IdleHandler (DoIt));
Application.Run ();
}
private static bool DoIt ()
{
MailViewerWindow mvw = new MailViewerWindow (path, offset);
return false;
}
}
public class MailViewerWindow {
[Widget] Window win;
private Gecko.WebControl gecko;
string mail_body = "";
public MailViewerWindow (string path, long offset) {
GMime.Message message = ReadMessage (path, offset);
if (message == null) {
// FIXME: We should pop up a window
Console.WriteLine ("Could not read message from {0} at byte offset {1}.", path, offset);
return;
}
ConstructWindow ();
RenderMessage (message);
}
GMime.Message ReadMessage (string path, long offset)
{
int mbox_fd = Syscall.open (path, OpenFlags.O_RDONLY);
GMime.StreamFs mbox_stream = new GMime.StreamFs (mbox_fd);
mbox_stream.Seek ((int) offset);
GMime.Parser mbox_parser = new GMime.Parser (mbox_stream);
mbox_parser.ScanFrom = true;
GMime.Message message = mbox_parser.ConstructMessage ();
mbox_stream.Close ();
if (message.Headers == null || message.Headers == "")
return null;
return message;
}
void RenderMessage (GMime.Message message)
{
string sender = Htmlify (message.Sender);
string to = Htmlify (message.GetRecipientsAsString (GMime.Message.RecipientType.To));
string cc = message.GetRecipientsAsString (GMime.Message.RecipientType.Cc);
if (cc == null)
cc = "";
else
cc = "<b>Cc:</b> " + Htmlify (cc) + "<br>";
string subject = Htmlify (message.Subject);
GetMessageBody (message);
string html = String.Format ("<html><body>" +
"<b>From:</b> {0}<br>" +
"<b>To:</b> {1}<br>" +
"{2}" +
"<b>Subject:</b> {3}" +
"<hr>" +
"{4}" +
"</body></html>",
sender,
to,
cc,
subject,
mail_body);
gecko.RenderData(html, "file:///tmp/foo", "text/html");
Console.WriteLine (html);
}
string Htmlify (string s)
{
return Beagle.Util.StringFu.EscapeStringForHtml (s, false);
}
void GetMessageBody (GMime.Message message)
{
this.OnEachPart (message.MimePart);
}
void OnEachPart (GMime.Object part)
{
if (part is GMime.MessagePart) {
Console.WriteLine ("** message part: " + part.ToString ());
Console.WriteLine ("fe ** mp------------------------------------------------------");
GMime.MessagePart msg_part = (GMime.MessagePart) part;
msg_part.Message.ForeachPart (new GMime.PartFunc (this.OnEachPart));
} else if (part is GMime.Multipart) {
Console.WriteLine ("mp multipart: " + part.ToString ());
Console.WriteLine ("mp ------------------------------------------------------");
GMime.Multipart multipart = (GMime.Multipart) part;
multipart.ForeachPart (new GMime.PartFunc (this.OnEachPart));
Console.WriteLine ("femp ------------------------------------------------------");
} else {
MemoryStream stream = new MemoryStream (part.GetData ());
StreamReader reader = new StreamReader (stream);
Console.WriteLine ("CT: {0} ID: {1}", part.ContentType, part.ContentId);
Console.WriteLine ("String: " + reader.ReadToEnd ());
Console.WriteLine ("------------------------------------------------------");
mail_body += System.Text.Encoding.ASCII.GetString (part.GetData ());
Console.WriteLine ("Body: " + mail_body);
}
}
Gtk.AccelGroup accel_group;
GlobalKeybinder global_keys;
void ConstructWindow ()
{
win = new Gtk.Window ("Beagle Mail Viewer");
win.SetDefaultSize (600, 500);
Gtk.ScrolledWindow sw = new ScrolledWindow ();
sw.HscrollbarPolicy = Gtk.PolicyType.Automatic;
sw.VscrollbarPolicy = Gtk.PolicyType.Automatic;
gecko = new Gecko.WebControl ();
gecko.Show ();
sw.Add (gecko);
win.Add (sw);
accel_group = new Gtk.AccelGroup ();
win.AddAccelGroup (accel_group);
global_keys = new GlobalKeybinder (accel_group);
// Close window (Ctrl-W)
global_keys.AddAccelerator (new EventHandler (this.CloseWindow),
(uint) Gdk.Key.w,
Gdk.ModifierType.ControlMask,
Gtk.AccelFlags.Visible);
// Close window (Escape)
global_keys.AddAccelerator (new EventHandler (this.CloseWindow),
(uint) Gdk.Key.Escape,
0,
Gtk.AccelFlags.Visible);
win.ShowAll ();
}
private void CloseWindow (object o, EventArgs args)
{
Application.Quit ();
}
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]