Statistics
| Revision:

root / src / send_message.c @ 1623

History | View | Annotate | Download (19.2 kB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2006 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 "prefs_common.h"
44
#include "prefs_account.h"
45
#include "procheader.h"
46
#include "account.h"
47
#include "folder.h"
48
#include "procmsg.h"
49
#include "filter.h"
50
#include "progressdialog.h"
51
#include "statusbar.h"
52
#include "alertpanel.h"
53
#include "manage_window.h"
54
#include "socket.h"
55
#include "utils.h"
56
#include "inc.h"
57
58
#define SMTP_PORT        25
59
#if USE_SSL
60
#define SSMTP_PORT        465
61
#endif
62
63
typedef struct _SendProgressDialog        SendProgressDialog;
64
65
struct _SendProgressDialog
66
{
67
        ProgressDialog *dialog;
68
        Session *session;
69
        gboolean cancelled;
70
};
71
72
static gint send_message_local                (const gchar                *command,
73
                                         FILE                        *fp);
74
static gint send_message_smtp                (PrefsAccount                *ac_prefs,
75
                                         GSList                        *to_list,
76
                                         FILE                        *fp);
77
78
static gint send_recv_message                (Session                *session,
79
                                         const gchar                *msg,
80
                                         gpointer                 data);
81
static gint send_send_data_progressive        (Session                *session,
82
                                         guint                         cur_len,
83
                                         guint                         total_len,
84
                                         gpointer                 data);
85
static gint send_send_data_finished        (Session                *session,
86
                                         guint                         len,
87
                                         gpointer                 data);
88
89
static SendProgressDialog *send_progress_dialog_create(void);
90
static void send_progress_dialog_destroy(SendProgressDialog *dialog);
91
92
static void send_cancel_button_cb        (GtkWidget        *widget,
93
                                         gpointer         data);
94
95
static void send_put_error                (Session        *session);
96
97
98
gint send_message(const gchar *file, PrefsAccount *ac_prefs, GSList *to_list)
99
{
100
        FILE *fp;
101
        gint val;
102
103
        g_return_val_if_fail(file != NULL, -1);
104
        g_return_val_if_fail(ac_prefs != NULL, -1);
105
        g_return_val_if_fail(to_list != NULL, -1);
106
107
        if ((fp = g_fopen(file, "rb")) == NULL) {
108
                FILE_OP_ERROR(file, "fopen");
109
                return -1;
110
        }
111
112
        if (prefs_common.use_extsend && prefs_common.extsend_cmd) {
113
                val = send_message_local(prefs_common.extsend_cmd, fp);
114
                fclose(fp);
115
                return val;
116
        }
117
118
        val = send_message_smtp(ac_prefs, to_list, fp);
119
120
        fclose(fp);
121
        return val;
122
}
123
124
enum
125
{
126
        Q_SENDER     = 0,
127
        Q_SMTPSERVER = 1,
128
        Q_RECIPIENTS = 2,
129
        Q_ACCOUNT_ID = 3
130
};
131
132
QueueInfo *send_get_queue_info(const gchar *file)
133
{
134
        static HeaderEntry qentry[] = {{"S:",   NULL, FALSE},
135
                                       {"SSV:", NULL, FALSE},
136
                                       {"R:",   NULL, FALSE},
137
                                       {"AID:", NULL, FALSE},
138
                                       {NULL,   NULL, FALSE}};
139
        FILE *fp;
140
        gchar buf[BUFFSIZE];
141
        gint hnum;
142
        QueueInfo *qinfo;
143
144
        g_return_val_if_fail(file != NULL, NULL);
145
146
        if ((fp = g_fopen(file, "rb")) == NULL) {
147
                FILE_OP_ERROR(file, "fopen");
148
                return NULL;
149
        }
150
151
        qinfo = g_new0(QueueInfo, 1);
152
153
        while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry))
