diff --git a/plugins/mail-notification/Makefile.am b/plugins/mail-notification/Makefile.am
index e70dca5..add62dd 100644
--- a/plugins/mail-notification/Makefile.am
+++ b/plugins/mail-notification/Makefile.am
@@ -21,9 +21,9 @@ liborg_gnome_mail_notification_la_CPPFLAGS =	\
 	$(LIBNOTIFY_CFLAGS)			\
 	$(CANBERRA_CFLAGS)
 
-liborg_gnome_mail_notification_la_SOURCES = mail-notification.c
+liborg_gnome_mail_notification_la_SOURCES = mail-notification.c speech.c
 
-liborg_gnome_mail_notification_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED)
+liborg_gnome_mail_notification_la_LDFLAGS = -lspeechd -module -avoid-version $(NO_UNDEFINED)
 
 liborg_gnome_mail_notification_la_LIBADD = 		\
 	$(DBUS_GLIB_LIBS)				\
diff --git a/plugins/mail-notification/apps-evolution-mail-notification.schemas.in b/plugins/mail-notification/apps-evolution-mail-notification.schemas.in
index ad7dd91..2216137 100644
--- a/plugins/mail-notification/apps-evolution-mail-notification.schemas.in
+++ b/plugins/mail-notification/apps-evolution-mail-notification.schemas.in
@@ -102,6 +102,67 @@
         <long>Play themed sound when new messages arrive, if not in beep mode.</long>
       </locale>
     </schema>	
+
+    <schema>
+      <key>/schemas/apps/evolution/eplugin/mail-notification/speech-enabled</key>
+      <applyto>/apps/evolution/eplugin/mail-notification/speech-enabled</applyto>
+      <owner>evolution-mail</owner>
+      <type>bool</type>
+      <default>true</default>
+      <locale name="C">
+        <short>Announce sender and subject.</short>
+        <long>Speak aloud the sender and subject of newly received mail.</long>
+      </locale>
+    </schema>
+    <schema>
+      <key>/schemas/apps/evolution/eplugin/mail-notification/speech-say-sender</key>
+      <applyto>/apps/evolution/eplugin/mail-notification/speech-say-sender</applyto>
+      <owner>evolution-mail</owner>
+      <type>bool</type>
+      <default>true</default>
+      <gettext_domain>evolution-2.30</gettext_domain>
+      <locale name="C">
+        <short>Say sender's name.</short>
+        <long>Say the name of the sender when announcing new messages.</long>
+      </locale>
+    </schema>
+    <schema>
+      <key>/schemas/apps/evolution/eplugin/mail-notification/speech-say-subject</key>
+      <applyto>/apps/evolution/eplugin/mail-notification/speech-say-subject</applyto>
+      <owner>evolution-mail</owner>
+      <type>bool</type>
+      <default>true</default>
+      <gettext_domain>evolution-2.30</gettext_domain>
+      <locale name="C">
+        <short>Say subject.</short>
+        <long>Say the subject of the e-mailwhen announcing new messages.</long>
+      </locale>
+    </schema>
+    <schema>
+      <key>/schemas/apps/evolution/eplugin/mail-notification/speech-voice</key>
+      <applyto>/apps/evolution/eplugin/mail-notification/speech-voice</applyto>
+      <owner>evolution-mail</owner>
+      <type>string</type>
+      <default>default</default>
+      <gettext_domain>evolution-2.30</gettext_domain>
+      <locale name="C">
+        <short>Set voice.</short>
+        <long>Set which voice to announce new messages in.</long>
+      </locale>
+    </schema>
+    <schema>
+      <key>/schemas/apps/evolution/eplugin/mail-notification/speech-voice-idx</key>
+      <applyto>/apps/evolution/eplugin/mail-notification/speech-voice-idx</applyto>
+      <owner>evolution-mail</owner>
+      <type>int</type>
+      <default>0</default>
+      <gettext_domain>evolution-2.30</gettext_domain>
+      <locale name="C">
+        <short>Remembers index for combo box.</short>
+        <long>Does not directly affect voice selection, just simplifies voice combo box's memory.</long>
+      </locale>
+    </schema>
+
   </schemalist>
 </gconfschemafile>
 
diff --git a/plugins/mail-notification/mail-notification.c b/plugins/mail-notification/mail-notification.c
index 2b0d768..5a683bf 100644
--- a/plugins/mail-notification/mail-notification.c
+++ b/plugins/mail-notification/mail-notification.c
@@ -1,3 +1,4 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -47,11 +48,14 @@
 #include <mail/em-folder-tree.h>
 #include <shell/e-shell-view.h>
 
