Statistics
| Revision:

root / src / send_message.c @ 489

History | View | Annotate | Download (16.9 kB)

1 1 hiro
/*
2 1 hiro
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 321 hiro
 * Copyright (C) 1999-2005 Hiroyuki Yamamoto
4 1 hiro
 *
5 1 hiro
 * This program is free software; you can redistribute it and/or modify
6 1 hiro
 * it under the terms of the GNU General Public License as published by
7 1 hiro
 * the Free Software Foundation; either version 2 of the License, or
8 1 hiro
 * (at your option) any later version.
9 1 hiro
 *
10 1 hiro
 * This program is distributed in the hope that it will be useful,
11 1 hiro
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 1 hiro
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 1 hiro
 * GNU General Public License for more details.
14 1 hiro
 *
15 1 hiro
 * You should have received a copy of the GNU General Public License
16 1 hiro
 * along with this program; if not, write to the Free Software
17 1 hiro
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 1 hiro
 */
19 1 hiro
20 1 hiro
#ifdef HAVE_CONFIG_H
21 1 hiro
#  include "config.h"
22 1 hiro
#endif
23 1 hiro
24 1 hiro
#include "defs.h"
25 1 hiro
26 1 hiro
#include <glib.h>
27 92 hiro
#include <glib/gi18n.h>
28 1 hiro
#include <gtk/gtkmain.h>
29 1 hiro
#include <gtk/gtksignal.h>
30 1 hiro
#include <gtk/gtkwindow.h>
31 1 hiro
#include <stdio.h>
32 1 hiro
#include <string.h>
33 347 hiro
#include <sys/types.h>
34 469 hiro
#if HAVE_SYS_WAIT_H
35 469 hiro
#  include <sys/wait.h>
36 469 hiro
#endif
37 1 hiro
38 1 hiro
#include "send_message.h"
39 1 hiro
#include "session.h"
40 1 hiro
#include "ssl.h"
41 1 hiro
#include "smtp.h"
42 1 hiro
#include "news.h"
43 1 hiro
#include "prefs_common.h"
44 1 hiro
#include "prefs_account.h"
45 1 hiro
#include "procheader.h"
46 1 hiro
#include "account.h"
47 1 hiro
#include "progressdialog.h"
48 1 hiro
#include "statusbar.h"
49 1 hiro
#include "inputdialog.h"
50 1 hiro
#include "alertpanel.h"
51 1 hiro
#include "manage_window.h"
52 288 hiro
#include "socket.h"
53 1 hiro
#include "utils.h"
54 1 hiro
55 1 hiro
#define SMTP_PORT        25
56 1 hiro
#if USE_SSL
57 1 hiro
#define SSMTP_PORT        465
58 1 hiro
#endif
59 1 hiro
60 1 hiro
typedef struct _SendProgressDialog        SendProgressDialog;
61 1 hiro
62 1 hiro
struct _SendProgressDialog
63 1 hiro
{
64 1 hiro
        ProgressDialog *dialog;
65 1 hiro
        Session *session;
66 1 hiro
        gboolean cancelled;
67 1 hiro
};
68 1 hiro
69 1 hiro
static gint send_message_local                (const gchar                *command,
70 1 hiro
                                         FILE                        *fp);
71 1 hiro
static gint send_message_smtp                (PrefsAccount                *ac_prefs,
72 1 hiro
                                         GSList                        *to_list,
73 1 hiro
                                         FILE                        *fp);
74 1 hiro
75 1 hiro
static gint send_recv_message                (Session                *session,
76 1 hiro
                                         const gchar                *msg,
77 1 hiro
                                         gpointer                 data);
78 1 hiro
static gint send_send_data_progressive        (Session                *session,
79 1 hiro
                                         guint                         cur_len,
80 1 hiro
                                         guint                         total_len,
81 1 hiro
                                         gpointer                 data);
82 1 hiro
static gint send_send_data_finished        (Session                *session,
83 1 hiro
                                         guint                         len,
84 1 hiro
                                         gpointer                 data);
85 1 hiro
86 1 hiro
static SendProgressDialog *send_progress_dialog_create(void);
87 1 hiro
static void send_progress_dialog_destroy(SendProgressDialog *dialog);
88 1 hiro
89 1 hiro
static void send_cancel_button_cb        (GtkWidget        *widget,
90 1 hiro
                                         gpointer         data);