154
               != -1) {
155
                gchar *p;
156
157
                p = buf + strlen(qentry[hnum].name);
158
159
                switch (hnum) {
160
                case Q_SENDER:
161
                        if (!qinfo->from)
162
                                qinfo->from = g_strdup(p);
163
                        break;
164
                case Q_SMTPSERVER:
165
                        if (!qinfo->server)
166
                                qinfo->server = g_strdup(p);
167
                        break;
168
                case Q_RECIPIENTS:
169
                        qinfo->to_list =
170
                                address_list_append(qinfo->to_list, p);
171
                        break;
172
                case Q_ACCOUNT_ID:
173
                        qinfo->ac = account_find_from_id(atoi(p));
174
                        break;
175
                default:
176
                        break;
177
                }
178
        }
179
180
        qinfo->fp = fp;
181
182
        if (((!qinfo->ac || (qinfo->ac && qinfo->ac->protocol != A_NNTP)) &&
183
             !qinfo->to_list) || !qinfo->from) {
184
                g_warning(_("Queued message header is broken.\n"));
185
                send_queue_info_free(qinfo);
186
                return NULL;
187
        }
188
189
        if (!qinfo->ac) {
190
                qinfo->ac = account_find_from_smtp_server(qinfo->from,
191
                                                          qinfo->server);
192
                if (!qinfo->ac) {
193
                        g_warning("Account not found. "
194
                                  "Using current account...\n");
195
                        qinfo->ac = cur_account;
196
                }
197
        }
198
199
        return qinfo;
200
}
201
202
gint send_get_queue_contents(QueueInfo *qinfo, const gchar *dest)
203
{
204
        FILE *fp;
205
        glong pos;
206
        gchar buf[BUFFSIZE];
207
208
        g_return_val_if_fail(qinfo != NULL, -1);
209
        g_return_val_if_fail(qinfo->fp != NULL, -1);
210
        g_return_val_if_fail(dest != NULL, -1);
211
212
        if ((fp = g_fopen(dest, "wb")) == NULL) {
213
                FILE_OP_ERROR(dest, "fopen");
214
                return -1;
215
        }
216
217
        pos = ftell(qinfo->fp);
218
219
        while (fgets(buf, sizeof(buf), qinfo->fp) != NULL)
220
                fputs(buf, fp);
221
222
        if (fclose(fp) < 0) {
223
                FILE_OP_ERROR(dest, "fclose");
224
                g_unlink(dest);
225
                return -1;
226
        }
227
228
        fseek(qinfo->fp, pos, SEEK_SET);
229
230
        return 0;
231
}
232
233
void send_queue_info_free(QueueInfo *qinfo)
234
{
235
        if (qinfo == NULL) return;
236
237
        slist_free_strings(qinfo->to_list);
238
        g_slist_free(qinfo->to_list);
239
        g_free(qinfo->from);
240
        g_free(qinfo->server);
241
        if (qinfo->fp)
242
                fclose(qinfo->fp);
243
        g_free(qinfo);
244
}
245
246
gint send_message_queue(QueueInfo *qinfo)
247
{
248
        gint val = 0;
249
        glong fpos;
250
        PrefsAccount *mailac = NULL, *newsac = NULL;
251
252
        g_return_val_if_fail(qinfo != NULL, -1);
253
254
        fpos = ftell(qinfo->fp);
255
256
        if (prefs_common.use_extsend && prefs_common.extsend_cmd) {
257
                val = send_message_local(prefs_common.extsend_cmd, qinfo->fp);
258
        } else {
259
                if (qinfo->ac && qinfo->ac->protocol == A_NNTP) {
260
                        newsac = qinfo->ac;
261
262
                        /* search mail account */
263
                        mailac = account_find_from_address(qinfo->from);
264
                        if (!mailac) {
265
                                if (cur_account &&
266
                                    cur_account->protocol != A_NNTP)
267
                                        mailac = cur_account;
268
                                else {
269
                                        mailac = account_get_default();
270
                                        if (mailac->protocol == A_NNTP)
271
                                                mailac = NULL;
272
                                }
273
                        }
274
                } else
275
                        mailac = qinfo->ac;
276
277
                if (qinfo->to_list) {
278
                        if (mailac)
279
                                val = send_message_smtp(mailac, qinfo->to_list,
280
                                                        qinfo->fp);
281
                        else {
282
                                PrefsAccount tmp_ac;
283
284
                                g_warning("Account not found.\n");
285
286
                                memset(&tmp_ac, 0, sizeof(PrefsAccount));
287
                                tmp_ac.address = qinfo->from;
288
                                tmp_ac.smtp_server = qinfo->server;
289
                                tmp_ac.smtpport = SMTP_PORT;
290
                                val = send_message_smtp(&tmp_ac, qinfo->to_list,
291
                                                        qinfo->fp);
292
                        }
293
                }
294
295
                if (val == 0 && newsac) {
296
                        fseek(qinfo->fp, fpos, SEEK_SET);
297
                        val = news_post_stream(FOLDER(newsac->folder),
298
                                               qinfo->fp);
299
                        if (val < 0)
300
                                alertpanel_error(_("Error occurred while posting the message to %s ."),
301
                                                 newsac->nntp_server);
302
                }
303
        }
304
305
        fseek(qinfo->fp, fpos, SEEK_SET);
306
307
        return val;
308
}
309
310
gint send_message_queue_all(FolderItem *queue, gboolean save_msgs,
311
                            gboolean filter_msgs)