+#include "speech.h"
+
 #ifdef HAVE_LIBNOTIFY
 #include <libnotify/notify.h>
 #endif
 
-#define GCONF_KEY_ROOT			"/apps/evolution/eplugin/mail-notification/"
+#define GCONF_KEY_ROOTDIR		"/apps/evolution/eplugin/mail-notification"
+#define GCONF_KEY_ROOT			GCONF_KEY_ROOTDIR "/"
 #define GCONF_KEY_NOTIFY_ONLY_INBOX	GCONF_KEY_ROOT "notify-only-inbox"
 #define GCONF_KEY_ENABLED_DBUS		GCONF_KEY_ROOT "dbus-enabled"
 #define GCONF_KEY_ENABLED_STATUS	GCONF_KEY_ROOT "status-enabled"
@@ -113,7 +117,6 @@ is_part_enabled (const gchar *gconf_key)
 #define DBUS_INTERFACE		"org.gnome.evolution.mail.dbus.Signal"
 
 static DBusConnection *bus = NULL;
-
 static gboolean init_dbus (void);
 
 static void
@@ -661,40 +664,44 @@ get_config_widget_status (void)
 #define GCONF_KEY_SOUND_FILE		GCONF_KEY_ROOT "sound-file"
 #define GCONF_KEY_SOUND_PLAY_FILE	GCONF_KEY_ROOT "sound-play-file"
 #define GCONF_KEY_SOUND_USE_THEME       GCONF_KEY_ROOT "sound-use-theme"
+#define GCONF_KEY_SOUND_SPEECH          GCONF_KEY_ROOT "sound-speech"
 
 #ifdef HAVE_CANBERRA
 static ca_context *mailnotification = NULL;
 #endif
 
 static void
