2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2005 Hiroyuki Yamamoto
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include <glib/gi18n.h>
31 #include "procheader.h"
32 #include "send_message.h"
34 #include "statusbar.h"
35 #include "prefs_filtering.h"
36 #include "filtering.h"
38 #include "prefs_common.h"
40 #include "alertpanel.h"
44 #include "partial_download.h"
46 static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_session);
54 Q_MAIL_ACCOUNT_ID = 4,
55 Q_NEWS_ACCOUNT_ID = 5,
56 Q_SAVE_COPY_FOLDER = 6,
57 Q_REPLY_MESSAGE_ID = 7,
64 GHashTable *procmsg_msg_hash_table_create(GSList *mlist)
66 GHashTable *msg_table;
68 if (mlist == NULL) return NULL;
70 msg_table = g_hash_table_new(NULL, g_direct_equal);
71 procmsg_msg_hash_table_append(msg_table, mlist);
76 void procmsg_msg_hash_table_append(GHashTable *msg_table, GSList *mlist)
81 if (msg_table == NULL || mlist == NULL) return;
83 for (cur = mlist; cur != NULL; cur = cur->next) {
84 msginfo = (MsgInfo *)cur->data;
86 g_hash_table_insert(msg_table,
87 GUINT_TO_POINTER(msginfo->msgnum),
92 GHashTable *procmsg_to_folder_hash_table_create(GSList *mlist)
94 GHashTable *msg_table;
98 if (mlist == NULL) return NULL;
100 msg_table = g_hash_table_new(NULL, g_direct_equal);
102 for (cur = mlist; cur != NULL; cur = cur->next) {
103 msginfo = (MsgInfo *)cur->data;
104 g_hash_table_insert(msg_table, msginfo->to_folder, msginfo);
110 gint procmsg_get_last_num_in_msg_list(GSList *mlist)
116 for (cur = mlist; cur != NULL; cur = cur->next) {
117 msginfo = (MsgInfo *)cur->data;
118 if (msginfo && msginfo->msgnum > last)
119 last = msginfo->msgnum;
125 void procmsg_msg_list_free(GSList *mlist)
130 for (cur = mlist; cur != NULL; cur = cur->next) {
131 msginfo = (MsgInfo *)cur->data;
132 procmsg_msginfo_free(msginfo);
146 /* CLAWS subject threading:
148 in the first round it inserts subject lines in a
149 relation (subject <-> node)
151 the second round finishes the threads by attaching
152 matching subject lines to the one found in the
153 relation. will use the oldest node with the same
154 subject that is not more then thread_by_subject_max_age
155 days old (see subject_relation_lookup)
158 static void subject_relation_insert(GRelation *relation, GNode *node)
163 g_return_if_fail(relation != NULL);
164 g_return_if_fail(node != NULL);
165 msginfo = (MsgInfo *) node->data;
166 g_return_if_fail(msginfo != NULL);
168 subject = msginfo->subject;
171 subject += subject_get_prefix_length(subject);
173 g_relation_insert(relation, subject, node);
176 static GNode *subject_relation_lookup(GRelation *relation, MsgInfo *msginfo)
183 g_return_val_if_fail(relation != NULL, NULL);
185 subject = msginfo->subject;
188 prefix_length = subject_get_prefix_length(subject);
189 if (prefix_length <= 0)
191 subject += prefix_length;
193 tuples = g_relation_select(relation, subject, 0);
197 if (tuples->len > 0) {
199 GNode *relation_node;
200 MsgInfo *relation_msginfo = NULL, *best_msginfo = NULL;
203 /* check all nodes with the same subject to find the best parent */
204 for (i = 0; i < tuples->len; i++) {
205 relation_node = (GNode *) g_tuples_index(tuples, i, 1);
206 relation_msginfo = (MsgInfo *) relation_node->data;
209 /* best node should be the oldest in the found nodes */
210 /* parent node must not be older then msginfo */
211 if ((relation_msginfo->date_t < msginfo->date_t) &&
212 ((best_msginfo == NULL) ||
213 (best_msginfo->date_t > relation_msginfo->date_t)))
216 /* parent node must not be more then thread_by_subject_max_age
217 days older then msginfo */
218 if (abs(difftime(msginfo->date_t, relation_msginfo->date_t)) >
219 prefs_common.thread_by_subject_max_age * 3600 * 24)
222 /* can add new tests for all matching
223 nodes found by subject */
226 node = relation_node;
227 best_msginfo = relation_msginfo;
232 g_tuples_destroy(tuples);
236 /* return the reversed thread tree */
237 GNode *procmsg_get_thread_tree(GSList *mlist)
239 GNode *root, *parent, *node, *next;
240 GHashTable *msgid_table;
241 GRelation *subject_relation;
246 root = g_node_new(NULL);
247 msgid_table = g_hash_table_new(g_str_hash, g_str_equal);
248 subject_relation = g_relation_new(2);
249 g_relation_index(subject_relation, 0, g_str_hash, g_str_equal);
251 for (; mlist != NULL; mlist = mlist->next) {
252 msginfo = (MsgInfo *)mlist->data;
255 if (msginfo->inreplyto) {
256 parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto);
257 if (parent == NULL) {
261 node = g_node_insert_data_before
262 (parent, parent == root ? parent->children : NULL,
264 if ((msgid = msginfo->msgid) && g_hash_table_lookup(msgid_table, msgid) == NULL)
265 g_hash_table_insert(msgid_table, (gchar *)msgid, node);
267 /* CLAWS: add subject to relation (without prefix) */
268 if (prefs_common.thread_by_subject) {
269 subject_relation_insert(subject_relation, node);
273 /* complete the unfinished threads */
274 for (node = root->children; node != NULL; ) {
276 msginfo = (MsgInfo *)node->data;
279 if (msginfo->inreplyto)
280 parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto);
282 /* try looking for the indirect parent */
283 if (!parent && msginfo->references) {
284 for (reflist = msginfo->references;
285 reflist != NULL; reflist = reflist->next)
286 if ((parent = g_hash_table_lookup
287 (msgid_table, reflist->data)) != NULL)
291 /* node should not be the parent, and node should not
292 be an ancestor of parent (circular reference) */
293 if (parent && parent != node &&
294 !g_node_is_ancestor(node, parent)) {
297 (parent, parent->children, node);
303 if (prefs_common.thread_by_subject) {
304 for (node = root->children; node && node != NULL;) {
306 msginfo = (MsgInfo *) node->data;
308 parent = subject_relation_lookup(subject_relation, msginfo);
310 /* the node may already be threaded by IN-REPLY-TO, so go up
312 find the parent node */
313 if (parent != NULL) {
314 if (g_node_is_ancestor(node, parent))
322 g_node_append(parent, node);
329 g_relation_destroy(subject_relation);
330 g_hash_table_destroy(msgid_table);
335 void procmsg_move_messages(GSList *mlist)
337 GSList *cur, *movelist = NULL;
339 FolderItem *dest = NULL;
343 folder_item_update_freeze();
345 for (cur = mlist; cur != NULL; cur = cur->next) {
346 msginfo = (MsgInfo *)cur->data;
348 dest = msginfo->to_folder;
349 movelist = g_slist_append(movelist, msginfo);
350 } else if (dest == msginfo->to_folder) {
351 movelist = g_slist_append(movelist, msginfo);
353 folder_item_move_msgs(dest, movelist);
354 g_slist_free(movelist);
356 dest = msginfo->to_folder;
357 movelist = g_slist_append(movelist, msginfo);
359 procmsg_msginfo_set_to_folder(msginfo, NULL);
363 folder_item_move_msgs(dest, movelist);
364 g_slist_free(movelist);
367 folder_item_update_thaw();
370 void procmsg_copy_messages(GSList *mlist)
372 GSList *cur, *copylist = NULL;
374 FolderItem *dest = NULL;
378 folder_item_update_freeze();
380 for (cur = mlist; cur != NULL; cur = cur->next) {
381 msginfo = (MsgInfo *)cur->data;
383 dest = msginfo->to_folder;
384 copylist = g_slist_append(copylist, msginfo);
385 } else if (dest == msginfo->to_folder) {
386 copylist = g_slist_append(copylist, msginfo);
388 folder_item_copy_msgs(dest, copylist);
389 g_slist_free(copylist);
391 dest = msginfo->to_folder;
392 copylist = g_slist_append(copylist, msginfo);
394 procmsg_msginfo_set_to_folder(msginfo, NULL);
398 folder_item_copy_msgs(dest, copylist);
399 g_slist_free(copylist);
402 folder_item_update_thaw();
405 gchar *procmsg_get_message_file_path(MsgInfo *msginfo)
409 g_return_val_if_fail(msginfo != NULL, NULL);
411 if (msginfo->plaintext_file)
412 file = g_strdup(msginfo->plaintext_file);
414 file = folder_item_fetch_msg(msginfo->folder, msginfo->msgnum);
420 gchar *procmsg_get_message_file(MsgInfo *msginfo)
422 gchar *filename = NULL;
424 g_return_val_if_fail(msginfo != NULL, NULL);
426 filename = folder_item_fetch_msg(msginfo->folder, msginfo->msgnum);
428 debug_print("can't fetch message %d\n", msginfo->msgnum);
433 GSList *procmsg_get_message_file_list(GSList *mlist)
435 GSList *file_list = NULL;
437 MsgFileInfo *fileinfo;
440 while (mlist != NULL) {
441 msginfo = (MsgInfo *)mlist->data;
442 file = procmsg_get_message_file(msginfo);
444 procmsg_message_file_list_free(file_list);
447 fileinfo = g_new(MsgFileInfo, 1);
448 fileinfo->msginfo = procmsg_msginfo_new_ref(msginfo);
449 fileinfo->file = file;
450 fileinfo->flags = g_new(MsgFlags, 1);
451 *fileinfo->flags = msginfo->flags;
452 file_list = g_slist_prepend(file_list, fileinfo);
456 file_list = g_slist_reverse(file_list);
461 void procmsg_message_file_list_free(MsgInfoList *file_list)
464 MsgFileInfo *fileinfo;
466 for (cur = file_list; cur != NULL; cur = cur->next) {
467 fileinfo = (MsgFileInfo *)cur->data;
468 procmsg_msginfo_free(fileinfo->msginfo);
469 g_free(fileinfo->file);
470 g_free(fileinfo->flags);
474 g_slist_free(file_list);
477 FILE *procmsg_open_message(MsgInfo *msginfo)
482 g_return_val_if_fail(msginfo != NULL, NULL);
484 file = procmsg_get_message_file_path(msginfo);
485 g_return_val_if_fail(file != NULL, NULL);
487 if (!is_file_exist(file)) {
489 file = procmsg_get_message_file(msginfo);
494 if ((fp = fopen(file, "rb")) == NULL) {
495 FILE_OP_ERROR(file, "fopen");
502 if (MSG_IS_QUEUED(msginfo->flags) || MSG_IS_DRAFT(msginfo->flags)) {
505 while (fgets(buf, sizeof(buf), fp) != NULL)
506 if (buf[0] == '\r' || buf[0] == '\n') break;
512 gboolean procmsg_msg_exist(MsgInfo *msginfo)
517 if (!msginfo) return FALSE;
519 path = folder_item_get_path(msginfo->folder);
521 ret = !folder_item_is_msg_changed(msginfo->folder, msginfo);
527 void procmsg_get_filter_keyword(MsgInfo *msginfo, gchar **header, gchar **key,
528 PrefsFilterType type)
530 static HeaderEntry hentry[] = {{"X-BeenThere:", NULL, TRUE},
531 {"X-ML-Name:", NULL, TRUE},
532 {"X-List:", NULL, TRUE},
533 {"X-Mailing-list:", NULL, TRUE},
534 {"List-Id:", NULL, TRUE},
535 {"X-Sequence:", NULL, TRUE},
536 {NULL, NULL, FALSE}};
542 H_X_MAILING_LIST = 3,
549 g_return_if_fail(msginfo != NULL);
550 g_return_if_fail(header != NULL);
551 g_return_if_fail(key != NULL);
560 if ((fp = procmsg_open_message(msginfo)) == NULL)
562 procheader_get_header_fields(fp, hentry);
565 #define SET_FILTER_KEY(hstr, idx) \
567 *header = g_strdup(hstr); \
568 *key = hentry[idx].body; \
569 hentry[idx].body = NULL; \
572 if (hentry[H_X_BEENTHERE].body != NULL) {
573 SET_FILTER_KEY("header \"X-BeenThere\"", H_X_BEENTHERE);
574 } else if (hentry[H_X_ML_NAME].body != NULL) {
575 SET_FILTER_KEY("header \"X-ML-Name\"", H_X_ML_NAME);
576 } else if (hentry[H_X_LIST].body != NULL) {
577 SET_FILTER_KEY("header \"X-List\"", H_X_LIST);
578 } else if (hentry[H_X_MAILING_LIST].body != NULL) {
579 SET_FILTER_KEY("header \"X-Mailing-List\"", H_X_MAILING_LIST);
580 } else if (hentry[H_LIST_ID].body != NULL) {
581 SET_FILTER_KEY("header \"List-Id\"", H_LIST_ID);
582 extract_list_id_str(*key);
583 } else if (hentry[H_X_SEQUENCE].body != NULL) {
586 SET_FILTER_KEY("X-Sequence", H_X_SEQUENCE);
589 while (*p != '\0' && !isspace(*p)) p++;
590 while (isspace(*p)) p++;
597 } else if (msginfo->subject) {
598 *header = g_strdup("subject");
599 *key = g_strdup(msginfo->subject);
602 #undef SET_FILTER_KEY
604 g_free(hentry[H_X_BEENTHERE].body);
605 hentry[H_X_BEENTHERE].body = NULL;
606 g_free(hentry[H_X_ML_NAME].body);
607 hentry[H_X_ML_NAME].body = NULL;
608 g_free(hentry[H_X_LIST].body);
609 hentry[H_X_LIST].body = NULL;
610 g_free(hentry[H_X_MAILING_LIST].body);
611 hentry[H_X_MAILING_LIST].body = NULL;
612 g_free(hentry[H_LIST_ID].body);
613 hentry[H_LIST_ID].body = NULL;
617 *header = g_strdup("from");
618 *key = g_strdup(msginfo->from);
621 *header = g_strdup("to");
622 *key = g_strdup(msginfo->to);
624 case FILTER_BY_SUBJECT:
625 *header = g_strdup("subject");
626 *key = g_strdup(msginfo->subject);
633 void procmsg_empty_trash(FolderItem *trash)
635 if (trash && trash->total_msgs > 0) {
636 GSList *mlist = folder_item_get_msg_list(trash);
638 for (cur = mlist ; cur != NULL ; cur = cur->next) {
639 MsgInfo * msginfo = (MsgInfo *) cur->data;
640 partial_mark_for_delete(msginfo);
641 procmsg_msginfo_free(msginfo);
644 folder_item_remove_all_msg(trash);
648 void procmsg_empty_all_trash(void)
653 for (cur = folder_get_list(); cur != NULL; cur = cur->next) {
654 trash = FOLDER(cur->data)->trash;
655 procmsg_empty_trash(trash);
659 static PrefsAccount *procmsg_get_account_from_file(const gchar *file)
661 PrefsAccount *mailac = NULL;
666 g_return_val_if_fail(file != NULL, NULL);
668 if ((fp = fopen(file, "rb")) == NULL) {
669 FILE_OP_ERROR(file, "fopen");
672 static HeaderEntry qentry[] = {{"S:", NULL, FALSE},
673 {"SSV:", NULL, FALSE},
675 {"NG:", NULL, FALSE},
676 {"MAID:", NULL, FALSE},
677 {"NAID:", NULL, FALSE},
678 {"SCF:", NULL, FALSE},
679 {"RMID:", NULL, FALSE},
680 {"FMID:", NULL, FALSE},
681 {"X-Sylpheed-Privacy-System:", NULL, FALSE},
682 {"X-Sylpheed-Encrypt:", NULL, FALSE},
683 {"X-Sylpheed-Encrypt-Data:", NULL, FALSE},
684 {NULL, NULL, FALSE}};
686 while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry))
688 gchar *p = buf + strlen(qentry[hnum].name);
690 if (hnum == Q_MAIL_ACCOUNT_ID) {
691 mailac = account_find_from_id(atoi(p));
699 static GSList *procmsg_list_sort_by_account(FolderItem *queue, GSList *list)
701 GSList *result = NULL;
703 PrefsAccount *last_account = NULL;
706 gboolean nothing_to_sort = TRUE;
711 orig = g_slist_copy(list);
713 msg = (MsgInfo *)orig->data;
715 for (cur = orig; cur; cur = cur->next)
716 debug_print("sort before %s\n", ((MsgInfo *)cur->data)->from);
721 nothing_to_sort = TRUE;
725 msg = (MsgInfo *)cur->data;
726 file = folder_item_fetch_msg(queue, msg->msgnum);
727 PrefsAccount *ac = procmsg_get_account_from_file(file);
730 if (last_account == NULL || (ac != NULL && ac == last_account)) {
731 result = g_slist_append(result, msg);
732 orig = g_slist_remove(orig, msg);
734 nothing_to_sort = FALSE;
740 if (orig || g_slist_length(orig)) {
741 if (!last_account && nothing_to_sort) {
742 /* can't find an account for the rest of the list */
745 result = g_slist_append(result, cur->data);
756 for (cur = result; cur; cur = cur->next)
757 debug_print("sort after %s\n", ((MsgInfo *)cur->data)->from);
764 static gboolean procmsg_is_last_for_account(FolderItem *queue, MsgInfo *msginfo, GSList *elem)
766 gchar *file = folder_item_fetch_msg(queue, msginfo->msgnum);
767 PrefsAccount *ac = procmsg_get_account_from_file(file);
770 for (cur = elem; cur; cur = cur->next) {
771 MsgInfo *cur_msginfo = (MsgInfo *)cur->data;
772 PrefsAccount *cur_ac = NULL;
773 file = folder_item_fetch_msg(queue, cur_msginfo->msgnum);
775 if (cur_msginfo != msginfo && !MSG_IS_LOCKED(cur_msginfo->flags)) {
776 if (procmsg_get_account_from_file(file) == ac) {
788 *\brief Send messages in queue
790 *\param queue Queue folder to process
791 *\param save_msgs Unused
793 *\return Number of messages sent, negative if an error occurred
794 * positive if no error occurred
796 gint procmsg_send_queue(FolderItem *queue, gboolean save_msgs)
798 gint sent = 0, err = 0;
800 GSList *sorted_list = NULL;
803 queue = folder_get_default_queue();
804 g_return_val_if_fail(queue != NULL, -1);
806 folder_item_scan(queue);
807 list = folder_item_get_msg_list(queue);
809 /* sort the list per sender account; this helps reusing the same SMTP server */
810 sorted_list = procmsg_list_sort_by_account(queue, list);
812 for (elem = sorted_list; elem != NULL; elem = elem->next) {
816 msginfo = (MsgInfo *)(elem->data);
817 if (!MSG_IS_LOCKED(msginfo->flags)) {
818 file = folder_item_fetch_msg(queue, msginfo->msgnum);
820 if (procmsg_send_message_queue_full(file,
821 !procmsg_is_last_for_account(queue, msginfo, elem)) < 0) {
822 g_warning("Sending queued message %d failed.\n",
827 * We save in procmsg_send_message_queue because
828 * we need the destination folder from the queue
832 procmsg_save_to_outbox
833 (queue->folder->outbox,
837 folder_item_remove_msg(queue, msginfo->msgnum);
842 /* FIXME: supposedly if only one message is locked, and queue
843 * is being flushed, the following free says something like
844 * "freeing msg ## in folder (nil)". */
845 procmsg_msginfo_free(msginfo);
848 g_slist_free(sorted_list);
850 return (err != 0 ? -err : sent);
853 gint procmsg_remove_special_headers(const gchar *in, const gchar *out)
858 if ((fp = fopen(in, "rb")) == NULL) {
859 FILE_OP_ERROR(in, "fopen");
862 if ((outfp = fopen(out, "wb")) == NULL) {
863 FILE_OP_ERROR(out, "fopen");
867 while (fgets(buf, sizeof(buf), fp) != NULL)
868 if (buf[0] == '\r' || buf[0] == '\n') break;
869 while (fgets(buf, sizeof(buf), fp) != NULL)
876 gint procmsg_save_to_outbox(FolderItem *outbox, const gchar *file,
880 MsgInfo *msginfo, *tmp_msginfo;
881 MsgFlags flag = {0, 0};
883 debug_print("saving sent message...\n");
886 outbox = folder_get_default_outbox();
887 g_return_val_if_fail(outbox != NULL, -1);
889 /* remove queueing headers */
891 gchar tmp[MAXPATHLEN + 1];
893 g_snprintf(tmp, sizeof(tmp), "%s%ctmpmsg.out.%08x",
894 get_rc_dir(), G_DIR_SEPARATOR, (guint) rand());
896 if (procmsg_remove_special_headers(file, tmp) !=0)
899 folder_item_scan(outbox);
900 if ((num = folder_item_add_msg(outbox, tmp, &flag, TRUE)) < 0) {
901 g_warning("can't save message\n");
906 folder_item_scan(outbox);
907 if ((num = folder_item_add_msg
908 (outbox, file, &flag, FALSE)) < 0) {
909 g_warning("can't save message\n");
914 msginfo = folder_item_get_msginfo(outbox, num); /* refcnt++ */
915 tmp_msginfo = procmsg_msginfo_get_full_info(msginfo); /* refcnt++ */
916 if (msginfo != NULL) {
917 procmsg_msginfo_unset_flags(msginfo, ~0, 0);
918 procmsg_msginfo_free(msginfo); /* refcnt-- */
919 /* tmp_msginfo == msginfo */
920 if (tmp_msginfo && (msginfo->dispositionnotificationto ||
921 msginfo->returnreceiptto)) {
922 procmsg_msginfo_set_flags(msginfo, MSG_RETRCPT_SENT, 0);
923 procmsg_msginfo_free(msginfo); /* refcnt-- */
930 void procmsg_print_message(MsgInfo *msginfo, const gchar *cmdline)
932 static const gchar *def_cmd = "lpr %s";
939 g_return_if_fail(msginfo);
941 if ((tmpfp = procmime_get_first_text_content(msginfo)) == NULL) {
942 g_warning("Can't get text part\n");
946 prtmp = g_strdup_printf("%s%cprinttmp.%08x",
947 get_mime_tmp_dir(), G_DIR_SEPARATOR, id++);
949 if ((prfp = fopen(prtmp, "wb")) == NULL) {
950 FILE_OP_ERROR(prtmp, "fopen");
956 if (msginfo->date) fprintf(prfp, "Date: %s\n", msginfo->date);
957 if (msginfo->from) fprintf(prfp, "From: %s\n", msginfo->from);
958 if (msginfo->to) fprintf(prfp, "To: %s\n", msginfo->to);
959 if (msginfo->cc) fprintf(prfp, "Cc: %s\n", msginfo->cc);
960 if (msginfo->newsgroups)
961 fprintf(prfp, "Newsgroups: %s\n", msginfo->newsgroups);
962 if (msginfo->subject) fprintf(prfp, "Subject: %s\n", msginfo->subject);
965 while (fgets(buf, sizeof(buf), tmpfp) != NULL)
971 if (cmdline && (p = strchr(cmdline, '%')) && *(p + 1) == 's' &&
973 g_snprintf(buf, sizeof(buf) - 1, cmdline, prtmp);
976 g_warning("Print command line is invalid: `%s'\n",
978 g_snprintf(buf, sizeof(buf) - 1, def_cmd, prtmp);
984 if (buf[strlen(buf) - 1] != '&') strcat(buf, "&");
988 MsgInfo *procmsg_msginfo_new_ref(MsgInfo *msginfo)
995 MsgInfo *procmsg_msginfo_new(void)
999 newmsginfo = g_new0(MsgInfo, 1);
1000 newmsginfo->refcnt = 1;
1005 MsgInfo *procmsg_msginfo_copy(MsgInfo *msginfo)
1007 MsgInfo *newmsginfo;
1010 if (msginfo == NULL) return NULL;
1012 newmsginfo = g_new0(MsgInfo, 1);
1014 newmsginfo->refcnt = 1;
1016 #define MEMBCOPY(mmb) newmsginfo->mmb = msginfo->mmb
1017 #define MEMBDUP(mmb) newmsginfo->mmb = msginfo->mmb ? \
1018 g_strdup(msginfo->mmb) : NULL
1033 MEMBDUP(newsgroups);
1040 MEMBCOPY(to_folder);
1043 MEMBDUP(dispositionnotificationto);
1044 MEMBDUP(returnreceiptto);
1046 refs = msginfo->references;
1047 for (refs = msginfo->references; refs != NULL; refs = refs->next) {
1048 newmsginfo->references = g_slist_prepend
1049 (newmsginfo->references, g_strdup(refs->data));
1051 newmsginfo->references = g_slist_reverse(newmsginfo->references);
1054 MEMBCOPY(threadscore);
1055 MEMBDUP(plaintext_file);
1060 MsgInfo *procmsg_msginfo_get_full_info(MsgInfo *msginfo)
1062 MsgInfo *full_msginfo;
1065 if (msginfo == NULL) return NULL;
1067 file = procmsg_get_message_file_path(msginfo);
1068 if (!file || !is_file_exist(file)) {
1070 file = procmsg_get_message_file(msginfo);
1072 if (!file || !is_file_exist(file)) {
1073 g_warning("procmsg_msginfo_get_full_info(): can't get message file.\n");
1077 full_msginfo = procheader_parse_file(file, msginfo->flags, TRUE, FALSE);
1079 if (!full_msginfo) return NULL;
1081 /* CLAWS: make sure we add the missing members; see:
1082 * procheader.c::procheader_get_headernames() */
1083 if (!msginfo->xface)
1084 msginfo->xface = g_strdup(full_msginfo->xface);
1085 if (!msginfo->dispositionnotificationto)
1086 msginfo->dispositionnotificationto =
1087 g_strdup(full_msginfo->dispositionnotificationto);
1088 if (!msginfo->returnreceiptto)
1089 msginfo->returnreceiptto = g_strdup
1090 (full_msginfo->returnreceiptto);
1091 if (!msginfo->partial_recv && full_msginfo->partial_recv)
1092 msginfo->partial_recv = g_strdup
1093 (full_msginfo->partial_recv);
1094 msginfo->total_size = full_msginfo->total_size;
1095 if (!msginfo->account_server && full_msginfo->account_server)
1096 msginfo->account_server = g_strdup
1097 (full_msginfo->account_server);
1098 if (!msginfo->account_login && full_msginfo->account_login)
1099 msginfo->account_login = g_strdup
1100 (full_msginfo->account_login);
1101 msginfo->planned_download = full_msginfo->planned_download;
1102 procmsg_msginfo_free(full_msginfo);
1104 return procmsg_msginfo_new_ref(msginfo);
1107 void procmsg_msginfo_free(MsgInfo *msginfo)
1109 if (msginfo == NULL) return;
1112 if (msginfo->refcnt > 0)
1115 if (msginfo->to_folder) {
1116 msginfo->to_folder->op_count--;
1117 folder_item_update(msginfo->to_folder, F_ITEM_UPDATE_MSGCNT);
1120 g_free(msginfo->fromspace);
1121 g_free(msginfo->returnreceiptto);
1122 g_free(msginfo->dispositionnotificationto);
1123 g_free(msginfo->xface);
1125 g_free(msginfo->fromname);
1127 g_free(msginfo->date);
1128 g_free(msginfo->from);
1129 g_free(msginfo->to);
1130 g_free(msginfo->cc);
1131 g_free(msginfo->newsgroups);
1132 g_free(msginfo->subject);
1133 g_free(msginfo->msgid);
1134 g_free(msginfo->inreplyto);
1135 g_free(msginfo->xref);
1137 g_free(msginfo->partial_recv);
1138 g_free(msginfo->account_server);
1139 g_free(msginfo->account_login);
1141 slist_free_strings(msginfo->references);
1142 g_slist_free(msginfo->references);
1144 g_free(msginfo->plaintext_file);
1149 guint procmsg_msginfo_memusage(MsgInfo *msginfo)
1153 memusage += sizeof(MsgInfo);
1154 if (msginfo->fromname)
1155 memusage += strlen(msginfo->fromname);
1157 memusage += strlen(msginfo->date);
1159 memusage += strlen(msginfo->from);
1161 memusage += strlen(msginfo->to);
1163 memusage += strlen(msginfo->cc);
1164 if (msginfo->newsgroups)
1165 memusage += strlen(msginfo->newsgroups);
1166 if (msginfo->subject)
1167 memusage += strlen(msginfo->subject);
1169 memusage += strlen(msginfo->msgid);
1170 if (msginfo->inreplyto)
1171 memusage += strlen(msginfo->inreplyto);
1173 memusage += strlen(msginfo->xface);
1174 if (msginfo->dispositionnotificationto)
1175 memusage += strlen(msginfo->dispositionnotificationto);
1176 if (msginfo->returnreceiptto)
1177 memusage += strlen(msginfo->returnreceiptto);
1178 #warning FIXME: Calculate size of references list
1180 if (msginfo->references)
1181 memusage += strlen(msginfo->references);
1183 if (msginfo->fromspace)
1184 memusage += strlen(msginfo->fromspace);
1189 gint procmsg_cmp_msgnum_for_sort(gconstpointer a, gconstpointer b)
1191 const MsgInfo *msginfo1 = a;
1192 const MsgInfo *msginfo2 = b;
1199 return msginfo1->msgnum - msginfo2->msgnum;
1202 static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_session)
1204 static HeaderEntry qentry[] = {{"S:", NULL, FALSE},
1205 {"SSV:", NULL, FALSE},
1206 {"R:", NULL, FALSE},
1207 {"NG:", NULL, FALSE},
1208 {"MAID:", NULL, FALSE},
1209 {"NAID:", NULL, FALSE},
1210 {"SCF:", NULL, FALSE},
1211 {"RMID:", NULL, FALSE},
1212 {"FMID:", NULL, FALSE},
1213 {"X-Sylpheed-Privacy-System:", NULL, FALSE},
1214 {"X-Sylpheed-Encrypt:", NULL, FALSE},
1215 {"X-Sylpheed-Encrypt-Data:", NULL, FALSE},
1216 {NULL, NULL, FALSE}};
1219 gint mailval = 0, newsval = 0;
1221 gchar *smtpserver = NULL;
1222 GSList *to_list = NULL;
1223 GSList *newsgroup_list = NULL;
1224 gchar *savecopyfolder = NULL;
1225 gchar *replymessageid = NULL;
1226 gchar *fwdmessageid = NULL;
1227 gchar *privacy_system = NULL;
1228 gboolean encrypt = FALSE;
1229 gchar *encrypt_data = NULL;
1230 gchar buf[BUFFSIZE];
1232 PrefsAccount *mailac = NULL, *newsac = NULL;
1233 gboolean save_clear_text = TRUE;
1234 gchar *tmp_enc_file = NULL;
1238 g_return_val_if_fail(file != NULL, -1);
1240 if ((fp = fopen(file, "rb")) == NULL) {
1241 FILE_OP_ERROR(file, "fopen");
1245 while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry))
1247 gchar *p = buf + strlen(qentry[hnum].name);
1255 if (smtpserver == NULL)
1256 smtpserver = g_strdup(p);
1259 to_list = address_list_append(to_list, p);
1262 newsgroup_list = newsgroup_list_append(newsgroup_list, p);
1264 case Q_MAIL_ACCOUNT_ID:
1265 mailac = account_find_from_id(atoi(p));
1267 case Q_NEWS_ACCOUNT_ID:
1268 newsac = account_find_from_id(atoi(p));
1270 case Q_SAVE_COPY_FOLDER:
1271 if (savecopyfolder == NULL)
1272 savecopyfolder = g_strdup(p);
1274 case Q_REPLY_MESSAGE_ID:
1275 if (replymessageid == NULL)
1276 replymessageid = g_strdup(p);
1278 case Q_FWD_MESSAGE_ID:
1279 if (fwdmessageid == NULL)
1280 fwdmessageid = g_strdup(p);
1282 case Q_PRIVACY_SYSTEM:
1283 if (privacy_system == NULL)
1284 privacy_system = g_strdup(p);
1290 case Q_ENCRYPT_DATA:
1291 if (encrypt_data == NULL)
1292 encrypt_data = g_strdup(p);
1296 filepos = ftell(fp);
1301 save_clear_text = (mailac != NULL && mailac->save_encrypted_as_clear_text);
1306 mimeinfo = procmime_scan_queue_file(file);
1307 if (!privacy_encrypt(privacy_system, mimeinfo, encrypt_data)
1308 || (fp = my_tmpfile()) == NULL
1309 || procmime_write_mimeinfo(mimeinfo, fp) < 0) {
1312 procmime_mimeinfo_free_all(mimeinfo);
1315 slist_free_strings(to_list);
1316 g_slist_free(to_list);
1317 slist_free_strings(newsgroup_list);
1318 g_slist_free(newsgroup_list);
1319 g_free(savecopyfolder);
1320 g_free(replymessageid);
1321 g_free(fwdmessageid);
1322 g_free(privacy_system);
1323 g_free(encrypt_data);
1328 if (!save_clear_text) {
1329 gchar *content = NULL;
1330 FILE *tmpfp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmp_enc_file);
1334 content = file_read_stream_to_str(fp);
1337 str_write_to_file(content, tmp_enc_file);
1340 g_warning("couldn't get tempfile\n");
1344 procmime_mimeinfo_free_all(mimeinfo);
1350 debug_print("Sending message by mail\n");
1352 g_warning("Queued message header is broken.\n");
1354 } else if (mailac && mailac->use_mail_command &&
1355 mailac->mail_command && (* mailac->mail_command)) {
1356 mailval = send_message_local(mailac->mail_command, fp);
1360 mailac = account_find_from_smtp_server(from, smtpserver);
1362 g_warning("Account not found. "
1363 "Using current account...\n");
1364 mailac = cur_account;
1369 mailval = send_message_smtp_full(mailac, to_list, fp, keep_session);
1371 PrefsAccount tmp_ac;
1373 g_warning("Account not found.\n");
1375 memset(&tmp_ac, 0, sizeof(PrefsAccount));
1376 tmp_ac.address = from;
1377 tmp_ac.smtp_server = smtpserver;
1378 tmp_ac.smtpport = SMTP_PORT;
1379 mailval = send_message_smtp(&tmp_ac, to_list, fp);
1384 fseek(fp, filepos, SEEK_SET);
1385 if (newsgroup_list && (mailval == 0)) {
1390 /* write to temporary file */
1391 tmp = g_strdup_printf("%s%ctmp%d", g_get_tmp_dir(),
1392 G_DIR_SEPARATOR, (gint)file);
1393 if ((tmpfp = fopen(tmp, "wb")) == NULL) {
1394 FILE_OP_ERROR(tmp, "fopen");
1396 alertpanel_error(_("Could not create temporary file for news sending."));
1398 if (change_file_mode_rw(tmpfp, tmp) < 0) {
1399 FILE_OP_ERROR(tmp, "chmod");
1400 g_warning("can't change file mode\n");
1403 while ((newsval == 0) && fgets(buf, sizeof(buf), fp) != NULL) {
1404 if (fputs(buf, tmpfp) == EOF) {
1405 FILE_OP_ERROR(tmp, "fputs");
1407 alertpanel_error(_("Error when writing temporary file for news sending."));
1413 debug_print("Sending message by news\n");
1415 folder = FOLDER(newsac->folder);
1417 newsval = news_post(folder, tmp);
1419 alertpanel_error(_("Error occurred while posting the message to %s ."),
1420 newsac->nntp_server);
1430 /* save message to outbox */
1431 if (mailval == 0 && newsval == 0 && savecopyfolder) {
1434 debug_print("saving sent message...\n");
1436 outbox = folder_find_item_from_identifier(savecopyfolder);
1438 outbox = folder_get_default_outbox();
1440 if (save_clear_text || tmp_enc_file == NULL) {
1441 procmsg_save_to_outbox(outbox, file, TRUE);
1443 procmsg_save_to_outbox(outbox, tmp_enc_file, FALSE);
1447 if (tmp_enc_file != NULL) {
1448 unlink(tmp_enc_file);
1450 tmp_enc_file = NULL;
1453 if (replymessageid != NULL || fwdmessageid != NULL) {
1457 if (replymessageid != NULL)
1458 tokens = g_strsplit(replymessageid, "\x7f", 0);
1460 tokens = g_strsplit(fwdmessageid, "\x7f", 0);
1461 item = folder_find_item_from_identifier(tokens[0]);
1463 /* check if queued message has valid folder and message id */
1464 if (item != NULL && tokens[2] != NULL) {
1467 msginfo = folder_item_get_msginfo(item, atoi(tokens[1]));
1469 /* check if referring message exists and has a message id */
1470 if ((msginfo != NULL) &&
1471 (msginfo->msgid != NULL) &&
1472 (strcmp(msginfo->msgid, tokens[2]) != 0)) {
1473 procmsg_msginfo_free(msginfo);
1477 if (msginfo == NULL) {
1478 msginfo = folder_item_get_msginfo_by_msgid(item, tokens[2]);
1481 if (msginfo != NULL) {
1482 if (replymessageid != NULL) {
1483 procmsg_msginfo_unset_flags(msginfo, MSG_FORWARDED, 0);
1484 procmsg_msginfo_set_flags(msginfo, MSG_REPLIED, 0);
1486 procmsg_msginfo_unset_flags(msginfo, MSG_REPLIED, 0);
1487 procmsg_msginfo_set_flags(msginfo, MSG_FORWARDED, 0);
1489 procmsg_msginfo_free(msginfo);
1497 slist_free_strings(to_list);
1498 g_slist_free(to_list);
1499 slist_free_strings(newsgroup_list);
1500 g_slist_free(newsgroup_list);
1501 g_free(savecopyfolder);
1502 g_free(replymessageid);
1503 g_free(fwdmessageid);
1504 g_free(privacy_system);
1505 g_free(encrypt_data);
1507 return (newsval != 0 ? newsval : mailval);
1510 gint procmsg_send_message_queue(const gchar *file)
1512 return procmsg_send_message_queue_full(file, FALSE);
1515 static void update_folder_msg_counts(FolderItem *item, MsgInfo *msginfo, MsgPermFlags old_flags)
1517 MsgPermFlags new_flags = msginfo->flags.perm_flags;
1520 if (!(old_flags & MSG_NEW) && (new_flags & MSG_NEW)) {
1524 if ((old_flags & MSG_NEW) && !(new_flags & MSG_NEW)) {
1529 if (!(old_flags & MSG_UNREAD) && (new_flags & MSG_UNREAD)) {
1530 item->unread_msgs++;
1531 if (procmsg_msg_has_marked_parent(msginfo))
1532 item->unreadmarked_msgs++;
1535 if ((old_flags & MSG_UNREAD) && !(new_flags & MSG_UNREAD)) {
1536 item->unread_msgs--;
1537 if (procmsg_msg_has_marked_parent(msginfo))
1538 item->unreadmarked_msgs--;
1542 if (!(old_flags & MSG_MARKED) && (new_flags & MSG_MARKED)) {
1543 procmsg_update_unread_children(msginfo, TRUE);
1546 if ((old_flags & MSG_MARKED) && !(new_flags & MSG_MARKED)) {
1547 procmsg_update_unread_children(msginfo, FALSE);
1551 void procmsg_msginfo_set_flags(MsgInfo *msginfo, MsgPermFlags perm_flags, MsgTmpFlags tmp_flags)
1554 MsgInfoUpdate msginfo_update;
1555 MsgPermFlags perm_flags_new, perm_flags_old;
1556 MsgTmpFlags tmp_flags_old;
1558 g_return_if_fail(msginfo != NULL);
1559 item = msginfo->folder;
1560 g_return_if_fail(item != NULL);
1562 debug_print("Setting flags for message %d in folder %s\n", msginfo->msgnum, item->path);
1564 /* Perm Flags handling */
1565 perm_flags_old = msginfo->flags.perm_flags;
1566 perm_flags_new = msginfo->flags.perm_flags | perm_flags;
1567 if ((perm_flags & MSG_IGNORE_THREAD) || (perm_flags_old & MSG_IGNORE_THREAD)) {
1568 perm_flags_new &= ~(MSG_NEW | MSG_UNREAD);
1571 if (perm_flags_old != perm_flags_new) {
1572 folder_item_change_msg_flags(msginfo->folder, msginfo, perm_flags_new);
1574 update_folder_msg_counts(item, msginfo, perm_flags_old);
1578 /* Tmp flags handling */
1579 tmp_flags_old = msginfo->flags.tmp_flags;
1580 msginfo->flags.tmp_flags |= tmp_flags;
1582 /* update notification */
1583 if ((perm_flags_old != perm_flags_new) || (tmp_flags_old != msginfo->flags.tmp_flags)) {
1584 msginfo_update.msginfo = msginfo;
1585 msginfo_update.flags = MSGINFO_UPDATE_FLAGS;
1586 hooks_invoke(MSGINFO_UPDATE_HOOKLIST, &msginfo_update);
1587 folder_item_update(msginfo->folder, F_ITEM_UPDATE_MSGCNT);
1591 void procmsg_msginfo_unset_flags(MsgInfo *msginfo, MsgPermFlags perm_flags, MsgTmpFlags tmp_flags)
1594 MsgInfoUpdate msginfo_update;
1595 MsgPermFlags perm_flags_new, perm_flags_old;
1596 MsgTmpFlags tmp_flags_old;
1598 g_return_if_fail(msginfo != NULL);
1599 item = msginfo->folder;
1600 g_return_if_fail(item != NULL);
1602 debug_print("Unsetting flags for message %d in folder %s\n", msginfo->msgnum, item->path);
1604 /* Perm Flags handling */
1605 perm_flags_old = msginfo->flags.perm_flags;
1606 perm_flags_new = msginfo->flags.perm_flags & ~perm_flags;
1608 if (perm_flags_old != perm_flags_new) {
1609 folder_item_change_msg_flags(msginfo->folder, msginfo, perm_flags_new);
1611 update_folder_msg_counts(item, msginfo, perm_flags_old);
1613 msginfo_update.msginfo = msginfo;
1614 msginfo_update.flags = MSGINFO_UPDATE_FLAGS;
1615 hooks_invoke(MSGINFO_UPDATE_HOOKLIST, &msginfo_update);
1616 folder_item_update(msginfo->folder, F_ITEM_UPDATE_MSGCNT);
1619 /* Tmp flags hanlding */
1620 tmp_flags_old = msginfo->flags.tmp_flags;
1621 msginfo->flags.tmp_flags &= ~tmp_flags;
1623 /* update notification */
1624 if ((perm_flags_old != perm_flags_new) || (tmp_flags_old != msginfo->flags.tmp_flags)) {
1625 msginfo_update.msginfo = msginfo;
1626 msginfo_update.flags = MSGINFO_UPDATE_FLAGS;
1627 hooks_invoke(MSGINFO_UPDATE_HOOKLIST, &msginfo_update);
1628 folder_item_update(msginfo->folder, F_ITEM_UPDATE_MSGCNT);
1633 *\brief check for flags (e.g. mark) in prior msgs of current thread
1635 *\param info Current message
1636 *\param perm_flags Flags to be checked
1637 *\param parentmsgs Hash of prior msgs to avoid loops
1639 *\return gboolean TRUE if perm_flags are found
1641 gboolean procmsg_msg_has_flagged_parent_real(MsgInfo *info,
1642 MsgPermFlags perm_flags, GHashTable *parentmsgs)
1646 g_return_val_if_fail(info != NULL, FALSE);
1648 if (info != NULL && info->folder != NULL && info->inreplyto != NULL) {
1649 tmp = folder_item_get_msginfo_by_msgid(info->folder,
1651 if (tmp && (tmp->flags.perm_flags & perm_flags)) {
1652 procmsg_msginfo_free(tmp);
1654 } else if (tmp != NULL) {
1657 if (g_hash_table_lookup(parentmsgs, info)) {
1658 debug_print("loop detected: %s%c%d\n",
1659 folder_item_get_path(info->folder),
1660 G_DIR_SEPARATOR, info->msgnum);
1663 g_hash_table_insert(parentmsgs, info, "1");
1664 result = procmsg_msg_has_flagged_parent_real(
1665 tmp, perm_flags, parentmsgs);
1667 procmsg_msginfo_free(tmp);
1677 *\brief Callback for cleaning up hash of parentmsgs
1679 gboolean parentmsgs_hash_remove(gpointer key,
1687 *\brief Set up list of parentmsgs
1688 * See procmsg_msg_has_flagged_parent_real()
1690 gboolean procmsg_msg_has_flagged_parent(MsgInfo *info, MsgPermFlags perm_flags)
1693 GHashTable *parentmsgs = g_hash_table_new(NULL, NULL);
1695 result = procmsg_msg_has_flagged_parent_real(info, perm_flags, parentmsgs);
1696 g_hash_table_foreach_remove(parentmsgs, parentmsgs_hash_remove, NULL);
1697 g_hash_table_destroy(parentmsgs);
1702 *\brief Check if msgs prior in thread are marked
1703 * See procmsg_msg_has_flagged_parent_real()
1705 gboolean procmsg_msg_has_marked_parent(MsgInfo *info)
1707 return procmsg_msg_has_flagged_parent(info, MSG_MARKED);
1711 GSList *procmsg_find_children_func(MsgInfo *info,
1712 GSList *children, GSList *all)
1716 g_return_val_if_fail(info!=NULL, children);
1717 if (info->msgid == NULL)
1720 for (cur = all; cur != NULL; cur = g_slist_next(cur)) {
1721 MsgInfo *tmp = (MsgInfo *)cur->data;
1722 if (tmp->inreplyto && !strcmp(tmp->inreplyto, info->msgid)) {
1723 /* Check if message is already in the list */
1724 if ((children == NULL) ||
1725 (g_slist_index(children, tmp) == -1)) {
1726 children = g_slist_prepend(children,
1727 procmsg_msginfo_new_ref(tmp));
1728 children = procmsg_find_children_func(tmp,
1737 GSList *procmsg_find_children (MsgInfo *info)
1742 g_return_val_if_fail(info!=NULL, NULL);
1743 all = folder_item_get_msg_list(info->folder);
1744 children = procmsg_find_children_func(info, NULL, all);
1745 if (children != NULL) {
1746 for (cur = all; cur != NULL; cur = g_slist_next(cur)) {
1747 /* this will not free the used pointers
1748 created with procmsg_msginfo_new_ref */
1749 procmsg_msginfo_free((MsgInfo *)cur->data);
1757 void procmsg_update_unread_children(MsgInfo *info, gboolean newly_marked)
1759 GSList *children = procmsg_find_children(info);
1761 for (cur = children; cur != NULL; cur = g_slist_next(cur)) {
1762 MsgInfo *tmp = (MsgInfo *)cur->data;
1763 if(MSG_IS_UNREAD(tmp->flags) && !MSG_IS_IGNORE_THREAD(tmp->flags)) {
1765 info->folder->unreadmarked_msgs++;
1767 info->folder->unreadmarked_msgs--;
1768 folder_item_update(info->folder, F_ITEM_UPDATE_MSGCNT);
1770 procmsg_msginfo_free(tmp);
1772 g_slist_free(children);
1776 * Set the destination folder for a copy or move operation
1778 * \param msginfo The message which's destination folder is changed
1779 * \param to_folder The destination folder for the operation
1781 void procmsg_msginfo_set_to_folder(MsgInfo *msginfo, FolderItem *to_folder)
1783 if(msginfo->to_folder != NULL) {
1784 msginfo->to_folder->op_count--;
1785 folder_item_update(msginfo->to_folder, F_ITEM_UPDATE_MSGCNT);
1787 msginfo->to_folder = to_folder;
1788 if(to_folder != NULL) {
1789 to_folder->op_count++;
1790 folder_item_update(msginfo->to_folder, F_ITEM_UPDATE_MSGCNT);
1795 * Apply filtering actions to the msginfo
1797 * \param msginfo The MsgInfo describing the message that should be filtered
1798 * \return TRUE if the message was moved and MsgInfo is now invalid,
1801 gboolean procmsg_msginfo_filter(MsgInfo *msginfo)
1803 MailFilteringData mail_filtering_data;
1805 mail_filtering_data.msginfo = msginfo;
1806 if (hooks_invoke(MAIL_FILTERING_HOOKLIST, &mail_filtering_data))
1809 /* filter if enabled in prefs or move to inbox if not */
1810 if((filtering_rules != NULL) &&
1811 filter_message_by_msginfo(filtering_rules, msginfo))
1817 MsgInfo *procmsg_msginfo_new_from_mimeinfo(MsgInfo *src_msginfo, MimeInfo *mimeinfo)
1819 MsgInfo *tmp_msginfo = NULL;
1820 MsgFlags flags = {0, 0};
1823 if (!mimeinfo || mimeinfo->type != MIMETYPE_MESSAGE ||
1824 g_ascii_strcasecmp(mimeinfo->subtype, "rfc822")) {
1825 g_warning("procmsg_msginfo_new_from_mimeinfo(): unsuitable mimeinfo");
1829 if (mimeinfo->content == MIMECONTENT_MEM) {
1830 gchar *tmpfile = get_tmp_file();
1831 str_write_to_file(mimeinfo->data.mem, tmpfile);
1832 g_free(mimeinfo->data.mem);
1833 mimeinfo->content == MIMECONTENT_FILE;
1834 mimeinfo->data.filename = g_strdup(tmpfile);
1838 tmp_msginfo = procheader_parse_file(mimeinfo->data.filename,
1839 flags, TRUE, FALSE);
1841 if (tmp_msginfo != NULL) {
1842 tmp_msginfo->folder = src_msginfo->folder;
1843 tmp_msginfo->plaintext_file = g_strdup(mimeinfo->data.filename);
1845 g_warning("procmsg_msginfo_new_from_mimeinfo(): Can't generate new msginfo");