312
{
313
        gint ret = 0;
314
        GSList *mlist = NULL;
315
        GSList *cur;
316
317
        if (!queue)
318
                queue = folder_get_default_queue();
319
        g_return_val_if_fail(queue != NULL, -1);
320
321
        mlist = folder_item_get_msg_list(queue, FALSE);
322
        mlist = procmsg_sort_msg_list(mlist, SORT_BY_NUMBER, SORT_ASCENDING);
323
324
        for (cur = mlist; cur != NULL; cur = cur->next) {
325
                gchar *file;
326
                MsgInfo *msginfo = (MsgInfo *)cur->data;
327
                QueueInfo *qinfo;
328
                gchar tmp[MAXPATHLEN + 1];
329
330
                file = procmsg_get_message_file(msginfo);
331
                if (!file)
332
                        continue;
333
334
                qinfo = send_get_queue_info(file);
335
                if (!qinfo || send_message_queue(qinfo) < 0) {
336
                        g_warning("Sending queued message %d failed.\n",
337
                                  msginfo->msgnum);
338
                        send_queue_info_free(qinfo);
339
                        g_free(file);
340
                        continue;
341
                }
342
343
                g_snprintf(tmp, sizeof(tmp), "%s%ctmpmsg.out.%08x",
344
                           get_rc_dir(), G_DIR_SEPARATOR, g_random_int());
345
346
                if (send_get_queue_contents(qinfo, tmp) == 0) {
347
                        if (save_msgs) {
348
                                FolderItem *outbox;
349
                                gboolean drop_done = FALSE;
350
351
                                if (filter_msgs) {
352
                                        FilterInfo *fltinfo;
353
354
                                        fltinfo = filter_info_new();
355
                                        fltinfo->account = qinfo->ac;
356
                                        fltinfo->flags.perm_flags = 0;
357
                                        fltinfo->flags.tmp_flags = MSG_RECEIVED;
358
359
                                        filter_apply(prefs_common.fltlist, tmp,
360
                                                     fltinfo);
361
362
                                        drop_done = fltinfo->drop_done;
363
                                        filter_info_free(fltinfo);
364
                                }
365
366
                                if (!drop_done) {
367
                                        outbox = account_get_special_folder
368
                                                (qinfo->ac, F_OUTBOX);
369
                                        procmsg_save_to_outbox(outbox, tmp);
370
                                }
371
                        }
372
                        g_unlink(tmp);
373
                }
374
375
                send_queue_info_free(qinfo);
376
                g_free(file);
377
378
                folder_item_remove_msg(queue, msginfo);
379
                ret++;
380
        }
381
382
        procmsg_msg_list_free(mlist);
383
384
        procmsg_clear_cache(queue);
385
        queue->cache_dirty = FALSE;
386
        queue->mtime = 0;
387
388
        return ret;
389
}
390
391
static gint send_message_local(const gchar *command, FILE *fp)
392
{
393
        gchar **argv;
394
        GPid pid;
395
        gint child_stdin;
396
        gchar buf[BUFFSIZE];
397
        gboolean err = FALSE;
398
        gint status;
399
400
        g_return_val_if_fail(command != NULL, -1);
401
        g_return_val_if_fail(fp != NULL, -1);
402
403
        log_message(_("Sending message using command: %s\n"), command);
404
405
        argv = strsplit_with_quote(command, " ", 0);
406
407
        if (g_spawn_async_with_pipes(NULL, argv, NULL,
408
                                     G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
409
                                     &pid, &child_stdin, NULL, NULL,
410
                                     NULL) == FALSE) {
411
                g_snprintf(buf, sizeof(buf),
412
                           _("Can't execute command: %s"), command);
413
                log_warning("%s\n", buf);
414
                alertpanel_error("%s", buf);
415
                g_strfreev(argv);
416
                return -1;
417
        }
418
        g_strfreev(argv);
419
420
        while (fgets(buf, sizeof(buf), fp) != NULL) {
421
                strretchomp(buf);
422
                if (buf[0] == '.' && buf[1] == '\0') {
423
                        if (fd_write_all(child_stdin, ".", 1) < 0) {
424
                                err = TRUE;
425
                                break;
426
                        }
427
                }
428
                if (fd_write_all(child_stdin, buf, strlen(buf)) < 0 ||
429
                    fd_write_all(child_stdin, "\n", 1) < 0) {
430
                        err = TRUE;
431
                        break;
432
                }
433
        }
434
435
        fd_close(child_stdin);
436
437
#ifdef G_OS_UNIX
438
        waitpid(pid, &status, 0);
439
        if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
440
                err = TRUE;
441
#endif
442
443
        g_spawn_close_pid(pid);
444
445
        if (err) {
446
                g_snprintf(buf, sizeof(buf),
447
                           _("Error occurred while executing command: %s"),
448
                           command);
449
                log_warning("%s\n", buf);
450
                alertpanel_error("%s", buf);
451
                return -1;
452
        }
453
454
        return 0;
455
}
456
457
static gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
458
{
459
        Session *session;
460
        SMTPSession *smtp_session;
461
        FILE *out_fp;
462
        gushort port;
463
        SendProgressDialog *dialog;
464
        gchar buf[BUFFSIZE];
465
        gint ret = 0;
466
467
        g_return_val_if_fail(ac_prefs != NULL, -1);
468
        g_return_val_if_fail(ac_prefs->address != NULL, -1);
469
        g_return_val_if_fail(ac_prefs->smtp_server != NULL, -1);
470
        g_return_val_if_fail(to_list != NULL, -1);
471
        g_return_val_if_fail(fp != NULL, -1);
472
473
        session = smtp_session_new();
474
        smtp_session = SMTP_SESSION(session);
475
476
        smtp_session->hostname =
477
                ac_prefs->set_domain ? g_strdup(ac_prefs->domain) : NULL;
478
479
        if (ac_prefs->use_smtp_auth) {
480
                inc_lock();
481
482
                smtp_session->forced_auth_type = ac_prefs->smtp_auth_type;
483
484
                if (ac_prefs->smtp_userid) {
485
                        smtp_session->user = g_strdup(ac_prefs->smtp_userid);
486
                        if (ac_prefs->smtp_passwd)
487
                                smtp_session->pass =
488
                                        g_strdup(ac_prefs->smtp_passwd);
489
                        else if (ac_prefs->tmp_smtp_pass)
490
                                smtp_session->pass =
491
                                        g_strdup(ac_prefs->tmp_smtp_pass);
492
                        else {
493
                                smtp_session->pass =
494
                                        input_query_password
495
                                                (ac_prefs->smtp_server,
496
                                                 smtp_session->user);
497
                                if (!smtp_session->pass)
498
                                        smtp_session->pass = g_strdup("");
499
                                ac_prefs->tmp_smtp_pass =
500
                                        g_strdup(smtp_session->pass);
501
                        }
502
                } else {
503
                        smtp_session->user = g_strdup(ac_prefs->userid);
504
                        if (ac_prefs->passwd)
505
                                smtp_session->pass = g_strdup(ac_prefs->passwd);
506
                        else if (ac_prefs->tmp_pass)
507
                                smtp_session->pass =
508
                                        g_strdup(ac_prefs->tmp_pass);
509
                        else {
510
                                smtp_session->pass =
511
                                        input_query_password
512
                                                (ac_prefs->smtp_server,
513
                                                 smtp_session->user);
514
                                if (!smtp_session->pass)
515
                                        smtp_session->pass = g_strdup("");
516
                                ac_prefs->tmp_pass =
517
                                        g_strdup(smtp_session->pass);
518
                        }
519
                }
520
521
                inc_unlock();
522
        } else {
523
                smtp_session->user = NULL;
524
                smtp_session->pass = NULL;
525
        }
526
527
        smtp_session->from = g_strdup(ac_prefs->address);
528
        smtp_session->to_list = to_list;
529
        smtp_session->cur_to = to_list;
530
531
        out_fp = get_outgoing_rfc2822_file(fp);
532
        if (!out_fp) {
533
                session_destroy(session);
534
                return -1;
535
        }
536
        smtp_session->send_data_fp = out_fp;
537
        smtp_session->send_data_len = get_left_file_size(out_fp);
538
        if (smtp_session->send_data_len < 0) {
539
                session_destroy(session);
540
                return -1;
541
        }
542
543
#if USE_SSL
544
        port = ac_prefs->set_smtpport ? ac_prefs->smtpport :
545
                ac_prefs->ssl_smtp == SSL_TUNNEL ? SSMTP_PORT : SMTP_PORT;
546
        session->ssl_type = ac_prefs->ssl_smtp;
547
        if (ac_prefs->ssl_smtp != SSL_NONE)
548
                session->nonblocking = ac_prefs->use_nonblocking_ssl;
549
#else
550
        port = ac_prefs->set_smtpport ? ac_prefs->smtpport : SMTP_PORT;
551
#endif
552
553
        if (ac_prefs->pop_before_smtp && ac_prefs->protocol == A_POP3) {
554
                if (inc_pop_before_smtp(ac_prefs) < 0) {
555
                        session_destroy(session);
556
                        return -1;
557
                }
558
        }
559
560
        dialog = send_progress_dialog_create();
561
        dialog->session = session;
562
563
        progress_dialog_append(dialog->dialog, NULL, ac_prefs->smtp_server,
564
                               _("Connecting"), NULL);
565
566
        g_snprintf(buf, sizeof(buf), _("Connecting to SMTP server: %s ..."),
567
                   ac_prefs->smtp_server);
568
        progress_dialog_set_label(dialog->dialog, buf);
569
        log_message("%s\n", buf);
570
571
        session_set_recv_message_notify(session, send_recv_message, dialog);
572
        session_set_send_data_progressive_notify
573
                (session, send_send_data_progressive, dialog);
574
        session_set_send_data_notify(session, send_send_data_finished, dialog);
575
576
        session_set_timeout(session, prefs_common.io_timeout_secs * 1000);
577
578
        inc_lock();
579
580
        if (session_connect(session, ac_prefs->smtp_server, port) < 0) {
581
                session_destroy(session);
582
                send_progress_dialog_destroy(dialog);
583
                inc_unlock();
584
                return -1;
585
        }
586
587
        debug_print("send_message_smtp(): begin event loop\n");
588
589
        while (session_is_connected(session) && dialog->cancelled == FALSE)
590
                gtk_main_iteration();
591
592
        if (SMTP_SESSION(session)->error_val == SM_AUTHFAIL) {
593
                if (ac_prefs->smtp_userid && ac_prefs->tmp_smtp_pass) {
594
                        g_free(ac_prefs->tmp_smtp_pass);
595
                        ac_prefs->tmp_smtp_pass = NULL;
596
                }
597
                ret = -1;
598
        } else if (session->state == SESSION_EOF &&
599
                   SMTP_SESSION(session)->state == SMTP_QUIT) {
600
                /* consider EOF right after QUIT successful */
601
                log_warning("%s\n", _("Connection closed by the remote host."));
602
                ret = 0;
603
        } else if (session->state == SESSION_ERROR ||
604
                   session->state == SESSION_EOF ||
605
                   session->state == SESSION_TIMEOUT ||
606
                   SMTP_SESSION(session)->state == SMTP_ERROR ||
607
                   SMTP_SESSION(session)->error_val != SM_OK)
608
                ret = -1;
609
        else if (dialog->cancelled == TRUE)
610
                ret = -1;
611
612
        if (ret == -1) {
613
                manage_window_focus_in(dialog->dialog->window, NULL, NULL);
614
                send_put_error(session);
615
                manage_window_focus_out(dialog->dialog->window, NULL, NULL);
616
        }
617
618
        session_destroy(session);
619
        send_progress_dialog_destroy(dialog);
620
        inc_unlock();
621
622
        return ret;
623
}
624
625
static gint send_recv_message(Session *session, const gchar *msg, gpointer data)
626
{
627
        gchar buf[BUFFSIZE];
628
        SMTPSession *smtp_session = SMTP_SESSION(session);
629
        SendProgressDialog *dialog = (SendProgressDialog *)data;
630
        gchar *state_str = NULL;
631
632
        g_return_val_if_fail(dialog != NULL, -1);
633
634
        switch (smtp_session->state) {
635
        case SMTP_READY:
636
        case SMTP_CONNECTED:
637
                return 0;
638
        case SMTP_HELO:
639
                g_snprintf(buf, sizeof(buf), _("Sending HELO..."));
640
                state_str = _("Authenticating");
641
                statusbar_print_all(_("Sending message..."));
642
                break;
643
        case SMTP_EHLO:
644
                g_snprintf(buf, sizeof(buf), _("Sending EHLO..."));
645
                state_str = _("Authenticating");
646
                statusbar_print_all(_("Sending message..."));
647
                break;
648
        case SMTP_AUTH:
649
                g_snprintf(buf, sizeof(buf), _("Authenticating..."));
650
                state_str = _("Authenticating");
651
                break;
652
        case SMTP_FROM:
653
                g_snprintf(buf, sizeof(buf), _("Sending MAIL FROM..."));
654
                state_str = _("Sending");
655
                break;
656
        case SMTP_RCPT:
657
                g_snprintf(buf, sizeof(buf), _("Sending RCPT TO..."));
658
                state_str = _("Sending");
659
                break;
660
        case SMTP_DATA:
661
        case SMTP_EOM:
662
                g_snprintf(buf, sizeof(buf), _("Sending DATA..."));
663
                state_str = _("Sending");
664
                break;
665
        case SMTP_QUIT:
666
                g_snprintf(buf, sizeof(buf), _("Quitting..."));
667
                state_str = _("Quitting");
668
                break;
669
        case SMTP_ERROR:
670
                g_warning("send: error: %s\n", msg);
671
                return 0;
672
        default:
673
                return 0;
674
        }
675
676
        progress_dialog_set_label(dialog->dialog, buf);
677
        progress_dialog_set_row_status(dialog->dialog, 0, state_str);
678
679
        return 0;
680
}
681
682
static gint send_send_data_progressive(Session *session, guint cur_len,
683
                                       guint total_len, gpointer data)