91 1 hiro
92 1 hiro
static void send_put_error                (Session        *session);
93 1 hiro
94 1 hiro
95 1 hiro
gint send_message(const gchar *file, PrefsAccount *ac_prefs, GSList *to_list)
96 1 hiro
{
97 1 hiro
        FILE *fp;
98 1 hiro
        gint val;
99 1 hiro
100 1 hiro
        g_return_val_if_fail(file != NULL, -1);
101 1 hiro
        g_return_val_if_fail(ac_prefs != NULL, -1);
102 1 hiro
        g_return_val_if_fail(to_list != NULL, -1);
103 1 hiro
104 478 hiro
        if ((fp = g_fopen(file, "rb")) == NULL) {
105 1 hiro
                FILE_OP_ERROR(file, "fopen");
106 1 hiro
                return -1;
107 1 hiro
        }
108 1 hiro
109 1 hiro
        if (prefs_common.use_extsend && prefs_common.extsend_cmd) {
110 1 hiro
                val = send_message_local(prefs_common.extsend_cmd, fp);
111 1 hiro
                fclose(fp);
112 1 hiro
                return val;
113 1 hiro
        }
114 1 hiro
115 1 hiro
        val = send_message_smtp(ac_prefs, to_list, fp);
116 1 hiro
117 1 hiro
        fclose(fp);
118 1 hiro
        return val;
119 1 hiro
}
120 1 hiro
121 1 hiro
enum
122 1 hiro
{
123 1 hiro
        Q_SENDER     = 0,
124 1 hiro
        Q_SMTPSERVER = 1,
125 1 hiro
        Q_RECIPIENTS = 2,
126 1 hiro
        Q_ACCOUNT_ID = 3
127 1 hiro
};
128 1 hiro
129 1 hiro
QueueInfo *send_get_queue_info(const gchar *file)
130 1 hiro
{
131 1 hiro
        static HeaderEntry qentry[] = {{"S:",   NULL, FALSE},
132 1 hiro
                                       {"SSV:", NULL, FALSE},
133 1 hiro
                                       {"R:",   NULL, FALSE},
134 1 hiro
                                       {"AID:", NULL, FALSE},
135 1 hiro
                                       {NULL,   NULL, FALSE}};
136 1 hiro
        FILE *fp;
137 1 hiro
        gchar buf[BUFFSIZE];
138 1 hiro
        gint hnum;
139 1 hiro
        QueueInfo *qinfo;
140 1 hiro
141 1 hiro
        g_return_val_if_fail(file != NULL, NULL);
142 1 hiro
143 478 hiro
        if ((fp = g_fopen(file, "rb")) == NULL) {
144 1 hiro
                FILE_OP_ERROR(file, "fopen");
145 1 hiro
                return NULL;
146 1 hiro
        }
147 1 hiro
148 1 hiro
        qinfo = g_new0(QueueInfo, 1);
149 1 hiro
150 1 hiro
        while ((hnum = procheader_get_one_field(buf, sizeof(buf), fp, qentry))
151 1 hiro
               != -1) {
152 1 hiro
                gchar *p;
153 1 hiro
154 1 hiro
                p = buf + strlen(qentry[hnum].name);
155 1 hiro
156 1 hiro
                switch (hnum) {
157 1 hiro
                case Q_SENDER:
158 1 hiro
                        if (!qinfo->from)
159 1 hiro
                                qinfo->from = g_strdup(p);
160 1 hiro
                        break;
161 1 hiro
                case Q_SMTPSERVER:
162 1 hiro
                        if (!qinfo->server)
163 1 hiro
                                qinfo->server = g_strdup(p);
164 1 hiro
                        break;
165 1 hiro
                case Q_RECIPIENTS:
166 1 hiro
                        qinfo->to_list =
167 1 hiro
                                address_list_append(qinfo->to_list, p);
168 1 hiro
                        break;
169 1 hiro
                case Q_ACCOUNT_ID:
170 1 hiro
                        qinfo->ac = account_find_from_id(atoi(p));
171 1 hiro
                        break;
172 1 hiro
                default:
173 1 hiro
                        break;
174 1 hiro
                }
175 1 hiro
        }
176 1 hiro
177 1 hiro
        qinfo->fp = fp;
178 1 hiro
179 1 hiro
        if (((!qinfo->ac || (qinfo->ac && qinfo->ac->protocol != A_NNTP)) &&
180 1 hiro
             !qinfo->to_list) || !qinfo->from) {
181 1 hiro
                g_warning(_("Queued message header is broken.\n"));
182 1 hiro
                send_queue_info_free(qinfo);
183 1 hiro
                return NULL;
184 1 hiro
        }
185 1 hiro
186 1 hiro
        if (!qinfo->ac) {
187 1 hiro
                qinfo->ac = account_find_from_smtp_server(qinfo->from,
188 1 hiro
                                                          qinfo->server);
189 1 hiro
                if (!qinfo->ac) {
190 1 hiro
                        g_warning("Account not found. "
191 1 hiro
                                  "Using current account...\n");
192 1 hiro
                        qinfo->ac = cur_account;
193 1 hiro
                }
194 1 hiro
        }
195 1 hiro
196 1 hiro
        return qinfo;
197 1 hiro
}
198 1 hiro
199 317 hiro
gint send_get_queue_contents(QueueInfo *qinfo, const gchar *dest)
200 317 hiro
{
201 317 hiro
        FILE *fp;
202 317 hiro
        glong pos;
203 317 hiro
        gchar buf[BUFFSIZE];
204 317 hiro
205 317 hiro
        g_return_val_if_fail(qinfo != NULL, -1);
206 317 hiro
        g_return_val_if_fail(qinfo->fp != NULL, -1);
207 317 hiro
        g_return_val_if_fail(dest != NULL, -1);
208 317 hiro
209 478 hiro
        if ((fp = g_fopen(dest, "wb")) == NULL) {
210 317 hiro
                FILE_OP_ERROR(dest, "fopen");
211 317 hiro
                return -1;
212 317 hiro
        }
213 317 hiro
214 317 hiro
        pos = ftell(qinfo->fp);
215 317 hiro
216 317 hiro
        while (fgets(buf, sizeof(buf), qinfo->fp) != NULL)
217 317 hiro
                fputs(buf, fp);
218 317 hiro
219 317 hiro
        if (fclose(fp) < 0) {
220 317 hiro
                FILE_OP_ERROR(dest, "fclose");
221 478 hiro
                g_unlink(dest);
222 317 hiro
                return -1;
223 317 hiro
        }
224 317 hiro
225 317 hiro
        fseek(qinfo->fp, pos, SEEK_SET);
226 317 hiro
227 317 hiro
        return 0;
228 317 hiro
}
229 317 hiro
230 1 hiro
void send_queue_info_free(QueueInfo *qinfo)
231 1 hiro
{
232 1 hiro
        if (qinfo == NULL) return;
233 1 hiro
234 1 hiro
        slist_free_strings(qinfo->to_list);
235 1 hiro
        g_slist_free(qinfo->to_list);
236 1 hiro
        g_free(qinfo->from);
237 1 hiro
        g_free(qinfo->server);
238 1 hiro
        if (qinfo->fp)
239 1 hiro
                fclose(qinfo->fp);
240 1 hiro
        g_free(qinfo);
241 1 hiro
}
242 1 hiro
243 1 hiro
gint send_message_queue(QueueInfo *qinfo)
244 1 hiro
{
245 1 hiro
        gint val = 0;
246 1 hiro
        glong fpos;
247 1 hiro
        PrefsAccount *mailac = NULL, *newsac = NULL;
248 1 hiro
249 1 hiro
        g_return_val_if_fail(qinfo != NULL, -1);
250 1 hiro
251 317 hiro
        fpos = ftell(qinfo->fp);
252 317 hiro
253 1 hiro
        if (prefs_common.use_extsend && prefs_common.extsend_cmd) {
254 1 hiro
                val = send_message_local(prefs_common.extsend_cmd, qinfo->fp);
255 1 hiro
        } else {
256 1 hiro
                if (qinfo->ac && qinfo->ac->protocol == A_NNTP) {
257 1 hiro
                        newsac = qinfo->ac;
258 1 hiro
259 1 hiro
                        /* search mail account */
260 1 hiro
                        mailac = account_find_from_address(qinfo->from);
261 1 hiro
                        if (!mailac) {
262 1 hiro
                                if (cur_account &&
263 1 hiro
                                    cur_account->protocol != A_NNTP)
264 1 hiro
                                        mailac = cur_account;
265 1 hiro
                                else {
266 1 hiro
                                        mailac = account_get_default();
267 1 hiro
                                        if (mailac->protocol == A_NNTP)
268 1 hiro
                                                mailac = NULL;
269 1 hiro
                                }
270 1 hiro
                        }
271 1 hiro
                } else
272 1 hiro
                        mailac = qinfo->ac;
273 1 hiro
274 1 hiro
                if (qinfo->to_list) {
275 1 hiro
                        if (mailac)
276 1 hiro
                                val = send_message_smtp(mailac, qinfo->to_list,
277 1 hiro
                                                        qinfo->fp);
278 1 hiro
                        else {
279 1 hiro
                                PrefsAccount tmp_ac;
280 1 hiro
281 1 hiro
                                g_warning("Account not found.\n");
282 1 hiro
283 1 hiro
                                memset(&tmp_ac, 0, sizeof(PrefsAccount));
284 1 hiro
                                tmp_ac.address = qinfo->from;
285 1 hiro
                                tmp_ac.smtp_server = qinfo->server;
286 1 hiro
                                tmp_ac.smtpport = SMTP_PORT;
287 1 hiro
                                val = send_message_smtp(&tmp_ac, qinfo->to_list,
288 1 hiro
                                                        qinfo->fp);
289 1 hiro
                        }
290 1 hiro
                }
291 1 hiro
292 1 hiro
                if (val == 0 && newsac) {
293 1 hiro
                        fseek(qinfo->fp, fpos, SEEK_SET);
294 1 hiro
                        val = news_post_stream(FOLDER(newsac->folder),
295 1 hiro
                                               qinfo->fp);
296 1 hiro
                        if (val < 0)
297 1 hiro
                                alertpanel_error(_("Error occurred while posting the message to %s ."),
298 1 hiro
                                                 newsac->nntp_server);
299 1 hiro
                }
300 1 hiro
        }
301 1 hiro
302 317 hiro
        fseek(qinfo->fp, fpos, SEEK_SET);
303 317 hiro
304 1 hiro
        return val;
305 1 hiro
}
306 1 hiro
307 1 hiro
static gint send_message_local(const gchar *command, FILE *fp)
308 1 hiro
{
309 288 hiro
        gchar **argv;
310 288 hiro
        GPid pid;
311 288 hiro
        gint child_stdin;
312 1 hiro
        gchar buf[BUFFSIZE];
313 288 hiro
        gboolean err = FALSE;
314 347 hiro
        gint status;
315 1 hiro
316 1 hiro
        g_return_val_if_fail(command != NULL, -1);
317 1 hiro
        g_return_val_if_fail(fp != NULL, -1);
318 1 hiro
319 288 hiro
        log_message(_("Sending message using command: %s\n"), command);
320 288 hiro
321 288 hiro
        argv = strsplit_with_quote(command, " ", 0);
322 288 hiro
323 347 hiro
        if (g_spawn_async_with_pipes(NULL, argv, NULL,
324 347 hiro
                                     G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
325 347 hiro
                                     &pid, &child_stdin, NULL, NULL,
326 347 hiro
                                     NULL) == FALSE) {
327 288 hiro
                g_snprintf(buf, sizeof(buf),
328 288 hiro
                           _("Can't execute command: %s"), command);
329 288 hiro
                log_warning("%s\n", buf);
330 288 hiro
                alertpanel_error("%s", buf);
331 288 hiro
                g_strfreev(argv);
332 1 hiro
                return -1;
333 1 hiro
        }
334 288 hiro
        g_strfreev(argv);
335 1 hiro
336 1 hiro
        while (fgets(buf, sizeof(buf), fp) != NULL) {
337 1 hiro
                strretchomp(buf);
338 288 hiro
                if (buf[0] == '.' && buf[1] == '\0') {
339 288 hiro
                        if (fd_write_all(child_stdin, ".", 1) < 0) {
340 288 hiro
                                err = TRUE;
341 288 hiro
                                break;
342 288 hiro
                        }
343 288 hiro
                }
344 288 hiro
                if (fd_write_all(child_stdin, buf, strlen(buf)) < 0 ||
345 288 hiro
                    fd_write_all(child_stdin, "\n", 1) < 0) {
346 288 hiro
                        err = TRUE;
347 288 hiro
                        break;
348 288 hiro
                }
349 1 hiro
        }
350 1 hiro
351 288 hiro
        fd_close(child_stdin);
352 347 hiro
353 469 hiro
#ifdef G_OS_UNIX
354 347 hiro
        waitpid(pid, &status, 0);
355 347 hiro
        if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
356 347 hiro
                err = TRUE;
357 469 hiro
#endif
358 347 hiro
359 288 hiro
        g_spawn_close_pid(pid);
360 1 hiro
361 288 hiro
        if (err) {
362 288 hiro
                g_snprintf(buf, sizeof(buf),
363 288 hiro
                           _("Error occurred while executing command: %s"),
364 288 hiro
                           command);
365 288 hiro
                log_warning("%s\n", buf);
366 288 hiro
                alertpanel_error("%s", buf);
367 288 hiro
                return -1;
368 288 hiro
        }
369 288 hiro
370 1 hiro
        return 0;
371 1 hiro
}
372 1 hiro
373 1 hiro
static gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
374 1 hiro
{
375 1 hiro
        Session *session;
376 1 hiro
        SMTPSession *smtp_session;
377 1 hiro
        gushort port;
378 1 hiro
        SendProgressDialog *dialog;
379 1 hiro
        gchar buf[BUFFSIZE];
380 1 hiro
        gint ret = 0;
381 1 hiro
382 1 hiro
        g_return_val_if_fail(ac_prefs != NULL, -1);
383 1 hiro
        g_return_val_if_fail(ac_prefs->address != NULL, -1);
384 1 hiro
        g_return_val_if_fail(ac_prefs->smtp_server != NULL, -1);
385 1 hiro
        g_return_val_if_fail(to_list != NULL, -1);
386 1 hiro
        g_return_val_if_fail(fp != NULL, -1);
387 1 hiro
388 1 hiro
        session = smtp_session_new();
389 1 hiro
        smtp_session = SMTP_SESSION(session);
390 1 hiro
391 1 hiro
        smtp_session->hostname =
392 1 hiro
                ac_prefs->set_domain ? g_strdup(ac_prefs->domain) : NULL;
393 1 hiro
394 1 hiro
        if (ac_prefs->use_smtp_auth) {
395 1 hiro
                smtp_session->forced_auth_type = ac_prefs->smtp_auth_type;
396 1 hiro
397 1 hiro
                if (ac_prefs->smtp_userid) {
398 1 hiro
                        smtp_session->user = g_strdup(ac_prefs->smtp_userid);
399 1 hiro
                        if (ac_prefs->smtp_passwd)
400 1 hiro
                                smtp_session->pass =
401 1 hiro
                                        g_strdup(ac_prefs->smtp_passwd);
402 1 hiro
                        else if (ac_prefs->tmp_smtp_pass)
403 1 hiro
                                smtp_session->pass =
404 1 hiro
                                        g_strdup(ac_prefs->tmp_smtp_pass);
405 1 hiro
                        else {
406 1 hiro
                                smtp_session->pass =
407 1 hiro
                                        input_dialog_query_password
408 1 hiro
                                                (ac_prefs->smtp_server,
409 1 hiro
                                                 smtp_session->user);
410 1 hiro
                                if (!smtp_session->pass)
411 1 hiro
                                        smtp_session->pass = g_strdup("");
412 1 hiro
                                ac_prefs->tmp_smtp_pass =
413 1 hiro
                                        g_strdup(smtp_session->pass);
414 1 hiro
                        }
415 1 hiro
                } else {
416 1 hiro
                        smtp_session->user = g_strdup(ac_prefs->userid);
417 1 hiro
                        if (ac_prefs->passwd)
418 1 hiro
                                smtp_session->pass = g_strdup(ac_prefs->passwd);
419 1 hiro
                        else if (ac_prefs->tmp_pass)
420 1 hiro
                                smtp_session->pass =
421 1 hiro
                                        g_strdup(ac_prefs->tmp_pass);
422 1 hiro
                        else {
423 1 hiro
                                smtp_session->pass =
424 1 hiro
                                        input_dialog_query_password
425 1 hiro
                                                (ac_prefs->smtp_server,
426 1 hiro
                                                 smtp_session->user);
427 1 hiro
                                if (!smtp_session->pass)
428 1 hiro
                                        smtp_session->pass = g_strdup("");
429 1 hiro
                                ac_prefs->tmp_pass =
430 1 hiro
                                        g_strdup(smtp_session->pass);
431 1 hiro
                        }
432 1 hiro
                }
433 1 hiro
        } else {
434 1 hiro
                smtp_session->user = NULL;
435 1 hiro
                smtp_session->pass = NULL;
436 1 hiro
        }
437 1 hiro
438 1 hiro
        smtp_session->from = g_strdup(ac_prefs->address);
439 1 hiro
        smtp_session->to_list = to_list;
440 1 hiro
        smtp_session->cur_to = to_list;
441 1 hiro
        smtp_session->send_data = get_outgoing_rfc2822_str(fp);
442 1 hiro
        smtp_session->send_data_len = strlen(smtp_session->send_data);
443 1 hiro
444 1 hiro
#if USE_SSL
445 1 hiro
        port = ac_prefs->set_smtpport ? ac_prefs->smtpport :
446 1 hiro
                ac_prefs->ssl_smtp == SSL_TUNNEL ? SSMTP_PORT : SMTP_PORT;
447 1 hiro
        session->ssl_type = ac_prefs->ssl_smtp;
448 1 hiro
        if (ac_prefs->ssl_smtp != SSL_NONE)
449 1 hiro
                session->nonblocking = ac_prefs->use_nonblocking_ssl;
450 1 hiro
#else
451 1 hiro
        port = ac_prefs->set_smtpport ? ac_prefs->smtpport : SMTP_PORT;
452 1 hiro
#endif
453 1 hiro
454 1 hiro
        dialog = send_progress_dialog_create();
455 1 hiro
        dialog->session = session;
456 1 hiro
457 321 hiro
        progress_dialog_append(dialog->dialog, NULL, ac_prefs->smtp_server,
458 321 hiro
                               _("Connecting"), NULL);
459 1 hiro
460 1 hiro
        g_snprintf(buf, sizeof(buf), _("Connecting to SMTP server: %s ..."),
461 1 hiro
                   ac_prefs->smtp_server);
462 1 hiro
        progress_dialog_set_label(dialog->dialog, buf);
463 1 hiro
        log_message("%s\n", buf);
464 1 hiro
465 1 hiro
        session_set_recv_message_notify(session, send_recv_message, dialog);
466 1 hiro
        session_set_send_data_progressive_notify
467 1 hiro
                (session, send_send_data_progressive, dialog);
468 1 hiro
        session_set_send_data_notify(session, send_send_data_finished, dialog);
469 1 hiro
470 1 hiro
        if (session_connect(session, ac_prefs->smtp_server, port) < 0) {
471 1 hiro
                session_destroy(session);
472 1 hiro
                send_progress_dialog_destroy(dialog);
473 1 hiro
                return -1;
474 1 hiro
        }
475 1 hiro
476 1 hiro
        debug_print("send_message_smtp(): begin event loop\n");
477 1 hiro
478 1 hiro
        while (session_is_connected(session) && dialog->cancelled == FALSE)
479 1 hiro
                gtk_main_iteration();
480 1 hiro
481 1 hiro
        if (SMTP_SESSION(session)->error_val == SM_AUTHFAIL) {
482 1 hiro
                if (ac_prefs->smtp_userid && ac_prefs->tmp_smtp_pass) {
483 1 hiro
                        g_free(ac_prefs->tmp_smtp_pass);
484 1 hiro
                        ac_prefs->tmp_smtp_pass = NULL;
485 1 hiro
                }
486 1 hiro
                ret = -1;
487 201 hiro
        } else if (session->state == SESSION_EOF &&
488 201 hiro
                   SMTP_SESSION(session)->state == SMTP_QUIT) {
489 201 hiro
                /* consider EOF right after QUIT successful */
490 201 hiro
                log_warning("%s\n", _("Connection closed by the remote host."));
491 201 hiro
                ret = 0;
492 1 hiro
        } else if (session->state == SESSION_ERROR ||
493 1 hiro
                   session->state == SESSION_EOF ||
494 1 hiro
                   session->state == SESSION_TIMEOUT ||
495 1 hiro
                   SMTP_SESSION(session)->state == SMTP_ERROR ||
496 1 hiro
                   SMTP_SESSION(session)->error_val != SM_OK)
497 1 hiro
                ret = -1;
498 1 hiro
        else if (dialog->cancelled == TRUE)
499 1 hiro
                ret = -1;
500 1 hiro
501 1 hiro
        if (ret == -1) {
502 1 hiro
                manage_window_focus_in(dialog->dialog->window, NULL, NULL);
503 1 hiro
                send_put_error(session);
504 1 hiro
                manage_window_focus_out(dialog->dialog->window, NULL, NULL);
505 1 hiro
        }
506 1 hiro
507 1 hiro
        session_destroy(session);
508 1 hiro
        send_progress_dialog_destroy(dialog);
509 1 hiro
510 1 hiro
        return ret;
511 1 hiro
}
512 1 hiro
513 1 hiro
static gint send_recv_message(Session *session, const gchar *msg, gpointer data)
514 1 hiro
{
515 1 hiro
        gchar buf[BUFFSIZE];
516 1 hiro
        SMTPSession *smtp_session = SMTP_SESSION(session);
517 1 hiro
        SendProgressDialog *dialog = (SendProgressDialog *)data;
518 1 hiro
        gchar *state_str = NULL;
519 1 hiro
520 1 hiro
        g_return_val_if_fail(dialog != NULL, -1);
521 1 hiro
522 1 hiro
        switch (smtp_session->state) {
523 1 hiro
        case SMTP_READY:
524 1 hiro
        case SMTP_CONNECTED:
525 1 hiro
                return 0;
526 1 hiro
        case SMTP_HELO:
527 1 hiro
                g_snprintf(buf, sizeof(buf), _("Sending HELO..."));
528 1 hiro
                state_str = _("Authenticating");
529 1 hiro
                statusbar_print_all(_("Sending message..."));
530 1 hiro
                break;
531 1 hiro
        case SMTP_EHLO:
532 1 hiro
                g_snprintf(buf, sizeof(buf), _("Sending EHLO..."));
533 1 hiro
                state_str = _("Authenticating");
534 1 hiro
                statusbar_print_all(_("Sending message..."));
535 1 hiro
                break;
536 1 hiro
        case SMTP_AUTH:
537 1 hiro
                g_snprintf(buf, sizeof(buf), _("Authenticating..."));
538 1 hiro
                state_str = _("Authenticating");
539 1 hiro
                break;
540 1 hiro
        case SMTP_FROM:
541 1 hiro
                g_snprintf(buf, sizeof(buf), _("Sending MAIL FROM..."));
542 1 hiro
                state_str = _("Sending");
543 1 hiro
                break;
544 1 hiro
        case SMTP_RCPT:
545 1 hiro
                g_snprintf(buf, sizeof(buf), _("Sending RCPT TO..."));
546 1 hiro
                state_str = _("Sending");
547 1 hiro
                break;
548 1 hiro
        case SMTP_DATA:
549 1 hiro
        case SMTP_EOM:
550 1 hiro
                g_snprintf(buf, sizeof(buf), _("Sending DATA..."));
551 1 hiro
                state_str = _("Sending");
552 1 hiro
                break;
553 1 hiro
        case SMTP_QUIT:
554 1 hiro
                g_snprintf(buf, sizeof(buf), _("Quitting..."));
555 1 hiro
                state_str = _("Quitting");
556 1 hiro
                break;
557 1 hiro
        case SMTP_ERROR:
558 1 hiro
                g_warning("send: error: %s\n", msg);
559 1 hiro
                return 0;
560 1 hiro
        default:
561 1 hiro
                return 0;
562 1 hiro
        }
563 1 hiro
564 1 hiro
        progress_dialog_set_label(dialog->dialog, buf);
565 321 hiro
        progress_dialog_set_row_status(dialog->dialog, 0, state_str);
566 1 hiro
567 1 hiro
        return 0;
568 1 hiro
}
569 1 hiro
570 1 hiro
static gint send_send_data_progressive(Session *session, guint cur_len,
571 1 hiro
                                       guint total_len, gpointer data)
