Statistics
| Revision:

root / src / send_message.c @ 1623

History | View | Annotate | Download (19.2 kB)

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