2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2001 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.
30 #include "procheader.h"
33 #include "statusbar.h"
35 #include "prefs_common.h"
38 typedef struct _FlagInfo FlagInfo;
46 static void mark_sum_func (gpointer key,
50 static GHashTable *procmsg_read_mark_file (const gchar *folder);
51 static gint procmsg_cmp_msgnum (gconstpointer a,
53 static gint procmsg_cmp_flag_msgnum (gconstpointer a,
57 GHashTable *procmsg_msg_hash_table_create(GSList *mlist)
59 GHashTable *msg_table;
61 if (mlist == NULL) return NULL;
63 msg_table = g_hash_table_new(NULL, g_direct_equal);
64 procmsg_msg_hash_table_append(msg_table, mlist);
69 void procmsg_msg_hash_table_append(GHashTable *msg_table, GSList *mlist)
74 if (msg_table == NULL || mlist == NULL) return;
76 for (cur = mlist; cur != NULL; cur = cur->next) {
77 msginfo = (MsgInfo *)cur->data;
79 g_hash_table_insert(msg_table,
80 GUINT_TO_POINTER(msginfo->msgnum),
85 GHashTable *procmsg_to_folder_hash_table_create(GSList *mlist)
87 GHashTable *msg_table;
91 if (mlist == NULL) return NULL;
93 msg_table = g_hash_table_new(NULL, g_direct_equal);
95 for (cur = mlist; cur != NULL; cur = cur->next) {
96 msginfo = (MsgInfo *)cur->data;
97 g_hash_table_insert(msg_table, msginfo->to_folder, msginfo);
103 static gint procmsg_read_cache_data_str(FILE *fp, gchar **str)
109 if (fread(&len, sizeof(len), 1, fp) == 1) {
116 size_t size = MIN(len, BUFFSIZE - 1);
118 if (fread(buf, size, 1, fp) != 1) {
120 if (tmp) g_free(tmp);
127 *str = g_strconcat(tmp, buf, NULL);
131 tmp = *str = g_strdup(buf);
140 g_warning(_("Cache data is corrupted\n"));
145 #define READ_CACHE_DATA(data, fp) \
147 if (procmsg_read_cache_data_str(fp, &data) < 0) { \
148 procmsg_msginfo_free(msginfo); \
153 #define READ_CACHE_DATA_INT(n, fp) \
155 if (fread(&n, sizeof(n), 1, fp) != 1) { \
156 g_warning(_("Cache data is corrupted\n")); \
157 procmsg_msginfo_free(msginfo); \
162 GSList *procmsg_read_cache(FolderItem *item, gboolean scan_file)
164 GSList *mlist = NULL;
169 MsgFlags default_flags;
170 gchar file_buf[BUFFSIZE];
175 g_return_val_if_fail(item != NULL, NULL);
176 g_return_val_if_fail(item->folder != NULL, NULL);
177 type = item->folder->type;
179 default_flags.perm_flags = MSG_NEW|MSG_UNREAD;
180 default_flags.tmp_flags = MSG_CACHED;
182 if (item->stype == F_QUEUE) {
183 MSG_SET_TMP_FLAGS(default_flags, MSG_QUEUED);
184 } else if (item->stype == F_DRAFT) {
185 MSG_SET_TMP_FLAGS(default_flags, MSG_DRAFT);
187 } else if (type == F_IMAP) {
188 MSG_SET_TMP_FLAGS(default_flags, MSG_IMAP);
189 } else if (type == F_NEWS) {
190 MSG_SET_TMP_FLAGS(default_flags, MSG_NEWS);
196 path = folder_item_get_path(item);
197 if (change_dir(path) < 0) {
203 cache_file = folder_item_get_cache_file(item);
204 if ((fp = fopen(cache_file, "r")) == NULL) {
205 debug_print(_("\tNo cache file\n"));
209 setvbuf(fp, file_buf, _IOFBF, sizeof(file_buf));
212 debug_print(_("\tReading summary cache...\n"));
214 /* compare cache version */
215 if (fread(&ver, sizeof(ver), 1, fp) != 1 ||
216 CACHE_VERSION != ver) {
217 debug_print(_("Cache version is different. Discarding it.\n"));
222 while (fread(&num, sizeof(num), 1, fp) == 1) {
223 msginfo = g_new0(MsgInfo, 1);
224 msginfo->msgnum = num;
225 READ_CACHE_DATA_INT(msginfo->size, fp);
226 READ_CACHE_DATA_INT(msginfo->mtime, fp);
227 READ_CACHE_DATA_INT(msginfo->date_t, fp);
228 READ_CACHE_DATA_INT(msginfo->flags.tmp_flags, fp);
230 READ_CACHE_DATA(msginfo->fromname, fp);
232 READ_CACHE_DATA(msginfo->date, fp);
233 READ_CACHE_DATA(msginfo->from, fp);
234 READ_CACHE_DATA(msginfo->to, fp);
235 READ_CACHE_DATA(msginfo->cc, fp);
236 READ_CACHE_DATA(msginfo->newsgroups, fp);
237 READ_CACHE_DATA(msginfo->subject, fp);
238 READ_CACHE_DATA(msginfo->msgid, fp);
239 READ_CACHE_DATA(msginfo->inreplyto, fp);
240 READ_CACHE_DATA(msginfo->references, fp);
242 MSG_SET_PERM_FLAGS(msginfo->flags, default_flags.perm_flags);
243 MSG_SET_TMP_FLAGS(msginfo->flags, default_flags.tmp_flags);
245 /* if the message file doesn't exist or is changed,
246 don't add the data */
247 if (type == F_MH && scan_file &&
248 folder_item_is_msg_changed(item, msginfo))
249 procmsg_msginfo_free(msginfo);
251 msginfo->folder = item;
254 last = mlist = g_slist_append(NULL, msginfo);
256 last = g_slist_append(last, msginfo);
263 debug_print(_("done.\n"));
268 #undef READ_CACHE_DATA
269 #undef READ_CACHE_DATA_INT
271 void procmsg_set_flags(GSList *mlist, FolderItem *item)
278 GHashTable *mark_table;
282 g_return_if_fail(item != NULL);
283 g_return_if_fail(item->folder != NULL);
285 debug_print(_("\tMarking the messages...\n"));
287 markdir = folder_item_get_path(item);
288 if (!is_dir_exist(markdir))
289 make_dir_hier(markdir);
291 mark_table = procmsg_read_mark_file(markdir);
294 if (!mark_table) return;
296 for (cur = mlist; cur != NULL; cur = cur->next) {
297 msginfo = (MsgInfo *)cur->data;
299 if (lastnum < msginfo->msgnum)
300 lastnum = msginfo->msgnum;
302 flags = g_hash_table_lookup
303 (mark_table, GUINT_TO_POINTER(msginfo->msgnum));
306 /* add the permanent flags only */
307 msginfo->flags.perm_flags = flags->perm_flags;
308 if (item->folder->type == F_IMAP) {
309 MSG_SET_TMP_FLAGS(msginfo->flags, MSG_IMAP);
310 } else if (item->folder->type == F_NEWS) {
311 MSG_SET_TMP_FLAGS(msginfo->flags, MSG_NEWS);
314 /* not found (new message) */
316 for (tmp = mlist; tmp != cur; tmp = tmp->next)
318 (((MsgInfo *)tmp->data)->flags,
325 item->last_num = lastnum;
327 debug_print(_("done.\n"));
329 debug_print(_("\t%d new message(s)\n"), newmsg);
331 hash_free_value_mem(mark_table);
332 g_hash_table_destroy(mark_table);
335 gint procmsg_get_last_num_in_cache(GSList *mlist)
341 if (mlist == NULL) return 0;
343 for (cur = mlist; cur != NULL; cur = cur->next) {
344 msginfo = (MsgInfo *)cur->data;
345 if (msginfo && msginfo->msgnum > last)
346 last = msginfo->msgnum;
352 void procmsg_msg_list_free(GSList *mlist)
357 for (cur = mlist; cur != NULL; cur = cur->next) {
358 msginfo = (MsgInfo *)cur->data;
359 procmsg_msginfo_free(msginfo);
364 void procmsg_write_cache(MsgInfo *msginfo, FILE *fp)
366 MsgTmpFlags flags = msginfo->flags.tmp_flags & MSG_CACHED_FLAG_MASK;
368 WRITE_CACHE_DATA_INT(msginfo->msgnum, fp);
369 WRITE_CACHE_DATA_INT(msginfo->size, fp);
370 WRITE_CACHE_DATA_INT(msginfo->mtime, fp);
371 WRITE_CACHE_DATA_INT(msginfo->date_t, fp);
372 WRITE_CACHE_DATA_INT(flags, fp);
374 WRITE_CACHE_DATA(msginfo->fromname, fp);
376 WRITE_CACHE_DATA(msginfo->date, fp);
377 WRITE_CACHE_DATA(msginfo->from, fp);
378 WRITE_CACHE_DATA(msginfo->to, fp);
379 WRITE_CACHE_DATA(msginfo->cc, fp);
380 WRITE_CACHE_DATA(msginfo->newsgroups, fp);
381 WRITE_CACHE_DATA(msginfo->subject, fp);
382 WRITE_CACHE_DATA(msginfo->msgid, fp);
383 WRITE_CACHE_DATA(msginfo->inreplyto, fp);
384 WRITE_CACHE_DATA(msginfo->references, fp);
387 void procmsg_write_flags(MsgInfo *msginfo, FILE *fp)
389 MsgPermFlags flags = msginfo->flags.perm_flags;
391 WRITE_CACHE_DATA_INT(msginfo->msgnum, fp);
392 WRITE_CACHE_DATA_INT(flags, fp);
401 static void mark_sum_func(gpointer key, gpointer value, gpointer data)
403 MsgFlags *flags = value;
404 struct MarkSum *marksum = data;
406 if (MSG_IS_NEW(*flags) && !MSG_IS_IGNORE_THREAD(*flags)) (*marksum->new)++;
407 if (MSG_IS_UNREAD(*flags) && !MSG_IS_IGNORE_THREAD(*flags)) (*marksum->unread)++;
413 void procmsg_get_mark_sum(const gchar *folder,
414 gint *new, gint *unread, gint *total)
416 GHashTable *mark_table;
417 struct MarkSum marksum;
419 *new = *unread = *total = 0;
421 marksum.unread = unread;
422 marksum.total = total;
424 mark_table = procmsg_read_mark_file(folder);
427 g_hash_table_foreach(mark_table, mark_sum_func, &marksum);
428 g_hash_table_destroy(mark_table);
430 debug_print("mark->new = %d, mark->unread = %d, mark->total = %d\n",
431 *(marksum.new), *(marksum.unread), *(marksum.total));
434 static GHashTable *procmsg_read_mark_file(const gchar *folder)
437 GHashTable *mark_table = NULL;
440 MsgPermFlags perm_flags;
442 if ((fp = procmsg_open_mark_file(folder, FALSE)) == NULL)
445 mark_table = g_hash_table_new(NULL, g_direct_equal);
447 while (fread(&num, sizeof(num), 1, fp) == 1) {
448 if (fread(&perm_flags, sizeof(flags), 1, fp) != 1) break;
450 flags = g_new0(MsgFlags, 1);
451 flags->perm_flags = perm_flags;
453 g_hash_table_insert(mark_table, GUINT_TO_POINTER(num), flags);
460 FILE *procmsg_open_mark_file(const gchar *folder, gboolean append)
466 markfile = g_strconcat(folder, G_DIR_SEPARATOR_S, MARK_FILE, NULL);
468 if ((fp = fopen(markfile, "r")) == NULL)
469 debug_print(_("Mark file not found.\n"));
470 else if (fread(&ver, sizeof(ver), 1, fp) != 1 || MARK_VERSION != ver) {
471 debug_print(_("Mark version is different (%d != %d). "
472 "Discarding it.\n"), ver, MARK_VERSION);
478 if (append == FALSE) {
484 /* reopen with append mode */
486 if ((fp = fopen(markfile, "a")) == NULL)
487 g_warning(_("Can't open mark file with append mode.\n"));
489 /* open with overwrite mode if mark file doesn't exist or
490 version is different */
491 if ((fp = fopen(markfile, "w")) == NULL)
492 g_warning(_("Can't open mark file with write mode.\n"));
495 WRITE_CACHE_DATA_INT(ver, fp);
503 /* return the reversed thread tree */
504 GNode *procmsg_get_thread_tree(GSList *mlist)
506 GNode *root, *parent, *node, *next;
507 GHashTable *msgid_table;
508 GHashTable *subject_table;
511 const gchar *subject;
513 root = g_node_new(NULL);
514 msgid_table = g_hash_table_new(g_str_hash, g_str_equal);
515 subject_table = g_hash_table_new(g_str_hash, g_str_equal);
517 for (; mlist != NULL; mlist = mlist->next) {
518 msginfo = (MsgInfo *)mlist->data;
521 if (msginfo->inreplyto) {
522 parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto);
523 if (parent == NULL) {
526 if(MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags)) {
527 MSG_SET_PERM_FLAGS(msginfo->flags, MSG_IGNORE_THREAD);
531 node = g_node_insert_data_before
532 (parent, parent == root ? parent->children : NULL,
534 if ((msgid = msginfo->msgid) &&
535 g_hash_table_lookup(msgid_table, msgid) == NULL)
536 g_hash_table_insert(msgid_table, (gchar *)msgid, node);
538 subject = msginfo->subject;
539 if (subject_table_lookup(subject_table,
540 (gchar *) subject) == NULL)
541 subject_table_insert(subject_table, (gchar *)subject,
545 /* complete the unfinished threads */
546 for (node = root->children; node != NULL; ) {
548 msginfo = (MsgInfo *)node->data;
550 if (msginfo->inreplyto)
551 parent = g_hash_table_lookup(msgid_table, msginfo->inreplyto);
552 if (parent && parent != node) {
555 (parent, parent->children, node);
556 /* CLAWS: ignore thread */
557 if(MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags)) {
558 MSG_SET_PERM_FLAGS(msginfo->flags, MSG_IGNORE_THREAD);
564 /* CLAWS: now see if the first level (below root) still has some nodes that can be
565 * threaded by subject line. we need to handle this in a special way to prevent
566 * circular reference from a node that has already been threaded by IN-REPLY-TO
567 * but is also in the subject line hash table */
568 for (node = root->children; node != NULL; ) {
570 msginfo = (MsgInfo *) node->data;
572 if (subject_is_reply(msginfo->subject)) {
573 parent = subject_table_lookup(subject_table,
575 /* the node may already be threaded by IN-REPLY-TO,
576 so go up in the tree to find the parent node */
577 if (parent != NULL) {
578 if (g_node_is_ancestor(node, parent))
586 g_node_append(parent, node);
587 /* CLAWS: ignore thread */
588 if(MSG_IS_IGNORE_THREAD(((MsgInfo *)parent->data)->flags)) {
589 MSG_SET_PERM_FLAGS(msginfo->flags, MSG_IGNORE_THREAD);
596 g_hash_table_destroy(subject_table);
597 g_hash_table_destroy(msgid_table);
602 void procmsg_move_messages(GSList *mlist)
604 GSList *cur, *movelist = NULL;
606 FolderItem *dest = NULL;
611 hash = procmsg_to_folder_hash_table_create(mlist);
612 folder_item_scan_foreach(hash);
613 g_hash_table_destroy(hash);
615 for (cur = mlist; cur != NULL; cur = cur->next) {
616 msginfo = (MsgInfo *)cur->data;
618 dest = msginfo->to_folder;
619 movelist = g_slist_append(movelist, msginfo);
620 } else if (dest == msginfo->to_folder) {
621 movelist = g_slist_append(movelist, msginfo);
623 folder_item_move_msgs_with_dest(dest, movelist);
624 g_slist_free(movelist);
626 dest = msginfo->to_folder;
627 movelist = g_slist_append(movelist, msginfo);
632 folder_item_move_msgs_with_dest(dest, movelist);
633 g_slist_free(movelist);
637 void procmsg_copy_messages(GSList *mlist)
639 GSList *cur, *copylist = NULL;
641 FolderItem *dest = NULL;
646 hash = procmsg_to_folder_hash_table_create(mlist);
647 folder_item_scan_foreach(hash);
648 g_hash_table_destroy(hash);
650 for (cur = mlist; cur != NULL; cur = cur->next) {
651 msginfo = (MsgInfo *)cur->data;
653 dest = msginfo->to_folder;
654 copylist = g_slist_append(copylist, msginfo);
655 } else if (dest == msginfo->to_folder) {
656 copylist = g_slist_append(copylist, msginfo);
658 folder_item_copy_msgs_with_dest(dest, copylist);
659 g_slist_free(copylist);
661 dest = msginfo->to_folder;
662 copylist = g_slist_append(copylist, msginfo);
667 folder_item_copy_msgs_with_dest(dest, copylist);
668 g_slist_free(copylist);
672 gchar *procmsg_get_message_file_path(MsgInfo *msginfo)
676 g_return_val_if_fail(msginfo != NULL, NULL);
678 if (msginfo->plaintext_file)
679 file = g_strdup(msginfo->plaintext_file);
681 path = folder_item_get_path(msginfo->folder);
682 file = g_strconcat(path, G_DIR_SEPARATOR_S,
683 itos(msginfo->msgnum), NULL);
690 gchar *procmsg_get_message_file(MsgInfo *msginfo)
692 gchar *filename = NULL;
694 g_return_val_if_fail(msginfo != NULL, NULL);
696 filename = folder_item_fetch_msg(msginfo->folder, msginfo->msgnum);
698 g_warning(_("can't fetch message %d\n"), msginfo->msgnum);
703 FILE *procmsg_open_message(MsgInfo *msginfo)
708 g_return_val_if_fail(msginfo != NULL, NULL);
710 file = procmsg_get_message_file_path(msginfo);
711 g_return_val_if_fail(file != NULL, NULL);
713 if ((fp = fopen(file, "r")) == NULL) {
714 FILE_OP_ERROR(file, "fopen");
721 if (MSG_IS_QUEUED(msginfo->flags)) {
724 while (fgets(buf, sizeof(buf), fp) != NULL)
725 if (buf[0] == '\r' || buf[0] == '\n') break;
731 gboolean procmsg_msg_exist(MsgInfo *msginfo)
736 if (!msginfo) return FALSE;
738 path = folder_item_get_path(msginfo->folder);
740 ret = !folder_item_is_msg_changed(msginfo->folder, msginfo);
746 void procmsg_empty_trash(void)
751 for (cur = folder_get_list(); cur != NULL; cur = cur->next) {
752 trash = FOLDER(cur->data)->trash;
753 if (trash && trash->total > 0)
754 folder_item_remove_all_msg(trash);
758 gint procmsg_send_queue(void)
764 queue = folder_get_default_queue();
765 g_return_val_if_fail(queue != NULL, -1);
766 folder_item_scan(queue);
767 if (queue->last_num < 0) return -1;
768 else if (queue->last_num == 0) return 0;
770 for (i = 1; i <= queue->last_num; i++) {
773 file = folder_item_fetch_msg(queue, i);
775 if (procmsg_send_message_queue(file) < 0) {
776 g_warning(_("Sending queued message %d failed.\n"), i);
779 folder_item_remove_msg(queue, i);
787 void procmsg_print_message(MsgInfo *msginfo, const gchar *cmdline)
789 static const gchar *def_cmd = "lpr %s";
796 g_return_if_fail(msginfo);
798 if ((tmpfp = procmime_get_first_text_content(msginfo)) == NULL) {
799 g_warning(_("Can't get text part\n"));
803 prtmp = g_strdup_printf("%s%cprinttmp.%08x",
804 get_mime_tmp_dir(), G_DIR_SEPARATOR, id++);
806 if ((prfp = fopen(prtmp, "w")) == NULL) {
807 FILE_OP_ERROR(prtmp, "fopen");
813 if (msginfo->date) fprintf(prfp, "Date: %s\n", msginfo->date);
814 if (msginfo->from) fprintf(prfp, "From: %s\n", msginfo->from);
815 if (msginfo->to) fprintf(prfp, "To: %s\n", msginfo->to);
816 if (msginfo->cc) fprintf(prfp, "Cc: %s\n", msginfo->cc);
817 if (msginfo->newsgroups)
818 fprintf(prfp, "Newsgroups: %s\n", msginfo->newsgroups);
819 if (msginfo->subject) fprintf(prfp, "Subject: %s\n", msginfo->subject);
822 while (fgets(buf, sizeof(buf), tmpfp) != NULL)
828 if (cmdline && (p = strchr(cmdline, '%')) && *(p + 1) == 's' &&
830 g_snprintf(buf, sizeof(buf) - 1, cmdline, prtmp);
833 g_warning(_("Print command line is invalid: `%s'\n"),
835 g_snprintf(buf, sizeof(buf) - 1, def_cmd, prtmp);
841 if (buf[strlen(buf) - 1] != '&') strcat(buf, "&");
845 MsgInfo *procmsg_msginfo_copy(MsgInfo *msginfo)
849 if (msginfo == NULL) return NULL;
851 newmsginfo = g_new0(MsgInfo, 1);
853 #define MEMBCOPY(mmb) newmsginfo->mmb = msginfo->mmb
854 #define MEMBDUP(mmb) newmsginfo->mmb = msginfo->mmb ? \
855 g_strdup(msginfo->mmb) : NULL
878 MEMBDUP(dispositionnotificationto);
879 MEMBDUP(returnreceiptto);
883 MEMBCOPY(threadscore);
888 void procmsg_msginfo_free(MsgInfo *msginfo)
890 if (msginfo == NULL) return;
892 g_free(msginfo->fromspace);
893 g_free(msginfo->references);
894 g_free(msginfo->returnreceiptto);
895 g_free(msginfo->dispositionnotificationto);
896 g_free(msginfo->xface);
898 g_free(msginfo->fromname);
900 g_free(msginfo->date);
901 g_free(msginfo->from);
904 g_free(msginfo->newsgroups);
905 g_free(msginfo->subject);
906 g_free(msginfo->msgid);
907 g_free(msginfo->inreplyto);
912 static gint procmsg_cmp_msgnum(gconstpointer a, gconstpointer b)
914 const MsgInfo *msginfo = a;
915 const guint msgnum = GPOINTER_TO_UINT(b);
920 return msginfo->msgnum - msgnum;
923 gint procmsg_cmp_msgnum_for_sort(gconstpointer a, gconstpointer b)
925 const MsgInfo *msginfo1 = a;
926 const MsgInfo *msginfo2 = b;
933 return msginfo1->msgnum - msginfo2->msgnum;
936 static gint procmsg_cmp_flag_msgnum(gconstpointer a, gconstpointer b)
938 const FlagInfo *finfo = a;
939 const guint msgnum = GPOINTER_TO_UINT(b);
944 return finfo->msgnum - msgnum;
953 Q_MAIL_ACCOUNT_ID = 4,
954 Q_NEWS_ACCOUNT_ID = 5,
955 Q_SAVE_COPY_FOLDER = 6
958 gint procmsg_send_message_queue(const gchar *file)
960 static HeaderEntry qentry[] = {{"S:", NULL, FALSE},
961 {"SSV:", NULL, FALSE},
963 {"NG:", NULL, FALSE},
964 {"MAID:", NULL, FALSE},
965 {"NAID:", NULL, FALSE},
966 {"SCF:", NULL, FALSE},
967 {NULL, NULL, FALSE}};
970 gint mailval = 0, newsval = 0;
972 gchar *smtpserver = NULL;
973 GSList *to_list = NULL;
974 GSList *newsgroup_list = NULL;
975 gchar *savecopyfolder = NULL;
978 PrefsAccount *mailac = NULL, *newsac = NULL;
981 g_return_val_if_fail(file != NULL, -1);
983 if ((fp = fopen(file, "r")) == NULL) {
984 FILE_OP_ERROR(file, "fopen");
988 while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry))
990 gchar *p = buf + strlen(qentry[hnum].name);
994 if (!from) from = g_strdup(p);
997 if (!smtpserver) smtpserver = g_strdup(p);
1000 to_list = address_list_append(to_list, p);
1003 newsgroup_list = newsgroup_list_append(newsgroup_list, p);
1005 case Q_MAIL_ACCOUNT_ID:
1006 mailac = account_find_from_id(atoi(p));
1008 case Q_NEWS_ACCOUNT_ID:
1009 newsac = account_find_from_id(atoi(p));
1011 case Q_SAVE_COPY_FOLDER:
1012 if (!savecopyfolder) savecopyfolder = g_strdup(p);
1017 filepos = ftell(fp);
1019 if(newsgroup_list || prefs_common.savemsg) {
1022 /* write to temporary file */
1023 tmp = g_strdup_printf("%s%ctmp%d", g_get_tmp_dir(),
1024 G_DIR_SEPARATOR, (gint)file);
1025 if ((tmpfp = fopen(tmp, "w")) == NULL) {
1026 FILE_OP_ERROR(tmp, "fopen");
1029 if (change_file_mode_rw(tmpfp, tmp) < 0) {
1030 FILE_OP_ERROR(tmp, "chmod");
1031 g_warning(_("can't change file mode\n"));
1034 while ((newsval == 0) && fgets(buf, sizeof(buf), fp) != NULL) {
1035 if (fputs(buf, tmpfp) == EOF) {
1036 FILE_OP_ERROR(tmp, "fputs");
1043 fseek(fp, filepos, SEEK_SET);
1045 debug_print(_("Sending message by mail\n"));
1047 g_warning(_("Queued message header is broken.\n"));
1049 } else if (prefs_common.use_extsend && prefs_common.extsend_cmd) {
1050 mailval = send_message_local(prefs_common.extsend_cmd, fp);
1053 mailac = account_find_from_smtp_server(from, smtpserver);
1055 g_warning(_("Account not found. "
1056 "Using current account...\n"));
1057 mailac = cur_account;
1062 mailval = send_message_smtp(mailac, to_list, fp);
1064 PrefsAccount tmp_ac;
1066 g_warning(_("Account not found.\n"));
1068 memset(&tmp_ac, 0, sizeof(PrefsAccount));
1069 tmp_ac.address = from;
1070 tmp_ac.smtp_server = smtpserver;
1071 tmp_ac.smtpport = SMTP_PORT;
1072 mailval = send_message_smtp(&tmp_ac, to_list, fp);
1077 if(newsgroup_list) {
1080 debug_print(_("Sending message by news\n"));
1082 folder = FOLDER(newsac->folder);
1085 newsval = news_post(folder, tmp);
1087 alertpanel_error(_("Error occurred while posting the message to %s ."),
1088 newsac->nntp_server);
1094 /* save message to outbox */
1095 if (mailval == 0 && newsval == 0 && savecopyfolder) {
1101 debug_print(_("saving sent message...\n"));
1103 folder = folder_find_item_from_identifier(savecopyfolder);
1105 folder = folder_get_default_outbox();
1106 path = folder_item_get_path(folder);
1107 if (!is_dir_exist(path))
1108 make_dir_hier(path);
1110 folder_item_scan(folder);
1111 if ((num = folder_item_add_msg(folder, tmp, FALSE)) < 0) {
1112 g_warning(_("can't save message\n"));
1116 if ((fp = procmsg_open_mark_file(path, TRUE)) == NULL)
1117 g_warning(_("can't open mark file\n"));
1121 newmsginfo.msgnum = num;
1122 newmsginfo.flags.perm_flags = 0;
1123 newmsginfo.flags.tmp_flags = 0;
1124 procmsg_write_flags(&newmsginfo, fp);
1131 slist_free_strings(to_list);
1132 g_slist_free(to_list);
1133 slist_free_strings(newsgroup_list);
1134 g_slist_free(newsgroup_list);
1143 return (newsval != 0 ? newsval : mailval);