-do_play_sound (gboolean beep, gboolean use_theme, const gchar *file)
+do_play_sound ()
 {
-	if (!beep) {
+	gchar *file;
+	GConfClient *client;
+
+	if (is_part_enabled (GCONF_KEY_SOUND_BEEP))
+		gdk_beep ();
 #ifdef HAVE_CANBERRA
-		if (!use_theme && file && *file)
-			ca_context_play(mailnotification, 0,
-			CA_PROP_MEDIA_FILENAME, file,
-			NULL);
-		else
-			ca_context_play(mailnotification, 0,
-			CA_PROP_EVENT_ID,"message-new-email",
-			NULL);
+	if (is_part_enabled (GCONF_KEY_SOUND_USE_THEME)) {
+		ca_context_play(mailnotification, 0,
+				CA_PROP_EVENT_ID,"message-new-email",
+				NULL);
+	}
+	if (is_part_enabled (GCONF_KEY_SOUND_PLAY_FILE)) {
+		client = gconf_client_get_default ();
+		file = gconf_client_get_string (client, GCONF_KEY_SOUND_FILE, NULL);
+
+		ca_context_play(mailnotification, 0,
+				CA_PROP_MEDIA_FILENAME, file,
+				NULL);
+
+		g_object_unref (client);
+		g_free (file);
+	}
 #endif
+	if (is_part_enabled (GCONF_KEY_SOUND_SPEECH)) {
+		/* TODO: put the call to the speech API in here */
+		/* except I cannot, since it requires the context from elsewhere */
 	}
-	else
-		gdk_beep();
 }
 
-struct _SoundConfigureWidgets
-{
-	GtkWidget *enable;
-	GtkWidget *beep;
-	GtkWidget *use_theme;
-	GtkWidget *file;
-	GtkWidget *filechooser;
-	GtkWidget *play;
-};
-
 static void
 sound_file_set_cb (GtkWidget *widget, gpointer data)
 {
@@ -712,22 +719,11 @@ sound_file_set_cb (GtkWidget *widget, gpointer data)
 	g_free (file);
 }
 
+/* like sound_notify_idle_cb, but used by sound file preview button */
 static void
 sound_play_cb (GtkWidget *widget, gpointer data)
 {
-	struct _SoundConfigureWidgets *scw = (struct _SoundConfigureWidgets *) data;
-	gchar *file;
-
-	g_return_if_fail (data != NULL);
-
-	if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (scw->enable)))
-		return;
-
-	file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (scw->filechooser));
-	do_play_sound (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (scw->beep)),
-		       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (scw->use_theme)),
-		       file);
-	g_free (file);
+	do_play_sound ();
 }
 
 struct _SoundNotifyData {
@@ -735,24 +731,15 @@ struct _SoundNotifyData {
 	guint notify_idle_id;
 };
 
+/* like sound_play_cb, but used for real mail and not the preview button */
 static gboolean
 sound_notify_idle_cb (gpointer user_data)
 {
-	gchar *file;
-	GConfClient *client;
 	struct _SoundNotifyData *data = (struct _SoundNotifyData *) user_data;
 
 	g_return_val_if_fail (data != NULL, FALSE);
 
-	client = gconf_client_get_default ();
-	file = gconf_client_get_string (client, GCONF_KEY_SOUND_FILE, NULL);
-
-	do_play_sound (is_part_enabled (GCONF_KEY_SOUND_BEEP),
-		       is_part_enabled (GCONF_KEY_SOUND_USE_THEME),
-		       file);
-
-	g_object_unref (client);
-	g_free (file);
+	do_play_sound ();
 
 	time (&data->last_notify);
 
@@ -761,6 +748,53 @@ sound_notify_idle_cb (gpointer user_data)
 	return FALSE;
 }
 
+static void
+remove_sound_ui (GtkWidget *ui, gpointer alignment)
+{
+	gtk_container_remove (GTK_CONTAINER (alignment), ui);
+}
+
+static void
+sound_changed_cb (GtkComboBox *sound_combo, GtkContainer *sound_alignment)
+{
+	GConfClient *client;
+	GError *error = NULL;
+
+	gchar *sound_option;
+	GtkWidget *sound_ui;
+	gchar *key;
+
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	client = gconf_client_get_default ();
+	model = gtk_combo_box_get_model (sound_combo);
+	gtk_combo_box_get_active_iter (sound_combo, &iter);
+	gtk_tree_model_get (model, &iter, 0, &sound_option, 1, &sound_ui, 2, &key, -1);
+
+	/* disable other sounds */
+	/* TODO: should we handle these errors?  If so, how?  Create a generic function
+	 what we'll pass each key to, that will pop up a warning dialogue to the user?  */
+	gconf_client_set_bool (client, GCONF_KEY_SOUND_BEEP, FALSE, &error);
+	gconf_client_set_bool (client, GCONF_KEY_SOUND_PLAY_FILE, FALSE, &error);
+	gconf_client_set_bool (client, GCONF_KEY_SOUND_SPEECH, FALSE, &error);
+	gconf_client_set_bool (client, GCONF_KEY_SOUND_USE_THEME, FALSE, &error);
+
+	/* enable selected sound */
+	gconf_client_set_bool (client, key, TRUE, &error);
+
+	/* replace sound options UI */
+	gtk_container_foreach (sound_alignment, remove_sound_ui, sound_alignment);
+	if (sound_ui != NULL) {
+		gtk_container_add (sound_alignment, sound_ui);
+		gtk_widget_show_all (sound_ui);
+	}
+
+	g_object_unref (client);
+	g_free (sound_option);
+	g_free (key);
+}
+
 /* -------------------------------------------------------------------  */
 
 static void
@@ -774,6 +808,15 @@ new_notify_sound (EMEventTargetFolder *t)
 	/* just put it to the idle queue */
 	if (data.notify_idle_id == 0 && (last_newmail - data.last_notify >= NOTIFY_THROTTLE))
 		data.notify_idle_id = g_idle_add_full (G_PRIORITY_LOW, sound_notify_idle_cb, &data, NULL);
+
+	/* TODO: Kind of want to move this into do_play_sound()
+	   to be called by sound_notify_idle_cb() instead,
+	   but we need 't'.
+	   For that, should we add a g_object_ref (EMEventTargetFolder)
+	   to _SoundNotifyData, so sound_notify_idle_cb can pass
+	   it as a new parametre to do_play_sound() */
+	if (is_part_enabled (GCONF_KEY_SOUND_SPEECH))
+		speech_new_notify (t);
 }
 
 static void