572 1 hiro
{
573 1 hiro
        gchar buf[BUFFSIZE];
574 1 hiro
        SendProgressDialog *dialog = (SendProgressDialog *)data;
575 1 hiro
576 1 hiro
        g_return_val_if_fail(dialog != NULL, -1);
577 1 hiro
578 1 hiro
        if (SMTP_SESSION(session)->state != SMTP_SEND_DATA &&
579 1 hiro
            SMTP_SESSION(session)->state != SMTP_EOM)
580 1 hiro
                return 0;
581 1 hiro
582 1 hiro
        g_snprintf(buf, sizeof(buf), _("Sending message (%d / %d bytes)"),
583 1 hiro
                   cur_len, total_len);
584 1 hiro
        progress_dialog_set_label(dialog->dialog, buf);
585 1 hiro
        progress_dialog_set_percentage
586 1 hiro
                (dialog->dialog, (gfloat)cur_len / (gfloat)total_len);
587 1 hiro
588 1 hiro
        return 0;
589 1 hiro
}
590 1 hiro
591 1 hiro
static gint send_send_data_finished(Session *session, guint len, gpointer data)
592 1 hiro
{
593 1 hiro
        SendProgressDialog *dialog = (SendProgressDialog *)data;
594 1 hiro
595 1 hiro
        g_return_val_if_fail(dialog != NULL, -1);
596 1 hiro
597 1 hiro
        send_send_data_progressive(session, len, len, dialog);
598 1 hiro
        return 0;
599 1 hiro
}
600 1 hiro
601 1 hiro
static SendProgressDialog *send_progress_dialog_create(void)
602 1 hiro
{
603 1 hiro
        SendProgressDialog *dialog;
604 1 hiro
        ProgressDialog *progress;
605 1 hiro
606 1 hiro
        dialog = g_new0(SendProgressDialog, 1);
607 1 hiro
608 1 hiro
        progress = progress_dialog_create();
609 1 hiro
        gtk_window_set_title(GTK_WINDOW(progress->window),
610 1 hiro
                             _("Sending message"));
611 1 hiro
        g_signal_connect(G_OBJECT(progress->cancel_btn), "clicked",
612 1 hiro
                         G_CALLBACK(send_cancel_button_cb), dialog);
613 1 hiro
        g_signal_connect(G_OBJECT(progress->window), "delete_event",
614 1 hiro
                         G_CALLBACK(gtk_true), NULL);
615 1 hiro
        gtk_window_set_modal(GTK_WINDOW(progress->window), TRUE);
616 1 hiro
        manage_window_set_transient(GTK_WINDOW(progress->window));
617 1 hiro
618 1 hiro
        progress_dialog_set_value(progress, 0.0);
619 1 hiro
620 1 hiro
        gtk_widget_show_now(progress->window);
621 1 hiro
622 1 hiro
        dialog->dialog = progress;
623 1 hiro
624 1 hiro
        return dialog;
625 1 hiro
}
626 1 hiro
627 1 hiro
static void send_progress_dialog_destroy(SendProgressDialog *dialog)
628 1 hiro
{
629 1 hiro
        g_return_if_fail(dialog != NULL);
630 1 hiro
631 300 hiro
        manage_window_destroy(dialog->dialog->window, NULL);
632 1 hiro
        progress_dialog_destroy(dialog->dialog);
633 1 hiro
        g_free(dialog);
634 1 hiro
}
635 1 hiro
636 1 hiro
static void send_cancel_button_cb(GtkWidget *widget, gpointer data)
637 1 hiro
{
638 1 hiro
        SendProgressDialog *dialog = (SendProgressDialog *)data;
639 1 hiro
640 1 hiro
        dialog->cancelled = TRUE;
641 1 hiro
}
642 1 hiro
643 1 hiro
static void send_put_error(Session *session)
644 1 hiro
{
645 1 hiro
        gchar *msg;
646 1 hiro
        gchar *log_msg = NULL;
647 1 hiro
        gchar *err_msg = NULL;
648 1 hiro
649 1 hiro
        msg = SMTP_SESSION(session)->error_msg;
650 1 hiro
651 1 hiro
        switch (SMTP_SESSION(session)->error_val) {
652 1 hiro
        case SM_ERROR:
653 1 hiro
        case SM_UNRECOVERABLE:
654 1 hiro
                log_msg = _("Error occurred while sending the message.");
655 1 hiro
                if (msg)
656 1 hiro
                        err_msg = g_strdup_printf
657 1 hiro
                                (_("Error occurred while sending the message:\n%s"),
658 1 hiro
                                 msg);
659 1 hiro
                else
660 1 hiro
                        err_msg = g_strdup(log_msg);
661 1 hiro
                break;
662 1 hiro
        case SM_AUTHFAIL:
663 1 hiro
                log_msg = _("Authentication failed.");
664 1 hiro
                if (msg)
665 1 hiro
                        err_msg = g_strdup_printf
666 1 hiro
                                (_("Authentication failed:\n%s"), msg);
667 1 hiro
                else
668 1 hiro
                        err_msg = g_strdup(log_msg);
669 1 hiro
                break;
670 1 hiro
        default:
671 1 hiro
                switch (session->state) {
672 1 hiro
                case SESSION_ERROR:
673 1 hiro
                        log_msg =
674 1 hiro
                                _("Error occurred while sending the message.");
675 1 hiro
                        err_msg = g_strdup(log_msg);
676 1 hiro
                        break;
677 1 hiro
                case SESSION_EOF:
678 1 hiro
                        log_msg = _("Connection closed by the remote host.");
679 1 hiro
                        err_msg = g_strdup(log_msg);
680 1 hiro
                        break;
681 1 hiro
                case SESSION_TIMEOUT:
682 1 hiro
                        log_msg = _("Session timed out.");
683 1 hiro
                        err_msg = g_strdup(log_msg);
684 1 hiro
                        break;
685 1 hiro
                default:
686 1 hiro
                        break;
687 1 hiro
                }
688 1 hiro
                break;
689 1 hiro
        }
690 1 hiro
691 1 hiro
        if (log_msg)
692 1 hiro
                log_warning("%s\n", log_msg);
693 1 hiro
        if (err_msg) {
694 1 hiro
                alertpanel_error("%s", err_msg);
695 1 hiro
                g_free(err_msg);
696 1 hiro
        }
697 1 hiro
}