FolderItem *bogofilter_get_spam_folder(MsgInfo *msginfo) { FolderItem *item = folder_find_item_from_identifier(config.save_folder); if (item || msginfo == NULL || msginfo->folder == NULL) return item; if (msginfo->folder->folder && msginfo->folder->folder->account && msginfo->folder->folder->account->set_trash_folder) { item = folder_find_item_from_identifier( msginfo->folder->folder->account->trash_folder); } if (item == NULL && msginfo->folder->folder && msginfo->folder->folder->trash) item = msginfo->folder->folder->trash; if (item == NULL) item = folder_get_default_trash(); debug_print("bogo spam dir: %s\n", folder_item_get_path(item)); return item; }
static gboolean mail_filtering_hook(gpointer source, gpointer data) { MailFilteringData *mail_filtering_data = (MailFilteringData *) source; MsgInfo *msginfo = mail_filtering_data->msginfo; MimeInfo *mimeinfo; struct clamd_result result; if (!config.clamav_enable) return FALSE; mimeinfo = procmime_scan_message(msginfo); if (!mimeinfo) return FALSE; debug_print("Scanning message %d for viruses\n", msginfo->msgnum); if (message_callback != NULL) message_callback(_("ClamAV: scanning message...")); g_node_traverse(mimeinfo->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, scan_func, &result); debug_print("status: %d\n", result.status); if (result.status == VIRUS) { if (config.clamav_recv_infected) { FolderItem *clamav_save_folder; if ((!config.clamav_save_folder) || (config.clamav_save_folder[0] == '\0') || ((clamav_save_folder = folder_find_item_from_identifier(config.clamav_save_folder)) == NULL)) clamav_save_folder = folder_get_default_trash(); procmsg_msginfo_unset_flags(msginfo, ~0, 0); msginfo->filter_op = IS_MOVE; msginfo->to_filter_folder = clamav_save_folder; } else { folder_item_remove_msg(msginfo->folder, msginfo->msgnum); } } procmime_mimeinfo_free_all(mimeinfo); return (result.status == OK) ? FALSE : TRUE; }
static gboolean mail_filtering_hook(gpointer source, gpointer data) { MailFilteringData *mail_filtering_data = (MailFilteringData *) source; MsgInfo *msginfo = mail_filtering_data->msginfo; GSList *msglist = mail_filtering_data->msglist; GSList *cur = NULL; static gboolean warned_error = FALSE; int status = 0; int total = 0, curnum = 0; GSList *new_hams = NULL, *new_spams = NULL; GSList *new_unsure, *whitelisted_new_spams = NULL; gchar *bogo_exec = (config.bogopath && *config.bogopath) ? config.bogopath:"bogofilter"; gchar *bogo_args[4]; gboolean ok_to_thread = TRUE; bogo_args[0] = bogo_exec; bogo_args[1] = "-T"; bogo_args[2] = "-b"; bogo_args[3] = NULL; if (!config.process_emails) { return FALSE; } if (msglist == NULL && msginfo != NULL) { g_warning("wrong call to bogofilter mail_filtering_hook"); return FALSE; } total = g_slist_length(msglist); /* we have to make sure the mails are cached - or it'll break on IMAP */ if (message_callback != NULL) message_callback(_("Bogofilter: fetching bodies..."), total, 0, FALSE); for (cur = msglist; cur; cur = cur->next) { gchar *file = procmsg_get_message_file((MsgInfo *)cur->data); if (file == NULL) ok_to_thread = FALSE; if (message_callback != NULL) message_callback(NULL, total, curnum++, FALSE); g_free(file); } if (message_callback != NULL) message_callback(NULL, 0, 0, FALSE); if (message_callback != NULL) message_callback(_("Bogofilter: filtering messages..."), total, 0, FALSE); #ifdef USE_PTHREAD while (pthread_mutex_trylock(&list_mutex) != 0) { GTK_EVENTS_FLUSH(); usleep(100); } #endif to_filter_data = g_new0(BogoFilterData, 1); to_filter_data->msglist = msglist; to_filter_data->mail_filtering_data = mail_filtering_data; to_filter_data->new_hams = NULL; to_filter_data->new_unsure = NULL; to_filter_data->new_spams = NULL; to_filter_data->whitelisted_new_spams = NULL; to_filter_data->done = FALSE; to_filter_data->status = -1; to_filter_data->bogo_args = bogo_args; #ifdef USE_PTHREAD to_filter_data->in_thread = (filter_th != 0 && ok_to_thread); #else to_filter_data->in_thread = FALSE; #endif #ifdef USE_PTHREAD pthread_mutex_unlock(&list_mutex); if (filter_th != 0 && ok_to_thread) { debug_print("waking thread to let it filter things\n"); pthread_mutex_lock(&wait_mutex); pthread_cond_broadcast(&wait_cond); pthread_mutex_unlock(&wait_mutex); while (!to_filter_data->done) { GTK_EVENTS_FLUSH(); usleep(100); } } while (pthread_mutex_trylock(&list_mutex) != 0) { GTK_EVENTS_FLUSH(); usleep(100); } if (filter_th == 0 || !ok_to_thread) bogofilter_do_filter(to_filter_data); #else bogofilter_do_filter(to_filter_data); #endif new_hams = to_filter_data->new_hams; new_unsure = to_filter_data->new_unsure; new_spams = to_filter_data->new_spams; whitelisted_new_spams = to_filter_data->whitelisted_new_spams; status = to_filter_data->status; g_free(to_filter_data); to_filter_data = NULL; #ifdef USE_PTHREAD pthread_mutex_unlock(&list_mutex); #endif /* unflag hams */ for (cur = new_hams; cur; cur = cur->next) { MsgInfo *msginfo = (MsgInfo *)cur->data; procmsg_msginfo_unset_flags(msginfo, MSG_SPAM, 0); debug_print("unflagging ham: %d\n", msginfo->msgnum); } /* unflag unsure */ for (cur = new_unsure; cur; cur = cur->next) { MsgInfo *msginfo = (MsgInfo *)cur->data; procmsg_msginfo_unset_flags(msginfo, MSG_SPAM, 0); debug_print("unflagging unsure: %d\n", msginfo->msgnum); } if (config.learn_from_whitelist && whitelisted_new_spams) { /* flag whitelisted spams */ for (cur = whitelisted_new_spams; cur; cur = cur->next) { MsgInfo *msginfo = (MsgInfo *)cur->data; procmsg_msginfo_set_flags(msginfo, MSG_SPAM, 0); debug_print("flagging whitelisted non-ham: %d\n", msginfo->msgnum); } /* correct bogo */ bogofilter_learn(NULL, whitelisted_new_spams, FALSE); /* unflag them */ for (cur = whitelisted_new_spams; cur; cur = cur->next) { MsgInfo *msginfo = (MsgInfo *)cur->data; procmsg_msginfo_unset_flags(msginfo, MSG_SPAM, 0); debug_print("unflagging whitelisted non-ham: %d\n", msginfo->msgnum); } } else { for (cur = whitelisted_new_spams; cur; cur = cur->next) { MsgInfo *msginfo = (MsgInfo *)cur->data; procmsg_msginfo_unset_flags(msginfo, MSG_SPAM, 0); debug_print("not flagging whitelisted non-ham: %d\n", msginfo->msgnum); } } /* flag spams and delete them if config.receive_spam == 0 * (if config.receive_spam is set to 1, we'll move them later, * mark as spam only if set to 2) */ for (cur = new_spams; cur; cur = cur->next) { MsgInfo *msginfo = (MsgInfo *)cur->data; if (config.receive_spam != SPAM_DELETE) { if (config.mark_as_read) procmsg_msginfo_unset_flags(msginfo, ~0, 0); procmsg_msginfo_set_flags(msginfo, MSG_SPAM, 0); } else { folder_item_remove_msg(msginfo->folder, msginfo->msgnum); } } if (status < 0 || status > 2) { /* I/O or other errors */ gchar *msg = NULL; if (status == 3) msg = g_strdup_printf(_("The Bogofilter plugin couldn't filter " "a message. The probable cause of the " "error is that it didn't learn from any mail.\n" "Use \"/Mark/Mark as spam\" and \"/Mark/Mark as " "ham\" to train Bogofilter with a few hundred " "spam and ham messages.")); else msg = g_strdup_printf(_("The Bogofilter plugin couldn't filter " "a message. The command `%s %s %s` couldn't be run."), bogo_args[0], bogo_args[1], bogo_args[2]); if (!prefs_common_get_prefs()->no_recv_err_panel) { if (!warned_error) { alertpanel_error("%s", msg); } warned_error = TRUE; } else { log_error(LOG_PROTOCOL, "%s\n", msg); } g_free(msg); } if (status < 0 || status > 2) { g_slist_free(mail_filtering_data->filtered); g_slist_free(mail_filtering_data->unfiltered); mail_filtering_data->filtered = NULL; mail_filtering_data->unfiltered = NULL; } else { if (config.receive_spam == SPAM_MARK_AND_SAVE && new_spams) { FolderItem *save_folder = NULL; if ((!config.save_folder) || (config.save_folder[0] == '\0') || ((save_folder = folder_find_item_from_identifier(config.save_folder)) == NULL)) { if (mail_filtering_data->account && mail_filtering_data->account->set_trash_folder) { save_folder = folder_find_item_from_identifier( mail_filtering_data->account->trash_folder); if (save_folder) debug_print("found trash folder from account's advanced settings\n"); } if (save_folder == NULL && mail_filtering_data->account && mail_filtering_data->account->folder) { save_folder = mail_filtering_data->account->folder->trash; if (save_folder) debug_print("found trash folder from account's trash\n"); } if (save_folder == NULL && mail_filtering_data->account && !mail_filtering_data->account->folder) { if (mail_filtering_data->account->inbox) { FolderItem *item = folder_find_item_from_identifier( mail_filtering_data->account->inbox); if (item && item->folder->trash) { save_folder = item->folder->trash; debug_print("found trash folder from account's inbox\n"); } } if (!save_folder && mail_filtering_data->account->local_inbox) { FolderItem *item = folder_find_item_from_identifier( mail_filtering_data->account->local_inbox); if (item && item->folder->trash) { save_folder = item->folder->trash; debug_print("found trash folder from account's local_inbox\n"); } } } if (save_folder == NULL) { debug_print("using default trash folder\n"); save_folder = folder_get_default_trash(); } } if (save_folder) { for (cur = new_spams; cur; cur = cur->next) { msginfo = (MsgInfo *)cur->data; msginfo->filter_op = IS_MOVE; msginfo->to_filter_folder = save_folder; } } } if (config.save_unsure && new_unsure) { FolderItem *save_unsure_folder = NULL; if ((!config.save_unsure_folder) || (config.save_unsure_folder[0] == '\0') || ((save_unsure_folder = folder_find_item_from_identifier(config.save_unsure_folder)) == NULL)) { if (mail_filtering_data->account) save_unsure_folder = folder_find_item_from_identifier( mail_filtering_data->account->inbox); if (save_unsure_folder == NULL && mail_filtering_data->account && mail_filtering_data->account->folder) save_unsure_folder = mail_filtering_data->account->folder->inbox; if (save_unsure_folder == NULL && mail_filtering_data->account && !mail_filtering_data->account->folder) { if (mail_filtering_data->account->inbox) { FolderItem *item = folder_find_item_from_identifier( mail_filtering_data->account->inbox); if (item) { save_unsure_folder = item; } } if (!save_unsure_folder && mail_filtering_data->account->local_inbox) { FolderItem *item = folder_find_item_from_identifier( mail_filtering_data->account->local_inbox); if (item) { save_unsure_folder = item; } } } if (save_unsure_folder == NULL) save_unsure_folder = folder_get_default_inbox(); } if (save_unsure_folder) { for (cur = new_unsure; cur; cur = cur->next) { msginfo = (MsgInfo *)cur->data; msginfo->filter_op = IS_MOVE; msginfo->to_filter_folder = save_unsure_folder; } } } } g_slist_free(new_hams); g_slist_free(new_unsure); g_slist_free(new_spams); g_slist_free(whitelisted_new_spams); if (message_callback != NULL) message_callback(NULL, 0, 0, FALSE); mail_filtering_data->filtered = g_slist_reverse( mail_filtering_data->filtered); mail_filtering_data->unfiltered = g_slist_reverse( mail_filtering_data->unfiltered); return FALSE; }
static gboolean mail_filtering_hook(gpointer source, gpointer data) { MailFilteringData *mail_filtering_data = (MailFilteringData *) source; MsgInfo *msginfo = mail_filtering_data->msginfo; gboolean is_spam = FALSE, error = FALSE; static gboolean warned_error = FALSE; FILE *fp = NULL; int pid = 0; int status; /* SPAMASSASSIN_DISABLED : keep test for compatibility purpose */ if (!config.enable || config.transport == SPAMASSASSIN_DISABLED) { log_warning(LOG_PROTOCOL, _("SpamAssassin plugin is disabled by its preferences.\n")); return FALSE; } debug_print("Filtering message %d\n", msginfo->msgnum); if (message_callback != NULL) message_callback(_("SpamAssassin: filtering message...")); if ((fp = procmsg_open_message(msginfo)) == NULL) { debug_print("failed to open message file\n"); return FALSE; } if (config.whitelist_ab) { gchar *ab_folderpath; gboolean whitelisted = FALSE; if (*config.whitelist_ab_folder == '\0' || strcasecmp(config.whitelist_ab_folder, "Any") == 0) { /* match the whole addressbook */ ab_folderpath = NULL; } else { /* match the specific book/folder of the addressbook */ ab_folderpath = config.whitelist_ab_folder; } start_address_completion(ab_folderpath); if (msginfo->from && sa_found_in_addressbook(msginfo->from)) whitelisted = TRUE; end_address_completion(); if (whitelisted) { debug_print("message is ham (whitelisted)\n"); fclose(fp); return FALSE; } } pid = fork(); if (pid == 0) { _exit(msg_is_spam(fp)); } else { gint running = 0; running |= CHILD_RUNNING; g_timeout_add(50, timeout_func, &running); running |= TIMEOUT_RUNNING; while(running & CHILD_RUNNING) { int ret; ret = waitpid(pid, &status, WNOHANG); if (ret == pid) { if (WIFEXITED(status)) { MsgStatus result = MSG_IS_HAM; running &= ~CHILD_RUNNING; result = WEXITSTATUS(status); is_spam = (result == MSG_IS_SPAM) ? TRUE : FALSE; error = (result == MSG_FILTERING_ERROR); } } if (ret < 0) { running &= ~CHILD_RUNNING; } /* ret == 0 continue */ g_main_context_iteration(NULL, TRUE); } while (running & TIMEOUT_RUNNING) g_main_context_iteration(NULL, TRUE); } fclose(fp); if (is_spam) { debug_print("message is spam\n"); procmsg_msginfo_set_flags(msginfo, MSG_SPAM, 0); if (config.receive_spam) { FolderItem *save_folder = NULL; if ((!config.save_folder) || (config.save_folder[0] == '\0') || ((save_folder = folder_find_item_from_identifier(config.save_folder)) == NULL)) { if (mail_filtering_data->account && mail_filtering_data->account->set_trash_folder) { save_folder = folder_find_item_from_identifier( mail_filtering_data->account->trash_folder); if (save_folder) debug_print("found trash folder from account's advanced settings\n"); } if (save_folder == NULL && mail_filtering_data->account && mail_filtering_data->account->folder) { save_folder = mail_filtering_data->account->folder->trash; if (save_folder) debug_print("found trash folder from account's trash\n"); } if (save_folder == NULL && mail_filtering_data->account && !mail_filtering_data->account->folder) { if (mail_filtering_data->account->inbox) { FolderItem *item = folder_find_item_from_identifier( mail_filtering_data->account->inbox); if (item && item->folder->trash) { save_folder = item->folder->trash; debug_print("found trash folder from account's inbox\n"); } } if (!save_folder && mail_filtering_data->account->local_inbox) { FolderItem *item = folder_find_item_from_identifier( mail_filtering_data->account->local_inbox); if (item && item->folder->trash) { save_folder = item->folder->trash; debug_print("found trash folder from account's local_inbox\n"); } } } if (save_folder == NULL) { debug_print("using default trash folder\n"); save_folder = folder_get_default_trash(); } } if (config.mark_as_read) procmsg_msginfo_unset_flags(msginfo, ~0, 0); procmsg_msginfo_set_flags(msginfo, MSG_SPAM, 0); msginfo->filter_op = IS_MOVE; msginfo->to_filter_folder = save_folder; } else { folder_item_remove_msg(msginfo->folder, msginfo->msgnum); } return TRUE; } else { debug_print("message is ham\n"); procmsg_msginfo_unset_flags(msginfo, MSG_SPAM, 0); } if (error) { gchar *msg = _("The SpamAssassin plugin couldn't filter " "a message. The probable cause of the error " "is an unreachable spamd daemon. Please make " "sure spamd is running and accessible."); if (!prefs_common_get_prefs()->no_recv_err_panel) { if (!warned_error) { alertpanel_error("%s", msg); } warned_error = TRUE; } else { log_error(LOG_PROTOCOL, "%s\n", msg); } } return FALSE; }