@@ -804,131 +847,138 @@ get_config_widget_sound (void)
 {
 	GtkWidget *vbox;
 	GtkWidget *container;
-	GtkWidget *master;
 	GtkWidget *widget;
 	gchar *file;
 	GConfBridge *bridge;
 	GConfClient *client;
-	GSList *group = NULL;
-	struct _SoundConfigureWidgets *scw;
 	const gchar *text;
 
-	bridge = gconf_bridge_get ();
+	GtkWidget *sound_enable_combo_box;
+	GtkWidget *sound_enable_button;
+	GtkListStore *sound_store;
+	GtkWidget *sound_combo;
+	GtkCellRenderer *cell;
+	GtkTreeIter iter;
+	GtkWidget *sound_alignment;
+
+	GtkWidget *sound_file_box;
+	GtkWidget *sound_speech_box;
 
-	scw = g_malloc0 (sizeof (struct _SoundConfigureWidgets));
+	bridge = gconf_bridge_get ();
 
 	vbox = gtk_vbox_new (FALSE, 6);
 	gtk_widget_show (vbox);
-
 	container = vbox;
 
-	text = _("_Play sound when new messages arrive");
-	widget = gtk_check_button_new_with_mnemonic (text);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
-
-	gconf_bridge_bind_property (
-		bridge, GCONF_KEY_ENABLED_SOUND,
-		G_OBJECT (widget), "active");
-
-	master = widget;
-	scw->enable = widget;
-
-	widget = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
-	gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 12, 0);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
-
-	e_binding_new (
-		master, "active",
-		widget, "sensitive");
-
-	container = widget;
-
-	widget = gtk_vbox_new (FALSE, 6);
-	gtk_container_add (GTK_CONTAINER (container), widget);
-	gtk_widget_show (widget);
-
-	container = widget;
+	sound_enable_combo_box = gtk_hbox_new (FALSE, 6);
+	gtk_widget_show (sound_enable_combo_box);
+	gtk_box_pack_start (GTK_BOX (container), sound_enable_combo_box, FALSE, FALSE, 0);
 
-	text = _("_Beep");
-	widget = gtk_radio_button_new_with_mnemonic (group, text);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
+	/* Master Sound Flag */
+	sound_enable_button = gtk_check_button_new ();
+	gtk_widget_show (sound_enable_button);
+	gtk_box_pack_start (GTK_BOX (sound_enable_combo_box), sound_enable_button, FALSE, FALSE, 0);
 
 	gconf_bridge_bind_property (
-		bridge, GCONF_KEY_SOUND_BEEP,
-		G_OBJECT (widget), "active");
-
-	scw->beep = widget;
-
-	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
-
-	text = _("Use sound _theme");
-	widget = gtk_radio_button_new_with_mnemonic (group, text);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
+		bridge, GCONF_KEY_ENABLED_SOUND,
+		G_OBJECT (sound_enable_button), "active");
 
-	gconf_bridge_bind_property (
-		bridge, GCONF_KEY_SOUND_USE_THEME,
-		G_OBJECT (widget), "active");
+	/* Sound Combo Box */
+	sound_store = gtk_list_store_new (3,
+					  G_TYPE_STRING, /* text */
+					  G_TYPE_OBJECT, /* ui */
+					  G_TYPE_STRING); /* gconf key */
+	sound_combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (sound_store));
+	cell = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (sound_combo), cell, FALSE);
+	gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (sound_combo), GTK_CELL_RENDERER (cell), "text", 0);
+	gtk_box_pack_start (GTK_BOX (sound_enable_combo_box), sound_combo, FALSE, FALSE, 0);
 
-	scw->use_theme = widget;
+	/* Sound Option UI */
+	sound_alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+	gtk_alignment_set_padding (GTK_ALIGNMENT (sound_alignment), 0, 0, 12, 0);
 
-	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+	g_signal_connect (G_OBJECT (sound_combo), "changed", G_CALLBACK (sound_changed_cb), sound_alignment);
 
-	widget = gtk_hbox_new (FALSE, 6);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
+	gtk_box_pack_start (GTK_BOX (container), GTK_WIDGET (sound_alignment), FALSE, FALSE, 0);
 
-	container = widget;
+	gtk_widget_show_all (container);
 
-	text = _("Play _file:");
-	widget = gtk_radio_button_new_with_mnemonic (group, text);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
+	gconf_bridge_bind_property (bridge, GCONF_KEY_ENABLED_SOUND, G_OBJECT (sound_alignment), "sensitive");
+	gconf_bridge_bind_property (bridge, GCONF_KEY_ENABLED_SOUND, G_OBJECT (sound_combo), "sensitive");
 