684
{
685
        gchar buf[BUFFSIZE];
686
        SendProgressDialog *dialog = (SendProgressDialog *)data;
687
688
        g_return_val_if_fail(dialog != NULL, -1);
689
690
        if (SMTP_SESSION(session)->state != SMTP_SEND_DATA &&
691
            SMTP_SESSION(session)->state != SMTP_EOM)
692
                return 0;
693
694
        g_snprintf(buf, sizeof(buf), _("Sending message (%d / %d bytes)"),
695
                   cur_len, total_len);
696
        progress_dialog_set_label(dialog->dialog, buf);
697
        progress_dialog_set_percentage
698
                (dialog->dialog, (gfloat)cur_len / (gfloat)total_len);
699
#ifdef G_OS_WIN32
700
        GTK_EVENTS_FLUSH();
701
#endif
702
703
        return 0;
704
}
705
706
static gint send_send_data_finished(Session *session, guint len, gpointer data)
707
{
708
        SendProgressDialog *dialog = (SendProgressDialog *)data;
709
710
        g_return_val_if_fail(dialog != NULL, -1);
711
712
        send_send_data_progressive(session, len, len, dialog);
713
        return 0;
714
}
715
716
static SendProgressDialog *send_progress_dialog_create(void)
717
{
718
        SendProgressDialog *dialog;
719
        ProgressDialog *progress;
720
721
        dialog = g_new0(SendProgressDialog, 1);
722
723
        progress = progress_dialog_create();
724
        gtk_window_set_title(GTK_WINDOW(progress->window),
725
                             _("Sending message"));
726
        g_signal_connect(G_OBJECT(progress->cancel_btn), "clicked",
727
                         G_CALLBACK(send_cancel_button_cb), dialog);
728
        g_signal_connect(G_OBJECT(progress->window), "delete_event",
729
                         G_CALLBACK(gtk_true), NULL);
730
        gtk_window_set_modal(GTK_WINDOW(progress->window), TRUE);
731
        manage_window_set_transient(GTK_WINDOW(progress->window));
732
733
        progress_dialog_set_value(progress, 0.0);
734
735
        gtk_widget_show_now(progress->window);
736
737
        dialog->dialog = progress;
738
739
        return dialog;
740
}
741
742
static void send_progress_dialog_destroy(SendProgressDialog *dialog)
743
{
744
        g_return_if_fail(dialog != NULL);
745
746
        manage_window_destroy(dialog->dialog->window, NULL);
747
        progress_dialog_destroy(dialog->dialog);
748
        g_free(dialog);
749
}
750
751
static void send_cancel_button_cb(GtkWidget *widget, gpointer data)
752
{
753
        SendProgressDialog *dialog = (SendProgressDialog *)data;
754
755
        dialog->cancelled = TRUE;
756
        session_disconnect(dialog->session);
757
}
758
759
static void send_put_error(Session *session)
760
{
761
        gchar *msg;
762
        gchar *log_msg = NULL;
763
        gchar *err_msg = NULL;
764
765
        msg = SMTP_SESSION(session)->error_msg;
766
767
        switch (SMTP_SESSION(session)->error_val) {
768
        case SM_ERROR:
769
        case SM_UNRECOVERABLE:
770
                log_msg = _("Error occurred while sending the message.");
771
                if (msg)
772
                        err_msg = g_strdup_printf
773
                                (_("Error occurred while sending the message:\n%s"),
774
                                 msg);
775
                else
776
                        err_msg = g_strdup(log_msg);
777
                break;
778
        case SM_AUTHFAIL:
779
                log_msg = _("Authentication failed.");
780
                if (msg)
781
                        err_msg = g_strdup_printf
782
                                (_("Authentication failed:\n%s"), msg);
783
                else
784
                        err_msg = g_strdup(log_msg);
785
                break;
786
        default:
787
                switch (session->state) {
788
                case SESSION_ERROR:
789
                        log_msg =
790
                                _("Error occurred while sending the message.");
791
                        err_msg = g_strdup(log_msg);
792
                        break;
793
                case SESSION_EOF:
794
                        log_msg = _("Connection closed by the remote host.");
795
                        err_msg = g_strdup(log_msg);
796
                        break;
797
                case SESSION_TIMEOUT:
798
                        log_msg = _("Session timed out.");
799
                        err_msg = g_strdup(log_msg);
800
                        break;
801
                default:
802
                        break;
803
                }
804
                break;
805
        }
806
807
        if (log_msg)
808
                log_warning("%s\n", log_msg);
809
        if (err_msg) {
810
                alertpanel_error("%s", err_msg);
811
                g_free(err_msg);
812
        }
813
}
814