aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
authorRadek Doulik <rodo@src.gnome.org>2003-11-13 05:13:05 +0800
committerRadek Doulik <rodo@src.gnome.org>2003-11-13 05:13:05 +0800
commit8e1251fa17b522d0539a8fcfb7463ba8cef1b31a (patch)
tree9be2f3a8a184446361a8c72879947f7a6e7d8d75 /mail
parent8187001a14295b4b64cc3e973fb1ab1e551133f2 (diff)
downloadgsoc2013-evolution-8e1251fa17b522d0539a8fcfb7463ba8cef1b31a.tar
gsoc2013-evolution-8e1251fa17b522d0539a8fcfb7463ba8cef1b31a.tar.gz
gsoc2013-evolution-8e1251fa17b522d0539a8fcfb7463ba8cef1b31a.tar.bz2
gsoc2013-evolution-8e1251fa17b522d0539a8fcfb7463ba8cef1b31a.tar.lz
gsoc2013-evolution-8e1251fa17b522d0539a8fcfb7463ba8cef1b31a.tar.xz
gsoc2013-evolution-8e1251fa17b522d0539a8fcfb7463ba8cef1b31a.tar.zst
gsoc2013-evolution-8e1251fa17b522d0539a8fcfb7463ba8cef1b31a.zip
merged spam filtering branch
svn path=/trunk/; revision=23302
Diffstat (limited to 'mail')
-rw-r--r--mail/Makefile.am4
-rw-r--r--mail/em-folder-tree.c6
-rw-r--r--mail/em-folder-view.c20
-rw-r--r--mail/em-junk-filter.c327
-rw-r--r--mail/em-junk-filter.h30
-rw-r--r--mail/em-junk-plugin.c24
-rw-r--r--mail/em-junk-plugin.h47
-rw-r--r--mail/em-popup.c5
-rw-r--r--mail/em-popup.h4
-rw-r--r--mail/mail-component.c11
-rw-r--r--mail/mail-folder-cache.c14
-rw-r--r--mail/mail-ops.c151
-rw-r--r--mail/mail-ops.h4
-rw-r--r--mail/mail-session.c7
-rw-r--r--mail/mail-tools.c13
-rw-r--r--mail/mail-vfolder.c6
-rw-r--r--mail/message-list.c112
-rw-r--r--mail/message-list.h3
18 files changed, 717 insertions, 71 deletions
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 0d9a101462..417ee0be24 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -109,6 +109,10 @@ libevolution_mail_la_SOURCES = \
em-sync-stream.h \
em-icon-stream.c \
em-icon-stream.h \
+ em-junk-filter.c \
+ em-junk-filter.h \
+ em-junk-plugin.c \
+ em-junk-plugin.h \
em-html-stream.c \
em-html-stream.h \
folder-browser-factory.c \
diff --git a/mail/em-folder-tree.c b/mail/em-folder-tree.c
index 7dcdc1d9e8..e6274abe37 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -144,7 +144,8 @@ enum {
FOLDER_ICON_NORMAL,
FOLDER_ICON_INBOX,
FOLDER_ICON_OUTBOX,
- FOLDER_ICON_TRASH
+ FOLDER_ICON_TRASH,
+ FOLDER_ICON_JUNK
};
static GdkPixbuf *folder_icons[4];
@@ -163,6 +164,7 @@ render_pixbuf (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
folder_icons[1] = gdk_pixbuf_load_from_file (EVOLUTION_ICONSDIR "/inbox-mini.png");
folder_icons[2] = gdk_pixbuf_load_from_file (EVOLUTION_ICONSDIR "/outbox-mini.png");
folder_icons[3] = gdk_pixbuf_load_from_file (EVOLUTION_ICONSDIR "/evolution-trash-mini.png");
+ folder_icons[4] = gdk_pixbuf_load_from_file (EVOLUTION_ICONSDIR "/evolution-junk-mini.png");
initialised = TRUE;
}
@@ -176,6 +178,8 @@ render_pixbuf (GtkTreeViewColumn *column, GtkCellRenderer *renderer,
pixbuf = folder_icons[FOLDER_ICON_OUTBOX];
else if (!strcasecmp (name, "/Trash"))
pixbuf = folder_icons[FOLDER_ICON_TRASH];
+ else if (!strcasecmp (name, "/Junk"))
+ pixbuf = folder_icons[FOLDER_ICON_JUNK];
else
pixbuf = folder_icons[FOLDER_ICON_NORMAL];
}
diff --git a/mail/em-folder-view.c b/mail/em-folder-view.c
index 0c52a49fe1..45fe46dbbb 100644
--- a/mail/em-folder-view.c
+++ b/mail/em-folder-view.c
@@ -524,6 +524,18 @@ emfv_popup_mark_unimportant(GtkWidget *w, EMFolderView *emfv)
}
static void
+emfv_popup_mark_junk (GtkWidget *w, EMFolderView *emfv)
+{
+ mail_mark_junk (emfv->folder, emfv->list, TRUE);
+}
+
+static void
+emfv_popup_mark_nojunk (GtkWidget *w, EMFolderView *emfv)
+{
+ mail_mark_junk (emfv->folder, emfv->list, FALSE);
+}
+
+static void
emfv_popup_delete(GtkWidget *w, EMFolderView *emfv)
{
GPtrArray *uids;
@@ -676,6 +688,8 @@ static EMPopupItem emfv_popup_menu[] = {
{ EM_POPUP_ITEM, "30.emfv.01", N_("Mark as _Unread"), G_CALLBACK(emfv_popup_mark_unread), NULL, "mail-new.xpm", EM_POPUP_SELECT_MARK_UNREAD },
{ EM_POPUP_ITEM, "30.emfv.02", N_("Mark as _Important"), G_CALLBACK(emfv_popup_mark_important), NULL, "priority-high.xpm", EM_POPUP_SELECT_MARK_IMPORTANT },
{ EM_POPUP_ITEM, "30.emfv.03", N_("_Mark as Unimportant"), G_CALLBACK(emfv_popup_mark_unimportant), NULL, NULL, EM_POPUP_SELECT_MARK_UNIMPORTANT },
+ { EM_POPUP_ITEM, "30.emfv.04", N_("Mark as _Junk"), G_CALLBACK(emfv_popup_mark_junk), NULL, NULL, EM_POPUP_SELECT_MARK_JUNK },
+ { EM_POPUP_ITEM, "30.emfv.05", N_("Mark as _Not Junk"), G_CALLBACK(emfv_popup_mark_nojunk), NULL, NULL, EM_POPUP_SELECT_MARK_NOJUNK },
{ EM_POPUP_BAR, "40.emfv" },
{ EM_POPUP_ITEM, "40.emfv.00", N_("_Delete"), G_CALLBACK(emfv_popup_delete), NULL, "evolution-trash-mini.png", EM_POPUP_SELECT_DELETE },
@@ -821,6 +835,8 @@ EMFV_MAP_CALLBACK(emfv_message_mark_read, emfv_popup_mark_read)
EMFV_MAP_CALLBACK(emfv_message_mark_unread, emfv_popup_mark_unread)
EMFV_MAP_CALLBACK(emfv_message_mark_important, emfv_popup_mark_important)
EMFV_MAP_CALLBACK(emfv_message_mark_unimportant, emfv_popup_mark_unimportant)
+EMFV_MAP_CALLBACK(emfv_message_mark_junk, emfv_popup_mark_junk)
+EMFV_MAP_CALLBACK(emfv_message_mark_nojunk, emfv_popup_mark_nojunk)
EMFV_MAP_CALLBACK(emfv_message_delete, emfv_popup_delete)
EMFV_MAP_CALLBACK(emfv_message_undelete, emfv_popup_undelete)
EMFV_MAP_CALLBACK(emfv_message_followup_flag, emfv_popup_flag_followup)
@@ -1246,6 +1262,8 @@ static BonoboUIVerb emfv_message_verbs[] = {
BONOBO_UI_UNSAFE_VERB ("MessageMarkAsUnRead", emfv_message_mark_unread),
BONOBO_UI_UNSAFE_VERB ("MessageMarkAsImportant", emfv_message_mark_important),
BONOBO_UI_UNSAFE_VERB ("MessageMarkAsUnimportant", emfv_message_mark_unimportant),
+ BONOBO_UI_UNSAFE_VERB ("MessageMarkAsJunk", emfv_message_mark_junk),
+ BONOBO_UI_UNSAFE_VERB ("MessageMarkAsNojunk", emfv_message_mark_nojunk),
BONOBO_UI_UNSAFE_VERB ("MessageFollowUpFlag", emfv_message_followup_flag),
BONOBO_UI_UNSAFE_VERB ("MessageMove", emfv_message_move),
BONOBO_UI_UNSAFE_VERB ("MessageOpen", emfv_message_open),
@@ -1348,6 +1366,8 @@ static const EMFolderViewEnable emfv_enable_map[] = {
{ "MessageMarkAsUnRead", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_UNREAD },
{ "MessageMarkAsImportant", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_IMPORTANT },
{ "MessageMarkAsUnimportant", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_UNIMPORTANT },
+ { "MessageMarkAsJunk", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_JUNK },
+ { "MessageMarkAsNojunk", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_NOJUNK },
{ "MessageFollowUpFlag", EM_POPUP_SELECT_MANY },
{ "MessageMove", EM_POPUP_SELECT_MANY },
{ "MessageOpen", EM_POPUP_SELECT_MANY },
diff --git a/mail/em-junk-filter.c b/mail/em-junk-filter.c
new file mode 100644
index 0000000000..04bbadc2ba
--- /dev/null
+++ b/mail/em-junk-filter.c
@@ -0,0 +1,327 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Author:
+ * Radek Doulik <rodo@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * 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
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <pthread.h>
+
+#include <camel/camel-data-wrapper.h>
+#include <camel/camel-stream-fs.h>
+
+#include "em-junk-filter.h"
+
+#define LOCK(x) pthread_mutex_lock(&x)
+#define UNLOCK(x) pthread_mutex_unlock(&x)
+
+static pthread_mutex_t em_junk_sa_test_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static const char * em_junk_sa_get_name (void);
+static gboolean em_junk_sa_check_junk (CamelMimeMessage *msg);
+static void em_junk_sa_report_junk (CamelMimeMessage *msg);
+static void em_junk_sa_report_notjunk (CamelMimeMessage *msg);
+static void em_junk_sa_commit_reports (void);
+
+static EMJunkPlugin spam_assassin_plugin =
+{
+ {
+ em_junk_sa_get_name,
+ 1,
+ em_junk_sa_check_junk,
+ em_junk_sa_report_junk,
+ em_junk_sa_report_notjunk,
+ em_junk_sa_commit_reports,
+ },
+ NULL,
+ NULL
+};
+
+static gboolean em_junk_sa_spamd_tested = FALSE;
+static gboolean em_junk_sa_use_spamc = FALSE;
+static gint em_junk_sa_spamd_port = -1;
+
+#define d(x) x
+
+static const char *
+em_junk_sa_get_name (void)
+{
+ return _("Spamassassin (built-in)");
+}
+
+static int
+pipe_to_sa (CamelMimeMessage *msg, gchar *in, int argc, gchar **argv)
+{
+ CamelStream *stream;
+ int result, status;
+ int in_fds[2];
+ pid_t pid;
+
+ if (argc < 1 || argv[0] == '\0')
+ return 0;
+
+ if (pipe (in_fds) == -1) {
+ /* camel_exception_setv (fms->ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Failed to create pipe to '%s': %s"),
+ argv[0]->value.string, g_strerror (errno)); */
+ return -1;
+ }
+
+ if (!(pid = fork ())) {
+ /* child process */
+ int maxfd, fd;
+
+ fd = open ("/dev/null", O_WRONLY);
+
+ if (dup2 (in_fds[0], STDIN_FILENO) < 0 ||
+ dup2 (fd, STDOUT_FILENO) < 0 ||
+ dup2 (fd, STDERR_FILENO) < 0)
+ _exit (255);
+
+ setsid ();
+
+ maxfd = sysconf (_SC_OPEN_MAX);
+ if (maxfd > 0) {
+ for (fd = 0; fd < maxfd; fd++) {
+ if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
+ close (fd);
+ }
+ }
+
+ execvp (argv [0], argv);
+
+ d(printf ("Could not execute %s: %s\n", argv [0], g_strerror (errno)));
+ _exit (255);
+ } else if (pid < 0) {
+ /* camel_exception_setv (fms->ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Failed to create create child process '%s': %s"),
+ argv[0]->value.string, g_strerror (errno)); */
+ return -1;
+ }
+
+ /* parent process */
+ close (in_fds[0]);
+ fcntl (in_fds[1], F_SETFL, O_NONBLOCK);
+
+ if (msg) {
+ stream = camel_stream_fs_new_with_fd (in_fds[1]);
+
+ camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (msg), stream);
+ camel_stream_flush (stream);
+ camel_object_unref (CAMEL_OBJECT (stream));
+ } else if (in) {
+ write (in_fds [1], in, strlen (in));
+ close (in_fds [1]);
+ }
+
+ result = waitpid (pid, &status, 0);
+
+ if (result == -1 && errno == EINTR) {
+ /* child process is hanging... */
+ kill (pid, SIGTERM);
+ sleep (1);
+ result = waitpid (pid, &status, WNOHANG);
+ if (result == 0) {
+ /* ...still hanging, set phasers to KILL */
+ kill (pid, SIGKILL);
+ sleep (1);
+ result = waitpid (pid, &status, WNOHANG);
+ }
+ }
+
+ if (result != -1 && WIFEXITED (status))
+ return WEXITSTATUS (status);
+ else
+ return -1;
+}
+
+
+#define NPORTS 1
+
+static int
+em_junk_sa_test_spamd_running (gint port)
+{
+ static gchar *sac_args [3] = {
+ "/bin/sh",
+ "-c",
+ NULL
+ };
+ int retval;
+
+ d(fprintf (stderr, "test if spamd is running (port %d)\n", port);)
+ sac_args [2] = port > 0 ? g_strdup_printf ("spamc -x -p %d", port) : g_strdup_printf ("spamc -x");
+
+ retval = pipe_to_sa (NULL, "From test@127.0.0.1", 3, sac_args) == 0;
+ g_free (sac_args [2]);
+
+ return retval;
+}
+
+static void
+em_junk_sa_test_spamd ()
+{
+ gint i, port = 7830;
+
+ em_junk_sa_use_spamc = FALSE;
+
+ /* if (em_junk_sa_test_spamd_running (-1)) {
+ em_junk_sa_use_spamc = TRUE;
+ em_junk_sa_spamd_port = -1;
+ } else { */
+ for (i = 0; i < NPORTS; i ++) {
+ if (em_junk_sa_test_spamd_running (port)) {
+ em_junk_sa_use_spamc = TRUE;
+ em_junk_sa_spamd_port = port;
+ break;
+ }
+ port ++;
+ }
+ /* } */
+
+ if (!em_junk_sa_use_spamc) {
+ static gchar *sad_args [3] = {
+ "/bin/sh",
+ "-c",
+ NULL
+ };
+ gint i, port = 7830;
+
+ d(fprintf (stderr, "looks like spamd is not running\n");)
+
+ for (i = 0; i < NPORTS; i ++) {
+ d(fprintf (stderr, "trying to run spamd at port %d\n", port));
+
+ sad_args [2] = g_strdup_printf ("spamd --port %d --local --daemonize", port);
+ if (!pipe_to_sa (NULL, NULL, 3, sad_args)) {
+ g_free (sad_args [2]);
+ em_junk_sa_use_spamc = TRUE;
+ em_junk_sa_spamd_port = port;
+ d(fprintf (stderr, "success at port %d\n", port));
+ break;
+ }
+ g_free (sad_args [2]);
+ port ++;
+ }
+ }
+
+ d(fprintf (stderr, "use spamd %d at port %d\n", em_junk_sa_use_spamc, em_junk_sa_spamd_port);)
+
+ em_junk_sa_spamd_tested = TRUE;
+}
+
+static gboolean
+em_junk_sa_check_junk (CamelMimeMessage *msg)
+{
+ static gchar *args [3] = {
+ "/bin/sh",
+ "-c",
+ NULL
+ };
+ gint retval;
+
+ d(fprintf (stderr, "em_junk_sa_check_junk\n"));
+
+ LOCK (em_junk_sa_test_lock);
+ if (!em_junk_sa_spamd_tested)
+ em_junk_sa_test_spamd ();
+ UNLOCK (em_junk_sa_test_lock);
+
+ args [2] = em_junk_sa_use_spamc
+ ? (em_junk_sa_spamd_port == -1
+ ? g_strdup ("spamc -c") /* Exit with a non-zero exit code if the
+ tested message was junk */
+ : g_strdup_printf ("spamc"
+ " -c" /* Exit with a non-zero exit code if the
+ tested message was junk */
+ " -p %d", em_junk_sa_spamd_port))
+ : g_strdup ("spamassassin"
+ " --exit-code" /* Exit with a non-zero exit code if the
+ tested message was junk */
+ " --local"); /* Local tests only (no online tests) */
+
+ retval = pipe_to_sa (msg, NULL, 3, args);
+
+ g_free (args [2]);
+
+ return retval;
+}
+
+static void
+em_junk_sa_report_junk (CamelMimeMessage *msg)
+{
+ static gchar *args [3] = {
+ "/bin/sh",
+ "-c",
+ "sa-learn"
+ " --no-rebuild" /* do not rebuild db */
+ " --spam" /* report junk */
+ " --single" /* single message */
+ " --local" /* local only */
+ };
+
+ d(fprintf (stderr, "em_junk_sa_report_junk\n");)
+
+ pipe_to_sa (msg, NULL, 3, args) > 0;
+}
+
+static void
+em_junk_sa_report_notjunk (CamelMimeMessage *msg)
+{
+ static gchar *args [3] = {
+ "/bin/sh",
+ "-c",
+ "sa-learn"
+ " --no-rebuild" /* do not rebuild db */
+ " --ham" /* report notjunk */
+ " --single" /* single message */
+ " --local" /* local only */
+ };
+
+ d(fprintf (stderr, "em_junk_sa_report_notjunk\n");)
+
+ pipe_to_sa (msg, NULL, 3, args) > 0;
+}
+
+static void
+em_junk_sa_commit_reports (void)
+{
+ static gchar *args [3] = {
+ "/bin/sh",
+ "-c",
+ "sa-learn"
+ " --rebuild" /* do not rebuild db */
+ " --local" /* local only */
+ };
+
+ d(fprintf (stderr, "em_junk_sa_commit_reports\n");)
+
+ pipe_to_sa (NULL, NULL, 3, args) > 0;
+}
+
+const EMJunkPlugin *
+em_junk_filter_get_plugin (void)
+{
+ return &spam_assassin_plugin;
+}
diff --git a/mail/em-junk-filter.h b/mail/em-junk-filter.h
new file mode 100644
index 0000000000..f62ca7bfad
--- /dev/null
+++ b/mail/em-junk-filter.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Author:
+ * Radek Doulik <rodo@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * 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
+ */
+
+#ifndef _EM_JUNK_FILTER_H
+#define _EM_JUNK_FILTER_H
+
+#include "em-junk-plugin.h"
+
+const EMJunkPlugin * em_junk_filter_get_plugin (void);
+
+#endif
diff --git a/mail/em-junk-plugin.c b/mail/em-junk-plugin.c
new file mode 100644
index 0000000000..5ea2a40119
--- /dev/null
+++ b/mail/em-junk-plugin.c
@@ -0,0 +1,24 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Author:
+ * Radek Doulik <rodo@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * 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
+ */
+
+#include "em-junk-plugin.h"
+
diff --git a/mail/em-junk-plugin.h b/mail/em-junk-plugin.h
new file mode 100644
index 0000000000..0c7eacd165
--- /dev/null
+++ b/mail/em-junk-plugin.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Author:
+ * Radek Doulik <rodo@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * 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
+ */
+
+#ifndef _EM_JUNK_PLUGIN_H
+#define _EM_JUNK_PLUGIN_H
+
+#include <camel/camel-junk-plugin.h>
+#include <gtk/gtkwidget.h>
+
+#define EM_JUNK_PLUGIN(x) ((EMJunkPlugin *) x)
+
+typedef struct _EMJunkPlugin EMJunkPlugin;
+
+struct _EMJunkPlugin
+{
+ CamelJunkPlugin csp;
+
+ /* when called, it should insert own GUI configuration into supplied.
+ container. returns data pointer which is later passed to apply,
+ plugin has to call (*changed_cb) (); whenever configuration
+ is changed to notify settings dialog about a change.
+ if setup_config_ui is NULL, it means there are no options */
+
+ gpointer (*setup_config_ui) (GtkWidget *container, void (*changed_cb) ());
+ void (*apply) (gpointer data);
+};
+
+#endif
diff --git a/mail/em-popup.c b/mail/em-popup.c
index 63159848bf..760aed48d5 100644
--- a/mail/em-popup.c
+++ b/mail/em-popup.c
@@ -459,6 +459,11 @@ em_popup_target_new_select(struct _CamelFolder *folder, const char *folder_uri,
mask &= ~EM_POPUP_SELECT_MARK_UNIMPORTANT;
else
mask &= ~EM_POPUP_SELECT_MARK_IMPORTANT;
+
+ if (info->flags & CAMEL_MESSAGE_JUNK)
+ mask &= ~EM_POPUP_SELECT_MARK_NOJUNK;
+ else
+ mask &= ~EM_POPUP_SELECT_MARK_JUNK;
tmp = camel_tag_get (&info->user_tags, "follow-up");
if (tmp && *tmp) {
diff --git a/mail/em-popup.h b/mail/em-popup.h
index 0ad1d0015c..831d586efe 100644
--- a/mail/em-popup.h
+++ b/mail/em-popup.h
@@ -88,7 +88,9 @@ enum {
EM_POPUP_SELECT_FLAG_COMPLETED = 1<<12,
EM_POPUP_SELECT_FLAG_CLEAR = 1<<13,
EM_POPUP_SELECT_ADD_SENDER = 1<<14,
- EM_POPUP_SELECT_LAST = 1<<16 /* reserve 2 slots */
+ EM_POPUP_SELECT_MARK_JUNK = 1<<15,
+ EM_POPUP_SELECT_MARK_NOJUNK = 1<<16,
+ EM_POPUP_SELECT_LAST = 1<<18 /* reserve 2 slots */
};
/* Flags that describe a TARGET_URI */
diff --git a/mail/mail-component.c b/mail/mail-component.c
index f22cb656b3..ea20dae624 100644
--- a/mail/mail-component.c
+++ b/mail/mail-component.c
@@ -269,6 +269,12 @@ type_is_vtrash (const char *type)
return !strcmp (type, "vtrash");
}
+static inline gboolean
+type_is_vjunk (const char *type)
+{
+ return !strcmp (type, "vjunk");
+}
+
static void
storage_go_online (gpointer key, gpointer value, gpointer data)
{
@@ -410,6 +416,11 @@ create_view_callback (EStorageBrowser *browser,
control = folder_browser_factory_new_control ("vtrash:file:/");
else
control = folder_browser_factory_new_control (physical_uri);
+ } else if (type_is_vjunk (folder_type)) {
+ if (!strncasecmp (physical_uri, "file:", 5))
+ control = folder_browser_factory_new_control ("vjunk:file:/");
+ else
+ control = folder_browser_factory_new_control (physical_uri);
} else
return NULL;
diff --git a/mail/mail-folder-cache.c b/mail/mail-folder-cache.c
index 3d4eb96d53..a75ed046e9 100644
--- a/mail/mail-folder-cache.c
+++ b/mail/mail-folder-cache.c
@@ -240,9 +240,17 @@ real_flush_updates(void *o, void *event_data, void *data)
g_warning ("No folder at %s ?!", up->path);
}
} else if (storage != NULL) {
- char *type = (strncmp(up->uri, "vtrash:", 7)==0)?"vtrash":"mail";
- EFolder *new_folder = e_folder_new (up->name, type, NULL);
+ char *type;
+ EFolder *new_folder;
+ if (strncmp(up->uri, "vtrash:", 7)==0) {
+ type = "vtrash";
+ } else if (strncmp(up->uri, "vjunk:", 6)==0) {
+ type = "vjunk";
+ } else
+ type = "mail";
+
+ new_folder = e_folder_new (up->name, type, NULL);
d(printf("Adding new folder: %s\n", up->path));
e_folder_set_physical_uri (new_folder, up->uri);
@@ -461,7 +469,7 @@ folder_changed (CamelObject *o, gpointer event_data, gpointer user_data)
if (mfi->folder != folder)
return;
- if (!CAMEL_IS_VTRASH_FOLDER (folder) && folder != outbox_folder && folder != sent_folder && changes && changes->uid_added)
+ if (!CAMEL_IS_VTRASH_FOLDER (folder) && !CAMEL_IS_VJUNK_FOLDER (folder) && folder != outbox_folder && folder != sent_folder && changes && changes->uid_added)
new = changes->uid_added->len;
LOCK(info_lock);
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index 8d3711ff4e..b7aad2e55b 100644
--- a/mail/mail-ops.c
+++ b/mail/mail-ops.c
@@ -1063,9 +1063,9 @@ get_folderinfo_desc (struct _mail_msg *mm, int done)
}
static void
-add_vtrash_info (CamelStore *store, CamelFolderInfo *info)
+add_vtrash_or_vjunk_info (CamelStore *store, CamelFolderInfo *info, gchar *name, gchar *full_name, gchar *url_base, gboolean unread_count)
{
- CamelFolderInfo *fi, *vtrash, *parent;
+ CamelFolderInfo *fi, *vinfo, *parent;
char *uri, *path;
CamelURL *url;
@@ -1073,14 +1073,14 @@ add_vtrash_info (CamelStore *store, CamelFolderInfo *info)
parent = NULL;
for (fi = info; fi; fi = fi->sibling) {
- if (!strcmp (fi->name, CAMEL_VTRASH_NAME))
+ if (!strcmp (fi->name, name))
break;
parent = fi;
}
- /* create our vTrash URL */
+ /* create our vTrash/vJunk URL */
url = camel_url_new (info->url, NULL);
- path = g_strdup_printf ("/%s", CAMEL_VTRASH_NAME);
+ path = g_strdup_printf ("/%s", name);
if (url->fragment)
camel_url_set_fragment (url, path);
else
@@ -1090,32 +1090,45 @@ add_vtrash_info (CamelStore *store, CamelFolderInfo *info)
camel_url_free (url);
if (fi) {
- /* We're going to replace the physical Trash folder with our vTrash folder */
- vtrash = fi;
- g_free (vtrash->full_name);
- g_free (vtrash->name);
- g_free (vtrash->url);
+ /* We're going to replace the physical Trash/Junk folder with our vTrash/vJunk folder */
+ vinfo = fi;
+ g_free (vinfo->full_name);
+ g_free (vinfo->name);
+ g_free (vinfo->url);
} else {
- /* There wasn't a Trash folder so create a new folder entry */
- vtrash = g_new0 (CamelFolderInfo, 1);
+ /* There wasn't a Trash/Junk folder so create a new folder entry */
+ vinfo = g_new0 (CamelFolderInfo, 1);
g_assert(parent != NULL);
/* link it into the right spot */
- vtrash->sibling = parent->sibling;
- parent->sibling = vtrash;
+ vinfo->sibling = parent->sibling;
+ parent->sibling = vinfo;
}
/* Fill in the new fields */
- vtrash->full_name = g_strdup (_("Trash"));
- vtrash->name = g_strdup(vtrash->full_name);
- vtrash->url = g_strdup_printf ("vtrash:%s", uri);
- vtrash->unread_message_count = -1;
- vtrash->path = g_strdup_printf("/%s", vtrash->name);
+ vinfo->full_name = g_strdup (full_name);
+ vinfo->name = g_strdup(vinfo->full_name);
+ vinfo->url = g_strdup_printf ("%s:%s", url_base, uri);
+ if (!unread_count)
+ vinfo->unread_message_count = -1;
+ vinfo->path = g_strdup_printf("/%s", vinfo->name);
g_free (uri);
}
static void
+add_vtrash_info (CamelStore *store, CamelFolderInfo *info)
+{
+ add_vtrash_or_vjunk_info (store, info, CAMEL_VTRASH_NAME, _("Trash"), "vtrash", FALSE);
+}
+
+static void
+add_vjunk_info (CamelStore *store, CamelFolderInfo *info)
+{
+ add_vtrash_or_vjunk_info (store, info, CAMEL_VJUNK_NAME, _("Junk"), "vjunk", TRUE);
+}
+
+static void
add_unmatched_info(CamelFolderInfo *fi)
{
for (; fi; fi = fi->sibling) {
@@ -1142,6 +1155,8 @@ get_folderinfo_get (struct _mail_msg *mm)
if (m->info) {
if (m->info->url && (m->store->flags & CAMEL_STORE_VTRASH))
add_vtrash_info(m->store, m->info);
+ if (m->info->url && (m->store->flags & CAMEL_STORE_VJUNK))
+ add_vjunk_info(m->store, m->info);
if (CAMEL_IS_VEE_STORE(m->store))
add_unmatched_info(m->info);
}
@@ -2329,3 +2344,101 @@ mail_execute_shell_command (CamelFilterDriver *driver, int argc, char **argv, vo
gnome_execute_async_fds (NULL, argc, argv, TRUE);
}
+
+/* [Un]mark junk flag */
+
+struct _mark_junk_mail_msg {
+ struct _mail_msg msg;
+
+ CamelFolder *folder;
+ MessageList *list;
+ gboolean junk;
+};
+
+static char *
+mark_junk_describe (struct _mail_msg *mm, int complete)
+{
+ return g_strdup (_("Changing junk status"));
+}
+
+/* filter a folder, or a subset thereof, uses source_folder/source_uids */
+/* this is shared with fetch_mail */
+static void
+mark_junk_mark (struct _mail_msg *mm)
+{
+ struct _mark_junk_mail_msg *m = (struct _mark_junk_mail_msg *) mm;
+ CamelJunkPlugin *csp = NULL;
+ GPtrArray *uids;
+ gboolean commit_reports = FALSE;
+ int i;
+
+ if (m->folder == NULL)
+ return;
+
+ uids = message_list_get_selected (m->list);
+ camel_folder_freeze (m->folder);
+
+ for (i=0; i<uids->len; i++) {
+ guint32 flags;
+
+ flags = camel_folder_get_message_flags (m->folder, uids->pdata[i]);
+ if (((flags & CAMEL_MESSAGE_JUNK) == CAMEL_MESSAGE_JUNK) != m->junk) {
+ CamelMimeMessage *msg = camel_folder_get_message (m->folder, uids->pdata[i], NULL);
+
+ if (msg) {
+ csp = CAMEL_SERVICE (m->folder->parent_store)->session->junk_plugin;
+ if (m->junk)
+ camel_junk_plugin_report_junk (csp, msg);
+ else
+ camel_junk_plugin_report_notjunk (csp, msg);
+
+ commit_reports = TRUE;
+ camel_object_unref (msg);
+ }
+ }
+ camel_folder_set_message_flags(m->folder, uids->pdata[i],
+ CAMEL_MESSAGE_JUNK | (m->junk ? CAMEL_MESSAGE_DELETED : 0),
+ m->junk ? CAMEL_MESSAGE_JUNK : 0);
+ }
+
+ if (commit_reports)
+ camel_junk_plugin_commit_reports (csp);
+
+ message_list_free_uids(m->list, uids);
+ camel_folder_thaw(m->folder);
+}
+
+static void
+mark_junk_marked (struct _mail_msg *mm)
+{
+}
+
+static void
+mark_junk_free (struct _mail_msg *mm)
+{
+ struct _mark_junk_mail_msg *m = (struct _mark_junk_mail_msg *)mm;
+
+ if (m->folder)
+ camel_object_unref (m->folder);
+}
+
+static struct _mail_msg_op mark_junk_op = {
+ mark_junk_describe,
+ mark_junk_mark,
+ mark_junk_marked,
+ mark_junk_free,
+};
+
+void
+mail_mark_junk (CamelFolder *folder, MessageList *list, gboolean junk)
+{
+ struct _mark_junk_mail_msg *m;
+
+ m = mail_msg_new (&mark_junk_op, NULL, sizeof (*m));
+ m->folder = folder;
+ camel_object_ref (folder);
+ m->list = list;
+ m->junk = junk;
+
+ e_thread_put (mail_thread_new, (EMsg *) m);
+}
diff --git a/mail/mail-ops.h b/mail/mail-ops.h
index e15d7729c2..081e1a1425 100644
--- a/mail/mail-ops.h
+++ b/mail/mail-ops.h
@@ -36,6 +36,8 @@ extern "C" {
#include "camel/camel-mime-message.h"
#include "camel/camel-operation.h"
+#include "message-list.h"
+
#include "evolution-storage.h" /*EvolutionStorage */
#include "e-util/e-msgport.h"
#include "e-util/e-account.h"
@@ -164,6 +166,8 @@ int mail_store_set_offline(CamelStore *store, gboolean offline,
/* filter driver execute shell command async callback */
void mail_execute_shell_command (CamelFilterDriver *driver, int argc, char **argv, void *data);
+void mail_mark_junk (CamelFolder *folder, MessageList *list, gboolean junk);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/mail/mail-session.c b/mail/mail-session.c
index 58773513c4..0db6f38ba8 100644
--- a/mail/mail-session.c
+++ b/mail/mail-session.c
@@ -48,6 +48,7 @@
#include "mail-ops.h"
#include "e-util/e-passwords.h"
#include "e-util/e-msgport.h"
+#include "em-junk-filter.h"
#define d(x)
@@ -626,6 +627,9 @@ main_get_filter_driver (CamelSession *session, const char *type, CamelException
fsearch = g_string_new ("");
faction = g_string_new ("");
+
+ /* implicit junk check as 1st rule */
+ camel_filter_driver_add_rule (driver, "Junk check", "(junk-test)", "(begin (set-system-flag \"junk\"))");
/* add the user-defined rules next */
while ((rule = rule_context_next_rule (fc, rule, type))) {
@@ -634,7 +638,6 @@ main_get_filter_driver (CamelSession *session, const char *type, CamelException
filter_rule_build_code (rule, fsearch);
filter_filter_build_action ((FilterFilter *) rule, faction);
-
camel_filter_driver_add_rule (driver, rule->name, fsearch->str, faction->str);
}
@@ -755,6 +758,8 @@ mail_session_init (const char *base_directory)
camel_dir = g_strdup_printf ("%s/mail", base_directory);
camel_session_construct (session, camel_dir);
+
+ session->junk_plugin = CAMEL_JUNK_PLUGIN (em_junk_filter_get_plugin ());
/* The shell will tell us to go online. */
camel_session_set_online ((CamelSession *) session, FALSE);
diff --git a/mail/mail-tools.c b/mail/mail-tools.c
index b85a18c12f..0538efd354 100644
--- a/mail/mail-tools.c
+++ b/mail/mail-tools.c
@@ -312,6 +312,8 @@ mail_tool_uri_to_folder (const char *uri, guint32 flags, CamelException *ex)
/* This hack is still needed for file:/ since it's its own EvolutionStorage type */
if (!strncmp (uri, "vtrash:", 7))
offset = 7;
+ else if (!strncmp (uri, "vjunk:", 6))
+ offset = 6;
url = camel_url_new (uri + offset, ex);
if (!url) {
@@ -333,9 +335,14 @@ mail_tool_uri_to_folder (const char *uri, guint32 flags, CamelException *ex)
name = "";
}
- if (offset)
- folder = camel_store_get_trash (store, ex);
- else
+ if (offset) {
+ if (offset == 7)
+ folder = camel_store_get_trash (store, ex);
+ else if (offset == 6)
+ folder = camel_store_get_junk (store, ex);
+ else
+ g_assert (FALSE);
+ } else
folder = camel_store_get_folder (store, name, flags, ex);
camel_object_unref (store);
}
diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c
index f47fe4c660..2bb08a587e 100644
--- a/mail/mail-vfolder.c
+++ b/mail/mail-vfolder.c
@@ -345,7 +345,7 @@ mail_vfolder_add_uri(CamelStore *store, const char *uri, int remove)
GCompareFunc uri_cmp = CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(store))->compare_folder_name;
int is_ignore;
- if (CAMEL_IS_VEE_STORE(store) || !strncmp(uri, "vtrash:", 7) || context == NULL)
+ if (CAMEL_IS_VEE_STORE(store) || !strncmp(uri, "vtrash:", 7) || !strncmp(uri, "vjunk:", 6) || context == NULL)
return;
g_assert(pthread_self() == mail_gui_thread);
@@ -426,7 +426,7 @@ mail_vfolder_delete_uri(CamelStore *store, const char *uri)
CamelVeeFolder *vf;
GString *changed;
- if (context == NULL || !strncmp(uri, "vtrash:", 7))
+ if (context == NULL || !strncmp(uri, "vtrash:", 7) || !strncmp(uri, "vjunk:", 6))
return;
d(printf ("Deleting uri to check: %s\n", uri));
@@ -492,7 +492,7 @@ mail_vfolder_rename_uri(CamelStore *store, const char *from, const char *to)
d(printf("vfolder rename uri: %s to %s\n", from, to));
- if (context == NULL || !strncmp(from, "vtrash:", 7) || !strncmp(to, "vtrash:", 7))
+ if (context == NULL || !strncmp(from, "vtrash:", 7) || !strncmp(to, "vtrash:", 7) || !strncmp(from, "vjunk:", 6) || !strncmp(to, "vjunk:", 6))
return;
g_assert(pthread_self() == mail_gui_thread);
diff --git a/mail/message-list.c b/mail/message-list.c
index a16c40f265..430d2f4896 100644
--- a/mail/message-list.c
+++ b/mail/message-list.c
@@ -188,6 +188,9 @@ static struct {
{ NULL, NULL }
};
+/* FIXME: junk prefs */
+static gboolean junk_folder = TRUE;
+
#ifdef SMART_ADDRESS_COMPARE
static EMailAddress *
e_mail_address_new (const char *address)
@@ -2377,11 +2380,44 @@ build_flat_diff(MessageList *ml, CamelFolderChangeInfo *changes)
static void
+mail_folder_hide_by_flag (CamelFolder *folder, MessageList *ml, CamelFolderChangeInfo **changes, int flag)
+{
+ CamelFolderChangeInfo *newchanges, *oldchanges = *changes;
+ CamelMessageInfo *info;
+ int i;
+
+ newchanges = camel_folder_change_info_new ();
+
+ for (i = 0; i < oldchanges->uid_changed->len; i++) {
+ ETreePath node = g_hash_table_lookup (ml->uid_nodemap, oldchanges->uid_changed->pdata[i]);
+
+ info = camel_folder_get_message_info (folder, oldchanges->uid_changed->pdata[i]);
+ if (node != NULL && info != NULL && (info->flags & flag) != 0)
+ camel_folder_change_info_remove_uid (newchanges, oldchanges->uid_changed->pdata[i]);
+ else if (node == NULL && info != NULL && (info->flags & flag) == 0)
+ camel_folder_change_info_add_uid (newchanges, oldchanges->uid_changed->pdata[i]);
+ else
+ camel_folder_change_info_change_uid (newchanges, oldchanges->uid_changed->pdata[i]);
+ camel_folder_free_message_info (folder, info);
+ }
+
+ if (newchanges->uid_added->len > 0 || newchanges->uid_removed->len > 0) {
+ for (i = 0; i < oldchanges->uid_added->len; i++)
+ camel_folder_change_info_add_uid (newchanges, oldchanges->uid_added->pdata[i]);
+ for (i = 0; i < oldchanges->uid_removed->len; i++)
+ camel_folder_change_info_remove_uid (newchanges, oldchanges->uid_removed->pdata[i]);
+ camel_folder_change_info_free (oldchanges);
+ *changes = newchanges;
+ } else {
+ camel_folder_change_info_free (newchanges);
+ }
+}
+
+static void
main_folder_changed (CamelObject *o, gpointer event_data, gpointer user_data)
{
MessageList *ml = MESSAGE_LIST (user_data);
- CamelFolderChangeInfo *changes = (CamelFolderChangeInfo *)event_data, *newchanges;
- CamelMessageInfo *info;
+ CamelFolderChangeInfo *changes = (CamelFolderChangeInfo *)event_data;
CamelFolder *folder = (CamelFolder *)o;
int i;
@@ -2402,35 +2438,9 @@ main_folder_changed (CamelObject *o, gpointer event_data, gpointer user_data)
}
/* check if the hidden state has changed, if so modify accordingly, then regenerate */
- if (ml->hidedeleted) {
- newchanges = camel_folder_change_info_new ();
-
- for (i = 0; i < changes->uid_changed->len; i++) {
- ETreePath node = g_hash_table_lookup (ml->uid_nodemap, changes->uid_changed->pdata[i]);
-
- info = camel_folder_get_message_info (folder, changes->uid_changed->pdata[i]);
- if (node != NULL && info != NULL && (info->flags & CAMEL_MESSAGE_DELETED) != 0) {
- camel_folder_change_info_remove_uid (newchanges, changes->uid_changed->pdata[i]);
- } else if (node == NULL && info != NULL && (info->flags & CAMEL_MESSAGE_DELETED) == 0) {
- camel_folder_change_info_add_uid (newchanges, changes->uid_changed->pdata[i]);
- } else {
- camel_folder_change_info_change_uid (newchanges, changes->uid_changed->pdata[i]);
- }
- camel_folder_free_message_info (folder, info);
- }
-
- if (newchanges->uid_added->len > 0 || newchanges->uid_removed->len > 0) {
- for (i = 0; i < changes->uid_added->len; i++)
- camel_folder_change_info_add_uid (newchanges, changes->uid_added->pdata[i]);
- for (i = 0; i < changes->uid_removed->len; i++)
- camel_folder_change_info_remove_uid (newchanges, changes->uid_removed->pdata[i]);
- camel_folder_change_info_free (changes);
- changes = newchanges;
- } else {
- camel_folder_change_info_free (newchanges);
- }
- }
-
+ if (ml->hidejunk || ml->hidedeleted)
+ mail_folder_hide_by_flag (folder, ml, &changes, (ml->hidejunk ? CAMEL_MESSAGE_JUNK : 0) | (ml->hidedeleted ? CAMEL_MESSAGE_DELETED : 0));
+
if (changes->uid_added->len == 0 && changes->uid_removed->len == 0 && changes->uid_changed->len < 100) {
for (i = 0; i < changes->uid_changed->len; i++) {
ETreePath node = g_hash_table_lookup (ml->uid_nodemap, changes->uid_changed->pdata[i]);
@@ -2579,6 +2589,7 @@ message_list_set_folder (MessageList *message_list, CamelFolder *folder, const c
gconf = mail_config_get_gconf_client ();
hide_deleted = !gconf_client_get_bool (gconf, "/apps/evolution/mail/display/show_deleted", NULL);
message_list->hidedeleted = hide_deleted && !(folder->folder_flags & CAMEL_FOLDER_IS_TRASH);
+ message_list->hidejunk = junk_folder && !(folder->folder_flags & CAMEL_FOLDER_IS_JUNK) && !(folder->folder_flags & CAMEL_FOLDER_IS_TRASH);
hide_load_state (message_list);
mail_regen_list (message_list, message_list->search, NULL, NULL);
@@ -3038,6 +3049,7 @@ struct _regen_list_msg {
CamelFolderChangeInfo *changes;
gboolean dotree; /* we are building a tree */
gboolean hidedel; /* we want to/dont want to show deleted messages */
+ gboolean hidejunk; /* we want to/dont want to show junk messages */
gboolean thread_subject;
CamelFolderThread *tree;
@@ -3076,17 +3088,36 @@ regen_list_regen (struct _mail_msg *mm)
} else if (m->hidedel) {
char *expr;
- if (m->search) {
- expr = alloca(strlen(m->search) + 64);
- sprintf(expr, "(and (match-all (not (system-flag \"deleted\")))\n %s)", m->search);
- } else
- expr = "(match-all (not (system-flag \"deleted\")))";
+ if (m->hidejunk) {
+ if (m->search) {
+ expr = alloca(strlen(m->search) + 92);
+ sprintf(expr, "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\"))))\n %s)", m->search);
+ } else
+ expr = "(match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\"))))";
+ } else {
+ if (m->search) {
+ expr = alloca(strlen(m->search) + 64);
+ sprintf(expr, "(and (match-all (not (system-flag \"deleted\")))\n %s)", m->search);
+ } else
+ expr = "(match-all (not (system-flag \"deleted\")))";
+ }
searchuids = uids = camel_folder_search_by_expression (m->folder, expr, &mm->ex);
} else {
- if (m->search)
- searchuids = uids = camel_folder_search_by_expression (m->folder, m->search, &mm->ex);
- else
- uids = camel_folder_get_uids (m->folder);
+ char *expr;
+
+ if (m->hidejunk) {
+ if (m->search) {
+ expr = alloca(strlen(m->search) + 64);
+ sprintf(expr, "(and (match-all (not (system-flag \"junk\")))\n %s)", m->search);
+ } else
+ expr = "(match-all (not (system-flag \"junk\")))";
+ searchuids = uids = camel_folder_search_by_expression (m->folder, expr, &mm->ex);
+ } else {
+ if (m->search)
+ searchuids = uids = camel_folder_search_by_expression (m->folder, m->search, &mm->ex);
+ else
+ uids = camel_folder_get_uids (m->folder);
+ }
}
if (camel_exception_is_set (&mm->ex))
@@ -3318,6 +3349,7 @@ mail_regen_list (MessageList *ml, const char *search, const char *hideexpr, Came
m->changes = changes;
m->dotree = ml->threaded;
m->hidedel = ml->hidedeleted;
+ m->hidejunk = ml->hidejunk;
m->thread_subject = gconf_client_get_bool (gconf, "/apps/evolution/mail/display/thread_subject", NULL);
g_object_ref(ml);
m->folder = ml->folder;
diff --git a/mail/message-list.h b/mail/message-list.h
index a5c88cf308..8052ed791b 100644
--- a/mail/message-list.h
+++ b/mail/message-list.h
@@ -113,6 +113,9 @@ struct _MessageList {
/* do we automatically hide deleted messages? */
guint hidedeleted : 1;
+
+ /* do we automatically hide junk messages? */
+ guint hidejunk : 1;
/* is the message-list object in a destroyed state? */
guint destroyed : 1;