-	gconf_bridge_bind_property (
-		bridge, GCONF_KEY_SOUND_PLAY_FILE,
-		G_OBJECT (widget), "active");
+	/* Beep */
+	gtk_list_store_append (sound_store, &iter);
+	gtk_list_store_set (sound_store, &iter,
+			    0, _("Play a beep"),
+			    1, NULL,
+			    2, GCONF_KEY_SOUND_BEEP,
+			    -1);
+	if (is_part_enabled (GCONF_KEY_SOUND_BEEP)) 
+		gtk_combo_box_set_active_iter (GTK_COMBO_BOX (sound_combo), &iter);
 
-	scw->file = widget;
+	/* Sound File */
+	sound_file_box = gtk_hbox_new (FALSE, 6);
 
 	text = _("Select sound file");
 	widget = gtk_file_chooser_button_new (
 		text, GTK_FILE_CHOOSER_ACTION_OPEN);
-	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	gtk_box_pack_start (GTK_BOX (sound_file_box), widget, TRUE, TRUE, 0);
 	gtk_widget_show (widget);
 
-	scw->filechooser = widget;
-
-	widget = gtk_button_new ();
-	gtk_button_set_image (
-		GTK_BUTTON (widget), gtk_image_new_from_icon_name (
-		"media-playback-start", GTK_ICON_SIZE_BUTTON));
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	gtk_widget_show (widget);
-
-	scw->play = widget;
-
 	client = gconf_client_get_default ();
 	file = gconf_client_get_string (client, GCONF_KEY_SOUND_FILE, NULL);
-
 	if (file && *file)
-		gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (scw->filechooser), file);
-
+		gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), file);
 	g_object_unref (client);
 	g_free (file);
 
 	g_signal_connect (
-		scw->filechooser, "file-set",
-		G_CALLBACK (sound_file_set_cb), scw);
-	g_signal_connect (
-		scw->play, "clicked",
-		G_CALLBACK (sound_play_cb), scw);
+		widget, "file-set",
+		G_CALLBACK (sound_file_set_cb), NULL);
 
-	/* to let structure free properly */
-	g_object_set_data_full (G_OBJECT (vbox), "scw-data", scw, g_free);
+	/* sound file preview button */
+	widget = gtk_button_new ();
+	gtk_button_set_image (
+		GTK_BUTTON (widget), gtk_image_new_from_icon_name (
+		"media-playback-start", GTK_ICON_SIZE_BUTTON));
+	gtk_box_pack_start (GTK_BOX (sound_file_box), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	g_signal_connect (
+		widget /* play button */, "clicked",
+		G_CALLBACK (sound_play_cb), NULL);
+
+	gtk_list_store_append (sound_store, &iter);
+	gtk_list_store_set (sound_store, &iter,
+			    0, _("Play a sound file"),
+			    1, sound_file_box,
+			    2, GCONF_KEY_SOUND_PLAY_FILE,
+			    -1);
+	if (is_part_enabled (GCONF_KEY_SOUND_PLAY_FILE))
+		gtk_combo_box_set_active_iter (GTK_COMBO_BOX (sound_combo), &iter);
+
+	/* Announcement */
+	sound_speech_box = speech_get_config_widget ();
+
+	gtk_list_store_append (sound_store, &iter);
+	gtk_list_store_set (sound_store, &iter,
+			    0, _("Play an announcement"),
+			    1, sound_speech_box,
+			    2, GCONF_KEY_SOUND_SPEECH,
+			    -1);
+	if (is_part_enabled (GCONF_KEY_SOUND_SPEECH))
+		gtk_combo_box_set_active_iter (GTK_COMBO_BOX (sound_combo), &iter);
+
+	/* Sound Theme */
+	gtk_list_store_append (sound_store, &iter);
+	gtk_list_store_set (sound_store, &iter,
+			    0, _("Use sound theme"),
+			    1, NULL,
+			    2, GCONF_KEY_SOUND_USE_THEME,
+			    -1);
+	if (is_part_enabled (GCONF_KEY_SOUND_USE_THEME))
+		gtk_combo_box_set_active_iter (GTK_COMBO_BOX (sound_combo), &iter);
 
 	return vbox;
 }
@@ -976,6 +1026,9 @@ get_cfg_widget (void)
 	widget = get_config_widget_sound ();
 	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
 
+	widget = speech_get_config_widget ();
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+
 	return container;
 }
 
