aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivasa Ragavan <sragavan@src.gnome.org>2007-04-03 17:06:19 +0800
committerSrinivasa Ragavan <sragavan@src.gnome.org>2007-04-03 17:06:19 +0800
commit161a51e4dfb33d6cb2b445d14930a059a8568590 (patch)
treeb2b4e87b8b81e4a3d2489c29365a8379f774a9f5
parentd67896196c85262bf7d6e35cf8474d44f034d0b9 (diff)
downloadgsoc2013-evolution-161a51e4dfb33d6cb2b445d14930a059a8568590.tar.gz
gsoc2013-evolution-161a51e4dfb33d6cb2b445d14930a059a8568590.tar.zst
gsoc2013-evolution-161a51e4dfb33d6cb2b445d14930a059a8568590.zip
Added bogofilter to Evolution.
svn path=/trunk/; revision=33364
-rw-r--r--plugins/bogo-junk-plugin/ChangeLog21
-rw-r--r--plugins/bogo-junk-plugin/Makefile.am2
-rw-r--r--plugins/bogo-junk-plugin/README35
-rw-r--r--plugins/bogo-junk-plugin/bf-junk-filter.c301
-rw-r--r--plugins/bogo-junk-plugin/bogo-junk-plugin.schemas.in.in18
-rw-r--r--plugins/bogo-junk-plugin/org-gnome-bogo-junk-plugin.eplug.in27
6 files changed, 404 insertions, 0 deletions
diff --git a/plugins/bogo-junk-plugin/ChangeLog b/plugins/bogo-junk-plugin/ChangeLog
new file mode 100644
index 0000000000..16f0edce05
--- /dev/null
+++ b/plugins/bogo-junk-plugin/ChangeLog
@@ -0,0 +1,21 @@
+2007-04-03 Srinivasa Ragavan <sragavan@novell.com>
+
+ ** Added bogofilter part of Evolution source.
+
+2006-02-19 Mikhail Zabaluev <mhz@altlinux.org>
+
+* configure.ac: Switched to evolution-plugin-2.6 for plugin configuration.
+Bumped version to 0.2.0.
+
+* org-altlinux-bf-junk-plugin.eplug.in: Templatized the plugin manifesto,
+with plugin install directory substituted.
+* configure.ac: Added org-altlinux-bf-junk-plugin.eplug to AC_CONFIG_FILES.
+* Makefile.am: Added org-altlinux-bf-junk-plugin.eplug.in to EXTRA_DIST.
+
+* README: Added bug reference to the initial ham training problem.
+
+2005-11-22 Mikhail Zabaluev <mhz@altlinux.org>
+
+* README: Added reference to Spam Trainer.
+
+* README: Reflect on the fix for bug #313096 that made it to Evolution 2.5.2.
diff --git a/plugins/bogo-junk-plugin/Makefile.am b/plugins/bogo-junk-plugin/Makefile.am
new file mode 100644
index 0000000000..8364a3a463
--- /dev/null
+++ b/plugins/bogo-junk-plugin/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = $(plugins_enabled)
+DIST_SUBDIRS = $(all_plugins_base) $(all_plugins_standard) $(all_plugins_experimental) profiler
diff --git a/plugins/bogo-junk-plugin/README b/plugins/bogo-junk-plugin/README
new file mode 100644
index 0000000000..a14bcf6dda
--- /dev/null
+++ b/plugins/bogo-junk-plugin/README
@@ -0,0 +1,35 @@
+Bogofilter plugin for Evolution
+
+This plugin implements junk filtering for the Evolution mailer,
+provided by the bogofilter utility. Bogofilter (http://www.bogofilter.org)
+if a fast and nimble mail filter using a so-called Bayesian technique to
+classify junk and non-junk email.
+
+CAVEATS:
+
+For Evolution versions before 2.5.2, the definition file for the stock
+junk filter plugin, 'org-gnome-sa-junk-plugin.eplug', must be removed
+from the plugin directory to avoid conflict with any alternate junk plugin.
+Simply disabling the SA plugin in the configuration won't help.
+This is due to a flaw in the loading code for this hook type
+(see GNOME bug #313096).
+
+To be able to classify emails as spam, bogofilter needs to have some
+messages in its ham (non-spam) wordlist. This presents something of a
+chicken-and-egg problem for Evolution, because it can feed messages
+to the junk filter for learning as non-junk only after these messages have been
+classified as junk and moved into a junk folder (GNOME bug #322105).
+Thus, if you haven't got a pre-existing bogofilter database, you may need
+to feed it some messages known to be non-junk, using its
+command line utility:
+
+bogofilter -n < saved-ham-message
+
+Alternatively, you may use Spam Trainer, which is a GUI tool that supports
+drag-and-drop from Evolution:
+
+http://spamtrainer.sourceforge.net/
+
+Set it up to use bogofilter commands for training:
+ Ham command: bogofilter -n < %f
+ Spam command: bogofilter -s < %f
diff --git a/plugins/bogo-junk-plugin/bf-junk-filter.c b/plugins/bogo-junk-plugin/bf-junk-filter.c
new file mode 100644
index 0000000000..0369ec5500
--- /dev/null
+++ b/plugins/bogo-junk-plugin/bf-junk-filter.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2005 Mikhail Zabaluev <mhz@altlinux.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#define G_LOG_DOMAIN "bf-junk-filter"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <e-util/e-plugin.h>
+#include "mail/em-config.h"
+#include <mail/em-junk-hook.h>
+#include <camel/camel-data-wrapper.h>
+#include <camel/camel-stream-fs.h>
+#include <camel/camel-debug.h>
+#include <gconf/gconf-client.h>
+
+
+#ifndef BOGOFILTER_BINARY
+#define BOGOFILTER_BINARY "/usr/bin/bogofilter"
+#endif
+
+#define BOGOFILTER_ERROR 3
+
+#define EM_JUNK_BF_GCONF_DIR "/apps/evolution/mail/junk/bogofilter"
+
+
+#define d(x) (camel_debug("junk")?(x):0)
+
+
+static gchar em_junk_bf_binary[] = BOGOFILTER_BINARY;
+
+static const gchar em_junk_bf_gconf_dir[] = EM_JUNK_BF_GCONF_DIR;
+GtkWidget * org_gnome_bogo_convert_unicode (struct _EPlugin *epl, struct _EConfigHookItemFactoryData *data);
+
+#define EM_JUNK_BF_GCONF_DIR_LENGTH (G_N_ELEMENTS (em_junk_bf_gconf_dir) - 1)
+
+
+static gboolean em_junk_bf_unicode = TRUE;
+
+
+static gint
+pipe_to_bogofilter (CamelMimeMessage *msg, gchar **argv)
+{
+ GPid child_pid;
+ gint bf_in;
+ CamelStream *stream;
+ GError *err = NULL;
+ gint status;
+ gint waitres;
+
+ if (camel_debug_start ("junk")) {
+ int i;
+
+ printf ("pipe_to_bogofilter ");
+ for (i = 0; argv[i]; i++)
+ printf ("%s ", argv[i]);
+ printf ("\n");
+ camel_debug_end ();
+ }
+
+ if (!g_spawn_async_with_pipes (NULL,
+ argv,
+ NULL,
+ G_SPAWN_DO_NOT_REAP_CHILD |
+ G_SPAWN_STDOUT_TO_DEV_NULL,
+ NULL,
+ NULL,
+ &child_pid,
+ &bf_in,
+ NULL,
+ NULL,
+ &err))
+ {
+ g_warning ("error occurred while spawning %s: %s",
+ argv[0],
+ err->message);
+ return BOGOFILTER_ERROR;
+ }
+
+ stream = camel_stream_fs_new_with_fd (bf_in);
+ camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (msg), stream);
+ camel_stream_flush (stream);
+ camel_stream_close (stream);
+ camel_object_unref (stream);
+
+ waitres = waitpid (child_pid, &status, 0);
+ if (waitres < 0 && errno == EINTR) {
+ /* child process is hanging... */
+ g_warning ("wait for bogofilter child process interrupted, terminating");
+ kill (child_pid, SIGTERM);
+ sleep (1);
+ waitres = waitpid (child_pid, &status, WNOHANG);
+ if (waitres == 0) {
+ /* ...still hanging, set phasers to KILL */
+ g_warning ("bogofilter child process does not respond, killing");
+ kill (child_pid, SIGKILL);
+ sleep (1);
+ waitres = waitpid (child_pid, &status, WNOHANG);
+ }
+ }
+
+ g_spawn_close_pid (child_pid);
+
+ if (waitres >= 0 && WIFEXITED (status)) {
+ return WEXITSTATUS (status);
+ } else {
+ return BOGOFILTER_ERROR;
+ }
+}
+
+static void
+em_junk_bf_setting_notify (GConfClient *gconf,
+ guint cnxn_id,
+ GConfEntry *entry,
+ void *data)
+{
+ const char *key;
+ GConfValue *value;
+
+ value = gconf_entry_get_value (entry);
+ if (value == NULL) {
+ return;
+ }
+
+ key = gconf_entry_get_key (entry);
+ g_return_if_fail (key != NULL);
+
+ g_return_if_fail (!strncmp (key, em_junk_bf_gconf_dir, EM_JUNK_BF_GCONF_DIR_LENGTH));
+ key += EM_JUNK_BF_GCONF_DIR_LENGTH;
+
+ g_return_if_fail (*key == '/');
+ ++key;
+
+ if (strcmp (key, "unicode") == 0) {
+ em_junk_bf_unicode = gconf_value_get_bool (value);
+ }
+}
+
+gboolean
+em_junk_bf_check_junk (EPlugin *ep, EMJunkHookTarget *target)
+{
+ CamelMimeMessage *msg = target->m;
+ int rv;
+
+ gchar *argv[] = {
+ em_junk_bf_binary,
+ NULL,
+ NULL
+ };
+
+ d(fprintf (stderr, "em_junk_bf_check_junk\n"));
+
+ if (em_junk_bf_unicode) {
+ argv[1] = "--unicode=yes";
+ }
+
+ rv = pipe_to_bogofilter (msg, argv);
+
+ d(fprintf (stderr, "em_junk_bf_check_junk rv = %d\n", rv));
+
+ return (rv == 0);
+}
+
+void
+em_junk_bf_report_junk (EPlugin *ep, EMJunkHookTarget *target)
+{
+ CamelMimeMessage *msg = target->m;
+
+ gchar *argv[] = {
+ em_junk_bf_binary,
+ "-s",
+ NULL,
+ NULL
+ };
+
+ d(fprintf (stderr, "em_junk_bf_report_junk\n"));
+
+ if (em_junk_bf_unicode) {
+ argv[2] = "--unicode=yes";
+ }
+
+ pipe_to_bogofilter (msg, argv);
+}
+
+void
+em_junk_bf_report_non_junk (EPlugin *ep, EMJunkHookTarget *target)
+{
+ CamelMimeMessage *msg = target->m;
+
+ gchar *argv[] = {
+ em_junk_bf_binary,
+ "-n",
+ NULL,
+ NULL
+ };
+
+ d(fprintf (stderr, "em_junk_bf_report_non_junk\n"));
+
+ if (em_junk_bf_unicode) {
+ argv[2] = "--unicode=yes";
+ }
+
+ pipe_to_bogofilter (msg, argv);
+}
+
+void
+em_junk_bf_commit_reports (EPlugin *ep, EMJunkHookTarget *target)
+{
+}
+
+gboolean
+em_junk_bf_validate_binary (EPlugin *ep, EMJunkHookTarget *target)
+{
+
+ return g_file_test (em_junk_bf_binary, G_FILE_TEST_EXISTS);
+
+}
+
+int
+e_plugin_lib_enable (EPluginLib *ep, int enable)
+{
+ GConfClient *gconf;
+
+ if (enable != 1) {
+ return 0;
+ }
+
+ gconf = gconf_client_get_default();
+
+ gconf_client_add_dir (gconf,
+ em_junk_bf_gconf_dir,
+ GCONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+
+ gconf_client_notify_add (gconf,
+ em_junk_bf_gconf_dir,
+ em_junk_bf_setting_notify,
+ NULL, NULL, NULL);
+
+ em_junk_bf_unicode = gconf_client_get_bool (gconf,
+ EM_JUNK_BF_GCONF_DIR "/unicode", NULL);
+
+ g_object_unref (gconf);
+
+ return 0;
+}
+
+static void
+convert_unicode_cb (GtkWidget *widget, gpointer data)
+{
+
+ gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+ GConfClient *gconf = gconf_client_get_default();
+
+ gconf_client_set_bool (gconf, data, active, NULL);
+}
+
+GtkWidget *
+org_gnome_bogo_convert_unicode (struct _EPlugin *epl, struct _EConfigHookItemFactoryData *data)
+{
+ GtkWidget *check;
+ guint i = ((GtkTable *)data->parent)->nrows;
+
+ if (data->old)
+ return data->old;
+
+ check = gtk_check_button_new_with_mnemonic (_("Convert mail text to _Unicode"));
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), em_junk_bf_unicode);
+ g_signal_connect (GTK_TOGGLE_BUTTON (check), "toggled", G_CALLBACK (convert_unicode_cb), "/apps/evolution/mail/junk/bogofilter/unicode");
+ gtk_table_attach((GtkTable *)data->parent, check, 0, 1, i, i+1, 0, 0, 0, 0);
+ gtk_widget_show (check);
+ return (GtkWidget *)check;
+}
+
+
diff --git a/plugins/bogo-junk-plugin/bogo-junk-plugin.schemas.in.in b/plugins/bogo-junk-plugin/bogo-junk-plugin.schemas.in.in
new file mode 100644
index 0000000000..ad4c67c07a
--- /dev/null
+++ b/plugins/bogo-junk-plugin/bogo-junk-plugin.schemas.in.in
@@ -0,0 +1,18 @@
+<gconfschemafile>
+ <schemalist>
+ <schema>
+ <key>/schemas/apps/evolution/mail/junk/bogofilter/unicode</key>
+ <applyto>/apps/evolution/mail/junk/bogofilter/unicode</applyto>
+ <owner>bf-eplugin</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Convert mail text to Unicode</short>
+ <long>
+ Convert message text to Unicode UTF-8 to unify spam/ham tokens
+ coming from different character sets.
+ </long>
+ </locale>
+ </schema>
+ </schemalist>
+</gconfschemafile>
diff --git a/plugins/bogo-junk-plugin/org-gnome-bogo-junk-plugin.eplug.in b/plugins/bogo-junk-plugin/org-gnome-bogo-junk-plugin.eplug.in
new file mode 100644
index 0000000000..3ce26cc0b7
--- /dev/null
+++ b/plugins/bogo-junk-plugin/org-gnome-bogo-junk-plugin.eplug.in
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<e-plugin-list>
+ <e-plugin type="shlib"
+ location="@PLUGINDIR@/liborg-gnome-bogo-junk-plugin.so"
+ id="org.gnome.evolution.bogo.bf_junk_plugin"
+ name="Bogofilter junk plugin">
+ <description>Filters junk messages using Bogofilter.</description>
+ <author name="Mikhail Zabaluev" email="mhz@altlinux.org"/>
+ <hook class="org.gnome.evolution.mail.junk:1.0">
+ <group id="EMJunk" >
+ <item name="Bogofilter" report_non_junk="em_junk_bf_report_non_junk"
+ report_junk="em_junk_bf_report_junk"
+ check_junk="em_junk_bf_check_junk"
+ commit_reports="em_junk_bf_commit_reports"
+ validate_binary="em_junk_bf_validate_binary"/>
+ </group>
+ </hook>
+ <!-- hook into the 'mail properties' menu -->
+ <hook class="org.gnome.evolution.mail.config:1.0">
+ <group target="prefs" id="org.gnome.evolution.mail.prefs">
+ <item type="section_table" path="40.junk/30.options" label="Bogofilter Options"/>
+ <item type="item_table" path="40.junk/40.options" factory="org_gnome_bogo_convert_unicode"/>
+ </group>
+ </hook>
+
+ </e-plugin>
+</e-plugin-list>