summaryrefslogtreecommitdiff
path: root/src/send_message.c
diff options
context:
space:
mode:
authorSimeon Simeonov2018-02-26 11:23:00 +0100
committerSimeon Simeonov2018-02-26 11:23:00 +0100
commit0b3cbf57875fd692e4ba0b336fefa4bee1ed00dc (patch)
treeaf916a30553c78ce9d4f2d8658656a175c5b6921 /src/send_message.c
Initial commit for sylpheed 3.7.0
Diffstat (limited to 'src/send_message.c')
-rw-r--r--src/send_message.c1034
1 files changed, 1034 insertions, 0 deletions
diff --git a/src/send_message.c b/src/send_message.c
new file mode 100644
index 0000000..a8c2c7a
--- /dev/null
+++ b/src/send_message.c
@@ -0,0 +1,1034 @@
1/*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2012 Hiroyuki Yamamoto
4 *
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.
9 *
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.
14 *
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.
18 */
19
20#ifdef HAVE_CONFIG_H
21# include "config.h"
22#endif
23
24#include "defs.h"
25
26#include <glib.h>
27#include <glib/gi18n.h>
28#include <gtk/gtkmain.h>
29#include <gtk/gtksignal.h>
30#include <gtk/gtkwindow.h>
31#include <stdio.h>
32#include <string.h>
33#include <sys/types.h>
34#if HAVE_SYS_WAIT_H
35# include <sys/wait.h>
36#endif
37
38#include "send_message.h"
39#include "session.h"
40#include "ssl.h"
41#include "smtp.h"
42#include "news.h"
43#include "imap.h"
44#include "prefs_common.h"
45#include "prefs_account.h"
46#include "procheader.h"
47#include "account.h"
48#include "folder.h"
49#include "procmsg.h"
50#include "filter.h"
51#include "progressdialog.h"
52#include "statusbar.h"
53#include "alertpanel.h"
54#include "manage_window.h"
55#include "socket.h"
56#include "socks.h"
57#include "utils.h"
58#include "inc.h"
59#include "mainwindow.h"
60#include "summaryview.h"
61
62#define SMTP_PORT 25
63#if USE_SSL
64#define SSMTP_PORT 465
65#endif
66
67typedef struct _SendProgressDialog SendProgressDialog;
68
69struct _SendProgressDialog
70{
71 ProgressDialog *dialog;
72 Session *session;
73 gboolean show_dialog;
74 gboolean cancelled;
75};
76
77static gint send_message_local (const gchar *command,
78 FILE *fp);
79static gint send_message_smtp (PrefsAccount *ac_prefs,
80 GSList *to_list,
81 FILE *fp);
82
83static gint send_recv_message (Session *session,
84 const gchar *msg,
85 gpointer data);
86static gint send_send_data_progressive (Session *session,
87 guint cur_len,
88 guint total_len,
89 gpointer data);
90static gint send_send_data_finished (Session *session,
91 guint len,
92 gpointer data);
93
94static SendProgressDialog *send_progress_dialog_create(void);
95static void send_progress_dialog_destroy(SendProgressDialog *dialog);
96
97static void send_cancel_button_cb (GtkWidget *widget,
98 gpointer data);
99
100static void send_put_error (Session *session);
101
102
103gint send_message(const gchar *file, PrefsAccount *ac_prefs, GSList *to_list)
104{
105 FILE *fp;
106 gint val;
107
108 g_return_val_if_fail(file != NULL, -1);
109 g_return_val_if_fail(ac_prefs != NULL, -1);
110 g_return_val_if_fail(to_list != NULL, -1);
111
112 if ((fp = g_fopen(file, "rb")) == NULL) {
113 FILE_OP_ERROR(file, "fopen");
114 return -1;
115 }
116
117 if (prefs_common.use_extsend && prefs_common.extsend_cmd) {
118 val = send_message_local(prefs_common.extsend_cmd, fp);
119 fclose(fp);
120 return val;
121 }
122
123 val = send_message_smtp(ac_prefs, to_list, fp);
124
125 fclose(fp);
126 return val;
127}
128
129enum
130{
131 Q_SENDER = 0,
132 Q_SMTPSERVER = 1,
133 Q_RECIPIENTS = 2,
134 Q_ACCOUNT_ID = 3,
135 Q_REPLY_TARGET = 4,
136 Q_FORWARD_TARGETS = 5
137};
138
139QueueInfo *send_get_queue_info(const gchar *file)
140{
141 static HeaderEntry qentry[] = {{"S:", NULL, FALSE},
142 {"SSV:", NULL, FALSE},
143 {"R:", NULL, FALSE},
144 {"AID:", NULL, FALSE},
145 {"REP:", NULL, FALSE},
146 {"FWD:", NULL, FALSE},
147 {NULL, NULL, FALSE}};
148 FILE *fp;
149 gchar buf[BUFFSIZE];
150 gint hnum;
151 QueueInfo *qinfo;
152
153 g_return_val_if_fail(file != NULL, NULL);
154
155 if ((fp = g_fopen(file, "rb")) == NULL) {
156 FILE_OP_ERROR(file, "fopen");
157 return NULL;
158 }
159
160 qinfo = g_new0(QueueInfo, 1);
161
162 while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry))
163 != -1) {
164 gchar *p;
165
166 p = buf + strlen(qentry[hnum].name);
167
168 switch (hnum) {
169 case Q_SENDER:
170 if (!qinfo->from)
171 qinfo->from = g_strdup(p);
172 break;
173 case Q_SMTPSERVER:
174 if (!qinfo->server)
175 qinfo->server = g_strdup(p);
176 break;
177 case Q_RECIPIENTS:
178 qinfo->to_list =
179 address_list_append(qinfo->to_list, p);
180 break;
181 case Q_ACCOUNT_ID:
182 qinfo->ac = account_find_from_id(atoi(p));
183 break;
184 case Q_REPLY_TARGET:
185 qinfo->reply_target = g_strdup(p);
186 break;
187 case Q_FORWARD_TARGETS:
188 qinfo->forward_targets = g_strdup(p);
189 break;
190 default:
191 break;
192 }
193 }
194
195 qinfo->fp = fp;
196
197 if (((!qinfo->ac || (qinfo->ac && qinfo->ac->protocol != A_NNTP)) &&
198 !qinfo->to_list) || !qinfo->from) {
199 g_warning(_("Queued message header is broken.\n"));
200 send_queue_info_free(qinfo);
201 return NULL;
202 }
203
204 if (!qinfo->ac) {
205 qinfo->ac = account_find_from_smtp_server(qinfo->from,
206 qinfo->server);
207 if (!qinfo->ac) {
208 g_warning("Account not found. "
209 "Using current account...\n");
210 qinfo->ac = cur_account;
211 }
212 }
213
214 return qinfo;
215}
216
217static gint send_get_queue_contents(QueueInfo *qinfo, const gchar *dest)
218{
219 FILE *fp;
220 glong pos;
221 gchar buf[BUFFSIZE];
222
223 g_return_val_if_fail(qinfo != NULL, -1);
224 g_return_val_if_fail(qinfo->fp != NULL, -1);
225 g_return_val_if_fail(dest != NULL, -1);
226
227 if ((fp = g_fopen(dest, "wb")) == NULL) {
228 FILE_OP_ERROR(dest, "fopen");
229 return -1;
230 }
231
232 pos = ftell(qinfo->fp);
233
234 while (fgets(buf, sizeof(buf), qinfo->fp) != NULL)
235 fputs(buf, fp);
236
237 if (fclose(fp) < 0) {
238 FILE_OP_ERROR(dest, "fclose");
239 g_unlink(dest);
240 return -1;
241 }
242
243 fseek(qinfo->fp, pos, SEEK_SET);
244
245 return 0;
246}
247
248static gint send_save_queued_message(QueueInfo *qinfo, gboolean filter_msgs)
249{
250 FolderItem *outbox;
251 gboolean drop_done = FALSE;
252 gchar tmp[MAXPATHLEN + 1];
253
254 g_snprintf(tmp, sizeof(tmp), "%s%ctmpmsg.out.%08x",
255 get_rc_dir(), G_DIR_SEPARATOR, g_random_int());
256
257 if (send_get_queue_contents(qinfo, tmp) < 0)
258 return -1;
259
260 if (filter_msgs) {
261 FilterInfo *fltinfo;
262
263 fltinfo = filter_info_new();
264 fltinfo->account = qinfo->ac;
265 fltinfo->flags.perm_flags = 0;
266 fltinfo->flags.tmp_flags = MSG_RECEIVED;
267
268 filter_apply(prefs_common.fltlist, tmp, fltinfo);
269
270 drop_done = fltinfo->drop_done;
271 filter_info_free(fltinfo);
272 }
273
274 if (!drop_done) {
275 outbox = account_get_special_folder(qinfo->ac, F_OUTBOX);
276 procmsg_save_to_outbox(outbox, tmp);
277 }
278
279 g_unlink(tmp);
280
281 return 0;
282}
283
284void send_queue_info_free(QueueInfo *qinfo)
285{
286 if (qinfo == NULL) return;
287
288 slist_free_strings(qinfo->to_list);
289 g_slist_free(qinfo->to_list);
290 g_free(qinfo->from);
291 g_free(qinfo->server);
292 g_free(qinfo->reply_target);
293 g_free(qinfo->forward_targets);
294 if (qinfo->fp)
295 fclose(qinfo->fp);
296 g_free(qinfo);
297}
298
299gint send_message_queue(QueueInfo *qinfo)
300{
301 gint val = 0;
302 glong fpos;
303 PrefsAccount *mailac = NULL, *newsac = NULL;
304
305 g_return_val_if_fail(qinfo != NULL, -1);
306
307 fpos = ftell(qinfo->fp);
308
309 if (prefs_common.use_extsend && prefs_common.extsend_cmd) {
310 val = send_message_local(prefs_common.extsend_cmd, qinfo->fp);
311 } else {
312 if (qinfo->ac && qinfo->ac->protocol == A_NNTP) {
313 newsac = qinfo->ac;
314
315 /* search mail account */
316 mailac = account_find_from_address(qinfo->from);
317 if (!mailac) {
318 if (cur_account &&
319 cur_account->protocol != A_NNTP)
320 mailac = cur_account;
321 else {
322 mailac = account_get_default();
323 if (mailac->protocol == A_NNTP)
324 mailac = NULL;
325 }
326 }
327 } else
328 mailac = qinfo->ac;
329
330 if (qinfo->to_list) {
331 if (mailac)
332 val = send_message_smtp(mailac, qinfo->to_list,
333 qinfo->fp);
334 else {
335 PrefsAccount tmp_ac;
336
337 g_warning("Account not found.\n");
338
339 memset(&tmp_ac, 0, sizeof(PrefsAccount));
340 tmp_ac.address = qinfo->from;
341 tmp_ac.smtp_server = qinfo->server;
342 tmp_ac.smtpport = SMTP_PORT;
343 val = send_message_smtp(&tmp_ac, qinfo->to_list,
344 qinfo->fp);
345 }
346 }
347
348 if (val == 0 && newsac) {
349 fseek(qinfo->fp, fpos, SEEK_SET);
350 val = news_post_stream(FOLDER(newsac->folder),
351 qinfo->fp);
352 if (val < 0)
353 alertpanel_error(_("Error occurred while posting the message to %s ."),
354 newsac->nntp_server);
355 }
356 }
357
358 fseek(qinfo->fp, fpos, SEEK_SET);
359
360 return val;
361}
362
363gint send_message_queue_all(FolderItem *queue, gboolean save_msgs,
364 gboolean filter_msgs)
365{
366 gint ret = 0;
367 GSList *mlist = NULL;
368 GSList *cur;
369
370 if (!queue)
371 queue = folder_get_default_queue();
372 g_return_val_if_fail(queue != NULL, -1);
373
374 mlist = folder_item_get_msg_list(queue, FALSE);
375 mlist = procmsg_sort_msg_list(mlist, SORT_BY_NUMBER, SORT_ASCENDING);
376
377 for (cur = mlist; cur != NULL; cur = cur->next) {
378 gchar *file;
379 MsgInfo *msginfo = (MsgInfo *)cur->data;
380 QueueInfo *qinfo;
381
382 file = procmsg_get_message_file(msginfo);
383 if (!file)
384 continue;
385
386 qinfo = send_get_queue_info(file);
387 if (!qinfo || send_message_queue(qinfo) < 0) {
388 g_warning("Sending queued message %d failed.\n",
389 msginfo->msgnum);
390 send_queue_info_free(qinfo);
391 g_free(file);
392 continue;
393 }
394
395 if (qinfo->reply_target)
396 send_message_set_reply_flag(qinfo->reply_target,
397 msginfo->inreplyto);
398 else if (qinfo->forward_targets)
399 send_message_set_forward_flags(qinfo->forward_targets);
400
401 if (save_msgs)
402 send_save_queued_message(qinfo, filter_msgs);
403
404 send_queue_info_free(qinfo);
405 g_free(file);
406
407 folder_item_remove_msg(queue, msginfo);
408 ret++;
409 }
410
411 procmsg_msg_list_free(mlist);
412
413 procmsg_clear_cache(queue);
414 queue->cache_dirty = FALSE;
415 queue->mtime = 0;
416
417 return ret;
418}
419
420gint send_message_set_reply_flag(const gchar *target, const gchar *msgid)
421{
422 FolderItem *item;
423 gint num;
424 MsgInfo *msginfo;
425 SummaryView *summaryview;
426
427 g_return_val_if_fail(target != NULL, -1);
428
429 debug_print("send_message_set_reply_flag(): "
430 "setting reply flag to: %s\n", target);
431
432 summaryview = main_window_get()->summaryview;
433
434 item = folder_find_item_and_num_from_id(target, &num);
435 if (!item || num <= 0)
436 return -1;
437
438 if (summaryview->folder_item == item) {
439 msginfo = summary_get_msginfo_by_msgnum(summaryview, num);
440 if (msginfo) {
441 if (msgid && strcmp2(msgid, msginfo->msgid) != 0) {
442 debug_print("send_message_set_reply_flag(): "
443 "message-id mismatch\n");
444 return -1;
445 }
446 MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_FORWARDED);
447 MSG_SET_PERM_FLAGS(msginfo->flags, MSG_REPLIED);
448 MSG_SET_TMP_FLAGS(msginfo->flags, MSG_FLAG_CHANGED);
449 if (MSG_IS_IMAP(msginfo->flags))
450 imap_msg_set_perm_flags(msginfo, MSG_REPLIED);
451 if (msginfo->folder)
452 msginfo->folder->mark_dirty = TRUE;
453 summary_update_by_msgnum(summaryview, msginfo->msgnum);
454 }
455 } else {
456 msginfo = procmsg_get_msginfo(item, num);
457 if (msginfo) {
458 if (msgid && strcmp2(msgid, msginfo->msgid) != 0) {
459 debug_print("send_message_set_reply_flag(): "
460 "message-id mismatch\n");
461 procmsg_msginfo_free(msginfo);
462 return -1;
463 }
464 MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_FORWARDED);
465 MSG_SET_PERM_FLAGS(msginfo->flags, MSG_REPLIED);
466 MSG_SET_TMP_FLAGS(msginfo->flags, MSG_FLAG_CHANGED);
467 if (MSG_IS_IMAP(msginfo->flags))
468 imap_msg_set_perm_flags(msginfo, MSG_REPLIED);
469 if (msginfo->folder)
470 msginfo->folder->mark_dirty = TRUE;
471 procmsg_add_flags(msginfo->folder, msginfo->msgnum,
472 msginfo->flags);
473 procmsg_msginfo_free(msginfo);
474 }
475 }
476
477 return 0;
478}
479
480gint send_message_set_forward_flags(const gchar *targets)
481{
482 FolderItem *item;
483 gint num;
484 MsgInfo *msginfo;
485 SummaryView *summaryview;
486 gchar **paths;
487 gint i;
488 GSList *mlist = NULL;
489
490 g_return_val_if_fail(targets != NULL, -1);
491
492 debug_print("send_message_set_forward_flags(): "
493 "setting forward flags to: %s\n", targets);
494
495 summaryview = main_window_get()->summaryview;
496
497 paths = g_strsplit(targets, "\n", 0);
498
499 for (i = 0; paths[i] != NULL; i++) {
500 g_strstrip(paths[i]);
501
502 item = folder_find_item_and_num_from_id(paths[i], &num);
503 if (!item || num <= 0)
504 continue;
505
506 if (summaryview->folder_item == item) {
507 msginfo = summary_get_msginfo_by_msgnum(summaryview,
508 num);
509 if (msginfo) {
510 MSG_UNSET_PERM_FLAGS(msginfo->flags,
511 MSG_REPLIED);
512 MSG_SET_PERM_FLAGS(msginfo->flags,
513 MSG_FORWARDED);
514 MSG_SET_TMP_FLAGS(msginfo->flags,
515 MSG_FLAG_CHANGED);
516 if (msginfo->folder)
517 msginfo->folder->mark_dirty = TRUE;
518 summary_update_by_msgnum
519 (summaryview, msginfo->msgnum);
520 msginfo = procmsg_msginfo_copy(msginfo);
521 }
522 } else {
523 msginfo = procmsg_get_msginfo(item, num);
524 if (msginfo) {
525 MSG_UNSET_PERM_FLAGS(msginfo->flags,
526 MSG_REPLIED);
527 MSG_SET_PERM_FLAGS(msginfo->flags,
528 MSG_FORWARDED);
529 MSG_SET_TMP_FLAGS(msginfo->flags,
530 MSG_FLAG_CHANGED);
531 if (msginfo->folder)
532 msginfo->folder->mark_dirty = TRUE;
533 procmsg_add_flags(msginfo->folder,
534 msginfo->msgnum,
535 msginfo->flags);
536 }
537 }
538
539 if (msginfo)
540 mlist = g_slist_append(mlist, msginfo);
541 }
542
543 if (mlist) {
544 msginfo = (MsgInfo *)mlist->data;
545 if (MSG_IS_IMAP(msginfo->flags))
546 imap_msg_list_unset_perm_flags(mlist, MSG_REPLIED);
547 }
548
549 procmsg_msg_list_free(mlist);
550 g_strfreev(paths);
551
552 return 0;
553}
554
555static gint send_message_local(const gchar *command, FILE *fp)
556{
557 gchar **argv;
558 GPid pid;
559 gint child_stdin;
560 gchar buf[BUFFSIZE];
561 gboolean err = FALSE;
562 gint status;
563
564 g_return_val_if_fail(command != NULL, -1);
565 g_return_val_if_fail(fp != NULL, -1);
566
567 log_message(_("Sending message using command: %s\n"), command);
568
569 argv = strsplit_with_quote(command, " ", 0);
570
571 if (g_spawn_async_with_pipes(NULL, argv, NULL,
572 G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
573 &pid, &child_stdin, NULL, NULL,
574 NULL) == FALSE) {
575 g_snprintf(buf, sizeof(buf),
576 _("Can't execute command: %s"), command);
577 log_warning("%s\n", buf);
578 alertpanel_error("%s", buf);
579 g_strfreev(argv);
580 return -1;
581 }
582 g_strfreev(argv);
583
584 while (fgets(buf, sizeof(buf), fp) != NULL) {
585 strretchomp(buf);
586 if (buf[0] == '.' && buf[1] == '\0') {
587 if (fd_write_all(child_stdin, ".", 1) < 0) {
588 err = TRUE;
589 break;
590 }
591 }
592 if (fd_write_all(child_stdin, buf, strlen(buf)) < 0 ||
593 fd_write_all(child_stdin, "\n", 1) < 0) {
594 err = TRUE;
595 break;
596 }
597 }
598
599 fd_close(child_stdin);
600
601#ifdef G_OS_UNIX
602 waitpid(pid, &status, 0);
603 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
604 err = TRUE;
605#endif
606
607 g_spawn_close_pid(pid);
608
609 if (err) {
610 g_snprintf(buf, sizeof(buf),
611 _("Error occurred while executing command: %s"),
612 command);
613 log_warning("%s\n", buf);
614 alertpanel_error("%s", buf);
615 return -1;
616 }
617
618 return 0;
619}
620
621static gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
622{
623 Session *session;
624 SMTPSession *smtp_session;
625 SocksInfo *socks_info = NULL;
626 FILE *out_fp;
627 gushort port;
628 SendProgressDialog *dialog;
629 gchar buf[BUFFSIZE];
630 gint ret = 0;
631
632 g_return_val_if_fail(ac_prefs != NULL, -1);
633 g_return_val_if_fail(ac_prefs->address != NULL, -1);
634 g_return_val_if_fail(ac_prefs->smtp_server != NULL, -1);
635 g_return_val_if_fail(to_list != NULL, -1);
636 g_return_val_if_fail(fp != NULL, -1);
637
638 session = smtp_session_new();
639 smtp_session = SMTP_SESSION(session);
640
641 smtp_session->hostname =
642 ac_prefs->set_domain ? g_strdup(ac_prefs->domain) : NULL;
643
644 if (ac_prefs->use_smtp_auth) {
645 inc_lock();
646
647 smtp_session->forced_auth_type = ac_prefs->smtp_auth_type;
648
649 if (ac_prefs->smtp_userid) {
650 smtp_session->user = g_strdup(ac_prefs->smtp_userid);
651 if (ac_prefs->smtp_passwd)
652 smtp_session->pass =
653 g_strdup(ac_prefs->smtp_passwd);
654 else if (ac_prefs->tmp_smtp_pass)
655 smtp_session->pass =
656 g_strdup(ac_prefs->tmp_smtp_pass);
657 else {
658 smtp_session->pass =
659 input_query_password
660 (ac_prefs->smtp_server,
661 smtp_session->user);
662 if (!smtp_session->pass)
663 smtp_session->pass = g_strdup("");
664 ac_prefs->tmp_smtp_pass =
665 g_strdup(smtp_session->pass);
666 }
667 } else {
668 smtp_session->user = g_strdup(ac_prefs->userid);
669 if (ac_prefs->passwd)
670 smtp_session->pass = g_strdup(ac_prefs->passwd);
671 else if (ac_prefs->tmp_pass)
672 smtp_session->pass =
673 g_strdup(ac_prefs->tmp_pass);
674 else {
675 smtp_session->pass =
676 input_query_password
677 (ac_prefs->smtp_server,
678 smtp_session->user);
679 if (!smtp_session->pass)
680 smtp_session->pass = g_strdup("");
681 ac_prefs->tmp_pass =
682 g_strdup(smtp_session->pass);
683 }
684 }
685
686 inc_unlock();
687 } else {
688 smtp_session->user = NULL;
689 smtp_session->pass = NULL;
690 }
691
692 smtp_session->from = g_strdup(ac_prefs->address);
693 smtp_session->to_list = to_list;
694 smtp_session->cur_to = to_list;
695
696 out_fp = get_outgoing_rfc2822_file(fp);
697 if (!out_fp) {
698 session_destroy(session);
699 return -1;
700 }
701 smtp_session->send_data_fp = out_fp;
702 smtp_session->send_data_len = get_left_file_size(out_fp);
703 if (smtp_session->send_data_len < 0) {
704 session_destroy(session);
705 return -1;
706 }
707
708#if USE_SSL
709 port = ac_prefs->set_smtpport ? ac_prefs->smtpport :
710 ac_prefs->ssl_smtp == SSL_TUNNEL ? SSMTP_PORT : SMTP_PORT;
711 session->ssl_type = ac_prefs->ssl_smtp;
712 if (ac_prefs->ssl_smtp != SSL_NONE)
713 session->nonblocking = ac_prefs->use_nonblocking_ssl;
714#else
715 port = ac_prefs->set_smtpport ? ac_prefs->smtpport : SMTP_PORT;
716#endif
717
718 if (ac_prefs->pop_before_smtp && ac_prefs->protocol == A_POP3) {
719 if (inc_pop_before_smtp(ac_prefs) < 0) {
720 session_destroy(session);
721 return -1;
722 }
723 }
724
725 dialog = send_progress_dialog_create();
726 dialog->session = session;
727
728 progress_dialog_append(dialog->dialog, NULL, ac_prefs->smtp_server,
729 _("Connecting"), "", NULL);
730
731 g_snprintf(buf, sizeof(buf), _("Connecting to SMTP server: %s ..."),
732 ac_prefs->smtp_server);
733 progress_dialog_set_label(dialog->dialog, buf);
734 log_message("%s\n", buf);
735
736 session_set_recv_message_notify(session, send_recv_message, dialog);
737 session_set_send_data_progressive_notify
738 (session, send_send_data_progressive, dialog);
739 session_set_send_data_notify(session, send_send_data_finished, dialog);
740
741 session_set_timeout(session, prefs_common.io_timeout_secs * 1000);
742
743 if (ac_prefs->use_socks && ac_prefs->use_socks_for_send) {
744 socks_info = socks_info_new(ac_prefs->socks_type,
745 ac_prefs->proxy_host,
746 ac_prefs->proxy_port,
747 ac_prefs->use_proxy_auth
748 ? ac_prefs->proxy_name : NULL,
749 ac_prefs->use_proxy_auth
750 ? ac_prefs->proxy_pass : NULL);
751 }
752
753 inc_lock();
754
755 if (session_connect_full(session, ac_prefs->smtp_server, port,
756 socks_info) < 0) {
757 if (dialog->show_dialog)
758 manage_window_focus_in(dialog->dialog->window, NULL, NULL);
759 send_put_error(session);
760 if (dialog->show_dialog)
761 manage_window_focus_out(dialog->dialog->window, NULL, NULL);
762 session_destroy(session);
763 send_progress_dialog_destroy(dialog);
764 inc_unlock();
765 return -1;
766 }
767
768 debug_print("send_message_smtp(): begin event loop\n");
769
770 while (session_is_connected(session) && dialog->cancelled == FALSE)
771 gtk_main_iteration();
772 log_window_flush();
773
774 if (SMTP_SESSION(session)->error_val == SM_AUTHFAIL) {
775 if (ac_prefs->smtp_userid && ac_prefs->tmp_smtp_pass) {
776 g_free(ac_prefs->tmp_smtp_pass);
777 ac_prefs->tmp_smtp_pass = NULL;
778 } else if (!ac_prefs->smtp_userid && ac_prefs->tmp_pass) {
779 g_free(ac_prefs->tmp_pass);
780 ac_prefs->tmp_pass = NULL;
781 }
782 ret = -1;
783 } else if (session->state == SESSION_EOF &&
784 SMTP_SESSION(session)->state == SMTP_QUIT) {
785 /* consider EOF right after QUIT successful */
786 log_warning("%s\n", _("Connection closed by the remote host."));
787 ret = 0;
788 } else if (session->state == SESSION_ERROR &&
789 SMTP_SESSION(session)->state == SMTP_QUIT) {
790 /* ignore errors right after QUIT */
791 log_warning("%s\n", _("Error occurred after QUIT command (ignored)"));
792 ret = 0;
793 } else if (session->state == SESSION_ERROR ||
794 session->state == SESSION_EOF ||
795 session->state == SESSION_TIMEOUT ||
796 SMTP_SESSION(session)->state == SMTP_ERROR ||
797 SMTP_SESSION(session)->error_val != SM_OK)
798 ret = -1;
799 else if (dialog->cancelled == TRUE)
800 ret = -1;
801
802 if (ret == -1) {
803 if (dialog->show_dialog)
804 manage_window_focus_in(dialog->dialog->window, NULL, NULL);
805 send_put_error(session);
806 if (dialog->show_dialog)
807 manage_window_focus_out(dialog->dialog->window, NULL, NULL);
808 }
809
810 session_destroy(session);
811 send_progress_dialog_destroy(dialog);
812 inc_unlock();
813
814 return ret;
815}
816
817static gint send_recv_message(Session *session, const gchar *msg, gpointer data)
818{
819 gchar buf[BUFFSIZE];
820 SMTPSession *smtp_session = SMTP_SESSION(session);
821 SendProgressDialog *dialog = (SendProgressDialog *)data;
822 gchar *state_str = NULL;
823
824 g_return_val_if_fail(dialog != NULL, -1);
825
826 gdk_threads_enter();
827
828 switch (smtp_session->state) {
829 case SMTP_READY:
830 case SMTP_CONNECTED:
831 gdk_threads_leave();
832 return 0;
833 case SMTP_HELO:
834 g_snprintf(buf, sizeof(buf), _("Sending HELO..."));
835 state_str = _("Authenticating");
836 statusbar_print_all(_("Sending message via %s:%d..."),
837 session->server, session->port);
838 break;
839 case SMTP_EHLO:
840 g_snprintf(buf, sizeof(buf), _("Sending EHLO..."));
841 state_str = _("Authenticating");
842 statusbar_print_all(_("Sending message via %s:%d..."),
843 session->server, session->port);
844 break;
845 case SMTP_AUTH:
846 g_snprintf(buf, sizeof(buf), _("Authenticating..."));
847 state_str = _("Authenticating");
848 break;
849 case SMTP_FROM:
850 g_snprintf(buf, sizeof(buf), _("Sending MAIL FROM..."));
851 state_str = _("Sending");
852 break;
853 case SMTP_RCPT:
854 g_snprintf(buf, sizeof(buf), _("Sending RCPT TO..."));
855 state_str = _("Sending");
856 break;
857 case SMTP_DATA:
858 case SMTP_EOM:
859 g_snprintf(buf, sizeof(buf), _("Sending DATA..."));
860 state_str = _("Sending");
861 break;
862 case SMTP_QUIT:
863 g_snprintf(buf, sizeof(buf), _("Quitting..."));
864 state_str = _("Quitting");
865 break;
866 case SMTP_ERROR:
867 g_warning("send: error: %s\n", msg);
868 gdk_threads_leave();
869 return 0;
870 default:
871 gdk_threads_leave();
872 return 0;
873 }
874
875 progress_dialog_set_label(dialog->dialog, buf);
876 progress_dialog_set_row_status(dialog->dialog, 0, state_str);
877
878 gdk_threads_leave();
879
880 return 0;
881}
882
883static gint send_send_data_progressive(Session *session, guint cur_len,
884 guint total_len, gpointer data)
885{
886 gchar buf[BUFFSIZE];
887 SendProgressDialog *dialog = (SendProgressDialog *)data;
888
889 g_return_val_if_fail(dialog != NULL, -1);
890
891 if (SMTP_SESSION(session)->state != SMTP_SEND_DATA &&
892 SMTP_SESSION(session)->state != SMTP_EOM)
893 return 0;
894
895 gdk_threads_enter();
896
897 g_snprintf(buf, sizeof(buf), _("Sending message (%d / %d bytes)"),
898 cur_len, total_len);
899 progress_dialog_set_label(dialog->dialog, buf);
900 progress_dialog_set_percentage
901 (dialog->dialog, (gfloat)cur_len / (gfloat)total_len);
902 g_snprintf(buf, sizeof(buf), _("%d / %d bytes"),
903 cur_len, total_len);
904 progress_dialog_set_row_progress(dialog->dialog, 0, buf);
905#ifdef G_OS_WIN32
906 GTK_EVENTS_FLUSH();
907#endif
908 gdk_threads_leave();
909
910 return 0;
911}
912
913static gint send_send_data_finished(Session *session, guint len, gpointer data)
914{
915 SendProgressDialog *dialog = (SendProgressDialog *)data;
916
917 g_return_val_if_fail(dialog != NULL, -1);
918
919 send_send_data_progressive(session, len, len, dialog);
920
921 return 0;
922}
923
924static SendProgressDialog *send_progress_dialog_create(void)
925{
926 SendProgressDialog *dialog;
927 ProgressDialog *progress;
928
929 dialog = g_new0(SendProgressDialog, 1);
930
931 progress = progress_dialog_create();
932 gtk_window_set_title(GTK_WINDOW(progress->window),
933 _("Sending message"));
934 g_signal_connect(G_OBJECT(progress->cancel_btn), "clicked",
935 G_CALLBACK(send_cancel_button_cb), dialog);
936 g_signal_connect(G_OBJECT(progress->window), "delete_event",
937 G_CALLBACK(gtk_true), NULL);
938 /* gtk_window_set_modal(GTK_WINDOW(progress->window), TRUE); */
939 manage_window_set_transient(GTK_WINDOW(progress->window));
940
941 progress_dialog_set_value(progress, 0.0);
942
943 if (prefs_common.show_send_dialog) {
944 dialog->show_dialog = TRUE;
945 gtk_widget_show_now(progress->window);
946 }
947
948 dialog->dialog = progress;
949
950 return dialog;
951}
952
953static void send_progress_dialog_destroy(SendProgressDialog *dialog)
954{
955 g_return_if_fail(dialog != NULL);
956
957 manage_window_destroy(dialog->dialog->window, NULL);
958 progress_dialog_destroy(dialog->dialog);
959 g_free(dialog);
960}
961
962static void send_cancel_button_cb(GtkWidget *widget, gpointer data)
963{
964 SendProgressDialog *dialog = (SendProgressDialog *)data;
965
966 dialog->cancelled = TRUE;
967 session_disconnect(dialog->session);
968}
969
970static void send_put_error(Session *session)
971{
972 gchar *msg;
973 gchar *log_msg = NULL;
974 gchar *err_msg = NULL;
975
976 msg = SMTP_SESSION(session)->error_msg;
977
978 switch (SMTP_SESSION(session)->error_val) {
979 case SM_ERROR:
980 case SM_UNRECOVERABLE:
981 log_msg = _("Error occurred while sending the message.");
982 if (msg)
983 err_msg = g_strdup_printf
984 (_("Error occurred while sending the message:\n%s"),
985 msg);
986 else
987 err_msg = g_strdup(log_msg);
988 break;
989 case SM_AUTHFAIL:
990 log_msg = _("Authentication failed.");
991 if (msg)
992 err_msg = g_strdup_printf
993 (_("Authentication failed:\n%s"), msg);
994 else
995 err_msg = g_strdup(log_msg);
996 break;
997 default:
998 switch (session->state) {
999 case SESSION_ERROR:
1000 if (session_get_error(session) == SESSION_ERROR_LOOKUP) {
1001 log_msg = _("Server not found.");
1002 err_msg = g_strdup_printf
1003 (_("SMTP server not found: %s:%d"), session->server, session->port);
1004 } else if (SMTP_SESSION(session)->state == SMTP_READY) {
1005 log_msg = _("Can't connect to SMTP server.");
1006 err_msg = g_strdup_printf
1007 (_("Can't connect to SMTP server: %s:%d"), session->server, session->port);
1008 } else {
1009 log_msg = _("Error occurred while sending the message.");
1010 err_msg = g_strdup(log_msg);
1011 }
1012 break;
1013 case SESSION_EOF:
1014 log_msg = _("Connection closed by the remote host.");
1015 err_msg = g_strdup(log_msg);
1016 break;
1017 case SESSION_TIMEOUT:
1018 log_msg = _("Session timed out.");
1019 err_msg = g_strdup(log_msg);
1020 break;
1021 default:
1022 break;
1023 }
1024 break;
1025 }
1026
1027 if (log_msg)
1028 log_warning("%s\n", log_msg);
1029 if (err_msg) {
1030 alertpanel_error("%s", err_msg);
1031 g_free(err_msg);
1032 }
1033}
1034