@@ -1032,6 +1085,8 @@ org_gnome_mail_read_notify (EPlugin *ep, EMEventTargetMessage *t)
 gint
 e_plugin_lib_enable (EPlugin *ep, gint enable)
 {
+	GConfClient *client;
+
 	if (enable) {
 		if (is_part_enabled (GCONF_KEY_ENABLED_DBUS))
 			enable_dbus (enable);
@@ -1039,6 +1094,11 @@ e_plugin_lib_enable (EPlugin *ep, gint enable)
 		if (is_part_enabled (GCONF_KEY_ENABLED_SOUND))
 			enable_sound (enable);
 
+		/* add our directory so key/values are cached */
+		client = gconf_client_get_default ();
+		gconf_client_add_dir (client, GCONF_KEY_ROOTDIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL /* TODO GError */);
+		g_object_unref (client);
+
 		enabled = TRUE;
 	} else {
 		enable_dbus (enable);
@@ -1047,6 +1107,8 @@ e_plugin_lib_enable (EPlugin *ep, gint enable)
 		enabled = FALSE;
 	}
 
+	speech_enable (enable);
+
 	return 0;
 }
 
diff --git a/plugins/mail-notification/org-gnome-mail-notification.eplug.xml b/plugins/mail-notification/org-gnome-mail-notification.eplug.xml
index 8cc4fd6..8a2e661 100644
--- a/plugins/mail-notification/org-gnome-mail-notification.eplug.xml
+++ b/plugins/mail-notification/org-gnome-mail-notification.eplug.xml
@@ -8,6 +8,7 @@
 		<_description>Notifies you when new mail messages arrive.</_description>
 		<author name="Miguel Angel López Hernández" email="miguel@gulev.org.mx"/>
 		<author name="Srinivasa Ragavan" email="sragavan@novell.com"/>
+		<author name="Richard Schwarting" email="aquarichy@gmail.com"/>
 
 		<hook class="org.gnome.evolution.mail.events:1.0">
 			<event id="folder.changed"
