Beispiel #1
0
FILE *procmsg_open_message(MsgInfo *msginfo)
{
	FILE *fp;
	gchar *file;

	g_return_val_if_fail(msginfo != NULL, NULL);

	file = procmsg_get_message_file_path(msginfo);
	g_return_val_if_fail(file != NULL, NULL);

	if (!is_file_exist(file)) {
		g_free(file);
		file = procmsg_get_message_file(msginfo);
		if (!file)
			return NULL;
	}

	if ((fp = fopen(file, "rb")) == NULL) {
		FILE_OP_ERROR(file, "fopen");
		g_free(file);
		return NULL;
	}

	g_free(file);

	if (MSG_IS_QUEUED(msginfo->flags) || MSG_IS_DRAFT(msginfo->flags)) {
		gchar buf[BUFFSIZE];

		while (fgets(buf, sizeof(buf), fp) != NULL)
			if (buf[0] == '\r' || buf[0] == '\n') break;
	}

	return fp;
}
Beispiel #2
0
GSList *procmsg_get_message_file_list(GSList *mlist)
{
        GSList *file_list = NULL;
        MsgInfo *msginfo;
        MsgFileInfo *fileinfo;
        gchar *file;

        while (mlist != NULL) {
                msginfo = (MsgInfo *)mlist->data;
                file = procmsg_get_message_file(msginfo);
                if (!file) {
                        procmsg_message_file_list_free(file_list);
                        return NULL;
                }
                fileinfo = g_new(MsgFileInfo, 1);
		fileinfo->msginfo = procmsg_msginfo_new_ref(msginfo);
                fileinfo->file = file;
                fileinfo->flags = g_new(MsgFlags, 1);
                *fileinfo->flags = msginfo->flags;
                file_list = g_slist_prepend(file_list, fileinfo);
                mlist = mlist->next;
        }

        file_list = g_slist_reverse(file_list);

        return file_list;
}
Beispiel #3
0
MsgInfo *procmsg_msginfo_get_full_info(MsgInfo *msginfo)
{
	MsgInfo *full_msginfo;
	gchar *file;

	if (msginfo == NULL) return NULL;

	file = procmsg_get_message_file_path(msginfo);
	if (!file || !is_file_exist(file)) {
		g_free(file);
		file = procmsg_get_message_file(msginfo);
	}
	if (!file || !is_file_exist(file)) {
		g_warning("procmsg_msginfo_get_full_info(): can't get message file.\n");
		return NULL;
	}

	full_msginfo = procheader_parse_file(file, msginfo->flags, TRUE, FALSE);
	g_free(file);
	if (!full_msginfo) return NULL;

	/* CLAWS: make sure we add the missing members; see: 
	 * procheader.c::procheader_get_headernames() */
	if (!msginfo->xface)
		msginfo->xface = g_strdup(full_msginfo->xface);
	if (!msginfo->dispositionnotificationto)
		msginfo->dispositionnotificationto = 
			g_strdup(full_msginfo->dispositionnotificationto);
	if (!msginfo->returnreceiptto)
		msginfo->returnreceiptto = g_strdup
			(full_msginfo->returnreceiptto);
	if (!msginfo->partial_recv && full_msginfo->partial_recv)
		msginfo->partial_recv = g_strdup
			(full_msginfo->partial_recv);
	msginfo->total_size = full_msginfo->total_size;
	if (!msginfo->account_server && full_msginfo->account_server)
		msginfo->account_server = g_strdup
			(full_msginfo->account_server);
	if (!msginfo->account_login && full_msginfo->account_login)
		msginfo->account_login = g_strdup
			(full_msginfo->account_login);
	msginfo->planned_download = full_msginfo->planned_download;
	procmsg_msginfo_free(full_msginfo);

	return procmsg_msginfo_new_ref(msginfo);
}
Beispiel #4
0
void source_window_show_msg(SourceWindow *sourcewin, MsgInfo *msginfo)
{
	gchar *file;
	gchar *title;
	FILE *fp;
	gchar buf[BUFFSIZE];

	cm_return_if_fail(msginfo != NULL);

	sourcewin->updating = TRUE;
	file = procmsg_get_message_file(msginfo);
	sourcewin->updating = FALSE;
	
	if (sourcewin->deferred_destroy) {
		g_free(file);
		source_window_destroy(sourcewin);
		return;
	}

	cm_return_if_fail(file != NULL);

	if ((fp = g_fopen(file, "rb")) == NULL) {
		FILE_OP_ERROR(file, "fopen");
		g_free(file);
		return;
	}

	debug_print("Displaying the source of %s ...\n", file);

	title = g_strdup_printf(_("%s - Source"), file);
	gtk_window_set_title(GTK_WINDOW(sourcewin->window), title);
	g_free(title);
	g_free(file);

	while (fgets(buf, sizeof(buf), fp) != NULL)
		source_window_append(sourcewin, buf);

	fclose(fp);
}
Beispiel #5
0
static gint mh_copy_msgs(Folder *folder, FolderItem *dest, MsgInfoList *msglist, 
			 GHashTable *relation)
{
	gboolean dest_need_scan = FALSE;
	gboolean src_need_scan = FALSE;
	FolderItem *src = NULL;
	gchar *srcfile;
	gchar *destfile;
	FolderItemPrefs *prefs;
	MsgInfo *msginfo = NULL;
	MsgInfoList *cur = NULL;
	gint curnum = 0, total = 0;
	gchar *srcpath = NULL;
	gboolean full_fetch = FALSE;
	time_t last_dest_mtime = (time_t)0;
	time_t last_src_mtime = (time_t)0;

	cm_return_val_if_fail(dest != NULL, -1);
	cm_return_val_if_fail(msglist != NULL, -1);
	
	msginfo = (MsgInfo *)msglist->data;

	cm_return_val_if_fail(msginfo != NULL, -1);

	if (msginfo->folder == dest) {
		g_warning("the src folder is identical to the dest.\n");
		return -1;
	}

	if (msginfo->folder->folder != dest->folder)
		full_fetch = TRUE;
	
	if (FOLDER_TYPE(msginfo->folder->folder) == F_MH) {
		src = msginfo->folder;
	}

	if (dest->last_num < 0) {
		mh_get_last_num(folder, dest);
		if (dest->last_num < 0) return -1;
	}

	prefs = dest->prefs;

	srcpath = folder_item_get_path(msginfo->folder);

	dest_need_scan = mh_scan_required(dest->folder, dest);
	last_dest_mtime = dest->mtime;

	if (src) {
		src_need_scan = mh_scan_required(src->folder, src);
		last_src_mtime = src->mtime;
	}

	total = g_slist_length(msglist);
	if (total > 100) {
		if (MSG_IS_MOVE(msginfo->flags))
			statusbar_print_all(_("Moving messages..."));
		else
			statusbar_print_all(_("Copying messages..."));
	}
	for (cur = msglist; cur; cur = cur->next) {
		msginfo = (MsgInfo *)cur->data;
		if (!msginfo) {
			goto err_reset_status;
		}
		if (!full_fetch) {
			srcfile = g_strconcat(srcpath, 
				G_DIR_SEPARATOR_S, 
				itos(msginfo->msgnum), NULL);
		} else {
			srcfile = procmsg_get_message_file(msginfo);
		}
		if (!srcfile) {
			goto err_reset_status;
		}
		destfile = mh_get_new_msg_filename(dest);
		if (!destfile) {
			g_free(srcfile);
			goto err_reset_status;
		}

		if (total > 100) {
			statusbar_progress_all(curnum, total, 100);
			if (curnum % 100 == 0)
				GTK_EVENTS_FLUSH();
			curnum++;
		}

		debug_print("Copying message %s%c%d to %s ...\n",
			    msginfo->folder->path, G_DIR_SEPARATOR,
			    msginfo->msgnum, dest->path);


		if (MSG_IS_MOVE(msginfo->flags)) {
			msginfo->flags.tmp_flags &= ~MSG_MOVE_DONE;
			if (move_file(srcfile, destfile, TRUE) < 0) {
				FILE_OP_ERROR(srcfile, "move");
				if (copy_file(srcfile, destfile, TRUE) < 0) {
					FILE_OP_ERROR(srcfile, "copy");
					g_free(srcfile);
					g_free(destfile);
					goto err_reset_status;
				}
			} else {
				/* say unlinking's not necessary */
				msginfo->flags.tmp_flags |= MSG_MOVE_DONE;
			}
		} else if (copy_file(srcfile, destfile, TRUE) < 0) {
			FILE_OP_ERROR(srcfile, "copy");
			g_free(srcfile);
			g_free(destfile);
			goto err_reset_status;
		} 
		if (prefs && prefs->enable_folder_chmod && prefs->folder_chmod) {
			if (chmod(destfile, prefs->folder_chmod) < 0)
				FILE_OP_ERROR(destfile, "chmod");
		}
		if (relation) {
			if (g_hash_table_lookup(relation, msginfo) != NULL)
				g_warning("already in : %p", msginfo);
			
			g_hash_table_insert(relation, msginfo, GINT_TO_POINTER(dest->last_num+1));
		}
		g_free(srcfile);
		g_free(destfile);
		dest->last_num++;
	}

	g_free(srcpath);
	mh_write_sequences(dest, TRUE);

	if (dest->mtime == last_dest_mtime && !dest_need_scan) {
		mh_set_mtime(folder, dest);
	}

	if (src && src->mtime == last_src_mtime && !src_need_scan) {
		mh_set_mtime(folder, src);
	}

	if (total > 100) {
		statusbar_progress_all(0,0,0);
		statusbar_pop_all();
	}
	return dest->last_num;
err_reset_status:
	g_free(srcpath);
	mh_write_sequences(dest, TRUE);
	if (total > 100) {
		statusbar_progress_all(0,0,0);
		statusbar_pop_all();
	}
	return -1;

}
Beispiel #6
0
int bogofilter_learn(MsgInfo *msginfo, GSList *msglist, gboolean spam)
{
	gchar *cmd = NULL;
	gchar *file = NULL;
	const gchar *bogo_exec = (config.bogopath && *config.bogopath) ? config.bogopath:"bogofilter";
	gint status = 0;

	if (msginfo == NULL && msglist == NULL) {
		return -1;
	}

	if (msginfo) {
		file = procmsg_get_message_file(msginfo);
		if (file == NULL) {
			return -1;
		} else {
			if (message_callback != NULL)
				message_callback(_("Bogofilter: learning from message..."), 0, 0, FALSE);
			if (spam)
				/* learn as spam */
				cmd = g_strdup_printf("%s -s -I '%s'", bogo_exec, file);
			else if (MSG_IS_SPAM(msginfo->flags))
				/* correct bogofilter, this wasn't spam */
				cmd = g_strdup_printf("%s -Sn -I '%s'", bogo_exec, file);
			else 
				/* learn as ham */
				cmd = g_strdup_printf("%s -n -I '%s'", bogo_exec, file);
				
			debug_print("%s\n", cmd);
			if ((status = execute_command_line(cmd, FALSE, NULL)) != 0)
				log_error(LOG_PROTOCOL, _("Learning failed; `%s` returned with status %d."),
						cmd, status);
			g_free(cmd);
			g_free(file);
			if (message_callback != NULL)
				message_callback(NULL, 0, 0, FALSE);
		}
	} else if (msglist) {
		GSList *cur = msglist;
		MsgInfo *info;
		int total = g_slist_length(msglist);
		int done = 0;
		gboolean some_correction = FALSE, some_no_correction = FALSE;
	
		if (message_callback != NULL)
			message_callback(_("Bogofilter: learning from messages..."), total, 0, FALSE);
		
		for (cur = msglist; cur && status == 0; cur = cur->next) {
			info = (MsgInfo *)cur->data;
			if (spam)
				some_no_correction = TRUE;
			else if (MSG_IS_SPAM(info->flags))
				/* correct bogofilter, this wasn't spam */
				some_correction = TRUE;
			else 
				some_no_correction = TRUE;
			
		}
		
		if (some_correction && some_no_correction) {
			/* we potentially have to do different stuff for every mail */
			for (cur = msglist; cur && status == 0; cur = cur->next) {
				info = (MsgInfo *)cur->data;
				file = procmsg_get_message_file(info);

				if (spam)
					/* learn as spam */
					cmd = g_strdup_printf("%s -s -I '%s'", bogo_exec, file);
				else if (MSG_IS_SPAM(info->flags))
					/* correct bogofilter, this wasn't spam */
					cmd = g_strdup_printf("%s -Sn -I '%s'", bogo_exec, file);
				else 
					/* learn as ham */
					cmd = g_strdup_printf("%s -n -I '%s'", bogo_exec, file);
				
				debug_print("%s\n", cmd);
				if ((status = execute_command_line(cmd, FALSE, NULL)) != 0)
					log_error(LOG_PROTOCOL, _("Learning failed; `%s` returned with status %d."),
							cmd, status);

				g_free(cmd);
				g_free(file);
				done++;
				if (message_callback != NULL)
					message_callback(NULL, total, done, FALSE);
			}
		} else if (some_correction || some_no_correction) {
			cur = msglist;
			
			gchar *bogo_args[4];
			GPid bogo_pid;
			gint bogo_stdin;
			GError *error = NULL;
			gboolean bogo_forked;

			bogo_args[0] = (gchar *)bogo_exec;
			if (some_correction && !some_no_correction)
				bogo_args[1] = "-Sn";
			else if (some_no_correction && !some_correction)
				bogo_args[1] = spam ? "-s":"-n";
			bogo_args[2] = "-b";
			bogo_args[3] = NULL;
			debug_print("|%s %s %s ...\n", bogo_args[0], bogo_args[1], bogo_args[2]);
			bogo_forked = g_spawn_async_with_pipes(
					NULL, bogo_args,NULL, G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,
					NULL, NULL, &bogo_pid, &bogo_stdin,
					NULL, NULL, &error);

			while (bogo_forked && cur) {
				gchar *tmp = NULL;
				info = (MsgInfo *)cur->data;
				file = procmsg_get_message_file(info);
				if (file) {
					tmp = g_strdup_printf("%s\n", 
						file);
					write_all(bogo_stdin, tmp, strlen(tmp));
					g_free(tmp);
				}
				g_free(file);
				done++;
				if (message_callback != NULL)
					message_callback(NULL, total, done, FALSE);
				cur = cur->next;
			}
			if (bogo_forked) {
				close(bogo_stdin);
				waitpid(bogo_pid, &status, 0);
				if (!WIFEXITED(status))
					status = -1;
				else
					status = WEXITSTATUS(status);
			}
			if (!bogo_forked || status != 0) {
				log_error(LOG_PROTOCOL, _("Learning failed; `%s %s %s` returned with error:\n%s"),
						bogo_args[0], bogo_args[1], bogo_args[2], 
						error ? error->message:_("Unknown error"));
				if (error)
					g_error_free(error);
			}

		}

		if (message_callback != NULL)
			message_callback(NULL, 0, 0, FALSE);
	}
	return 0;
}
Beispiel #7
0
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;
}
Beispiel #8
0
static void bogofilter_do_filter(BogoFilterData *data)
{
	GPid bogo_pid;
	gint bogo_stdin, bogo_stdout;
	GError *error = NULL;
	gboolean bogo_forked;
	int status = 0;
	MsgInfo *msginfo;
	GSList *cur = NULL;
	int total = 0, curnum = 1;
	gchar *file = NULL;
	gchar buf[BUFSIZ];

	total = g_slist_length(data->msglist);

	bogo_forked = g_spawn_async_with_pipes(
			NULL, data->bogo_args,NULL, G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,
			NULL, NULL, &bogo_pid, &bogo_stdin,
			&bogo_stdout, NULL, &error);
		
	if (bogo_forked == FALSE) {
		g_warning("%s", error ? error->message:"ERROR???");
		g_error_free(error);
		error = NULL;
		status = -1;
	} else {
	
		if (config.whitelist_ab) {
			gchar *ab_folderpath;

			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);
		}

		for (cur = data->msglist; cur; cur = cur->next) {
			gboolean whitelisted = FALSE;
			msginfo = (MsgInfo *)cur->data;
			debug_print("Filtering message %d (%d/%d)\n", msginfo->msgnum, curnum, total);

			if (message_callback != NULL)
				message_callback(NULL, total, curnum++, data->in_thread);

			if (config.whitelist_ab && msginfo->from && 
			    found_in_addressbook(msginfo->from))
				whitelisted = TRUE;

			/* can set flags (SCANNED, ATTACHMENT) but that's ok 
			 * as GUI updates are hooked not direct */

			file = procmsg_get_message_file(msginfo);

			if (file) {
				gchar *tmp = g_strdup_printf("%s\n",file);
				/* send filename to bogofilter */
				write_all(bogo_stdin, tmp, strlen(tmp));
				g_free(tmp);
				memset(buf, 0, sizeof(buf));
				/* get the result */
				if (read(bogo_stdout, buf, sizeof(buf)-1) < 0) {
					g_warning("bogofilter short read");
					debug_print("message %d is ham\n", msginfo->msgnum);
					data->mail_filtering_data->unfiltered = g_slist_prepend(
						data->mail_filtering_data->unfiltered, msginfo);
					data->new_hams = g_slist_prepend(data->new_hams, msginfo);
				} else {
					gchar **parts = NULL;

					buf[sizeof(buf) - 1] = '\0';
					if (strchr(buf, '/')) {
						tmp = strrchr(buf, '/')+1;
					} else {
						tmp = buf;
					}
					parts = g_strsplit(tmp, " ", 0);
					debug_print("read %s\n", buf);
					
					/* note the result if the header if needed */
					if (parts && parts[0] && parts[1] && parts[2] && 
					    FOLDER_TYPE(msginfo->folder->folder) == F_MH &&
					    config.insert_header) {
						gchar *tmpfile = get_tmp_file();
						FILE *input = claws_fopen(file, "r");
						FILE *output = claws_fopen(tmpfile, "w");
						if (strstr(parts[2], "\n"))
							*(strstr(parts[2], "\n")) = '\0';
						if (input && !output) 
							claws_fclose (input);
						else if (!input && output)
							claws_fclose (output);
						else if (input && output) {
							gchar tmpbuf[BUFFSIZE];
							gboolean err = FALSE;
							const gchar *bogosity = *parts[1] == 'S' ? "Spam":
										 (*parts[1] == 'H' ? "Ham":"Unsure");
							gchar *tmpstr = g_strdup_printf(
									"X-Bogosity: %s, spamicity=%s%s\n",
									bogosity, parts[2],
									whitelisted?" [whitelisted]":"");
							if (claws_fwrite(tmpstr, 1, strlen(tmpstr), output) < strlen(tmpstr)) {
								err = TRUE;
							} else {
								while (claws_fgets(tmpbuf, sizeof(buf), input)) {
									if (claws_fputs(tmpbuf, output) == EOF) {
										err = TRUE;
										break;
									}
								}
							}
							claws_fclose(input);
							if (claws_safe_fclose(output) == EOF)
								err = TRUE;
							if (!err)
								move_file(tmpfile, file, TRUE);
							g_free(tmpstr);
						}
						g_free(tmpfile);
					}

					/* file the mail */
					if (!whitelisted && parts && parts[0] && parts[1] && *parts[1] == 'S') {

						debug_print("message %d is spam\n", msginfo->msgnum);
						/* Spam will be filtered away, unless we want "mark only".
						 * In that case, we want it among unfiltered messages, so
						 * it gets processed further. */
						if (config.receive_spam == SPAM_MARK_ONLY) {
							data->mail_filtering_data->unfiltered = g_slist_prepend(
								data->mail_filtering_data->unfiltered, msginfo);
						} else {
							data->mail_filtering_data->filtered = g_slist_prepend(
								data->mail_filtering_data->filtered, msginfo);
						}
						data->new_spams = g_slist_prepend(data->new_spams, msginfo);

					} else if (whitelisted && parts && parts[0] && parts[1] && 
							(*parts[1] == 'S' || *parts[1] == 'U')) {

						debug_print("message %d is whitelisted %s\n", msginfo->msgnum,
							*parts[1] == 'S' ? "spam":"unsure");
						/* Whitelisted spam will *not* be filtered away, but continue
						 * their trip through filtering as if it was ham. */
						data->mail_filtering_data->unfiltered = g_slist_prepend(
							data->mail_filtering_data->unfiltered, msginfo);
						/* But it gets put in a different list, so that we 
						 * can still flag it and inform the user that it is
						 * considered a spam (so that he can teach bogo that 
						 * it was not). */
						data->whitelisted_new_spams = g_slist_prepend(data->whitelisted_new_spams, msginfo);

					} else if (config.save_unsure && parts && parts[0] && parts[1] && *parts[1] == 'U') {
						
						debug_print("message %d is unsure\n", msginfo->msgnum);
						/* Spam will be filtered away */
						data->mail_filtering_data->filtered = g_slist_prepend(
							data->mail_filtering_data->filtered, msginfo);
						data->new_unsure = g_slist_prepend(data->new_unsure, msginfo);

					} else {
						
						debug_print("message %d is ham\n", msginfo->msgnum);
						data->mail_filtering_data->unfiltered = g_slist_prepend(
							data->mail_filtering_data->unfiltered, msginfo);
						data->new_hams = g_slist_prepend(data->new_hams, msginfo);

					}
					g_strfreev(parts);
				}
				g_free(file);
			} else {
				data->mail_filtering_data->unfiltered = g_slist_prepend(
					data->mail_filtering_data->unfiltered, msginfo);
				data->new_hams = g_slist_prepend(data->new_hams, msginfo);
			}
		}
		if (config.whitelist_ab)
			end_address_completion();
	}
	if (status != -1) {
		close(bogo_stdout);
		close(bogo_stdin);
		waitpid(bogo_pid, &status, 0);
		if (!WIFEXITED(status))
			status = -1;
		else
			status = WEXITSTATUS(status);
	}

	to_filter_data->status = status; 
}
Beispiel #9
0
int spamassassin_learn(MsgInfo *msginfo, GSList *msglist, gboolean spam)
{
	gchar *cmd = NULL;
	gchar *file = NULL;
	const gchar *shell = g_getenv("SHELL");
	gchar *spamc_wrapper = NULL;

	if (msginfo == NULL && msglist == NULL) {
		return -1;
	}

	if (config.transport == SPAMASSASSIN_TRANSPORT_TCP
	&&  prefs_common_get_prefs()->work_offline
	&&  !inc_offline_should_override(TRUE,
		_("Claws Mail needs network access in order "
		  "to feed the mail to the remote learner."))) {
		return -1;
	}

	if (msginfo) {
		file = procmsg_get_message_file(msginfo);
		if (file == NULL) {
			return -1;
		}
		if (config.transport == SPAMASSASSIN_TRANSPORT_TCP) {
			spamc_wrapper = spamassassin_create_tmp_spamc_wrapper(spam);
			if (spamc_wrapper != NULL) {
				cmd = g_strconcat(shell?shell:"sh", " ",
								spamc_wrapper, " ", file, NULL);
			}
		} else {
			cmd = g_strdup_printf("sa-learn -u %s%s %s %s",
							config.username,
							prefs_common_get_prefs()->work_offline?" -L":"",
							spam?"--spam":"--ham", file);
		}
	}
	if (msglist) {
		GSList *cur = msglist;
		MsgInfo *info;

		if (config.transport == SPAMASSASSIN_TRANSPORT_TCP) {
			/* execute n-times the spamc command */
			for (; cur; cur = cur->next) {
				info = (MsgInfo *)cur->data;
				gchar *tmpcmd = NULL;
				gchar *tmpfile = get_tmp_file();

				if (spamc_wrapper == NULL) {
					spamc_wrapper = spamassassin_create_tmp_spamc_wrapper(spam);
				}

				if (spamc_wrapper && tmpfile &&
			    	copy_file(procmsg_get_message_file(info), tmpfile, TRUE) == 0) {
					tmpcmd = g_strconcat(shell?shell:"sh", " ", spamc_wrapper, " ",
										tmpfile, NULL);
					debug_print("%s\n", tmpcmd);
					execute_command_line(tmpcmd, FALSE, NULL);
					g_free(tmpcmd);
				}
				g_free(tmpfile);
			}
			g_free(spamc_wrapper);
			return 0;
		} else {
			cmd = g_strdup_printf("sa-learn -u %s%s %s",
					config.username,
					prefs_common_get_prefs()->work_offline?" -L":"",
					spam?"--spam":"--ham");

			/* concatenate all message tmpfiles to the sa-learn command-line */
			for (; cur; cur = cur->next) {
				info = (MsgInfo *)cur->data;
				gchar *tmpcmd = NULL;
				gchar *tmpfile = get_tmp_file();

				if (tmpfile &&
			    	copy_file(procmsg_get_message_file(info), tmpfile, TRUE) == 0) {			
					tmpcmd = g_strconcat(cmd, " ", tmpfile, NULL);
					g_free(cmd);
					cmd = tmpcmd;
				}
				g_free(tmpfile);
			}
		}
	}
	if (cmd == NULL) {
		return -1;
	}
	debug_print("%s\n", cmd);
	/* only run sync calls to sa-learn/spamc to prevent system lockdown */
	execute_command_line(cmd, FALSE, NULL);
	g_free(cmd);
	g_free(spamc_wrapper);

	return 0;
}