diff --git a/plugins/mail-notification/speech.c b/plugins/mail-notification/speech.c
new file mode 100644
index 0000000..ee22b1e
--- /dev/null
+++ b/plugins/mail-notification/speech.c
@@ -0,0 +1,280 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ *		Richard Schwarting <aquarichy@gmail.com>
+ *
+ * Copyright (C) 2010 Richard Schwarting
+ */
+
+#include <glib.h>
+#include <mail/em-event.h>
+#include <e-util/e-plugin.h>
+#include <libspeechd.h>
+#include <glib/gi18n.h>
+#include <e-util/gconf-bridge.h>
+#include "speech.h"
+
+#define GCONF_KEY_ROOT           "/apps/evolution/eplugin/mail-notification/speech-"
+#define GCONF_KEY_VOICE          GCONF_KEY_ROOT "voice"
+#define GCONF_KEY_VOICE_IDX      GCONF_KEY_ROOT "voice-idx"
+#define GCONF_KEY_SENDER         GCONF_KEY_ROOT "say-sender"
+#define GCONF_KEY_SUBJECT        GCONF_KEY_ROOT "say-subject"
+
+/* TODO: the 5 other plugins I looked at didn't attach
+         their data to the EPlugin; why? */
+static SPDConnection *spd_connection = NULL;
+
+void org_gnome_evo_aqua_new_notify (EPlugin *ep, EMEventTargetFolder *t);
+GtkWidget *e_plugin_lib_get_configure_widget (EPlugin *ep);
+
+static void
+transform_voice (GtkCellLayout *combo, GtkCellRenderer *cell, GtkTreeModel *model,
+		 GtkTreeIter *iter, gpointer data) {
+	gchar *lang = NULL;
+	gchar *voice = NULL;
+	gchar *variant = NULL;
+	gchar *string;
+	GValue val = {0};
+
+	gtk_tree_model_get (model, iter, 0, &lang, 1, &voice, 2, &variant, -1);
+
+	if (g_strcmp0 (variant, "none") != 0)
+		string = g_strdup_printf ("%s - %s (%s)", lang, voice, variant);
+	else
+		string = g_strdup_printf ("%s - %s", lang, voice);
+	g_free (lang);
+	g_free (voice);
+	g_free (variant);
+
+	g_value_init (&val, G_TYPE_STRING);
+	g_value_set_string (&val, string);
+	g_free (string);
+
+	g_object_set_property (G_OBJECT (cell), "text", &val);
+}
+
+static void
+speech_notify (gchar *msg_sender, gchar *msg_subject, guint new) {
+	GConfClient *client;
+	gboolean say_sender;
+	gboolean say_subject;
+	gchar *voice = NULL;
+	gchar *sender = NULL;
+	GError *error = NULL;
+	int len;
+	int i;
+
+	client = gconf_client_get_default ();
+
+	/* check config for saying sender's name */
+	say_sender = gconf_client_get_bool (client, GCONF_KEY_SENDER, &error);
+	if (error) {
+		g_warning ("mail-notification: Error retrieving GConf value for say_sender: %s", error->message);
+		g_clear_error (&error);
+		say_sender = TRUE;
+	}
+
+	/* check config for saying subject */
+	say_subject = gconf_client_get_bool (client, GCONF_KEY_SUBJECT, &error);
+	if (error) {
+		g_warning ("mail-notification: Error retrieving GConf value for say_subject: %s", error->message);
+		g_clear_error (&error);
+		say_subject = TRUE;
+	}
+
+	/* check config for voice to use */
+	voice = gconf_client_get_string (client, GCONF_KEY_VOICE, &error);
+	if (error) {
+		g_warning ("mail-notification: Error retrieving GConf value for voice: %s", error->message);
+		g_clear_error (&error);
+
+		if (voice != NULL)
+			g_free (voice);
+		voice = g_strdup ("default");
+	}
+
+	if (spd_connection != NULL) {
+		spd_set_synthesis_voice (spd_connection, voice);
+
+		if ((say_sender || say_subject) && (msg_sender != NULL && msg_subject != NULL)) {
+			/* strip the e-mail address and only keep the sender if there's a sender name of any notable length */
+			if (say_sender) {
+				len = strlen (msg_sender);
+				for (i = 0; i < len; i++) {
+					if (msg_sender[i] == '<')
+						break;
+				}
+				if (i == len || i <= 2) {
+					sender = g_strdup (msg_sender);
+				} else {
+					sender = g_strndup (msg_sender, i);
+				}
+			}
+
+			if (say_sender && say_subject) {
+				/* Translator example: "New mail from: Mary Poppins.  Titled: Subject of importance" */
+				spd_sayf (spd_connection, SPD_MESSAGE, _("New mail from: %s. Titled: %s"),
+					  sender, msg_subject);
+			} else if (say_sender) {
+				spd_sayf (spd_connection, SPD_MESSAGE, _("New mail from: %s."),
+					  sender);
+			} else if (say_subject) {
+				spd_sayf (spd_connection, SPD_MESSAGE, _("New mail titled: %s"),
+					  msg_subject);
+			}
+
+			if (sender != NULL) {
+				g_free (sender);
+			}
+		} else if (new == 1) {
+			spd_say (spd_connection, SPD_MESSAGE, _("You have a new message"));
+		} else {
+			/* Translator example: "You have 4 new e-mails.", where the number should be 2 or greater */
+			spd_sayf (spd_connection, SPD_MESSAGE, _("You have %u new e-mails."), new);
+		}
+	}
+
+	g_free (voice);
+}
+
+void
+speech_new_notify (EMEventTargetFolder *t)
+{
+	speech_notify (t->msg_sender, t->msg_subject, t->new);
+}
+
+gint
+speech_enable (gint enable)
+{
+	if (enable == 1) {
+		spd_connection = spd_open ("Evolution", "main", NULL, SPD_MODE_THREADED);
+		if (spd_connection == NULL) {
+			g_warning ("Mail Notification: Could not connect to Speech Dispatcher daemon.  Disabling plugin.");
+		}
+	} else if (spd_connection != NULL) {
+		spd_close (spd_connection);
+		spd_connection = NULL;
+	}
+
+	return 0;
+}
+
+static void
+demo_clicked_cb (GtkButton *button, gpointer data) {
+	gchar *sender = g_strdup ("Tux the Penguin");
+	gchar *subject = g_strdup ("Welcome to Evolution.");
+	speech_notify (sender, subject, 1);
+	g_free (sender);
+	g_free (subject);
+}
+
+static void
+voice_changed_cb (GtkComboBox *voices_combo, gpointer data) {
+	GtkTreeIter iter;
+	gchar *voice;
+	GConfClient *client;
+	GtkTreeModel *model;
+	GError *error = NULL;
+
+	model = gtk_combo_box_get_model (voices_combo);
+	gtk_combo_box_get_active_iter (voices_combo, &iter);
+
+	gtk_tree_model_get (model, &iter, 1, &voice, -1);
+
+	client = gconf_client_get_default ();
+	gconf_client_set_string (client, GCONF_KEY_VOICE, voice, &error);
+	if (error != NULL) {
+		g_warning ("Evo Aqua: Failed to set voice to '%s'.  %s", voice, error->message);
+		g_clear_error (&error);
+	}
+
+	g_free (voice);
+}
+
+GtkWidget *
+speech_get_config_widget ()
+{
+	GConfBridge *bridge;
+	GtkWidget *container;
+	GtkWidget *inner_container;
+	GtkWidget *say_options;
+	GtkWidget *say_sender;
+	GtkWidget *say_subject;
+	GtkWidget *voices_combo;
+	GtkWidget *demo_button;
+
+	int i;
+	SPDVoice **synth_voices;
+	GtkListStore *voice_store;
+	GtkTreeIter iter;
+	GtkCellRenderer *cell;
+
+	bridge = gconf_bridge_get ();
+	container = gtk_vbox_new (FALSE, 12);
+
+	/* Do not display if Speech Dispatcher isn't there
+	   Might want to hand it from the combo box, actually
+	   Whichever way, we need to make sure we don't call
+	   spd_list_synthesis_voices without a connection, as it'll segfault */
+	g_return_val_if_fail (spd_connection != NULL, container);
+
+	inner_container = gtk_vbox_new (FALSE, 12);
+
+	say_options = gtk_hbox_new (TRUE, 12);
+
+	/* Say Sender option */
+	say_sender = gtk_check_button_new_with_mnemonic (_("Say s_ender."));
+	gtk_box_pack_start (GTK_BOX (say_options), say_sender, FALSE, FALSE, 0);
+	gconf_bridge_bind_property (bridge, GCONF_KEY_SENDER, G_OBJECT (say_sender), "active");
+
+	/* Say Subject option */
+	say_subject = gtk_check_button_new_with_mnemonic (_("Say s_ubject."));
+	gtk_box_pack_start (GTK_BOX (say_options), say_subject, FALSE, FALSE, 0);
+	gconf_bridge_bind_property (bridge, GCONF_KEY_SUBJECT, G_OBJECT (say_subject), "active");
+
+	/* TODO: make sure that the _ mnemonics are alright, not conflicting */
+
+	/* Demo button */
+	demo_button = gtk_button_new_with_mnemonic (_("_Try it!")); /* translators: a button for users to test voice announcements */
+	gtk_box_pack_start (GTK_BOX (say_options), demo_button, FALSE, FALSE, 0);
+	g_signal_connect (G_OBJECT (demo_button), "clicked", G_CALLBACK (demo_clicked_cb), NULL);
+
+	gtk_box_pack_start (GTK_BOX (inner_container), say_options, FALSE, FALSE, 0);
+
+	/* Voice selector */
+	synth_voices = spd_list_synthesis_voices (spd_connection);
+	voice_store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+	voices_combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (voice_store));
+	cell = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (voices_combo), cell, FALSE);
+	gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (voices_combo),
+					    cell, transform_voice, NULL, NULL);
+
+	for (i = 0; synth_voices != NULL && synth_voices[i] != NULL; i++) {
+		gtk_list_store_append (voice_store, &iter);
+		gtk_list_store_set (voice_store, &iter,
+				    0, synth_voices[i]->language,
+				    1, synth_voices[i]->name,
+				    2, synth_voices[i]->variant,
+				    -1);
+	}
+	gtk_box_pack_start (GTK_BOX (inner_container), voices_combo, FALSE, FALSE, 0);
+	g_signal_connect (G_OBJECT (voices_combo), "changed", G_CALLBACK (voice_changed_cb), NULL);
+	gconf_bridge_bind_property (bridge, GCONF_KEY_VOICE_IDX, G_OBJECT (voices_combo), "active");
+
+	return inner_container;
+}
diff --git a/plugins/mail-notification/speech.h b/plugins/mail-notification/speech.h
new file mode 100644
index 0000000..892a6bf
--- /dev/null
+++ b/plugins/mail-notification/speech.h
@@ -0,0 +1,8 @@
+#ifndef SPEECH_D
+#define SPEECH_D
+
+void speech_new_notify (EMEventTargetFolder *t);
+GtkWidget *speech_get_config_widget ();
+gint speech_enable (gint enable);
+
+#endif
