1 /*
2 * msmtp.c
3 *
4 * This file is part of msmtp, an SMTP client.
5 *
6 * Copyright (C) 2000, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
7 * 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021
8 * Martin Lambers <marlam@marlam.de>
9 * Martin Stenberg <martin@gnutiken.se> (passwordeval support)
10 * Scott Shumate <sshumate@austin.rr.com> (aliases support)
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include <errno.h>
36 #include <time.h>
37 #include <getopt.h>
38 extern char *optarg;
39 extern int optind;
40 #include <unistd.h>
41 #include <fcntl.h>
42 #ifdef ENABLE_NLS
43 # include <locale.h>
44 #endif
45 #ifdef HAVE_SYSLOG
46 # include <syslog.h>
47 #endif
48 #ifdef HAVE_SIGNAL
49 # include <signal.h>
50 #endif
51
52 #include "gettext.h"
53 #define _(string) gettext(string)
54
55 #include "xalloc.h"
56 #include "conf.h"
57 #include "list.h"
58 #include "net.h"
59 #include "smtp.h"
60 #include "tools.h"
61 #include "aliases.h"
62 #include "password.h"
63 #ifdef HAVE_TLS
64 # include "mtls.h"
65 #endif /* HAVE_TLS */
66
67 /* Default file names. */
68 #ifdef W32_NATIVE
69 #define SYSCONFFILE "msmtprc.txt"
70 #define USERCONFFILE "msmtprc.txt"
71 #else /* UNIX */
72 #define SYSCONFFILE "msmtprc"
73 #define USERCONFFILE ".msmtprc"
74 #endif
75
76 /* The name of this program */
77 const char *prgname;
78
79
80 /*
81 * Die if memory allocation fails
82 */
83
xalloc_die(void)84 void xalloc_die(void)
85 {
86 /* TRANSLATORS: msmtp shares a lot of code and translatable strings with
87 mpop <https://marlam.de/mpop>. */
88 fprintf(stderr, _("%s: FATAL: %s\n"), prgname, strerror(ENOMEM));
89 exit(EX_OSERR);
90 }
91
92
93 /*
94 * msmtp_password_callback()
95 *
96 * This function will be called by smtp_auth() to get a password if none was
97 * given.
98 */
99
msmtp_password_callback(const char * hostname,const char * user)100 char *msmtp_password_callback(const char *hostname, const char *user)
101 {
102 return password_get(hostname, user, password_service_smtp, 1, 1);
103 }
104
105
106 /*
107 * msmtp_endsession()
108 *
109 * Quit an SMTP session and close the connection.
110 * QUIT is only sent when the flag 'quit' is set.
111 */
112
msmtp_endsession(smtp_server_t * srv,int quit)113 void msmtp_endsession(smtp_server_t *srv, int quit)
114 {
115 char *tmp_errstr;
116
117 if (quit)
118 {
119 tmp_errstr = NULL;
120 (void)smtp_quit(srv, &tmp_errstr);
121 free(tmp_errstr);
122 }
123 smtp_close(srv);
124 }
125
126
127 /*
128 * msmtp_rmqs()
129 *
130 * Sends an ETRN request to the SMTP server specified in the account 'acc'.
131 * If an error occurred, '*errstr' points to an allocated string that describes
132 * the error or is NULL, and '*msg' may contain the offending message from the
133 * SMTP server (or be NULL).
134 */
135
msmtp_rmqs(account_t * acc,int debug,const char * rmqs_argument,list_t ** msg,char ** errstr)136 int msmtp_rmqs(account_t *acc, int debug, const char *rmqs_argument,
137 list_t **msg, char **errstr)
138 {
139 smtp_server_t srv;
140 int e;
141 #ifdef HAVE_TLS
142 mtls_cert_info_t *tci = NULL;
143 char *mtls_parameter_description = NULL;
144 #endif /* HAVE_TLS */
145
146 *errstr = NULL;
147 *msg = NULL;
148
149 /* create a new smtp_server_t */
150 srv = smtp_new(debug ? stdout : NULL, acc->protocol);
151
152 /* connect */
153 if ((e = smtp_connect(&srv, acc->socketname, acc->proxy_host, acc->proxy_port,
154 acc->host, acc->port, acc->source_ip, acc->timeout,
155 NULL, NULL, errstr)) != NET_EOK)
156 {
157 return net_exitcode(e);
158 }
159
160 /* prepare tls */
161 #ifdef HAVE_TLS
162 if (acc->tls)
163 {
164 if ((e = smtp_tls_init(&srv,
165 acc->tls_key_file, acc->tls_cert_file, acc->password,
166 acc->tls_trust_file, acc->tls_crl_file,
167 acc->tls_sha256_fingerprint,
168 acc->tls_sha1_fingerprint, acc->tls_md5_fingerprint,
169 acc->tls_min_dh_prime_bits,
170 acc->tls_priorities,
171 acc->tls_host_override ? acc->tls_host_override : acc->host,
172 acc->tls_nocertcheck,
173 errstr)) != TLS_EOK)
174 {
175 return mtls_exitcode(e);
176 }
177 }
178 #endif /* HAVE_TLS */
179
180 /* start tls for smtps servers */
181 #ifdef HAVE_TLS
182 if (acc->tls && acc->tls_nostarttls)
183 {
184 if (debug)
185 {
186 tci = mtls_cert_info_new();
187 }
188 if ((e = smtp_tls(&srv, tci,
189 &mtls_parameter_description, errstr)) != TLS_EOK)
190 {
191 if (debug)
192 {
193 mtls_cert_info_free(tci);
194 free(mtls_parameter_description);
195 }
196 msmtp_endsession(&srv, 0);
197 return mtls_exitcode(e);
198 }
199 if (debug)
200 {
201 mtls_print_info(mtls_parameter_description, tci);
202 mtls_cert_info_free(tci);
203 free(mtls_parameter_description);
204 }
205 }
206 #endif /* HAVE_TLS */
207
208 /* get greeting */
209 if ((e = smtp_get_greeting(&srv, msg, NULL, errstr)) != SMTP_EOK)
210 {
211 msmtp_endsession(&srv, 0);
212 return smtp_exitcode(e);
213 }
214
215 /* initialize session */
216 if ((e = smtp_init(&srv, acc->domain, msg, errstr)) != SMTP_EOK)
217 {
218 msmtp_endsession(&srv, 0);
219 return smtp_exitcode(e);
220 }
221
222 /* start tls for starttls servers */
223 #ifdef HAVE_TLS
224 if (acc->tls && !acc->tls_nostarttls)
225 {
226 if (!(srv.cap.flags & SMTP_CAP_STARTTLS))
227 {
228 *errstr = xasprintf(_("the server does not support TLS "
229 "via the STARTTLS command"));
230 msmtp_endsession(&srv, 1);
231 return EX_UNAVAILABLE;
232 }
233 if ((e = smtp_tls_starttls(&srv, msg, errstr)) != SMTP_EOK)
234 {
235 msmtp_endsession(&srv, 0);
236 return smtp_exitcode(e);
237 }
238 if (debug)
239 {
240 tci = mtls_cert_info_new();
241 }
242 if ((e = smtp_tls(&srv, tci,
243 &mtls_parameter_description, errstr)) != TLS_EOK)
244 {
245 if (debug)
246 {
247 mtls_cert_info_free(tci);
248 free(mtls_parameter_description);
249 }
250 msmtp_endsession(&srv, 0);
251 return mtls_exitcode(e);
252 }
253 if (debug)
254 {
255 mtls_print_info(mtls_parameter_description, tci);
256 mtls_cert_info_free(tci);
257 free(mtls_parameter_description);
258 }
259 /* initialize again */
260 if ((e = smtp_init(&srv, acc->domain, msg, errstr)) != SMTP_EOK)
261 {
262 msmtp_endsession(&srv, 0);
263 return smtp_exitcode(e);
264 }
265 }
266 #endif /* HAVE_TLS */
267
268 if (!(srv.cap.flags & SMTP_CAP_ETRN))
269 {
270 *errstr = xasprintf(_("the server does not support "
271 "Remote Message Queue Starting"));
272 msmtp_endsession(&srv, 1);
273 return EX_UNAVAILABLE;
274 }
275
276 /* authenticate */
277 if (acc->auth_mech)
278 {
279 if (!(srv.cap.flags & SMTP_CAP_AUTH))
280 {
281 *errstr = xasprintf(
282 _("the server does not support authentication"));
283 msmtp_endsession(&srv, 1);
284 return EX_UNAVAILABLE;
285 }
286 if ((e = smtp_auth(&srv, acc->host, acc->port,
287 acc->username, acc->password,
288 acc->ntlmdomain, acc->auth_mech,
289 msmtp_password_callback, msg, errstr))
290 != SMTP_EOK)
291 {
292 msmtp_endsession(&srv, 0);
293 return smtp_exitcode(e);
294 }
295 }
296
297 /* send the ETRN request */
298 if ((e = smtp_etrn(&srv, rmqs_argument, msg, errstr)) != SMTP_EOK)
299 {
300 msmtp_endsession(&srv, 0);
301 return smtp_exitcode(e);
302 }
303
304 /* end session */
305 msmtp_endsession(&srv, 1);
306 return EX_OK;
307 }
308
309
310 /*
311 * msmtp_serverinfo()
312 *
313 * Prints information about the SMTP server specified in the account 'acc'.
314 * If an error occurred, '*errstr' points to an allocated string that describes
315 * the error or is NULL, and '*msg' may contain the offending message from the
316 * SMTP server (or be NULL).
317 */
318
msmtp_serverinfo(account_t * acc,int debug,list_t ** msg,char ** errstr)319 int msmtp_serverinfo(account_t *acc, int debug, list_t **msg, char **errstr)
320 {
321 smtp_server_t srv;
322 char *server_canonical_name = NULL;
323 char *server_address = NULL;
324 char *server_greeting = NULL;
325 int e;
326 #ifdef HAVE_TLS
327 mtls_cert_info_t *tci = NULL;
328 char *mtls_parameter_description = NULL;
329 #endif /* HAVE_TLS */
330
331 *errstr = NULL;
332 *msg = NULL;
333
334 /* create a new smtp_server_t */
335 srv = smtp_new(debug ? stdout : NULL, acc->protocol);
336
337 /* connect */
338 if ((e = smtp_connect(&srv, acc->socketname, acc->proxy_host, acc->proxy_port,
339 acc->host, acc->port, acc->source_ip, acc->timeout,
340 &server_canonical_name, &server_address, errstr))
341 != NET_EOK)
342 {
343 e = net_exitcode(e);
344 goto error_exit;
345 }
346
347 /* prepare tls */
348 #ifdef HAVE_TLS
349 if (acc->tls)
350 {
351 tci = mtls_cert_info_new();
352 if ((e = smtp_tls_init(&srv,
353 acc->tls_key_file, acc->tls_cert_file, acc->password,
354 acc->tls_trust_file, acc->tls_crl_file,
355 acc->tls_sha256_fingerprint,
356 acc->tls_sha1_fingerprint, acc->tls_md5_fingerprint,
357 acc->tls_min_dh_prime_bits,
358 acc->tls_priorities,
359 acc->tls_host_override ? acc->tls_host_override : acc->host,
360 acc->tls_nocertcheck,
361 errstr)) != TLS_EOK)
362 {
363 e = mtls_exitcode(e);
364 goto error_exit;
365 }
366 }
367 #endif /* HAVE_TLS */
368
369 /* start tls for smtps servers */
370 #ifdef HAVE_TLS
371 if (acc->tls && acc->tls_nostarttls)
372 {
373 if ((e = smtp_tls(&srv, tci,
374 &mtls_parameter_description, errstr)) != TLS_EOK)
375 {
376 msmtp_endsession(&srv, 0);
377 e = mtls_exitcode(e);
378 goto error_exit;
379 }
380 }
381 #endif /* HAVE_TLS */
382
383 /* get greeting */
384 if ((e = smtp_get_greeting(&srv, msg, &server_greeting,
385 errstr)) != SMTP_EOK)
386 {
387 msmtp_endsession(&srv, 0);
388 e = smtp_exitcode(e);
389 goto error_exit;
390 }
391
392 /* initialize session */
393 if ((e = smtp_init(&srv, acc->domain, msg, errstr)) != SMTP_EOK)
394 {
395 msmtp_endsession(&srv, 0);
396 e = smtp_exitcode(e);
397 goto error_exit;
398 }
399
400 /* start tls for starttls servers */
401 #ifdef HAVE_TLS
402 if (acc->tls && !acc->tls_nostarttls)
403 {
404 if (!(srv.cap.flags & SMTP_CAP_STARTTLS))
405 {
406 *errstr = xasprintf(_("the server does not support TLS "
407 "via the STARTTLS command"));
408 msmtp_endsession(&srv, 1);
409 e = EX_UNAVAILABLE;
410 goto error_exit;
411 }
412 if ((e = smtp_tls_starttls(&srv, msg, errstr)) != SMTP_EOK)
413 {
414 msmtp_endsession(&srv, 0);
415 e = smtp_exitcode(e);
416 goto error_exit;
417 }
418 if ((e = smtp_tls(&srv, tci,
419 &mtls_parameter_description, errstr)) != TLS_EOK)
420 {
421 msmtp_endsession(&srv, 0);
422 e = mtls_exitcode(e);
423 goto error_exit;
424 }
425 /* initialize again */
426 if ((e = smtp_init(&srv, acc->domain, msg, errstr)) != SMTP_EOK)
427 {
428 msmtp_endsession(&srv, 0);
429 e = smtp_exitcode(e);
430 goto error_exit;
431 }
432 }
433 #endif /* HAVE_TLS */
434
435 /* end session */
436 msmtp_endsession(&srv, 1);
437
438 /* print results */
439 if (server_canonical_name && server_address)
440 {
441 printf(_("%s server at %s (%s [%s]), port %d:\n"),
442 acc->protocol == SMTP_PROTO_SMTP ? "SMTP" : "LMTP",
443 acc->host, server_canonical_name, server_address, acc->port);
444 }
445 else if (server_canonical_name)
446 {
447 printf(_("%s server at %s (%s), port %d:\n"),
448 acc->protocol == SMTP_PROTO_SMTP ? "SMTP" : "LMTP",
449 acc->host, server_canonical_name, acc->port);
450 }
451 else if (server_address)
452 {
453 printf(_("%s server at %s ([%s]), port %d:\n"),
454 acc->protocol == SMTP_PROTO_SMTP ? "SMTP" : "LMTP",
455 acc->host, server_address, acc->port);
456 }
457 else
458 {
459 printf(_("%s server at %s, port %d:\n"),
460 acc->protocol == SMTP_PROTO_SMTP ? "SMTP" : "LMTP",
461 acc->host, acc->port);
462 }
463 if (*server_greeting != '\0')
464 {
465 printf(" %s\n", sanitize_string(server_greeting));
466 }
467 #ifdef HAVE_TLS
468 if (acc->tls)
469 {
470 mtls_print_info(mtls_parameter_description, tci);
471 }
472 #endif /* HAVE_TLS */
473 #ifdef HAVE_TLS
474 if (srv.cap.flags == 0 && !(acc->tls && !acc->tls_nostarttls))
475 #else /* not HAVE_TLS */
476 if (srv.cap.flags == 0)
477 #endif /* not HAVE_TLS */
478 {
479 printf(_("No special capabilities.\n"));
480 }
481 else
482 {
483 printf(_("Capabilities:\n"));
484 if (srv.cap.flags & SMTP_CAP_SIZE)
485 {
486 printf(" SIZE %ld:\n %s", srv.cap.size,
487 _("Maximum message size is "));
488 if (srv.cap.size == 0)
489 {
490 printf(_("unlimited\n"));
491 }
492 else
493 {
494 printf(_("%ld bytes"), srv.cap.size);
495 if (srv.cap.size > 1024 * 1024)
496 {
497 printf(_(" = %.2f MiB"),
498 (float)srv.cap.size / (float)(1024 * 1024));
499 }
500 else if (srv.cap.size > 1024)
501 {
502 printf(_(" = %.2f KiB"), (float)srv.cap.size / 1024.0f);
503 }
504 printf("\n");
505 }
506 }
507 if (srv.cap.flags & SMTP_CAP_PIPELINING)
508 {
509 printf(" PIPELINING:\n %s\n", _("Support for command "
510 "grouping for faster transmission"));
511 }
512 if (srv.cap.flags & SMTP_CAP_ETRN)
513 {
514 printf(" ETRN:\n %s\n", _("Support for RMQS "
515 "(Remote Message Queue Starting)"));
516 }
517 if (srv.cap.flags & SMTP_CAP_DSN)
518 {
519 printf(" DSN:\n %s\n", _("Support for "
520 "Delivery Status Notifications"));
521 }
522 #ifdef HAVE_TLS
523 if ((acc->tls && !acc->tls_nostarttls)
524 || (srv.cap.flags & SMTP_CAP_STARTTLS))
525 #else /* not HAVE_TLS */
526 if (srv.cap.flags & SMTP_CAP_STARTTLS)
527 #endif /* not HAVE_TLS */
528 {
529 printf(" STARTTLS:\n %s\n", _("Support for "
530 "TLS encryption via the STARTTLS command"));
531 }
532 if (srv.cap.flags & SMTP_CAP_AUTH)
533 {
534 printf(" AUTH:\n %s\n ",
535 _("Supported authentication methods:"));
536 if (srv.cap.flags & SMTP_CAP_AUTH_PLAIN)
537 {
538 printf("PLAIN ");
539 }
540 if (srv.cap.flags & SMTP_CAP_AUTH_SCRAM_SHA_1)
541 {
542 printf("SCRAM-SHA-1 ");
543 }
544 if (srv.cap.flags & SMTP_CAP_AUTH_SCRAM_SHA_256)
545 {
546 printf("SCRAM-SHA-256 ");
547 }
548 if (srv.cap.flags & SMTP_CAP_AUTH_EXTERNAL)
549 {
550 printf("EXTERNAL ");
551 }
552 if (srv.cap.flags & SMTP_CAP_AUTH_GSSAPI)
553 {
554 printf("GSSAPI ");
555 }
556 if (srv.cap.flags & SMTP_CAP_AUTH_CRAM_MD5)
557 {
558 printf("CRAM-MD5 ");
559 }
560 if (srv.cap.flags & SMTP_CAP_AUTH_DIGEST_MD5)
561 {
562 printf("DIGEST-MD5 ");
563 }
564 if (srv.cap.flags & SMTP_CAP_AUTH_LOGIN)
565 {
566 printf("LOGIN ");
567 }
568 if (srv.cap.flags & SMTP_CAP_AUTH_NTLM)
569 {
570 printf("NTLM ");
571 }
572 if (srv.cap.flags & SMTP_CAP_AUTH_OAUTHBEARER)
573 {
574 printf("OAUTHBEARER ");
575 }
576 if (srv.cap.flags & SMTP_CAP_AUTH_XOAUTH2)
577 {
578 printf("XOAUTH2 ");
579 }
580 printf("\n");
581 }
582 #ifdef HAVE_TLS
583 if ((srv.cap.flags & SMTP_CAP_STARTTLS) && !acc->tls)
584 #else /* not HAVE_TLS */
585 if (srv.cap.flags & SMTP_CAP_STARTTLS)
586 #endif /* not HAVE_TLS */
587 {
588 printf(_("This server might advertise more or other "
589 "capabilities when TLS is active.\n"));
590 }
591 }
592
593 e = EX_OK;
594
595 error_exit:
596 free(server_canonical_name);
597 free(server_address);
598 #ifdef HAVE_TLS
599 if (tci)
600 {
601 mtls_cert_info_free(tci);
602 }
603 free(mtls_parameter_description);
604 #endif /* HAVE_TLS */
605 free(server_greeting);
606 return e;
607 }
608
609
610 /*
611 * msmtp_read_headers()
612 *
613 * Copies the headers of the mail from 'mailf' to a temporary file 'tmpf',
614 * including the blank line that separates the header from the body of the mail.
615 *
616 * If 'recipients' is not NULL: extracts all recipients from the To, Cc, and Bcc
617 * headers and adds them to 'recipients'. If Resent-* headers are present, all
618 * recipients from the Resent-To, Resent-Cc, Resent-Bcc headers in the first
619 * block of Resent- headers are extracted instead.
620 *
621 * If 'from' is not NULL: extracts the address from the From header and stores
622 * it in an allocated string. A pointer to this string is stored in 'from'.
623 *
624 * If 'have_date' is not NULL: set this flag to 1 if a Date header is present
625 * , and to 0 otherwise.
626 *
627 * See RFC2822, section 3 for the format of these headers.
628 *
629 * Return codes: EX_OK, EX_IOERR
630 */
631
632 #define STATE_LINESTART_FRESH 0 /* a new line started; the
633 previous line was not a
634 recipient header */
635 #define STATE_LINESTART_AFTER_ADDRHDR 1 /* a new line started; the
636 previous line was a
637 recipient header */
638 #define STATE_OTHER_HDR 2 /* a header we don't
639 care about */
640 #define STATE_DATE1 3 /* we saw "^D" */
641 #define STATE_DATE2 4 /* we saw "^Da" */
642 #define STATE_DATE3 5 /* we saw "^Dat" */
643 #define STATE_DATE4 6 /* we saw "^Date" */
644 #define STATE_FROM1 7 /* we saw "^F" */
645 #define STATE_FROM2 8 /* we saw "^Fr" */
646 #define STATE_FROM3 9 /* we saw "^Fro" */
647 #define STATE_TO 10 /* we saw "^T" */
648 #define STATE_CC 11 /* we saw "^C" */
649 #define STATE_BCC1 12 /* we saw "^B" */
650 #define STATE_BCC2 13 /* we saw "^Bc" */
651 #define STATE_ADDRHDR_ALMOST 14 /* we saw "^To", "^Cc"
652 or "^Bcc" */
653 #define STATE_RESENT 15 /* we saw part of "^Resent-" */
654 #define STATE_ADDRHDR_DEFAULT 16 /* in_rcpt_hdr and in_rcpt
655 state our position */
656 #define STATE_ADDRHDR_DQUOTE 17 /* duoble quotes */
657 #define STATE_ADDRHDR_BRACKETS_START 18 /* entering <...> */
658 #define STATE_ADDRHDR_IN_BRACKETS 19 /* an address inside <> */
659 #define STATE_ADDRHDR_PARENTH_START 20 /* entering (...) */
660 #define STATE_ADDRHDR_IN_PARENTH 21 /* a comment inside () */
661 #define STATE_ADDRHDR_IN_ADDRESS 22 /* a bare address */
662 #define STATE_ADDRHDR_BACKQUOTE 23 /* we saw a '\\' */
663 #define STATE_HEADERS_END 24 /* we saw "^$", the blank line
664 between headers and body */
665
msmtp_read_headers(FILE * mailf,FILE * tmpf,list_t * recipients,char ** from,int * have_date,char ** errstr)666 int msmtp_read_headers(FILE *mailf, FILE *tmpf,
667 list_t *recipients,
668 char **from,
669 int *have_date,
670 char **errstr)
671 {
672 int c;
673 int state = STATE_LINESTART_FRESH;
674 int oldstate = STATE_LINESTART_FRESH;
675 int backquote_savestate = STATE_LINESTART_FRESH;
676 int parentheses_depth = 0;
677 int parentheses_savestate = STATE_LINESTART_FRESH;
678 int folded_rcpthdr_savestate = STATE_LINESTART_FRESH;
679 int from_hdr = -1; /* -1 = before, 0 = in, 1 = after first From: */
680 int resent_index = -1;
681 int resent_block = -1; /* -1 = before, 0 = in, 1 = after first block */
682 char *current_recipient = NULL;
683 size_t current_recipient_len = 0;
684 int forget_current_recipient = 0;
685 int finish_current_recipient = 0;
686 size_t bufsize = 0;
687 /* The buffer that is filled with the current recipient grows by
688 * 'bufsize_step' if the remaining space becomes too small. This value must
689 * be at least 2. Wasted characters are at most (bufsize_step - 1). A value
690 * of 10 means low wasted space and a low number of realloc()s per
691 * recipient. */
692 const size_t bufsize_step = 10;
693 /* We need two recipient lists: one for normal To, Cc, Bcc headers, and one
694 * for Resent-To, Resent-Cc, Resent-Bcc. The first list gathers adresses
695 * from all To, Cc, Bcc headers that are found. The second list gathers
696 * adresses only for the first block of Resent-* headers. If a Resent- block
697 * was seen, then the first list is ignored, and only the second list is
698 * appended to the recipient list given by the caller. */
699 list_t *normal_recipients_list = NULL;
700 list_t *normal_recipients = NULL;
701 list_t *resent_recipients_list = NULL;
702 list_t *resent_recipients = NULL;
703
704 if (from)
705 {
706 *from = NULL;
707 }
708 if (have_date)
709 {
710 *have_date = 0;
711 }
712 if (recipients)
713 {
714 normal_recipients_list = list_new();
715 normal_recipients = normal_recipients_list;
716 resent_recipients_list = list_new();
717 resent_recipients = resent_recipients_list;
718 }
719
720 for (;;)
721 {
722 c = fgetc(mailf);
723 /* Convert CRLF to LF. According to RFC 2822, CRs may only occur in a
724 * mail when they are followed by LF, so just ignoring CRs is ok. */
725 if (c == '\r')
726 {
727 continue;
728 }
729 oldstate = state;
730 if (c == EOF)
731 {
732 state = STATE_HEADERS_END;
733 if (current_recipient)
734 finish_current_recipient = 1;
735 }
736 else
737 {
738 switch (state)
739 {
740 case STATE_LINESTART_FRESH:
741 parentheses_depth = 0;
742 resent_index = -1;
743 if (have_date && (c == 'd' || c == 'D'))
744 state = STATE_DATE1;
745 else if (from && from_hdr < 0 && (c == 'f' || c == 'F'))
746 state = STATE_FROM1;
747 else if (recipients && (c == 't' || c == 'T'))
748 state = STATE_TO;
749 else if (recipients && (c == 'c' || c == 'C'))
750 state = STATE_CC;
751 else if (recipients && (c == 'b' || c == 'B'))
752 state = STATE_BCC1;
753 else if (recipients && resent_block <= 0
754 && (c == 'r' || c == 'R'))
755 {
756 resent_index = 0;
757 state = STATE_RESENT;
758 }
759 else if (c == '\n')
760 state = STATE_HEADERS_END;
761 else
762 state = STATE_OTHER_HDR;
763 break;
764
765 case STATE_LINESTART_AFTER_ADDRHDR:
766 resent_index = -1;
767 if (c != ' ' && c != '\t')
768 {
769 if (current_recipient)
770 finish_current_recipient = 1;
771 else if (from_hdr == 0)
772 from_hdr = -1; /* the preceding From: header was empty */
773 }
774 if (c == ' ' || c == '\t')
775 state = folded_rcpthdr_savestate;
776 else if (have_date && (c == 'd' || c == 'D'))
777 state = STATE_DATE1;
778 else if (from && from_hdr < 0 && (c == 'f' || c == 'F'))
779 state = STATE_FROM1;
780 else if (recipients && (c == 't' || c == 'T'))
781 state = STATE_TO;
782 else if (recipients && (c == 'c' || c == 'C'))
783 state = STATE_CC;
784 else if (recipients && (c == 'b' || c == 'B'))
785 state = STATE_BCC1;
786 else if (recipients && resent_block <= 0
787 && (c == 'r' || c == 'R'))
788 {
789 resent_index = 0;
790 state = STATE_RESENT;
791 }
792 else if (c == '\n')
793 state = STATE_HEADERS_END;
794 else
795 state = STATE_OTHER_HDR;
796 break;
797
798 case STATE_OTHER_HDR:
799 if (resent_block == 0 && resent_index != 6)
800 resent_block = 1;
801 if (c == '\n')
802 state = STATE_LINESTART_FRESH;
803 break;
804
805 case STATE_RESENT:
806 if (resent_index == 0 && (c == 'e' || c == 'E'))
807 resent_index++;
808 else if (resent_index == 1 && (c == 's' || c == 'S'))
809 resent_index++;
810 else if (resent_index == 2 && (c == 'e' || c == 'E'))
811 resent_index++;
812 else if (resent_index == 3 && (c == 'n' || c == 'N'))
813 resent_index++;
814 else if (resent_index == 4 && (c == 't' || c == 'T'))
815 resent_index++;
816 else if (resent_index == 5 && c == '-')
817 {
818 if (resent_block == -1)
819 resent_block = 0;
820 resent_index++;
821 }
822 else if (resent_index == 6 && (c == 't' || c == 'T'))
823 state = STATE_TO;
824 else if (resent_index == 6 && (c == 'c' || c == 'C'))
825 state = STATE_CC;
826 else if (resent_index == 6 && (c == 'b' || c == 'B'))
827 state = STATE_BCC1;
828 else if (c == '\n')
829 state = STATE_LINESTART_FRESH;
830 else
831 state = STATE_OTHER_HDR;
832 break;
833
834 case STATE_DATE1:
835 if (c == 'a' || c == 'A')
836 state = STATE_DATE2;
837 else if (c == '\n')
838 state = STATE_LINESTART_FRESH;
839 else
840 state = STATE_OTHER_HDR;
841 break;
842
843 case STATE_DATE2:
844 if (c == 't' || c == 'T')
845 state = STATE_DATE3;
846 else if (c == '\n')
847 state = STATE_LINESTART_FRESH;
848 else
849 state = STATE_OTHER_HDR;
850 break;
851
852 case STATE_DATE3:
853 if (c == 'e' || c == 'E')
854 state = STATE_DATE4;
855 else if (c == '\n')
856 state = STATE_LINESTART_FRESH;
857 else
858 state = STATE_OTHER_HDR;
859 break;
860
861 case STATE_DATE4:
862 if (c == ':')
863 {
864 *have_date = 1;
865 state = STATE_OTHER_HDR;
866 }
867 else if (c == '\n')
868 state = STATE_LINESTART_FRESH;
869 else
870 state = STATE_OTHER_HDR;
871 break;
872
873 case STATE_FROM1:
874 if (resent_block == 0 && resent_index != 6)
875 resent_block = 1;
876 if (c == 'r' || c == 'R')
877 state = STATE_FROM2;
878 else if (c == '\n')
879 state = STATE_LINESTART_FRESH;
880 else
881 state = STATE_OTHER_HDR;
882 break;
883
884 case STATE_FROM2:
885 if (c == 'o' || c == 'O')
886 state = STATE_FROM3;
887 else if (c == '\n')
888 state = STATE_LINESTART_FRESH;
889 else
890 state = STATE_OTHER_HDR;
891 break;
892
893 case STATE_FROM3:
894 if (c == 'm' || c == 'M')
895 {
896 from_hdr = 0;
897 state = STATE_ADDRHDR_ALMOST;
898 }
899 else if (c == '\n')
900 state = STATE_LINESTART_FRESH;
901 else
902 state = STATE_OTHER_HDR;
903 break;
904
905 case STATE_TO:
906 if (resent_block == 0 && resent_index != 6)
907 resent_block = 1;
908 if (c == 'o' || c == 'O')
909 state = STATE_ADDRHDR_ALMOST;
910 else if (c == '\n')
911 state = STATE_LINESTART_FRESH;
912 else
913 state = STATE_OTHER_HDR;
914 break;
915
916 case STATE_CC:
917 if (resent_block == 0 && resent_index != 6)
918 resent_block = 1;
919 if (c == 'c' || c == 'C')
920 state = STATE_ADDRHDR_ALMOST;
921 else if (c == '\n')
922 state = STATE_LINESTART_FRESH;
923 else
924 state = STATE_OTHER_HDR;
925 break;
926
927 case STATE_BCC1:
928 if (resent_block == 0 && resent_index != 6)
929 resent_block = 1;
930 if (c == 'c' || c == 'C')
931 state = STATE_BCC2;
932 else if (c == '\n')
933 state = STATE_LINESTART_FRESH;
934 else
935 state = STATE_OTHER_HDR;
936 break;
937
938 case STATE_BCC2:
939 if (c == 'c' || c == 'C')
940 state = STATE_ADDRHDR_ALMOST;
941 else if (c == '\n')
942 state = STATE_LINESTART_FRESH;
943 else
944 state = STATE_OTHER_HDR;
945 break;
946
947 case STATE_ADDRHDR_ALMOST:
948 if (from_hdr == 0 && c != ':')
949 from_hdr = -1;
950 if (c == ':')
951 state = STATE_ADDRHDR_DEFAULT;
952 else if (c == '\n')
953 state = STATE_LINESTART_FRESH;
954 else
955 state = STATE_OTHER_HDR;
956 break;
957
958 case STATE_ADDRHDR_DEFAULT:
959 if (c == '\n')
960 {
961 if (current_recipient)
962 finish_current_recipient = 1;
963 folded_rcpthdr_savestate = state;
964 state = STATE_LINESTART_AFTER_ADDRHDR;
965 }
966 else if (c == '\\')
967 {
968 backquote_savestate = state;
969 state = STATE_ADDRHDR_BACKQUOTE;
970 }
971 else if (c == '(')
972 {
973 parentheses_savestate = state;
974 state = STATE_ADDRHDR_PARENTH_START;
975 }
976 else if (c == '"')
977 {
978 if (current_recipient)
979 forget_current_recipient = 1;
980 state = STATE_ADDRHDR_DQUOTE;
981 }
982 else if (c == '<')
983 {
984 if (current_recipient)
985 forget_current_recipient = 1;
986 state = STATE_ADDRHDR_BRACKETS_START;
987 }
988 else if (c == ' ' || c == '\t')
989 ; /* keep state */
990 else if (c == ':')
991 {
992 if (current_recipient)
993 forget_current_recipient = 1;
994 }
995 else if (c == ';' || c == ',')
996 {
997 if (current_recipient)
998 finish_current_recipient = 1;
999 }
1000 else
1001 {
1002 if (current_recipient)
1003 forget_current_recipient = 1;
1004 state = STATE_ADDRHDR_IN_ADDRESS;
1005 }
1006 break;
1007
1008 case STATE_ADDRHDR_DQUOTE:
1009 if (c == '\n')
1010 {
1011 folded_rcpthdr_savestate = state;
1012 state = STATE_LINESTART_AFTER_ADDRHDR;
1013 }
1014 else if (c == '\\')
1015 {
1016 backquote_savestate = state;
1017 state = STATE_ADDRHDR_BACKQUOTE;
1018 }
1019 else if (c == '"')
1020 state = STATE_ADDRHDR_DEFAULT;
1021 break;
1022
1023 case STATE_ADDRHDR_BRACKETS_START:
1024 if (c == '\n')
1025 {
1026 folded_rcpthdr_savestate = state;
1027 state = STATE_LINESTART_AFTER_ADDRHDR;
1028 }
1029 else if (c == '(')
1030 {
1031 parentheses_savestate = state;
1032 state = STATE_ADDRHDR_PARENTH_START;
1033 }
1034 else if (c == '>')
1035 state = STATE_ADDRHDR_DEFAULT;
1036 else
1037 state = STATE_ADDRHDR_IN_BRACKETS;
1038 break;
1039
1040 case STATE_ADDRHDR_IN_BRACKETS:
1041 if (c == '\n')
1042 {
1043 folded_rcpthdr_savestate = state;
1044 state = STATE_LINESTART_AFTER_ADDRHDR;
1045 }
1046 else if (c == '\\')
1047 {
1048 backquote_savestate = state;
1049 state = STATE_ADDRHDR_BACKQUOTE;
1050 }
1051 else if (c == '(')
1052 {
1053 parentheses_savestate = state;
1054 state = STATE_ADDRHDR_PARENTH_START;
1055 }
1056 else if (c == '>')
1057 {
1058 finish_current_recipient = 1;
1059 state = STATE_ADDRHDR_DEFAULT;
1060 }
1061 break;
1062
1063 case STATE_ADDRHDR_PARENTH_START:
1064 if (c == '\n')
1065 {
1066 folded_rcpthdr_savestate = state;
1067 state = STATE_LINESTART_AFTER_ADDRHDR;
1068 }
1069 else if (c == ')')
1070 state = parentheses_savestate;
1071 else
1072 {
1073 parentheses_depth++;
1074 state = STATE_ADDRHDR_IN_PARENTH;
1075 }
1076 break;
1077
1078 case STATE_ADDRHDR_IN_PARENTH:
1079 if (c == '\n')
1080 {
1081 folded_rcpthdr_savestate = state;
1082 state = STATE_LINESTART_AFTER_ADDRHDR;
1083 }
1084 else if (c == '\\')
1085 {
1086 backquote_savestate = state;
1087 state = STATE_ADDRHDR_BACKQUOTE;
1088 }
1089 else if (c == '(')
1090 state = STATE_ADDRHDR_PARENTH_START;
1091 else if (c == ')')
1092 {
1093 parentheses_depth--;
1094 if (parentheses_depth == 0)
1095 state = parentheses_savestate;
1096 }
1097 break;
1098
1099 case STATE_ADDRHDR_IN_ADDRESS:
1100 if (c == '\n')
1101 {
1102 folded_rcpthdr_savestate = STATE_ADDRHDR_DEFAULT;
1103 state = STATE_LINESTART_AFTER_ADDRHDR;
1104 }
1105 else if (c == '\\')
1106 {
1107 backquote_savestate = state;
1108 state = STATE_ADDRHDR_BACKQUOTE;
1109 }
1110 else if (c == '"')
1111 {
1112 forget_current_recipient = 1;
1113 state = STATE_ADDRHDR_DQUOTE;
1114 }
1115 else if (c == '(')
1116 {
1117 parentheses_savestate = state;
1118 state = STATE_ADDRHDR_PARENTH_START;
1119 }
1120 else if (c == '<')
1121 {
1122 forget_current_recipient = 1;
1123 state = STATE_ADDRHDR_BRACKETS_START;
1124 }
1125 else if (c == ' ' || c == '\t')
1126 state = STATE_ADDRHDR_DEFAULT;
1127 else if (c == ':')
1128 {
1129 forget_current_recipient = 1;
1130 state = STATE_ADDRHDR_DEFAULT;
1131 }
1132 else if (c == ',' || c == ';')
1133 {
1134 finish_current_recipient = 1;
1135 state = STATE_ADDRHDR_DEFAULT;
1136 }
1137 break;
1138
1139 case STATE_ADDRHDR_BACKQUOTE:
1140 if (c == '\n')
1141 {
1142 folded_rcpthdr_savestate = STATE_ADDRHDR_DEFAULT;
1143 state = STATE_LINESTART_AFTER_ADDRHDR;
1144 }
1145 else
1146 state = backquote_savestate;
1147 break;
1148 }
1149 }
1150
1151 if (tmpf && c != EOF && fputc(c, tmpf) == EOF)
1152 {
1153 *errstr = xasprintf(_("cannot write mail headers to temporary "
1154 "file: output error"));
1155 goto error_exit;
1156 }
1157
1158 if (forget_current_recipient)
1159 {
1160 /* this was just junk */
1161 free(current_recipient);
1162 current_recipient = NULL;
1163 current_recipient_len = 0;
1164 bufsize = 0;
1165 forget_current_recipient = 0;
1166 }
1167 if (finish_current_recipient)
1168 {
1169 /* The current recipient just ended. Add it to the list */
1170 current_recipient[current_recipient_len] = '\0';
1171 if (from_hdr == 0)
1172 {
1173 *from = current_recipient;
1174 from_hdr = 1;
1175 }
1176 else if (recipients && resent_block == 0)
1177 {
1178 list_insert(resent_recipients, current_recipient);
1179 resent_recipients = resent_recipients->next;
1180 }
1181 else if (recipients)
1182 {
1183 list_insert(normal_recipients, current_recipient);
1184 normal_recipients = normal_recipients->next;
1185 }
1186 /* Reset for the next recipient */
1187 current_recipient = NULL;
1188 current_recipient_len = 0;
1189 bufsize = 0;
1190 finish_current_recipient = 0;
1191 }
1192 if ((state == STATE_ADDRHDR_IN_ADDRESS
1193 || state == STATE_ADDRHDR_IN_BRACKETS)
1194 && oldstate != STATE_ADDRHDR_PARENTH_START
1195 && oldstate != STATE_ADDRHDR_IN_PARENTH
1196 && oldstate != STATE_LINESTART_AFTER_ADDRHDR)
1197 {
1198 /* Add this character to the current recipient */
1199 current_recipient_len++;
1200 if (bufsize < current_recipient_len + 1)
1201 {
1202 bufsize += bufsize_step;
1203 current_recipient = xrealloc(current_recipient,
1204 bufsize * sizeof(char));
1205 }
1206 /* sanitize characters */
1207 if (!iscntrl((unsigned char)c) && !isspace((unsigned char)c))
1208 {
1209 current_recipient[current_recipient_len - 1] = (char)c;
1210 }
1211 else
1212 {
1213 current_recipient[current_recipient_len - 1] = '_';
1214 }
1215 }
1216
1217 if (state == STATE_HEADERS_END)
1218 {
1219 break;
1220 }
1221 }
1222
1223 /* Corner case: we saw a "From: " header without a recipient. */
1224 if (from_hdr == 0)
1225 {
1226 *from = xstrdup("");
1227 }
1228
1229 if (recipients)
1230 {
1231 if (resent_block >= 0)
1232 {
1233 list_xfree(normal_recipients_list, free);
1234 resent_recipients = resent_recipients_list;
1235 while (!list_is_empty(resent_recipients))
1236 {
1237 resent_recipients = resent_recipients->next;
1238 list_insert(recipients, resent_recipients->data);
1239 recipients = recipients->next;
1240 }
1241 list_free(resent_recipients_list);
1242 }
1243 else
1244 {
1245 list_xfree(resent_recipients_list, free);
1246 normal_recipients = normal_recipients_list;
1247 while (!list_is_empty(normal_recipients))
1248 {
1249 normal_recipients = normal_recipients->next;
1250 list_insert(recipients, normal_recipients->data);
1251 recipients = recipients->next;
1252 }
1253 list_free(normal_recipients_list);
1254 }
1255 normal_recipients_list = NULL;
1256 resent_recipients_list = NULL;
1257 }
1258
1259 if (ferror(mailf))
1260 {
1261 *errstr = xasprintf(_("input error while reading the mail"));
1262 goto error_exit;
1263 }
1264
1265 return EX_OK;
1266
1267 error_exit:
1268 if (normal_recipients_list)
1269 {
1270 list_xfree(normal_recipients_list, free);
1271 }
1272 if (resent_recipients_list)
1273 {
1274 list_xfree(resent_recipients_list, free);
1275 }
1276 if (from)
1277 {
1278 free(*from);
1279 *from = NULL;
1280 }
1281 free(current_recipient);
1282 return EX_IOERR;
1283 }
1284
1285
1286 /*
1287 * msmtp_sendmail()
1288 *
1289 * Sends a mail. Returns a value from sysexits.h.
1290 * If an error occurred, '*errstr' points to an allocated string that describes
1291 * the error or is NULL, and '*msg' may contain the offending message from the
1292 * SMTP server (or be NULL).
1293 * In case of success, 'mailsize' contains the number of bytes of the mail
1294 * transferred to the SMTP server. In case of failure, its contents are
1295 * undefined.
1296 */
1297
msmtp_sendmail(account_t * acc,list_t * recipients,FILE * prepend_header_file,int prepend_header_contains_from,FILE * header_file,FILE * f,int debug,long * mailsize,list_t ** lmtp_errstrs,list_t ** lmtp_error_msgs,list_t ** msg,char ** errstr)1298 int msmtp_sendmail(account_t *acc, list_t *recipients,
1299 FILE *prepend_header_file, int prepend_header_contains_from,
1300 FILE *header_file, FILE *f,
1301 int debug, long *mailsize,
1302 list_t **lmtp_errstrs, list_t **lmtp_error_msgs,
1303 list_t **msg, char **errstr)
1304 {
1305 smtp_server_t srv;
1306 int e;
1307 #ifdef HAVE_TLS
1308 mtls_cert_info_t *tci = NULL;
1309 char *mtls_parameter_description = NULL;
1310 #endif /* HAVE_TLS */
1311
1312 *errstr = NULL;
1313 *msg = NULL;
1314 *lmtp_errstrs = NULL;
1315 *lmtp_error_msgs = NULL;
1316
1317 /* create a new smtp_server_t */
1318 srv = smtp_new(debug ? stdout : NULL, acc->protocol);
1319
1320 /* prepare tls */
1321 #ifdef HAVE_TLS
1322 if (acc->tls)
1323 {
1324 if ((e = smtp_tls_init(&srv,
1325 acc->tls_key_file, acc->tls_cert_file, acc->password,
1326 acc->tls_trust_file, acc->tls_crl_file,
1327 acc->tls_sha256_fingerprint,
1328 acc->tls_sha1_fingerprint, acc->tls_md5_fingerprint,
1329 acc->tls_min_dh_prime_bits,
1330 acc->tls_priorities,
1331 acc->tls_host_override ? acc->tls_host_override : acc->host,
1332 acc->tls_nocertcheck,
1333 errstr)) != TLS_EOK)
1334 {
1335 e = mtls_exitcode(e);
1336 return e;
1337 }
1338 }
1339 #endif /* HAVE_TLS */
1340
1341 /* connect */
1342 if ((e = smtp_connect(&srv, acc->socketname, acc->proxy_host, acc->proxy_port,
1343 acc->host, acc->port, acc->source_ip, acc->timeout,
1344 NULL, NULL, errstr)) != NET_EOK)
1345 {
1346 e = net_exitcode(e);
1347 return e;
1348 }
1349
1350 /* start tls for smtps servers */
1351 #ifdef HAVE_TLS
1352 if (acc->tls && acc->tls_nostarttls)
1353 {
1354 if (debug)
1355 {
1356 tci = mtls_cert_info_new();
1357 }
1358 if ((e = smtp_tls(&srv, tci,
1359 &mtls_parameter_description, errstr)) != TLS_EOK)
1360 {
1361 if (debug)
1362 {
1363 mtls_cert_info_free(tci);
1364 free(mtls_parameter_description);
1365 }
1366 msmtp_endsession(&srv, 0);
1367 e = mtls_exitcode(e);
1368 return e;
1369 }
1370 if (debug)
1371 {
1372 mtls_print_info(mtls_parameter_description, tci);
1373 mtls_cert_info_free(tci);
1374 free(mtls_parameter_description);
1375 }
1376 }
1377 #endif /* HAVE_TLS */
1378
1379 /* get greeting */
1380 if ((e = smtp_get_greeting(&srv, msg, NULL, errstr)) != SMTP_EOK)
1381 {
1382 msmtp_endsession(&srv, 0);
1383 e = smtp_exitcode(e);
1384 return e;
1385 }
1386
1387 /* initialize session */
1388 if ((e = smtp_init(&srv, acc->domain, msg, errstr)) != SMTP_EOK)
1389 {
1390 msmtp_endsession(&srv, 0);
1391 e = smtp_exitcode(e);
1392 return e;
1393 }
1394
1395 /* start tls for starttls servers */
1396 #ifdef HAVE_TLS
1397 if (acc->tls && !acc->tls_nostarttls)
1398 {
1399 if (!(srv.cap.flags & SMTP_CAP_STARTTLS))
1400 {
1401 *errstr = xasprintf(_("the server does not support TLS "
1402 "via the STARTTLS command"));
1403 msmtp_endsession(&srv, 1);
1404 e = EX_UNAVAILABLE;
1405 return e;
1406 }
1407 if ((e = smtp_tls_starttls(&srv, msg, errstr)) != SMTP_EOK)
1408 {
1409 msmtp_endsession(&srv, 0);
1410 e = smtp_exitcode(e);
1411 return e;
1412 }
1413 if (debug)
1414 {
1415 tci = mtls_cert_info_new();
1416 }
1417 if ((e = smtp_tls(&srv, tci,
1418 &mtls_parameter_description, errstr)) != TLS_EOK)
1419 {
1420 if (debug)
1421 {
1422 mtls_cert_info_free(tci);
1423 free(mtls_parameter_description);
1424 }
1425 msmtp_endsession(&srv, 0);
1426 e = mtls_exitcode(e);
1427 return e;
1428 }
1429 if (debug)
1430 {
1431 mtls_print_info(mtls_parameter_description, tci);
1432 mtls_cert_info_free(tci);
1433 free(mtls_parameter_description);
1434 }
1435 /* initialize again */
1436 if ((e = smtp_init(&srv, acc->domain, msg, errstr)) != SMTP_EOK)
1437 {
1438 msmtp_endsession(&srv, 0);
1439 e = smtp_exitcode(e);
1440 return e;
1441 }
1442 }
1443 #endif /* HAVE_TLS */
1444
1445 /* test for needed features */
1446 if ((acc->dsn_return || acc->dsn_notify) && !(srv.cap.flags & SMTP_CAP_DSN))
1447 {
1448 *errstr = xasprintf(_("the server does not support DSN"));
1449 msmtp_endsession(&srv, 1);
1450 e = EX_UNAVAILABLE;
1451 return e;
1452 }
1453 /* authenticate */
1454 if (acc->auth_mech)
1455 {
1456 if (!(srv.cap.flags & SMTP_CAP_AUTH))
1457 {
1458 *errstr = xasprintf(
1459 _("the server does not support authentication"));
1460 msmtp_endsession(&srv, 1);
1461 e = EX_UNAVAILABLE;
1462 return e;
1463 }
1464 if ((e = smtp_auth(&srv, acc->host, acc->port,
1465 acc->username, acc->password,
1466 acc->ntlmdomain, acc->auth_mech,
1467 msmtp_password_callback, msg, errstr))
1468 != SMTP_EOK)
1469 {
1470 msmtp_endsession(&srv, 0);
1471 e = smtp_exitcode(e);
1472 return e;
1473 }
1474 }
1475
1476 /* send the envelope */
1477 if ((e = smtp_send_envelope(&srv, acc->from, recipients,
1478 acc->dsn_notify, acc->dsn_return, msg, errstr)) != SMTP_EOK)
1479 {
1480 msmtp_endsession(&srv, 0);
1481 e = smtp_exitcode(e);
1482 return e;
1483 }
1484 /* send header and body */
1485 *mailsize = 0;
1486 if (prepend_header_file)
1487 {
1488 /* first: prepended headers, if any */
1489 if ((e = smtp_send_mail(&srv, prepend_header_file,
1490 1, 1, 1, 1, mailsize,
1491 errstr)) != SMTP_EOK)
1492 {
1493 msmtp_endsession(&srv, 0);
1494 e = smtp_exitcode(e);
1495 return e;
1496 }
1497 }
1498 /* next: original mail headers */
1499 if ((e = smtp_send_mail(&srv, header_file,
1500 !prepend_header_contains_from, /* keep_from */
1501 !acc->undisclosed_recipients, /* keep_to */
1502 !acc->undisclosed_recipients, /* keep_cc */
1503 !acc->undisclosed_recipients
1504 && !acc->remove_bcc_headers, /* keep_bcc */
1505 mailsize, errstr)) != SMTP_EOK)
1506 {
1507 msmtp_endsession(&srv, 0);
1508 e = smtp_exitcode(e);
1509 return e;
1510 }
1511 /* then: the body from the original file */
1512 if ((e = smtp_send_mail(&srv, f, 1, 1, 1, 1, mailsize, errstr)) != SMTP_EOK)
1513 {
1514 msmtp_endsession(&srv, 0);
1515 e = smtp_exitcode(e);
1516 return e;
1517 }
1518 /* end the mail */
1519 if (acc->protocol == SMTP_PROTO_SMTP)
1520 {
1521 e = smtp_end_mail(&srv, msg, errstr);
1522 }
1523 else
1524 {
1525 e = smtp_end_mail_lmtp(&srv, recipients,
1526 lmtp_errstrs, lmtp_error_msgs, errstr);
1527 }
1528 if (e != SMTP_EOK)
1529 {
1530 msmtp_endsession(&srv, 0);
1531 e = smtp_exitcode(e);
1532 return e;
1533 }
1534
1535 /* end session */
1536 msmtp_endsession(&srv, 1);
1537
1538 return EX_OK;
1539 }
1540
1541
1542 /*
1543 * print_error()
1544 *
1545 * Print an error message
1546 */
1547
1548 /* make gcc print format warnings for this function */
1549 #ifdef __GNUC__
1550 void print_error(const char *format, ...)
1551 __attribute__ ((format (printf, 1, 2)));
1552 #endif
1553
print_error(const char * format,...)1554 void print_error(const char *format, ...)
1555 {
1556 va_list args;
1557 fprintf(stderr, "%s: ", prgname);
1558 va_start(args, format);
1559 vfprintf(stderr, format, args);
1560 va_end(args);
1561 fprintf(stderr, "\n");
1562 }
1563
1564
1565 /*
1566 * msmtp_configure()
1567 *
1568 * Tries autoconfiguration for the given mail address based on the methods
1569 * described in RFC 8314 (SRV records).
1570 * If successfull, this function will print a configuration file excerpt to
1571 * standard output and return EX_OK.
1572 * Otherwise, it will print an appropriate error message to standard error
1573 * and return an EX_* status.
1574 */
1575
msmtp_configure(const char * address,const char * conffile)1576 int msmtp_configure(const char *address, const char *conffile)
1577 {
1578 #ifdef HAVE_LIBRESOLV
1579
1580 int e;
1581
1582 char *local_part;
1583 char *domain_part;
1584
1585 char *submissions_query;
1586 char *submission_query;
1587
1588 char *hostname = NULL;
1589 int port = -1;
1590 int starttls = -1;
1591
1592 char *tmpstr;
1593
1594 split_mail_address(address, &local_part, &domain_part);
1595 if (!domain_part || domain_part[0] == '\0' || local_part[0] == '\0')
1596 {
1597 print_error(_("automatic configuration based on SRV records failed: %s"),
1598 _("invalid mail address"));
1599 free(local_part);
1600 free(domain_part);
1601 return EX_DATAERR;
1602 }
1603
1604 submissions_query = net_get_srv_query(domain_part, "submissions");
1605 e = net_get_srv_record(submissions_query, &hostname, &port);
1606 if (e == NET_EOK) {
1607 starttls = 0;
1608 } else {
1609 submission_query = net_get_srv_query(domain_part, "submission");
1610 e = net_get_srv_record(submission_query, &hostname, &port);
1611 if (e == NET_EOK) {
1612 starttls = 1;
1613 } else {
1614 char *errstr = xasprintf(_("no SRV records for %s or %s"),
1615 submissions_query, submission_query);
1616 print_error(_("automatic configuration based on SRV records failed: %s"),
1617 errstr);
1618 free(errstr);
1619 free(submissions_query);
1620 free(submission_query);
1621 free(local_part);
1622 free(domain_part);
1623 return EX_NOHOST;
1624 }
1625 free(submission_query);
1626 }
1627 free(submissions_query);
1628
1629 /* comment header */
1630
1631 tmpstr = xasprintf(_("copy this to your configuration file %s"), conffile);
1632 printf("# - %s\n", tmpstr);
1633 free(tmpstr);
1634 if (!check_hostname_matches_domain(hostname, domain_part))
1635 printf("# - %s\n", _("warning: the host does not match the mail domain; please check"));
1636 #if defined HAVE_LIBSECRET
1637 tmpstr = xasprintf("secret-tool store --label=msmtp host %s service smtp user %s", hostname, local_part);
1638 printf("# - %s\n# %s\n", _("add your password to the key ring:"), tmpstr);
1639 free(tmpstr);
1640 #elif defined HAVE_MACOSXKEYRING
1641 tmpstr = xasprintf("security add-internet-password -s %s -r smtp -a %s -w", hostname, local_part);
1642 printf("# - %s\n# %s\n", _("add your password to the key ring:"), tmpstr);
1643 free(tmpstr);
1644 #else
1645 printf("# - %s\n# %s\n", _("encrypt your password:"), "gpg -e -o ~/.msmtp-password.gpg");
1646 #endif
1647
1648 /* account definition */
1649 printf("account %s\n", address);
1650 printf("host %s\n", hostname);
1651 printf("port %d\n", port);
1652 printf("tls on\n");
1653 printf("tls_starttls %s\n", starttls ? "on" : "off");
1654 printf("auth on\n");
1655 printf("user %s\n", local_part);
1656 #if !defined HAVE_LIBSECRET && !defined HAVE_MACOSXKEYRING
1657 printf("passwordeval gpg --no-tty -q -d ~/.msmtp-password.gpg\n");
1658 #endif
1659 printf("from %s\n", address);
1660
1661 free(local_part);
1662 free(domain_part);
1663 free(hostname);
1664 return EX_OK;
1665
1666 #else
1667
1668 print_error(_("automatic configuration based on SRV records failed: %s"),
1669 _("this system lacks libresolv"));
1670 return EX_UNAVAILABLE;
1671
1672 #endif
1673 }
1674
1675
1676 /*
1677 * msmtp_get_log_info()
1678 *
1679 * Gather log information for syslog or logfile and put it in a string:
1680 * - host=%s
1681 * - tls=on|off
1682 * - auth=on|off
1683 * - user=%s (only if auth == on and username != NULL)
1684 * - from=%s
1685 * - recipients=%s,%s,...
1686 * - mailsize=%s (only if exitcode == EX_OK)
1687 * - smtpstatus=%s (only if a smtp msg is available)
1688 * - smtpmsg='%s' (only if a smtp msg is available)
1689 * - errormsg='%s' (only if exitcode != EX_OK and an error msg is available)
1690 * - exitcode=%s
1691 * 'exitcode' must be one of the sysexits.h exitcodes.
1692 * This function cannot fail.
1693 */
1694
msmtp_get_log_info(account_t * acc,list_t * recipients,long mailsize,list_t * errmsg,char * errstr,int exitcode)1695 char *msmtp_get_log_info(account_t *acc, list_t *recipients, long mailsize,
1696 list_t *errmsg, char *errstr, int exitcode)
1697 {
1698 int i;
1699 size_t s;
1700 list_t *l;
1701 char *line;
1702 int n;
1703 char *p;
1704 char *tmp;
1705 /* temporary strings: */
1706 char *mailsize_str = NULL;
1707 const char *exitcode_str;
1708 char *smtpstatus_str = NULL;
1709 char *smtperrmsg_str = NULL;
1710
1711
1712 /* gather information */
1713
1714 line = NULL;
1715 /* mailsize */
1716 if (exitcode == EX_OK)
1717 {
1718 mailsize_str = xasprintf("%ld", mailsize);
1719 }
1720 /* exitcode */
1721 exitcode_str = exitcode_to_string(exitcode);
1722 /* smtp status and smtp error message */
1723 if (errmsg)
1724 {
1725 smtpstatus_str = xasprintf("%d", smtp_msg_status(errmsg));
1726 l = errmsg;
1727 s = 0;
1728 while (!list_is_empty(l))
1729 {
1730 l = l->next;
1731 s += strlen(l->data) + 2;
1732 }
1733 s += 1;
1734 smtperrmsg_str = xmalloc(s * sizeof(char));
1735 smtperrmsg_str[0] = '\'';
1736 i = 1;
1737 l = errmsg;
1738 while (!list_is_empty(l))
1739 {
1740 l = l->next;
1741 p = sanitize_string(l->data);
1742 while (*p != '\0')
1743 {
1744 /* hide single quotes to make the info easy to parse */
1745 smtperrmsg_str[i] = (*p == '\'') ? '?' : *p;
1746 p++;
1747 i++;
1748 }
1749 smtperrmsg_str[i++] = '\\';
1750 smtperrmsg_str[i++] = 'n';
1751 }
1752 i -= 2;
1753 smtperrmsg_str[i++] = '\'';
1754 smtperrmsg_str[i++] = '\0';
1755 }
1756
1757 /* calculate the length of the log line */
1758
1759 s = 0;
1760 /* "host=%s " */
1761 s += 5 + strlen(acc->host) + 1;
1762 /* "tls=on|off " */
1763 s += 4 + (acc->tls ? 2 : 3) + 1;
1764 /* "auth=on|off " */
1765 s += 5 + (acc->auth_mech ? 2 : 3) + 1;
1766 /* "user=%s " */
1767 if (acc->auth_mech && acc->username)
1768 {
1769 s += 5 + strlen(acc->username) + 1;
1770 }
1771 /* "from=%s " */
1772 s += 5 + strlen(acc->from) + 1;
1773 /* "recipients=%s,%s,... " */
1774 s += 11;
1775 l = recipients;
1776 while (!list_is_empty(l))
1777 {
1778 l = l->next;
1779 s += strlen(l->data) + 1;
1780 }
1781 /* "mailsize=%s " */
1782 if (exitcode == EX_OK)
1783 {
1784 s += 9 + strlen(mailsize_str) + 1;
1785 }
1786 /* "smtpstatus=%s smtpmsg=%s " */
1787 if (errmsg)
1788 {
1789 s += 11 + strlen(smtpstatus_str) + 1 + 8 + strlen(smtperrmsg_str) + 1;
1790 }
1791 /* "errormsg='%s' */
1792 if (exitcode != EX_OK && errstr[0] != '\0')
1793 {
1794 s += 10 + strlen(errstr) + 2;
1795 }
1796 /* "exitcode=%s" */
1797 s += 9 + strlen(exitcode_str);
1798 /* '\0' */
1799 s++;
1800
1801 line = xmalloc(s * sizeof(char));
1802
1803 /* build the log line */
1804
1805 p = line;
1806 n = snprintf(p, s, "host=%s tls=%s auth=%s ",
1807 acc->host, (acc->tls ? "on" : "off"),
1808 (acc->auth_mech ? "on" : "off"));
1809 s -= n;
1810 p += n;
1811 if (acc->auth_mech && acc->username)
1812 {
1813 n = snprintf(p, s, "user=%s ", acc->username);
1814 s -= n;
1815 p += n;
1816 }
1817 n = snprintf(p, s, "from=%s recipients=", acc->from);
1818 s -= n;
1819 p += n;
1820 l = recipients;
1821 while (!list_is_empty(l))
1822 {
1823 l = l->next;
1824 n = snprintf(p, s, "%s,", (char *)(l->data));
1825 s -= n;
1826 p += n;
1827 }
1828 /* delete the last ',' */
1829 *(p - 1) = ' ';
1830 if (exitcode == EX_OK)
1831 {
1832 n = snprintf(p, s, "mailsize=%s ", mailsize_str);
1833 s -= n;
1834 p += n;
1835 }
1836 if (errmsg)
1837 {
1838 n = snprintf(p, s, "smtpstatus=%s smtpmsg=%s ",
1839 smtpstatus_str, smtperrmsg_str);
1840 s -= n;
1841 p += n;
1842 }
1843 if (exitcode != EX_OK && errstr[0] != '\0')
1844 {
1845 /* hide single quotes to make the info easy to parse */
1846 tmp = errstr;
1847 while (*tmp)
1848 {
1849 if (*tmp == '\'')
1850 {
1851 *tmp = '?';
1852 }
1853 tmp++;
1854 }
1855 n = snprintf(p, s, "errormsg='%s' ", sanitize_string(errstr));
1856 s -= n;
1857 p += n;
1858 }
1859 (void)snprintf(p, s, "exitcode=%s", exitcode_str);
1860
1861 free(mailsize_str);
1862 free(smtpstatus_str);
1863 free(smtperrmsg_str);
1864 return line;
1865 }
1866
1867
1868 /*
1869 * msmtp_log_to_file()
1870 *
1871 * Append a log entry to 'logfile' with the following information:
1872 * - date/time in the format given by 'logfile_time_format' (may be NULL)
1873 * - the log line as delivered by msmtp_get_log_info
1874 */
1875
msmtp_log_to_file(const char * logfile,const char * logfile_time_format,const char * loginfo)1876 void msmtp_log_to_file(const char *logfile, const char *logfile_time_format,
1877 const char *loginfo)
1878 {
1879 FILE *f = NULL;
1880 time_t t;
1881 struct tm *tm;
1882 char *failure_reason;
1883 const char *time_fmt;
1884 char time_str[128];
1885 int e;
1886
1887 /* get time */
1888 t = time(NULL); /* cannot fail */
1889 tm = localtime(&t); /* cannot fail */
1890 time_fmt = logfile_time_format ? logfile_time_format : "%b %d %H:%M:%S";
1891 if (strftime(time_str, sizeof(time_str), time_fmt, tm) == 0)
1892 {
1893 /* a return value of 0 is only an error with a non-empty time_fmt,
1894 * but we know it is non-empty since we cannot configure an empty
1895 * logfile_time_format in msmtp (it would be set to NULL). */
1896 failure_reason = xasprintf(_("invalid logfile_time_format"));
1897 goto log_failure;
1898 }
1899
1900 /* write log to file */
1901 if (strcmp(logfile, "-") == 0)
1902 {
1903 f = stdout;
1904 }
1905 else
1906 {
1907 if (!(f = fopen(logfile, "a")))
1908 {
1909 failure_reason = xasprintf(_("cannot open: %s"), strerror(errno));
1910 goto log_failure;
1911 }
1912 if ((e = lock_file(f, TOOLS_LOCK_WRITE, 10)) != 0)
1913 {
1914 if (e == 1)
1915 {
1916 failure_reason = xasprintf(
1917 _("cannot lock (tried for %d seconds): %s"),
1918 10, strerror(errno));
1919 }
1920 else
1921 {
1922 failure_reason = xasprintf(_("cannot lock: %s"),
1923 strerror(errno));
1924 }
1925 goto log_failure;
1926 }
1927 }
1928 if ((fputs(time_str, f) == EOF) || (fputc(' ', f) == EOF)
1929 || (fputs(loginfo, f) == EOF) || (fputc('\n', f) == EOF))
1930 {
1931 failure_reason = xstrdup(_("output error"));
1932 goto log_failure;
1933 }
1934 if (f != stdout && fclose(f) != 0)
1935 {
1936 failure_reason = xstrdup(strerror(errno));
1937 goto log_failure;
1938 }
1939
1940 return;
1941
1942 /* error exit target */
1943 log_failure:
1944 if (f && f != stdout)
1945 {
1946 fclose(f);
1947 }
1948 print_error(_("cannot log to %s: %s"), logfile, failure_reason);
1949 free(failure_reason);
1950 if (loginfo)
1951 {
1952 print_error(_("log info was: %s"), loginfo);
1953 }
1954 }
1955
1956
1957 /*
1958 * msmtp_log_to_syslog()
1959 *
1960 * Log the information delivered by msmtp_get_log_info() to syslog
1961 * the facility_str must be one of "LOG_MAIL", "LOG_USER", "LOG_LOCAL0", ...
1962 * "LOG_LOCAL7"
1963 * If 'error' is set, LOG_ERR is used, else LOG_INFO is used.
1964 */
1965
1966 #ifdef HAVE_SYSLOG
msmtp_log_to_syslog(const char * facility_str,const char * loginfo,int error)1967 void msmtp_log_to_syslog(const char *facility_str,
1968 const char *loginfo, int error)
1969 {
1970 int facility;
1971
1972 if (facility_str[4] == 'M')
1973 {
1974 facility = LOG_MAIL;
1975 }
1976 else if (facility_str[4] == 'U')
1977 {
1978 facility = LOG_USER;
1979 }
1980 else if (facility_str[9] == '0')
1981 {
1982 facility = LOG_LOCAL0;
1983 }
1984 else if (facility_str[9] == '1')
1985 {
1986 facility = LOG_LOCAL1;
1987 }
1988 else if (facility_str[9] == '2')
1989 {
1990 facility = LOG_LOCAL2;
1991 }
1992 else if (facility_str[9] == '3')
1993 {
1994 facility = LOG_LOCAL3;
1995 }
1996 else if (facility_str[9] == '4')
1997 {
1998 facility = LOG_LOCAL4;
1999 }
2000 else if (facility_str[9] == '5')
2001 {
2002 facility = LOG_LOCAL5;
2003 }
2004 else if (facility_str[9] == '6')
2005 {
2006 facility = LOG_LOCAL6;
2007 }
2008 else
2009 {
2010 facility = LOG_LOCAL7;
2011 }
2012
2013 openlog(PACKAGE_NAME, 0, facility);
2014 syslog(error ? LOG_ERR : LOG_INFO, "%s", loginfo);
2015 closelog();
2016 }
2017 #endif /* HAVE_SYSLOG */
2018
2019
2020 /*
2021 * msmtp_construct_env_from()
2022 *
2023 * OBSOLETE: triggered by auto_from, uses maildomain. both are replaced
2024 * with substitution patterns supported in from.
2025 *
2026 * Build an envelope from address for the current user.
2027 * If maildomain is not NULL and not the empty string, it will be the domain
2028 * part of the address. Otherwise, the address won't have a domain part.
2029 */
2030
msmtp_construct_env_from(const char * maildomain)2031 char *msmtp_construct_env_from(const char *maildomain)
2032 {
2033 char *envelope_from;
2034 size_t len;
2035
2036 envelope_from = get_username();
2037 if (maildomain && *maildomain != '\0')
2038 {
2039 len = strlen(envelope_from);
2040 envelope_from = xrealloc(envelope_from,
2041 ((len + 1 + strlen(maildomain) + 1) * sizeof(char)));
2042 envelope_from[len] = '@';
2043 strcpy(envelope_from + len + 1, maildomain);
2044 }
2045 return envelope_from;
2046 }
2047
2048
2049 /*
2050 * msmtp_print_version()
2051 *
2052 * Print --version information
2053 */
2054
msmtp_print_version(void)2055 void msmtp_print_version(void)
2056 {
2057 char *sysconfdir;
2058 char *sysconffile;
2059 char *userconffile;
2060
2061 printf(_("%s version %s\n"), PACKAGE_NAME, VERSION);
2062 printf(_("Platform: %s\n"), PLATFORM);
2063 /* TLS/SSL support */
2064 printf(_("TLS/SSL library: %s\n"),
2065 #ifdef HAVE_LIBGNUTLS
2066 "GnuTLS"
2067 #elif defined (HAVE_LIBSSL)
2068 "OpenSSL"
2069 #elif defined (HAVE_LIBTLS)
2070 "libtls"
2071 #else
2072 _("none")
2073 #endif
2074 );
2075 /* Authentication support */
2076 printf(_("Authentication library: %s\n"
2077 "Supported authentication methods:\n"),
2078 #ifdef HAVE_LIBGSASL
2079 _("GNU SASL; oauthbearer and xoauth2: built-in")
2080 #else
2081 _("built-in")
2082 #endif /* HAVE_LIBGSASL */
2083 );
2084 if (smtp_client_supports_authmech("PLAIN"))
2085 {
2086 printf("plain ");
2087 }
2088 if (smtp_client_supports_authmech("SCRAM-SHA-1"))
2089 {
2090 printf("scram-sha-1 ");
2091 }
2092 if (smtp_client_supports_authmech("SCRAM-SHA-256"))
2093 {
2094 printf("scram-sha-256 ");
2095 }
2096 if (smtp_client_supports_authmech("EXTERNAL"))
2097 {
2098 printf("external ");
2099 }
2100 if (smtp_client_supports_authmech("GSSAPI"))
2101 {
2102 printf("gssapi ");
2103 }
2104 if (smtp_client_supports_authmech("CRAM-MD5"))
2105 {
2106 printf("cram-md5 ");
2107 }
2108 if (smtp_client_supports_authmech("DIGEST-MD5"))
2109 {
2110 printf("digest-md5 ");
2111 }
2112 if (smtp_client_supports_authmech("LOGIN"))
2113 {
2114 printf("login ");
2115 }
2116 if (smtp_client_supports_authmech("NTLM"))
2117 {
2118 printf("ntlm ");
2119 }
2120 if (smtp_client_supports_authmech("OAUTHBEARER"))
2121 {
2122 printf("oauthbearer ");
2123 }
2124 if (smtp_client_supports_authmech("XOAUTH2"))
2125 {
2126 printf("xoauth2 ");
2127 }
2128 printf("\n");
2129 /* Internationalized Domain Names support */
2130 printf(_("IDN support: "));
2131 #if defined(HAVE_LIBIDN) \
2132 || (defined(HAVE_GAI_IDN) && (!defined(HAVE_TLS) \
2133 || (defined(HAVE_LIBGNUTLS) && GNUTLS_VERSION_NUMBER >= 0x030400)))
2134 printf(_("enabled"));
2135 #else
2136 printf(_("disabled"));
2137 #endif
2138 printf("\n");
2139 /* Native language support */
2140 printf(_("NLS: "));
2141 #ifdef ENABLE_NLS
2142 printf(_("enabled"));
2143 printf(_(", LOCALEDIR is %s"), LOCALEDIR);
2144 #else
2145 printf(_("disabled"));
2146 #endif
2147 printf("\n");
2148 printf(_("Keyring support: "));
2149 #if !defined HAVE_LIBSECRET && !defined HAVE_MACOSXKEYRING
2150 printf(_("none"));
2151 #else
2152 # ifdef HAVE_LIBSECRET
2153 printf(_("Gnome "));
2154 # endif
2155 # ifdef HAVE_MACOSXKEYRING
2156 printf(_("MacOS "));
2157 # endif
2158 #endif
2159 printf("\n");
2160 sysconfdir = get_sysconfdir();
2161 sysconffile = get_filename(sysconfdir, SYSCONFFILE);
2162 printf(_("System configuration file name: %s\n"), sysconffile);
2163 free(sysconffile);
2164 free(sysconfdir);
2165 userconffile = get_userconfig(USERCONFFILE);
2166 printf(_("User configuration file name: %s\n"), userconffile);
2167 free(userconffile);
2168 printf("\n");
2169 printf(_("Copyright (C) %d Martin Lambers and others.\n"
2170 "This is free software. You may redistribute copies of "
2171 "it under the terms of\n"
2172 "the GNU General Public License "
2173 "<http://www.gnu.org/licenses/gpl.html>.\n"
2174 "There is NO WARRANTY, to the extent permitted by law.\n"), 2021);
2175 }
2176
2177
2178 /*
2179 * msmtp_print_help()
2180 *
2181 * Print --help information
2182 */
2183
msmtp_print_help(void)2184 void msmtp_print_help(void)
2185 {
2186 printf(_("Usage:\n\n"));
2187 printf(_("Sendmail mode (default):\n"
2188 " %s [option...] [--] recipient...\n"
2189 " %s [option...] -t [--] [recipient...]\n"
2190 " Read a mail from standard input and transmit it to an SMTP "
2191 "or LMTP server.\n"), prgname, prgname);
2192 printf(_("Configuration mode:\n"
2193 " %s --configure=mailadress\n"
2194 " Generate and print configuration for address.\n"), prgname);
2195 printf(_("Server information mode:\n"
2196 " %s [option...] --serverinfo\n"
2197 " Print information about a server.\n"), prgname);
2198 printf(_("Remote Message Queue Starting mode:\n"
2199 " %s [option...] --rmqs=host|@domain|#queue\n"
2200 " Send a Remote Message Queue Starting request to a server.\n\n"),
2201 prgname);
2202 printf(_("General options:\n"));
2203 printf(_(" --version print version\n"));
2204 printf(_(" --help print help\n"));
2205 printf(_(" -P, --pretend print configuration info and exit\n"));
2206 printf(_(" -d, --debug print debugging information\n"));
2207 printf(_("Changing the mode of operation:\n"));
2208 printf(_(" --configure=mailaddress generate and print configuration for address\n"));
2209 printf(_(" -S, --serverinfo print information about the server\n"));
2210 printf(_(" --rmqs=host|@domain|#queue send a Remote Message Queue Starting request\n"));
2211 printf(_("Configuration options:\n"));
2212 printf(_(" -C, --file=filename set configuration file\n"));
2213 printf(_(" -a, --account=id use the given account instead of the account\n"
2214 " named \"default\"; its settings may be changed\n"
2215 " with command-line options\n"));
2216 printf(_(" --host=hostname set the server, use only command-line settings;\n"
2217 " do not use any configuration file data\n"));
2218 printf(_(" --port=number set port number\n"));
2219 printf(_(" --source-ip=[IP] set/unset source ip address to bind the socket to\n"));
2220 printf(_(" --proxy-host=[IP|hostname] set/unset proxy\n"));
2221 printf(_(" --proxy-port=[number] set/unset proxy port\n"));
2222 printf(_(" --socket=[socketname] set/unset local socket to connect to\n"));
2223 printf(_(" --timeout=(off|seconds) set/unset network timeout in seconds\n"));
2224 printf(_(" --protocol=(smtp|lmtp) use the given sub protocol\n"));
2225 printf(_(" --domain=string set the argument of EHLO or LHLO command\n"));
2226 printf(_(" --auth[=(on|off|method)] enable/disable authentication and optionally\n"
2227 " choose the method\n"));
2228 printf(_(" --user=[username] set/unset user name for authentication\n"));
2229 printf(_(" --passwordeval=[eval] evaluate password for authentication\n"));
2230 printf(_(" --tls[=(on|off)] enable/disable TLS encryption\n"));
2231 printf(_(" --tls-starttls[=(on|off)] enable/disable STARTTLS for TLS\n"));
2232 printf(_(" --tls-trust-file=[file] set/unset trust file for TLS\n"));
2233 printf(_(" --tls-crl-file=[file] set/unset revocation file for TLS\n"));
2234 printf(_(" --tls-fingerprint=[f] set/unset trusted certificate fingerprint for TLS\n"));
2235 printf(_(" --tls-certcheck[=(on|off)] enable/disable server certificate checks for TLS\n"));
2236 printf(_(" --tls-key-file=[file] set/unset private key file for TLS\n"));
2237 printf(_(" --tls-cert-file=[file] set/unset private cert file for TLS\n"));
2238 printf(_(" --tls-priorities=[prios] set/unset TLS priorities.\n"));
2239 printf(_(" --tls-host-override=[host] set/unset override for TLS host verification.\n"));
2240 printf(_(" --tls-min-dh-prime-bits=[b] set/unset minimum bit size of DH prime\n"));
2241 printf(_("Options specific to sendmail mode:\n"));
2242 printf(_(" --auto-from[=(on|off)] enable/disable automatic envelope-from addresses\n"));
2243 printf(_(" -f, --from=address set envelope from address\n"));
2244 printf(_(" --maildomain=[domain] set the domain for automatic envelope from\n"
2245 " addresses\n"));
2246 printf(_(" -N, --dsn-notify=(off|cond) set/unset DSN conditions\n"));
2247 printf(_(" -R, --dsn-return=(off|ret) set/unset DSN amount\n"));
2248 printf(_(" -X, --logfile=[file] set/unset log file\n"));
2249 printf(_(" --logfile-time-format=[fmt] set/unset log file time format for strftime()\n"));
2250 printf(_(" --syslog[=(on|off|facility)] enable/disable/configure syslog logging\n"));
2251 printf(_(" -t, --read-recipients read additional recipients from the mail\n"));
2252 printf(_(" --read-envelope-from read envelope from address from the mail\n"));
2253 printf(_(" --aliases=[file] set/unset aliases file\n"));
2254 printf(_(" --set-from-header[=(auto|on|off)] set From header handling\n"));
2255 printf(_(" --set-date-header[=(auto|off)] set Date header handling\n"));
2256 printf(_(" --remove-bcc-headers[=(on|off)] enable/disable removal of Bcc headers\n"));
2257 printf(_(" --undisclosed-recipients[=(on|off)] enable/disable replacement of To/Cc/Bcc\n"
2258 " with To: undisclosed-recipients:;\n"));
2259 printf(_(" -- end of options\n"));
2260 printf(_("Accepted but ignored: -A, -B, -bm, -F, -G, -h, -i, -L, -m, -n, -O, -o, -v\n"));
2261 printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
2262 }
2263
2264
2265 /*
2266 * msmtp_cmdline()
2267 *
2268 * Process the command line
2269 */
2270
2271 typedef struct
2272 {
2273 /* the configuration */
2274 int print_version;
2275 int print_help;
2276 int print_conf;
2277 int debug;
2278 int pretend;
2279 int read_recipients;
2280 int read_envelope_from;
2281 /* mode of operation */
2282 int sendmail;
2283 int configure;
2284 char *configure_address;
2285 int serverinfo;
2286 int rmqs;
2287 char *rmqs_argument;
2288 /* account information from the command line */
2289 account_t *cmdline_account;
2290 const char *account_id;
2291 char *user_conffile;
2292 /* additional information */
2293 char *full_name;
2294 /* the list of recipients */
2295 list_t *recipients;
2296 } msmtp_cmdline_conf_t;
2297
2298 /* long options without a corresponding short option */
2299 #define LONGONLYOPT_VERSION (256 + 0)
2300 #define LONGONLYOPT_HELP (256 + 1)
2301 #define LONGONLYOPT_HOST (256 + 2)
2302 #define LONGONLYOPT_PORT (256 + 3)
2303 #define LONGONLYOPT_TIMEOUT (256 + 4)
2304 #define LONGONLYOPT_AUTH (256 + 5)
2305 #define LONGONLYOPT_USER (256 + 6)
2306 #define LONGONLYOPT_PASSWORDEVAL (256 + 7)
2307 #define LONGONLYOPT_TLS (256 + 8)
2308 #define LONGONLYOPT_TLS_STARTTLS (256 + 9)
2309 #define LONGONLYOPT_TLS_TRUST_FILE (256 + 10)
2310 #define LONGONLYOPT_TLS_CRL_FILE (256 + 11)
2311 #define LONGONLYOPT_TLS_FINGERPRINT (256 + 12)
2312 #define LONGONLYOPT_TLS_KEY_FILE (256 + 13)
2313 #define LONGONLYOPT_TLS_CERT_FILE (256 + 14)
2314 #define LONGONLYOPT_TLS_CERTCHECK (256 + 15)
2315 #define LONGONLYOPT_TLS_FORCE_SSLV3 (256 + 16)
2316 #define LONGONLYOPT_TLS_MIN_DH_PRIME_BITS (256 + 17)
2317 #define LONGONLYOPT_TLS_PRIORITIES (256 + 18)
2318 #define LONGONLYOPT_TLS_HOST_OVERRIDE (256 + 19)
2319 #define LONGONLYOPT_PROTOCOL (256 + 20)
2320 #define LONGONLYOPT_DOMAIN (256 + 21)
2321 #define LONGONLYOPT_KEEPBCC (256 + 22)
2322 #define LONGONLYOPT_RMQS (256 + 23)
2323 #define LONGONLYOPT_SYSLOG (256 + 24)
2324 #define LONGONLYOPT_MAILDOMAIN (256 + 25)
2325 #define LONGONLYOPT_AUTO_FROM (256 + 26)
2326 #define LONGONLYOPT_READ_ENVELOPE_FROM (256 + 27)
2327 #define LONGONLYOPT_ALIASES (256 + 28)
2328 #define LONGONLYOPT_PROXY_HOST (256 + 29)
2329 #define LONGONLYOPT_PROXY_PORT (256 + 30)
2330 #define LONGONLYOPT_ADD_MISSING_FROM_HEADER (256 + 31)
2331 #define LONGONLYOPT_ADD_MISSING_DATE_HEADER (256 + 32)
2332 #define LONGONLYOPT_REMOVE_BCC_HEADERS (256 + 33)
2333 #define LONGONLYOPT_UNDISCLOSED_RECIPIENTS (256 + 34)
2334 #define LONGONLYOPT_SOURCE_IP (256 + 35)
2335 #define LONGONLYOPT_LOGFILE_TIME_FORMAT (256 + 36)
2336 #define LONGONLYOPT_CONFIGURE (256 + 37)
2337 #define LONGONLYOPT_SOCKET (256 + 38)
2338 #define LONGONLYOPT_SET_FROM_HEADER (256 + 39)
2339 #define LONGONLYOPT_SET_DATE_HEADER (256 + 40)
2340
msmtp_cmdline(msmtp_cmdline_conf_t * conf,int argc,char * argv[])2341 int msmtp_cmdline(msmtp_cmdline_conf_t *conf, int argc, char *argv[])
2342 {
2343 struct option options[] =
2344 {
2345 { "version", no_argument, 0, LONGONLYOPT_VERSION },
2346 { "help", no_argument, 0, LONGONLYOPT_HELP },
2347 { "configure", required_argument, 0, LONGONLYOPT_CONFIGURE },
2348 { "pretend", no_argument, 0, 'P' },
2349 /* accept an optional argument for sendmail compatibility: */
2350 { "debug", optional_argument, 0, 'd' },
2351 { "serverinfo", no_argument, 0, 'S' },
2352 { "rmqs", required_argument, 0, LONGONLYOPT_RMQS },
2353 { "file", required_argument, 0, 'C' },
2354 { "account", required_argument, 0, 'a' },
2355 { "host", required_argument, 0, LONGONLYOPT_HOST },
2356 { "port", required_argument, 0, LONGONLYOPT_PORT },
2357 { "timeout", required_argument, 0, LONGONLYOPT_TIMEOUT},
2358 /* for compatibility with versions <= 1.4.1: */
2359 { "connect-timeout", required_argument, 0, LONGONLYOPT_TIMEOUT},
2360 { "auto-from", optional_argument, 0, LONGONLYOPT_AUTO_FROM },
2361 { "from", required_argument, 0, 'f' },
2362 { "maildomain", required_argument, 0, LONGONLYOPT_MAILDOMAIN },
2363 { "auth", optional_argument, 0, LONGONLYOPT_AUTH },
2364 { "user", required_argument, 0, LONGONLYOPT_USER },
2365 { "passwordeval", required_argument, 0, LONGONLYOPT_PASSWORDEVAL },
2366 { "tls", optional_argument, 0, LONGONLYOPT_TLS },
2367 { "tls-starttls", optional_argument, 0, LONGONLYOPT_TLS_STARTTLS },
2368 { "tls-trust-file", required_argument, 0, LONGONLYOPT_TLS_TRUST_FILE },
2369 { "tls-crl-file", required_argument, 0, LONGONLYOPT_TLS_CRL_FILE },
2370 { "tls-fingerprint", required_argument, 0,
2371 LONGONLYOPT_TLS_FINGERPRINT },
2372 { "tls-key-file", required_argument, 0, LONGONLYOPT_TLS_KEY_FILE },
2373 { "tls-cert-file", required_argument, 0, LONGONLYOPT_TLS_CERT_FILE },
2374 { "tls-certcheck", optional_argument, 0, LONGONLYOPT_TLS_CERTCHECK },
2375 { "tls-force-sslv3", optional_argument, 0,
2376 LONGONLYOPT_TLS_FORCE_SSLV3 },
2377 { "tls-min-dh-prime-bits", required_argument, 0,
2378 LONGONLYOPT_TLS_MIN_DH_PRIME_BITS },
2379 { "tls-priorities", required_argument, 0, LONGONLYOPT_TLS_PRIORITIES },
2380 { "tls-host-override", required_argument, 0, LONGONLYOPT_TLS_HOST_OVERRIDE },
2381 { "dsn-notify", required_argument, 0, 'N' },
2382 { "dsn-return", required_argument, 0, 'R' },
2383 { "protocol", required_argument, 0, LONGONLYOPT_PROTOCOL },
2384 { "domain", required_argument, 0, LONGONLYOPT_DOMAIN },
2385 { "logfile", required_argument, 0, 'X' },
2386 { "logfile-time-format", required_argument, 0,
2387 LONGONLYOPT_LOGFILE_TIME_FORMAT },
2388 { "syslog", optional_argument, 0, LONGONLYOPT_SYSLOG },
2389 { "aliases", required_argument, 0, LONGONLYOPT_ALIASES },
2390 { "proxy-host", required_argument, 0, LONGONLYOPT_PROXY_HOST },
2391 { "proxy-port", required_argument, 0, LONGONLYOPT_PROXY_PORT },
2392 { "add-missing-from-header", optional_argument, 0,
2393 LONGONLYOPT_ADD_MISSING_FROM_HEADER },
2394 { "add-missing-date-header", optional_argument, 0,
2395 LONGONLYOPT_ADD_MISSING_DATE_HEADER },
2396 { "set-from-header", optional_argument, 0,
2397 LONGONLYOPT_SET_FROM_HEADER },
2398 { "set-date-header", optional_argument, 0,
2399 LONGONLYOPT_SET_DATE_HEADER },
2400 { "remove-bcc-headers", optional_argument, 0,
2401 LONGONLYOPT_REMOVE_BCC_HEADERS },
2402 { "undisclosed-recipients", optional_argument, 0,
2403 LONGONLYOPT_UNDISCLOSED_RECIPIENTS },
2404 { "source-ip", required_argument, 0, LONGONLYOPT_SOURCE_IP },
2405 { "socket", required_argument, 0, LONGONLYOPT_SOCKET },
2406 { "keepbcc", optional_argument, 0, LONGONLYOPT_KEEPBCC },
2407 { "read-recipients", no_argument, 0, 't' },
2408 { "read-envelope-from", no_argument, 0,
2409 LONGONLYOPT_READ_ENVELOPE_FROM },
2410 { 0, 0, 0, 0 }
2411 };
2412 int error_code;
2413 int c;
2414 int i;
2415 int rcptc;
2416 char **rcptv;
2417 FILE *tmpf = NULL;
2418 char *errstr;
2419 #ifdef HAVE_FMEMOPEN
2420 size_t rcptf_size;
2421 void *rcptf_buf = NULL;
2422 #endif
2423
2424 /* the program name */
2425 prgname = get_prgname(argv[0]);
2426 /* the configuration */
2427 conf->print_version = 0;
2428 conf->print_help = 0;
2429 conf->print_conf = 0;
2430 conf->debug = 0;
2431 conf->pretend = 0;
2432 conf->read_recipients = 0;
2433 conf->read_envelope_from = 0;
2434 /* mode of operation */
2435 conf->sendmail = 1;
2436 conf->configure = 0;
2437 conf->configure_address = NULL;
2438 conf->serverinfo = 0;
2439 conf->rmqs = 0;
2440 conf->rmqs_argument = NULL;
2441 /* account information from the command line */
2442 conf->cmdline_account = account_new(NULL, NULL);
2443 conf->account_id = NULL;
2444 conf->user_conffile = NULL;
2445 /* additional information */
2446 conf->full_name = NULL;
2447 /* the recipients */
2448 conf->recipients = NULL;
2449
2450 /* process the command line */
2451 error_code = 0;
2452 for (;;)
2453 {
2454 c = getopt_long(argc, argv, "Pd::SC:a:f:N:R:X:tA:B:b:F:Gh:iL:mnO:o:v",
2455 options, NULL);
2456 if (c == -1)
2457 {
2458 break;
2459 }
2460 switch(c)
2461 {
2462 case LONGONLYOPT_VERSION:
2463 conf->print_version = 1;
2464 conf->sendmail = 0;
2465 conf->serverinfo = 0;
2466 break;
2467
2468 case LONGONLYOPT_HELP:
2469 conf->print_help = 1;
2470 conf->sendmail = 0;
2471 conf->serverinfo = 0;
2472 break;
2473
2474 case LONGONLYOPT_CONFIGURE:
2475 conf->configure = 1;
2476 free(conf->configure_address);
2477 conf->configure_address = xstrdup(optarg);
2478 conf->sendmail = 0;
2479 conf->serverinfo = 0;
2480 break;
2481
2482 case 'P':
2483 conf->print_conf = 1;
2484 conf->pretend = 1;
2485 break;
2486
2487 case 'v':
2488 case 'd':
2489 conf->print_conf = 1;
2490 conf->debug = 1;
2491 /* only care about the optional argument if it's "0.1", which is
2492 * the only argument that's documented for sendmail: it prints
2493 * version information */
2494 if (optarg && strcmp(optarg, "0.1") == 0)
2495 {
2496 conf->print_version = 1;
2497 }
2498 break;
2499
2500 case 'S':
2501 if (conf->rmqs)
2502 {
2503 print_error(_("cannot use both --serverinfo and --rmqs"));
2504 error_code = 1;
2505 }
2506 else
2507 {
2508 conf->serverinfo = 1;
2509 conf->sendmail = 0;
2510 conf->rmqs = 0;
2511 }
2512 break;
2513
2514 case LONGONLYOPT_RMQS:
2515 if (conf->serverinfo)
2516 {
2517 print_error(_("cannot use both --serverinfo and --rmqs"));
2518 error_code = 1;
2519 }
2520 else
2521 {
2522 conf->rmqs = 1;
2523 conf->rmqs_argument = optarg;
2524 conf->sendmail = 0;
2525 conf->serverinfo = 0;
2526 }
2527 break;
2528
2529 case 'C':
2530 free(conf->user_conffile);
2531 conf->user_conffile = xstrdup(optarg);
2532 break;
2533
2534 case 'a':
2535 if (conf->cmdline_account->host)
2536 {
2537 print_error(_("cannot use both --host and --account"));
2538 error_code = 1;
2539 }
2540 else
2541 {
2542 conf->account_id = optarg;
2543 }
2544 break;
2545
2546 case LONGONLYOPT_HOST:
2547 if (conf->account_id)
2548 {
2549 print_error(_("cannot use both --host and --account"));
2550 error_code = 1;
2551 }
2552 else
2553 {
2554 free(conf->cmdline_account->host);
2555 conf->cmdline_account->host = xstrdup(optarg);
2556 conf->cmdline_account->mask |= ACC_HOST;
2557 }
2558 break;
2559
2560 case LONGONLYOPT_PORT:
2561 conf->cmdline_account->port = get_pos_int(optarg);
2562 if (conf->cmdline_account->port < 1
2563 || conf->cmdline_account->port > 65535)
2564 {
2565 print_error(_("invalid argument %s for %s"),
2566 optarg, "--port");
2567 error_code = 1;
2568 }
2569 conf->cmdline_account->mask |= ACC_PORT;
2570 break;
2571
2572 case LONGONLYOPT_TIMEOUT:
2573 if (is_off(optarg))
2574 {
2575 conf->cmdline_account->timeout = 0;
2576 }
2577 else
2578 {
2579 conf->cmdline_account->timeout =
2580 get_pos_int(optarg);
2581 if (conf->cmdline_account->timeout < 1)
2582 {
2583 print_error(_("invalid argument %s for %s"),
2584 optarg, "--timeout");
2585 error_code = 1;
2586 }
2587 }
2588 conf->cmdline_account->mask |= ACC_TIMEOUT;
2589 break;
2590
2591 case LONGONLYOPT_AUTO_FROM:
2592 if (!optarg || is_on(optarg))
2593 {
2594 conf->cmdline_account->auto_from = 1;
2595 }
2596 else if (is_off(optarg))
2597 {
2598 conf->cmdline_account->auto_from = 0;
2599 }
2600 else
2601 {
2602 print_error(_("invalid argument %s for %s"),
2603 optarg, "--auto-from");
2604 error_code = 1;
2605 }
2606 conf->cmdline_account->mask |= ACC_AUTO_FROM;
2607 break;
2608
2609 case 'f':
2610 if (conf->read_envelope_from)
2611 {
2612 print_error(_("cannot use both --from and "
2613 "--read-envelope-from"));
2614 error_code = 1;
2615 }
2616 else
2617 {
2618 free(conf->cmdline_account->from);
2619 /* Accept '<>' to mean an empty from address, to fix Debian
2620 * bug 612679. */
2621 if (strcmp(optarg, "<>") == 0)
2622 {
2623 conf->cmdline_account->from = xstrdup("");
2624 }
2625 else
2626 {
2627 conf->cmdline_account->from = xstrdup(optarg);
2628 }
2629 conf->cmdline_account->mask |= ACC_FROM;
2630 }
2631 break;
2632
2633 case LONGONLYOPT_MAILDOMAIN:
2634 free(conf->cmdline_account->maildomain);
2635 conf->cmdline_account->maildomain =
2636 (*optarg == '\0') ? NULL : xstrdup(optarg);
2637 conf->cmdline_account->mask |= ACC_MAILDOMAIN;
2638 break;
2639
2640 case LONGONLYOPT_AUTH:
2641 free(conf->cmdline_account->auth_mech);
2642 if (!optarg || is_on(optarg))
2643 {
2644 conf->cmdline_account->auth_mech = xstrdup("");
2645 }
2646 else if (is_off(optarg))
2647 {
2648 conf->cmdline_account->auth_mech = NULL;
2649 }
2650 else if (check_auth_arg(optarg) == 0)
2651 {
2652 conf->cmdline_account->auth_mech = xstrdup(optarg);
2653 }
2654 else
2655 {
2656 conf->cmdline_account->auth_mech = NULL;
2657 print_error(_("invalid argument %s for %s"),
2658 optarg, "--auth");
2659 error_code = 1;
2660 }
2661 conf->cmdline_account->mask |= ACC_AUTH_MECH;
2662 break;
2663
2664 case LONGONLYOPT_USER:
2665 free(conf->cmdline_account->username);
2666 conf->cmdline_account->username =
2667 (*optarg == '\0') ? NULL : xstrdup(optarg);
2668 conf->cmdline_account->mask |= ACC_USERNAME;
2669 break;
2670
2671 case LONGONLYOPT_PASSWORDEVAL:
2672 free(conf->cmdline_account->passwordeval);
2673 conf->cmdline_account->passwordeval =
2674 (*optarg == '\0') ? NULL : xstrdup(optarg);
2675 conf->cmdline_account->mask |= ACC_PASSWORDEVAL;
2676 break;
2677
2678 case LONGONLYOPT_TLS:
2679 if (!optarg || is_on(optarg))
2680 {
2681 conf->cmdline_account->tls = 1;
2682 }
2683 else if (is_off(optarg))
2684 {
2685 conf->cmdline_account->tls = 0;
2686 }
2687 else
2688 {
2689 print_error(_("invalid argument %s for %s"),
2690 optarg, "--tls");
2691 error_code = 1;
2692 }
2693 conf->cmdline_account->mask |= ACC_TLS;
2694 break;
2695
2696 case LONGONLYOPT_TLS_STARTTLS:
2697 if (!optarg || is_on(optarg))
2698 {
2699 conf->cmdline_account->tls_nostarttls = 0;
2700 }
2701 else if (is_off(optarg))
2702 {
2703 conf->cmdline_account->tls_nostarttls = 1;
2704 }
2705 else
2706 {
2707 print_error(_("invalid argument %s for %s"),
2708 optarg, "--tls-starttls");
2709 error_code = 1;
2710 }
2711 conf->cmdline_account->mask |= ACC_TLS_NOSTARTTLS;
2712 break;
2713
2714 case LONGONLYOPT_TLS_TRUST_FILE:
2715 free(conf->cmdline_account->tls_trust_file);
2716 if (*optarg)
2717 {
2718 conf->cmdline_account->tls_trust_file =
2719 expand_tilde(optarg);
2720 }
2721 else
2722 {
2723 conf->cmdline_account->tls_trust_file = NULL;
2724 }
2725 conf->cmdline_account->mask |= ACC_TLS_TRUST_FILE;
2726 break;
2727
2728 case LONGONLYOPT_TLS_CRL_FILE:
2729 free(conf->cmdline_account->tls_crl_file);
2730 if (*optarg)
2731 {
2732 conf->cmdline_account->tls_crl_file =
2733 expand_tilde(optarg);
2734 }
2735 else
2736 {
2737 conf->cmdline_account->tls_crl_file = NULL;
2738 }
2739 conf->cmdline_account->mask |= ACC_TLS_CRL_FILE;
2740 break;
2741
2742 case LONGONLYOPT_TLS_FINGERPRINT:
2743 free(conf->cmdline_account->tls_sha256_fingerprint);
2744 conf->cmdline_account->tls_sha256_fingerprint = NULL;
2745 free(conf->cmdline_account->tls_sha1_fingerprint);
2746 conf->cmdline_account->tls_sha1_fingerprint = NULL;
2747 free(conf->cmdline_account->tls_md5_fingerprint);
2748 conf->cmdline_account->tls_md5_fingerprint = NULL;
2749 if (*optarg)
2750 {
2751 if (strlen(optarg) == 2 * 32 + 31)
2752 {
2753 conf->cmdline_account->tls_sha256_fingerprint =
2754 get_fingerprint(optarg, 32);
2755 }
2756 else if (strlen(optarg) == 2 * 20 + 19)
2757 {
2758 conf->cmdline_account->tls_sha1_fingerprint =
2759 get_fingerprint(optarg, 20);
2760 }
2761 else if (strlen(optarg) == 2 * 16 + 15)
2762 {
2763 conf->cmdline_account->tls_md5_fingerprint =
2764 get_fingerprint(optarg, 16);
2765 }
2766 if (!conf->cmdline_account->tls_sha256_fingerprint
2767 && !conf->cmdline_account->tls_sha1_fingerprint
2768 && !conf->cmdline_account->tls_md5_fingerprint)
2769 {
2770 print_error(_("invalid argument %s for %s"),
2771 optarg, "--tls-fingerprint");
2772 error_code = 1;
2773 }
2774 }
2775 conf->cmdline_account->mask |= ACC_TLS_FINGERPRINT;
2776 break;
2777
2778 case LONGONLYOPT_TLS_KEY_FILE:
2779 free(conf->cmdline_account->tls_key_file);
2780 if (*optarg)
2781 {
2782 conf->cmdline_account->tls_key_file = expand_tilde(optarg);
2783 }
2784 else
2785 {
2786 conf->cmdline_account->tls_key_file = NULL;
2787 }
2788 conf->cmdline_account->mask |= ACC_TLS_KEY_FILE;
2789 break;
2790
2791 case LONGONLYOPT_TLS_CERT_FILE:
2792 free(conf->cmdline_account->tls_cert_file);
2793 if (*optarg)
2794 {
2795 conf->cmdline_account->tls_cert_file = expand_tilde(optarg);
2796 }
2797 else
2798 {
2799 conf->cmdline_account->tls_cert_file = NULL;
2800 }
2801 conf->cmdline_account->mask |= ACC_TLS_CERT_FILE;
2802 break;
2803
2804 case LONGONLYOPT_TLS_CERTCHECK:
2805 if (!optarg || is_on(optarg))
2806 {
2807 conf->cmdline_account->tls_nocertcheck = 0;
2808 }
2809 else if (is_off(optarg))
2810 {
2811 conf->cmdline_account->tls_nocertcheck = 1;
2812 }
2813 else
2814 {
2815 print_error(_("invalid argument %s for %s"),
2816 optarg, "--tls-certcheck");
2817 error_code = 1;
2818 }
2819 conf->cmdline_account->mask |= ACC_TLS_NOCERTCHECK;
2820 break;
2821
2822 case LONGONLYOPT_TLS_FORCE_SSLV3:
2823 /* silently ignored for compatibility with versions <= 1.4.32 */
2824 break;
2825
2826 case LONGONLYOPT_TLS_MIN_DH_PRIME_BITS:
2827 if (*optarg == '\0')
2828 {
2829 conf->cmdline_account->tls_min_dh_prime_bits = -1;
2830 }
2831 else
2832 {
2833 conf->cmdline_account->tls_min_dh_prime_bits =
2834 get_pos_int(optarg);
2835 if (conf->cmdline_account->tls_min_dh_prime_bits < 1)
2836 {
2837 print_error(_("invalid argument %s for %s"),
2838 optarg, "--tls-min-dh-prime-bits");
2839 error_code = 1;
2840 }
2841 }
2842 conf->cmdline_account->mask |= ACC_TLS_MIN_DH_PRIME_BITS;
2843 break;
2844
2845 case LONGONLYOPT_TLS_PRIORITIES:
2846 free(conf->cmdline_account->tls_priorities);
2847 if (*optarg)
2848 {
2849 conf->cmdline_account->tls_priorities = xstrdup(optarg);
2850 }
2851 else
2852 {
2853 conf->cmdline_account->tls_priorities = NULL;
2854 }
2855 conf->cmdline_account->mask |= ACC_TLS_PRIORITIES;
2856 break;
2857
2858 case LONGONLYOPT_TLS_HOST_OVERRIDE:
2859 free(conf->cmdline_account->tls_host_override);
2860 if (*optarg)
2861 {
2862 conf->cmdline_account->tls_host_override = xstrdup(optarg);
2863 }
2864 else
2865 {
2866 conf->cmdline_account->tls_host_override = NULL;
2867 }
2868 conf->cmdline_account->mask |= ACC_TLS_HOST_OVERRIDE;
2869 break;
2870
2871 case 'N':
2872 free(conf->cmdline_account->dsn_notify);
2873 if (is_off(optarg))
2874 {
2875 conf->cmdline_account->dsn_notify = NULL;
2876 }
2877 else if (check_dsn_notify_arg(optarg) == 0)
2878 {
2879 conf->cmdline_account->dsn_notify = xstrdup(optarg);
2880 }
2881 else
2882 {
2883 print_error(_("invalid argument %s for %s"),
2884 optarg, "--dsn-notify");
2885 error_code = 1;
2886 }
2887 conf->cmdline_account->mask |= ACC_DSN_NOTIFY;
2888 break;
2889
2890 case 'R':
2891 /* be compatible to both sendmail and the dsn_notify command */
2892 free(conf->cmdline_account->dsn_return);
2893 if (is_off(optarg))
2894 {
2895 conf->cmdline_account->dsn_return = NULL;
2896 }
2897 else if (strcmp(optarg, "hdrs") == 0
2898 || strcmp(optarg, "headers") == 0)
2899 {
2900 conf->cmdline_account->dsn_return = xstrdup("HDRS");
2901 }
2902 else if (strcmp(optarg, "full") == 0)
2903 {
2904 conf->cmdline_account->dsn_return = xstrdup("FULL");
2905 }
2906 else
2907 {
2908 print_error(_("invalid argument %s for %s"),
2909 optarg, "--dsn-return");
2910 error_code = 1;
2911 }
2912 conf->cmdline_account->mask |= ACC_DSN_RETURN;
2913 break;
2914
2915 case LONGONLYOPT_PROTOCOL:
2916 conf->cmdline_account->mask |= ACC_PROTOCOL;
2917 if (strcmp(optarg, "smtp") == 0)
2918 {
2919 conf->cmdline_account->protocol = SMTP_PROTO_SMTP;
2920 }
2921 else if (strcmp(optarg, "lmtp") == 0)
2922 {
2923 conf->cmdline_account->protocol = SMTP_PROTO_LMTP;
2924 }
2925 else
2926 {
2927 print_error(_("invalid argument %s for %s"),
2928 optarg, "--protocol");
2929 error_code = 1;
2930 }
2931 break;
2932
2933 case LONGONLYOPT_DOMAIN:
2934 free(conf->cmdline_account->domain);
2935 conf->cmdline_account->domain = xstrdup(optarg);
2936 conf->cmdline_account->mask |= ACC_DOMAIN;
2937 break;
2938
2939 case 'X':
2940 free(conf->cmdline_account->logfile);
2941 if (*optarg)
2942 {
2943 conf->cmdline_account->logfile = expand_tilde(optarg);
2944 }
2945 else
2946 {
2947 conf->cmdline_account->logfile = NULL;
2948 }
2949 conf->cmdline_account->mask |= ACC_LOGFILE;
2950 break;
2951
2952 case LONGONLYOPT_LOGFILE_TIME_FORMAT:
2953 free(conf->cmdline_account->logfile_time_format);
2954 if (*optarg)
2955 {
2956 conf->cmdline_account->logfile_time_format = xstrdup(optarg);
2957 }
2958 else
2959 {
2960 conf->cmdline_account->logfile_time_format = NULL;
2961 }
2962 conf->cmdline_account->mask |= ACC_LOGFILE_TIME_FORMAT;
2963 break;
2964
2965 case LONGONLYOPT_SYSLOG:
2966 free(conf->cmdline_account->syslog);
2967 if (!optarg || is_on(optarg))
2968 {
2969 conf->cmdline_account->syslog =
2970 get_default_syslog_facility();
2971 }
2972 else if (is_off(optarg))
2973 {
2974 conf->cmdline_account->syslog = NULL;
2975 }
2976 else
2977 {
2978 if (check_syslog_arg(optarg) != 0)
2979 {
2980 print_error(_("invalid argument %s for %s"),
2981 optarg, "--syslog");
2982 error_code = 1;
2983 }
2984 else
2985 {
2986 conf->cmdline_account->syslog = xstrdup(optarg);
2987 }
2988 }
2989 conf->cmdline_account->mask |= ACC_SYSLOG;
2990 break;
2991
2992 case LONGONLYOPT_ALIASES:
2993 free(conf->cmdline_account->aliases);
2994 if (*optarg)
2995 {
2996 conf->cmdline_account->aliases = expand_tilde(optarg);
2997 }
2998 else
2999 {
3000 conf->cmdline_account->aliases = NULL;
3001 }
3002 conf->cmdline_account->mask |= ACC_ALIASES;
3003 break;
3004
3005 case LONGONLYOPT_PROXY_HOST:
3006 free(conf->cmdline_account->proxy_host);
3007 if (*optarg)
3008 {
3009 conf->cmdline_account->proxy_host = xstrdup(optarg);
3010 }
3011 else
3012 {
3013 conf->cmdline_account->proxy_host = NULL;
3014 }
3015 conf->cmdline_account->mask |= ACC_PROXY_HOST;
3016 break;
3017
3018 case LONGONLYOPT_PROXY_PORT:
3019 if (*optarg)
3020 {
3021 conf->cmdline_account->proxy_port = get_pos_int(optarg);
3022 if (conf->cmdline_account->proxy_port < 1
3023 || conf->cmdline_account->proxy_port > 65535)
3024 {
3025 print_error(_("invalid argument %s for %s"),
3026 optarg, "--proxy-port");
3027 error_code = 1;
3028 }
3029 }
3030 else
3031 {
3032 conf->cmdline_account->proxy_port = 0;
3033 }
3034 conf->cmdline_account->mask |= ACC_PROXY_PORT;
3035 break;
3036
3037 case LONGONLYOPT_SET_FROM_HEADER:
3038 if (!optarg || is_auto(optarg))
3039 {
3040 conf->cmdline_account->set_from_header = 2;
3041 }
3042 else if (is_on(optarg))
3043 {
3044 conf->cmdline_account->set_from_header = 1;
3045 }
3046 else if (is_off(optarg))
3047 {
3048 conf->cmdline_account->set_from_header = 0;
3049 }
3050 else
3051 {
3052 print_error(_("invalid argument %s for %s"),
3053 optarg, "--set-from-header");
3054 error_code = 1;
3055 }
3056 conf->cmdline_account->mask |= ACC_SET_FROM_HEADER;
3057 break;
3058
3059 case LONGONLYOPT_SET_DATE_HEADER:
3060 if (!optarg || is_auto(optarg))
3061 {
3062 conf->cmdline_account->set_date_header = 2;
3063 }
3064 else if (is_off(optarg))
3065 {
3066 conf->cmdline_account->set_date_header = 0;
3067 }
3068 else
3069 {
3070 print_error(_("invalid argument %s for %s"),
3071 optarg, "--set-date-header");
3072 error_code = 1;
3073 }
3074 conf->cmdline_account->mask |= ACC_SET_DATE_HEADER;
3075 break;
3076
3077 case LONGONLYOPT_ADD_MISSING_FROM_HEADER:
3078 /* compatibility with < 1.8.8 */
3079 if (!optarg || is_on(optarg))
3080 {
3081 conf->cmdline_account->set_from_header = 2;
3082 }
3083 else if (is_off(optarg))
3084 {
3085 conf->cmdline_account->set_from_header = 0;
3086 }
3087 else
3088 {
3089 print_error(_("invalid argument %s for %s"),
3090 optarg, "--add-missing-from-header");
3091 error_code = 1;
3092 }
3093 conf->cmdline_account->mask |= ACC_SET_FROM_HEADER;
3094 break;
3095
3096 case LONGONLYOPT_ADD_MISSING_DATE_HEADER:
3097 /* compatibility with < 1.8.8 */
3098 if (!optarg || is_on(optarg))
3099 {
3100 conf->cmdline_account->set_date_header = 2;
3101 }
3102 else if (is_off(optarg))
3103 {
3104 conf->cmdline_account->set_date_header = 0;
3105 }
3106 else
3107 {
3108 print_error(_("invalid argument %s for %s"),
3109 optarg, "--add-missing-date-header");
3110 error_code = 1;
3111 }
3112 conf->cmdline_account->mask |= ACC_SET_DATE_HEADER;
3113 break;
3114
3115 case LONGONLYOPT_REMOVE_BCC_HEADERS:
3116 if (!optarg || is_on(optarg))
3117 {
3118 conf->cmdline_account->remove_bcc_headers = 1;
3119 }
3120 else if (is_off(optarg))
3121 {
3122 conf->cmdline_account->remove_bcc_headers = 0;
3123 }
3124 else
3125 {
3126 print_error(_("invalid argument %s for %s"),
3127 optarg, "--remove-bcc-headers");
3128 error_code = 1;
3129 }
3130 conf->cmdline_account->mask |= ACC_REMOVE_BCC_HEADERS;
3131 break;
3132
3133 case LONGONLYOPT_UNDISCLOSED_RECIPIENTS:
3134 if (!optarg || is_on(optarg))
3135 {
3136 conf->cmdline_account->undisclosed_recipients = 1;
3137 }
3138 else if (is_off(optarg))
3139 {
3140 conf->cmdline_account->undisclosed_recipients = 0;
3141 }
3142 else
3143 {
3144 print_error(_("invalid argument %s for %s"),
3145 optarg, "--undisclosed-recipients");
3146 error_code = 1;
3147 }
3148 conf->cmdline_account->mask |= ACC_UNDISCLOSED_RECIPIENTS;
3149 break;
3150
3151 case LONGONLYOPT_SOURCE_IP:
3152 free(conf->cmdline_account->source_ip);
3153 if (*optarg)
3154 {
3155 conf->cmdline_account->source_ip = xstrdup(optarg);
3156 }
3157 else
3158 {
3159 conf->cmdline_account->source_ip = NULL;
3160 }
3161 conf->cmdline_account->mask |= ACC_SOURCE_IP;
3162 break;
3163
3164 case LONGONLYOPT_SOCKET:
3165 free(conf->cmdline_account->socketname);
3166 if (*optarg)
3167 {
3168 conf->cmdline_account->socketname = xstrdup(optarg);
3169 }
3170 else
3171 {
3172 conf->cmdline_account->socketname = NULL;
3173 }
3174 conf->cmdline_account->mask |= ACC_SOCKET;
3175 break;
3176
3177 case 't':
3178 conf->read_recipients = 1;
3179 break;
3180
3181 case LONGONLYOPT_READ_ENVELOPE_FROM:
3182 if (conf->cmdline_account->from)
3183 {
3184 print_error(_("cannot use both --from and "
3185 "--read-envelope-from"));
3186 error_code = 1;
3187 }
3188 else
3189 {
3190 conf->read_envelope_from = 1;
3191 conf->cmdline_account->mask |= ACC_FROM;
3192 }
3193 break;
3194
3195 case 'b':
3196 /* only m makes sense */
3197 if (strcmp(optarg, "m") != 0)
3198 {
3199 print_error(_("unsupported operation mode b%s"), optarg);
3200 error_code = 1;
3201 }
3202 break;
3203
3204 case 'F':
3205 free(conf->full_name);
3206 conf->full_name = xstrdup(optarg);
3207 break;
3208
3209 case LONGONLYOPT_KEEPBCC:
3210 /* compatibility with 1.4.x */
3211 if (!optarg || is_on(optarg))
3212 {
3213 conf->cmdline_account->remove_bcc_headers = 0;
3214 }
3215 else if (is_off(optarg))
3216 {
3217 conf->cmdline_account->remove_bcc_headers = 1;
3218 }
3219 else
3220 {
3221 print_error(_("invalid argument %s for %s"),
3222 optarg, "--keepbcc");
3223 error_code = 1;
3224 }
3225 conf->cmdline_account->mask |= ACC_REMOVE_BCC_HEADERS;
3226 break;
3227
3228 case 'A':
3229 case 'B':
3230 case 'G':
3231 case 'h':
3232 case 'i':
3233 case 'L':
3234 case 'm':
3235 case 'n':
3236 case 'O':
3237 case 'o':
3238 break;
3239
3240 /* unknown option */
3241 default:
3242 error_code = 1;
3243 break;
3244 }
3245 if (error_code)
3246 {
3247 break;
3248 }
3249 }
3250 if (error_code)
3251 {
3252 return EX_USAGE;
3253 }
3254
3255 /* The list of recipients.
3256 * Write these to a temporary mail header so that msmtp_read_headers() can
3257 * parse them. */
3258 conf->recipients = list_new();
3259 rcptc = argc - optind;
3260 rcptv = &(argv[optind]);
3261 if (rcptc > 0)
3262 {
3263 #ifdef HAVE_FMEMOPEN
3264 rcptf_size = 2; /* terminating "\n\0" */
3265 for (i = 0; i < rcptc; i++)
3266 {
3267 rcptf_size += 4 + strlen(rcptv[i]) + 1;
3268 }
3269 rcptf_buf = xmalloc(rcptf_size);
3270 tmpf = fmemopen(rcptf_buf, rcptf_size, "w+");
3271 #else
3272 tmpf = tmpfile();
3273 #endif
3274 if (!tmpf)
3275 {
3276 print_error(_("cannot create temporary file: %s"),
3277 sanitize_string(strerror(errno)));
3278 error_code = EX_IOERR;
3279 goto error_exit;
3280 }
3281 for (i = 0; i < rcptc && error_code != EOF; i++)
3282 {
3283 error_code = fputs("To: ", tmpf);
3284 if (error_code != EOF)
3285 {
3286 error_code = fputs(rcptv[i], tmpf);
3287 }
3288 if (error_code != EOF)
3289 {
3290 error_code = fputc('\n', tmpf);
3291 }
3292 }
3293 if (error_code != EOF)
3294 {
3295 error_code = fputc('\n', tmpf);
3296 }
3297 if (error_code == EOF)
3298 {
3299 print_error(_("cannot write mail headers to temporary "
3300 "file: output error"));
3301 error_code = EX_IOERR;
3302 goto error_exit;
3303 }
3304 if (fseeko(tmpf, 0, SEEK_SET) != 0)
3305 {
3306 print_error(_("cannot rewind temporary file: %s"),
3307 sanitize_string(strerror(errno)));
3308 error_code = EX_IOERR;
3309 goto error_exit;
3310 }
3311 if ((error_code = msmtp_read_headers(tmpf, NULL,
3312 list_last(conf->recipients), NULL, NULL, &errstr))
3313 != EX_OK)
3314 {
3315 print_error("%s", sanitize_string(errstr));
3316 goto error_exit;
3317 }
3318 }
3319 error_code = EX_OK;
3320
3321 error_exit:
3322 if (tmpf)
3323 {
3324 fclose(tmpf);
3325 }
3326 #ifdef HAVE_FMEMOPEN
3327 free(rcptf_buf);
3328 #endif
3329 return error_code;
3330 }
3331
3332
3333 /*
3334 * msmtp_get_conffile_accounts()
3335 * Read the system and user configuration files and merge the data
3336 */
3337
msmtp_get_conffile_accounts(list_t ** account_list,int print_info,const char * user_conffile,char ** loaded_system_conffile,char ** loaded_user_conffile)3338 int msmtp_get_conffile_accounts(list_t **account_list,
3339 int print_info, const char *user_conffile,
3340 char **loaded_system_conffile, char **loaded_user_conffile)
3341 {
3342 char *errstr;
3343 char *system_confdir;
3344 char *system_conffile;
3345 char *real_user_conffile;
3346 list_t *system_account_list;
3347 list_t *user_account_list;
3348 list_t *lps;
3349 list_t *lpu;
3350 int securitycheck;
3351 int e;
3352
3353
3354 *loaded_system_conffile = NULL;
3355 *loaded_user_conffile = NULL;
3356
3357 /* Read the system configuration file.
3358 * It is not an error if system_conffile cannot be opened,
3359 * but it is an error is the file content is invalid */
3360 system_confdir = get_sysconfdir();
3361 system_conffile = get_filename(system_confdir, SYSCONFFILE);
3362 free(system_confdir);
3363 securitycheck = 0;
3364 if ((e = get_conf(system_conffile, securitycheck,
3365 &system_account_list, &errstr)) != CONF_EOK)
3366 {
3367 if (e == CONF_ECANTOPEN)
3368 {
3369 if (print_info)
3370 {
3371 printf(_("ignoring system configuration file %s: %s\n"),
3372 system_conffile, sanitize_string(errstr));
3373 }
3374 }
3375 else
3376 {
3377 print_error("%s: %s", system_conffile,
3378 sanitize_string(errstr));
3379 return (e == CONF_EIO) ? EX_IOERR : EX_CONFIG;
3380 }
3381 }
3382 else
3383 {
3384 if (print_info)
3385 {
3386 printf(_("loaded system configuration file %s\n"), system_conffile);
3387 }
3388 *loaded_system_conffile = xstrdup(system_conffile);
3389 }
3390 free(system_conffile);
3391
3392 /* Read the user configuration file.
3393 * It is not an error if user_conffile cannot be opened (unless it was
3394 * chosen with -C/--file), but it is an error is the file content is
3395 * invalid */
3396 if (user_conffile)
3397 {
3398 real_user_conffile = xstrdup(user_conffile);
3399 }
3400 else
3401 {
3402 real_user_conffile = get_userconfig(USERCONFFILE);
3403 }
3404 #ifdef W32_NATIVE
3405 securitycheck = 1;
3406 #else
3407 securitycheck = (geteuid() != 0);
3408 #endif
3409 if ((e = get_conf(real_user_conffile, securitycheck,
3410 &user_account_list, &errstr)) != CONF_EOK)
3411 {
3412 if (e == CONF_ECANTOPEN)
3413 {
3414 /* If the configuration file was set with -C/--file, it is an
3415 * error if we cannot open it */
3416 if (user_conffile)
3417 {
3418 print_error("%s: %s", real_user_conffile,
3419 sanitize_string(errstr));
3420 return EX_IOERR;
3421 }
3422 /* otherwise, we can ignore it */
3423 if (print_info)
3424 {
3425 printf(_("ignoring user configuration file %s: %s\n"),
3426 real_user_conffile, sanitize_string(errstr));
3427 }
3428 }
3429 else
3430 {
3431 print_error("%s: %s", real_user_conffile,
3432 sanitize_string(errstr));
3433 return (e == CONF_EIO) ? EX_IOERR : EX_CONFIG;
3434 }
3435 }
3436 else
3437 {
3438 if (print_info)
3439 {
3440 printf(_("loaded user configuration file %s\n"),
3441 real_user_conffile);
3442 }
3443 *loaded_user_conffile = xstrdup(real_user_conffile);
3444 }
3445 free(real_user_conffile);
3446
3447 /* Merge system_account_list and user_account_list into account_list.
3448 * If an account exist in both files, only the one from the user conffile is
3449 * kept. It is important that the order of accounts is maintained, so that
3450 * --from can choose the *first* account with a matching envelope from
3451 * address. */
3452 if (*loaded_system_conffile && *loaded_user_conffile)
3453 {
3454 lpu = user_account_list;
3455 lps = system_account_list;
3456 while (!list_is_empty(lps))
3457 {
3458 lps = lps->next;
3459 if (!find_account(user_account_list, ((account_t *)lps->data)->id))
3460 {
3461 list_insert(lpu, account_copy(lps->data));
3462 lpu = lpu->next;
3463 }
3464 }
3465 *account_list = user_account_list;
3466 list_xfree(system_account_list, account_free);
3467 }
3468 else if (*loaded_system_conffile)
3469 {
3470 *account_list = system_account_list;
3471 }
3472 else if (*loaded_user_conffile)
3473 {
3474 *account_list = user_account_list;
3475 }
3476 else
3477 {
3478 *account_list = list_new();
3479 }
3480
3481 return EX_OK;
3482 }
3483
3484
3485 /*
3486 * msmtp_print_conf
3487 *
3488 * Print configuration information, for example for --pretend
3489 */
3490
msmtp_print_conf(msmtp_cmdline_conf_t conf,account_t * account)3491 void msmtp_print_conf(msmtp_cmdline_conf_t conf, account_t *account)
3492 {
3493 char fingerprint_string[2 * 32 + 31 + 1];
3494
3495 if (account->id && account->conffile)
3496 {
3497 printf(_("using account %s from %s\n"),
3498 account->id, account->conffile);
3499 }
3500 printf("host = %s\n", account->host);
3501 printf("port = %d\n", account->port);
3502 printf("source ip = %s\n",
3503 account->source_ip ? account->source_ip : _("(not set)"));
3504 printf("proxy host = %s\n",
3505 account->proxy_host ? account->proxy_host : _("(not set)"));
3506 printf("proxy port = %d\n", account->proxy_port);
3507 printf("socket = %s\n",
3508 account->socketname ? account->socketname : _("(not set)"));
3509 printf("timeout = ");
3510 if (account->timeout <= 0)
3511 {
3512 printf(_("off\n"));
3513 }
3514 else
3515 {
3516 if (account->timeout > 1)
3517 {
3518 printf(_("%d seconds\n"), account->timeout);
3519 }
3520 else
3521 {
3522 printf(_("1 second\n"));
3523 }
3524 }
3525 printf("protocol = %s\n",
3526 account->protocol == SMTP_PROTO_SMTP ? "smtp" : "lmtp");
3527 printf("domain = %s\n", account->domain);
3528 printf("auth = ");
3529 if (!account->auth_mech)
3530 {
3531 printf(_("none\n"));
3532 }
3533 else if (account->auth_mech[0] == '\0')
3534 {
3535 printf(_("choose\n"));
3536 }
3537 else
3538 {
3539 printf("%s\n", account->auth_mech);
3540 }
3541 printf("user = %s\n",
3542 account->username ? account->username : _("(not set)"));
3543 printf("password = %s\n", account->password ? "*" : _("(not set)"));
3544 printf("passwordeval = %s\n",
3545 account->passwordeval ? account->passwordeval : _("(not set)"));
3546 printf("ntlmdomain = %s\n",
3547 account->ntlmdomain ? account->ntlmdomain : _("(not set)"));
3548 printf("tls = %s\n", account->tls ? _("on") : _("off"));
3549 printf("tls_starttls = %s\n", account->tls_nostarttls ? _("off") : _("on"));
3550 printf("tls_trust_file = %s\n",
3551 account->tls_trust_file ? account->tls_trust_file : _("(not set)"));
3552 printf("tls_crl_file = %s\n",
3553 account->tls_crl_file ? account->tls_crl_file : _("(not set)"));
3554 if (account->tls_sha256_fingerprint)
3555 {
3556 print_fingerprint(fingerprint_string,
3557 account->tls_sha256_fingerprint, 32);
3558 }
3559 else if (account->tls_sha1_fingerprint)
3560 {
3561 print_fingerprint(fingerprint_string,
3562 account->tls_sha1_fingerprint, 20);
3563 }
3564 else if (account->tls_md5_fingerprint)
3565 {
3566 print_fingerprint(fingerprint_string,
3567 account->tls_md5_fingerprint, 16);
3568 }
3569 printf("tls_fingerprint = %s\n",
3570 account->tls_sha256_fingerprint
3571 || account->tls_sha1_fingerprint || account->tls_md5_fingerprint
3572 ? fingerprint_string : _("(not set)"));
3573 printf("tls_key_file = %s\n",
3574 account->tls_key_file ? account->tls_key_file : _("(not set)"));
3575 printf("tls_cert_file = %s\n",
3576 account->tls_cert_file ? account->tls_cert_file : _("(not set)"));
3577 printf("tls_certcheck = %s\n",
3578 account->tls_nocertcheck ? _("off") : _("on"));
3579 printf("tls_min_dh_prime_bits = ");
3580 if (account->tls_min_dh_prime_bits >= 0)
3581 {
3582 printf("%d\n", account->tls_min_dh_prime_bits);
3583 }
3584 else
3585 {
3586 printf("%s\n", _("(not set)"));
3587 }
3588 printf("tls_priorities = %s\n",
3589 account->tls_priorities ? account->tls_priorities : _("(not set)"));
3590 printf("tls_host_override = %s\n",
3591 account->tls_host_override ? account->tls_host_override : _("(not set)"));
3592 if (conf.sendmail)
3593 {
3594 printf("auto_from = %s\n", account->auto_from ? _("on") : _("off"));
3595 printf("maildomain = %s\n",
3596 account->maildomain ? account->maildomain : _("(not set)"));
3597 printf("from = %s\n",
3598 account->from ? account->from : conf.read_envelope_from
3599 ? _("(read from mail)") : _("(not set)"));
3600 printf("set_from_header = %s\n",
3601 account->set_from_header == 2 ? _("auto")
3602 : account->set_from_header == 1 ? _("on") : _("off"));
3603 printf("set_date_header = %s\n",
3604 account->set_date_header == 2 ? _("auto")
3605 : _("off"));
3606 printf("remove_bcc_headers = %s\n",
3607 account->remove_bcc_headers ? _("on") : _("off"));
3608 printf("undisclosed_recipients = %s\n",
3609 account->undisclosed_recipients ? _("on") : _("off"));
3610 printf("dsn_notify = %s\n",
3611 account->dsn_notify ? account->dsn_notify : _("(not set)"));
3612 printf("dsn_return = %s\n",
3613 account->dsn_return ? account->dsn_return : _("(not set)"));
3614 printf("logfile = %s\n",
3615 account->logfile ? account->logfile : _("(not set)"));
3616 printf("logfile_time_format = %s\n",
3617 account->logfile_time_format ? account->logfile_time_format
3618 : _("(not set)"));
3619 printf("syslog = %s\n",
3620 account->syslog ? account->syslog : _("(not set)"));
3621 printf("aliases = %s\n",
3622 account->aliases ? account->aliases : _("(not set)"));
3623 if (conf.read_recipients)
3624 {
3625 printf(_("reading recipients from the command line "
3626 "and the mail\n"));
3627 }
3628 else
3629 {
3630 printf(_("reading recipients from the command line\n"));
3631 }
3632 }
3633 if (conf.rmqs)
3634 {
3635 printf("RMQS argument = %s\n", conf.rmqs_argument);
3636 }
3637 }
3638
3639
3640 /*
3641 * The main function.
3642 * It returns values from sysexits.h (like sendmail does).
3643 */
3644
main(int argc,char * argv[])3645 int main(int argc, char *argv[])
3646 {
3647 msmtp_cmdline_conf_t conf;
3648 /* account information from the configuration file(s) */
3649 list_t *account_list = NULL;
3650 char *loaded_system_conffile = NULL;
3651 char *loaded_user_conffile = NULL;
3652 /* environment variables */
3653 int allow_fallback_to_env;
3654 char *env_email;
3655 char *env_smtpserver;
3656 /* the account data that will be used */
3657 account_t *account = NULL;
3658 /* error handling */
3659 char *errstr;
3660 list_t *errmsg;
3661 int error_code;
3662 int e;
3663 list_t *lp;
3664 /* misc */
3665 #ifdef HAVE_TLS
3666 int tls_lib_initialized = 0;
3667 #endif
3668 int net_lib_initialized = 0;
3669 /* the size of a sent mail */
3670 long mailsize = 0;
3671 /* special LMTP error info */
3672 list_t *lmtp_errstrs;
3673 list_t *lmtp_error_msgs;
3674 list_t *lp_lmtp_errstrs;
3675 list_t *lp_lmtp_error_msgs;
3676 /* log information */
3677 char *log_info;
3678 /* needed to read the headers and extract addresses */
3679 FILE *header_tmpfile = NULL;
3680 FILE *prepend_header_tmpfile = NULL;
3681 int have_from_header = 0;
3682 int have_date_header = 0;
3683
3684
3685 /* Avoid the side effects of text mode interpretations on DOS systems. */
3686 #if defined W32_NATIVE
3687 setmode(fileno(stdin), O_BINARY);
3688 _fmode = O_BINARY;
3689 #endif
3690
3691 errstr = NULL;
3692 errmsg = NULL;
3693
3694 /* internationalization with gettext */
3695 #ifdef ENABLE_NLS
3696 setlocale(LC_ALL, "");
3697 bindtextdomain(PACKAGE, LOCALEDIR);
3698 textdomain(PACKAGE);
3699 #endif
3700
3701 /* Avoid receiving SIGPIPE when writing to sockets that were closed by the
3702 * remote end; we handle write errors where they occur. */
3703 #ifdef HAVE_SIGNAL
3704 #ifdef SIGPIPE
3705 signal(SIGPIPE, SIG_IGN);
3706 #endif
3707 #endif
3708
3709 /* the command line */
3710 if ((error_code = msmtp_cmdline(&conf, argc, argv)) != EX_OK)
3711 {
3712 goto exit;
3713 }
3714
3715 if (conf.print_version)
3716 {
3717 msmtp_print_version();
3718 }
3719 if (conf.print_help)
3720 {
3721 msmtp_print_help();
3722 }
3723
3724 if (conf.configure)
3725 {
3726 char *userconfigfile = conf.user_conffile ? xstrdup(conf.user_conffile) : get_userconfig(USERCONFFILE);
3727 error_code = msmtp_configure(conf.configure_address, userconfigfile);
3728 free(userconfigfile);
3729 free(conf.configure_address);
3730 goto exit;
3731 }
3732
3733 if (conf.print_help || conf.print_version
3734 || (!conf.sendmail && !conf.serverinfo && !conf.rmqs
3735 && !conf.print_conf))
3736 {
3737 error_code = EX_OK;
3738 goto exit;
3739 }
3740
3741 if ((conf.serverinfo || conf.rmqs) && !list_is_empty(conf.recipients))
3742 {
3743 print_error(_("too many arguments"));
3744 error_code = EX_USAGE;
3745 goto exit;
3746 }
3747 /* Read recipients and/or the envelope from address from the mail. */
3748 if (conf.sendmail)
3749 {
3750 char *envelope_from = NULL;
3751 if (!(header_tmpfile = tmpfile()))
3752 {
3753 print_error(_("cannot create temporary file: %s"),
3754 sanitize_string(strerror(errno)));
3755 error_code = EX_IOERR;
3756 goto exit;
3757 }
3758 if ((error_code = msmtp_read_headers(stdin, header_tmpfile,
3759 conf.read_recipients
3760 ? list_last(conf.recipients) : NULL,
3761 &envelope_from, &have_date_header, &errstr)) != EX_OK)
3762 {
3763 print_error("%s", sanitize_string(errstr));
3764 goto exit;
3765 }
3766 have_from_header = (envelope_from ? 1 : 0);
3767 if (conf.read_envelope_from)
3768 {
3769 conf.cmdline_account->from = envelope_from;
3770 if (conf.pretend || conf.debug)
3771 {
3772 printf(_("envelope from address extracted from mail: %s\n"),
3773 conf.cmdline_account->from);
3774 }
3775 }
3776 if (fseeko(header_tmpfile, 0, SEEK_SET) != 0)
3777 {
3778 print_error(_("cannot rewind temporary file: %s"),
3779 sanitize_string(strerror(errno)));
3780 error_code = EX_IOERR;
3781 goto exit;
3782 }
3783 }
3784 /* check the list of recipients */
3785 if (conf.sendmail && list_is_empty(conf.recipients) && !conf.pretend)
3786 {
3787 print_error(_("no recipients found"));
3788 error_code = EX_USAGE;
3789 goto exit;
3790 }
3791
3792 /* get the account to be used, either from the conffile(s) or from the
3793 * command line */
3794 allow_fallback_to_env = 0;
3795 if (!conf.cmdline_account->host)
3796 {
3797 if ((error_code = msmtp_get_conffile_accounts(&account_list,
3798 (conf.pretend || conf.debug), conf.user_conffile,
3799 &loaded_system_conffile, &loaded_user_conffile))
3800 != EX_OK)
3801 {
3802 goto exit;
3803 }
3804 if (!conf.account_id)
3805 {
3806 if (conf.cmdline_account->from)
3807 {
3808 /* No account was chosen, but the envelope from address is
3809 * given. Choose the right account with this address.
3810 */
3811 account = account_copy(find_account_by_envelope_from(
3812 account_list, conf.cmdline_account->from));
3813 if (account)
3814 {
3815 if (conf.pretend || conf.debug)
3816 {
3817 printf(_("account chosen by "
3818 "envelope from address %s: %s\n"),
3819 conf.cmdline_account->from, account->id);
3820 }
3821 }
3822 }
3823 if (!account)
3824 {
3825 /* No envelope from address or no matching account.
3826 * Use default if available, but allow fallback to environment
3827 * variables. */
3828 conf.account_id = "default";
3829 if (conf.pretend || conf.debug)
3830 {
3831 printf(_("falling back to default account\n"));
3832 }
3833 allow_fallback_to_env = 1;
3834 }
3835 }
3836 if (!account && !(account =
3837 account_copy(find_account(account_list, conf.account_id))))
3838 {
3839 env_email = getenv("EMAIL");
3840 env_smtpserver = getenv("SMTPSERVER");
3841 if (allow_fallback_to_env
3842 && (!conf.sendmail
3843 || conf.cmdline_account->from || env_email)
3844 && env_smtpserver)
3845 {
3846 if (conf.sendmail && !conf.cmdline_account->from)
3847 {
3848 conf.cmdline_account->from = xstrdup(env_email);
3849 }
3850 conf.cmdline_account->host = xstrdup(env_smtpserver);
3851 account = account_copy(conf.cmdline_account);
3852 if (conf.pretend || conf.debug)
3853 {
3854 printf(_("using environment variables "
3855 "EMAIL and SMTPSERVER\n"));
3856 }
3857 }
3858 else
3859 {
3860 if (loaded_system_conffile && loaded_user_conffile)
3861 {
3862 print_error(_("account %s not found in %s and %s"),
3863 conf.account_id, loaded_system_conffile,
3864 loaded_user_conffile);
3865 }
3866 else if (loaded_system_conffile)
3867 {
3868 print_error(_("account %s not found in %s"),
3869 conf.account_id, loaded_system_conffile);
3870 }
3871 else if (loaded_user_conffile)
3872 {
3873 print_error(_("account %s not found in %s"),
3874 conf.account_id, loaded_user_conffile);
3875 }
3876 else /* no conffile was read */
3877 {
3878 print_error(_("account %s not found: "
3879 "no configuration file available"),
3880 conf.account_id);
3881 }
3882 error_code = EX_CONFIG;
3883 goto exit;
3884 }
3885 }
3886 override_account(account, conf.cmdline_account);
3887 }
3888 else
3889 {
3890 account = account_copy(conf.cmdline_account);
3891 if (conf.pretend || conf.debug)
3892 {
3893 printf(_("using account specified on command line\n"));
3894 }
3895 }
3896
3897 /* OK, we're using the settings in 'account'. Complete them and check
3898 * them. */
3899 if (account->auth_mech && !account->password && account->passwordeval)
3900 {
3901 if (password_eval(account->passwordeval,
3902 &account->password, &errstr) != 0)
3903 {
3904 print_error("%s", sanitize_string(errstr));
3905 error_code = EX_CONFIG;
3906 goto exit;
3907 }
3908 }
3909 if (account->port == 0)
3910 {
3911 if (account->protocol == SMTP_PROTO_SMTP)
3912 {
3913 if (account->tls && account->tls_nostarttls)
3914 {
3915 account->port = 465;
3916 }
3917 else
3918 {
3919 account->port = 25;
3920 }
3921 }
3922 else /* LMTP. Has no default port as of 2006-06-17. */
3923 {
3924 }
3925 }
3926 if (!account->tls_trust_file && !(account->mask & ACC_TLS_TRUST_FILE))
3927 {
3928 account->tls_trust_file = xstrdup("system");
3929 }
3930 if (account->proxy_host && account->proxy_port == 0)
3931 {
3932 account->proxy_port = 1080;
3933 }
3934 if (expand_domain(&(account->domain), &errstr) != CONF_EOK)
3935 {
3936 print_error("%s", sanitize_string(errstr));
3937 error_code = EX_CONFIG;
3938 goto exit;
3939 }
3940 if (conf.sendmail && account->from)
3941 {
3942 if (expand_from(&(account->from), &errstr) != CONF_EOK)
3943 {
3944 print_error("%s", sanitize_string(errstr));
3945 error_code = EX_CONFIG;
3946 goto exit;
3947 }
3948 }
3949 if (conf.sendmail && account->auto_from /* obsolete */)
3950 {
3951 free(account->from);
3952 account->from = msmtp_construct_env_from(account->maildomain);
3953 }
3954 if (check_account(account, (conf.sendmail && !conf.pretend),
3955 &errstr) != CONF_EOK)
3956 {
3957 if (account->id && account->conffile)
3958 {
3959 print_error(_("account %s from %s: %s"), account->id,
3960 account->conffile, sanitize_string(errstr));
3961 }
3962 else
3963 {
3964 print_error("%s", sanitize_string(errstr));
3965 }
3966 error_code = EX_CONFIG;
3967 goto exit;
3968 }
3969
3970 /* print configuration */
3971 if (conf.print_conf)
3972 {
3973 msmtp_print_conf(conf, account);
3974 }
3975
3976 /* replace aliases */
3977 if (conf.sendmail && account->aliases)
3978 {
3979 if ((e = aliases_replace(account->aliases, conf.recipients,
3980 &errstr)) != ALIASES_EOK)
3981 {
3982 print_error("%s: %s", account->aliases,
3983 sanitize_string(errstr));
3984 error_code = EX_CONFIG;
3985 goto exit;
3986 }
3987 }
3988
3989 /* stop if there's nothing to do */
3990 if (conf.pretend || (!conf.sendmail && !conf.serverinfo && !conf.rmqs))
3991 {
3992 error_code = EX_OK;
3993 goto exit;
3994 }
3995
3996 /* initialize libraries */
3997 #ifndef HAVE_SYSLOG
3998 if (conf.sendmail && account->syslog)
3999 {
4000 print_error(_("this platform does not support syslog logging"));
4001 error_code = EX_UNAVAILABLE;
4002 goto exit;
4003 }
4004 #endif /* not HAVE_SYSLOG */
4005 if ((conf.sendmail || conf.rmqs) /* serverinfo does not use auth */
4006 && account->auth_mech && (strcmp(account->auth_mech, "") != 0)
4007 && !smtp_client_supports_authmech(account->auth_mech))
4008 {
4009 print_error(_("support for authentication method %s "
4010 "is not compiled in"),
4011 account->auth_mech);
4012 error_code = EX_UNAVAILABLE;
4013 goto exit;
4014 }
4015 if ((e = net_lib_init(&errstr)) != NET_EOK)
4016 {
4017 print_error(_("cannot initialize networking: %s"),
4018 sanitize_string(errstr));
4019 error_code = EX_SOFTWARE;
4020 goto exit;
4021 }
4022 net_lib_initialized = 1;
4023 if (account->tls)
4024 {
4025 #ifdef HAVE_TLS
4026 if ((e = mtls_lib_init(&errstr)) != TLS_EOK)
4027 {
4028 print_error(_("cannot initialize TLS library: %s"),
4029 sanitize_string(errstr));
4030 error_code = EX_SOFTWARE;
4031 goto exit;
4032 }
4033 tls_lib_initialized = 1;
4034 #else /* not HAVE_TLS */
4035 print_error(_("support for TLS is not compiled in"));
4036 error_code = EX_UNAVAILABLE;
4037 goto exit;
4038 #endif /* not HAVE_TLS */
4039 }
4040
4041 /* do the work */
4042 if (conf.sendmail)
4043 {
4044 int prepend_header_contains_from = 0;
4045 if (account->undisclosed_recipients
4046 || account->set_from_header == 1
4047 || (!have_from_header && account->set_from_header == 2)
4048 || (!have_date_header && account->set_date_header == 2))
4049 {
4050 if (!(prepend_header_tmpfile = tmpfile()))
4051 {
4052 print_error(_("cannot create temporary file: %s"),
4053 sanitize_string(strerror(errno)));
4054 error_code = EX_IOERR;
4055 goto exit;
4056 }
4057 }
4058 if (account->set_from_header == 1
4059 || (!have_from_header && account->set_from_header == 2))
4060 {
4061 if (conf.full_name)
4062 {
4063 fprintf(prepend_header_tmpfile, "From: %s <%s>\n",
4064 conf.full_name, account->from);
4065 }
4066 else
4067 {
4068 fprintf(prepend_header_tmpfile, "From: %s\n", account->from);
4069 }
4070 prepend_header_contains_from = 1;
4071 }
4072 if (account->undisclosed_recipients)
4073 {
4074 fputs("To: undisclosed-recipients:;\n", prepend_header_tmpfile);
4075 }
4076 if (!have_date_header && account->set_date_header == 2)
4077 {
4078 char rfc2822_timestamp[32];
4079 print_time_rfc2822(time(NULL), rfc2822_timestamp);
4080 fprintf(prepend_header_tmpfile, "Date: %s\n", rfc2822_timestamp);
4081 }
4082 if (prepend_header_tmpfile
4083 && fseeko(prepend_header_tmpfile, 0, SEEK_SET) != 0)
4084 {
4085 print_error(_("cannot rewind temporary file: %s"),
4086 sanitize_string(strerror(errno)));
4087 error_code = EX_IOERR;
4088 goto exit;
4089 }
4090 if ((error_code = msmtp_sendmail(account, conf.recipients,
4091 prepend_header_tmpfile, prepend_header_contains_from,
4092 header_tmpfile, stdin,
4093 conf.debug, &mailsize,
4094 &lmtp_errstrs, &lmtp_error_msgs,
4095 &errmsg, &errstr)) != EX_OK)
4096 {
4097 if (account->protocol == SMTP_PROTO_LMTP && lmtp_errstrs)
4098 {
4099 lp_lmtp_errstrs = lmtp_errstrs;
4100 lp_lmtp_error_msgs = lmtp_error_msgs;
4101 while (!list_is_empty(lp_lmtp_errstrs))
4102 {
4103 lp_lmtp_errstrs = lp_lmtp_errstrs->next;
4104 lp_lmtp_error_msgs = lp_lmtp_error_msgs->next;
4105 if (lp_lmtp_errstrs->data)
4106 {
4107 print_error("%s", sanitize_string(
4108 lp_lmtp_errstrs->data));
4109 if ((lp = lp_lmtp_error_msgs->data))
4110 {
4111 while (!list_is_empty(lp))
4112 {
4113 lp = lp->next;
4114 print_error(_("LMTP server message: %s"),
4115 sanitize_string(lp->data));
4116 }
4117 list_xfree(lp_lmtp_error_msgs->data, free);
4118 }
4119 }
4120 }
4121 list_xfree(lmtp_errstrs, free);
4122 list_free(lmtp_error_msgs);
4123 if (account->id && account->conffile)
4124 {
4125 print_error(_("could not send mail to all recipients "
4126 "(account %s from %s)"),
4127 account->id, account->conffile);
4128 }
4129 else
4130 {
4131 print_error(_("could not send mail to all recipients"));
4132 }
4133 }
4134 else
4135 {
4136 if (errstr)
4137 {
4138 print_error("%s", sanitize_string(errstr));
4139 }
4140 if (errmsg)
4141 {
4142 lp = errmsg;
4143 while (!list_is_empty(lp))
4144 {
4145 lp = lp->next;
4146 print_error(_("server message: %s"),
4147 sanitize_string(lp->data));
4148 }
4149 }
4150 if (account->id && account->conffile)
4151 {
4152 print_error(_("could not send mail (account %s from %s)"),
4153 account->id, account->conffile);
4154 }
4155 else
4156 {
4157 print_error(_("could not send mail"));
4158 }
4159 }
4160 }
4161 if (account->logfile || account->syslog)
4162 {
4163 if (account->protocol == SMTP_PROTO_LMTP && lmtp_errstrs)
4164 {
4165 /* errstr is NULL; print short info to it */
4166 errstr = xasprintf(
4167 _("delivery to one or more recipients failed"));
4168 /* we know that errmsg is NULL. that's ok. */
4169 }
4170 log_info = msmtp_get_log_info(account, conf.recipients, mailsize,
4171 errmsg, errstr, error_code);
4172 if (account->logfile)
4173 {
4174 msmtp_log_to_file(account->logfile, account->logfile_time_format, log_info);
4175 }
4176 #ifdef HAVE_SYSLOG
4177 if (account->syslog)
4178 {
4179 msmtp_log_to_syslog(account->syslog, log_info,
4180 (error_code != EX_OK));
4181 }
4182 #endif
4183 free(log_info);
4184 }
4185 }
4186 else if (conf.serverinfo)
4187 {
4188 if ((error_code = msmtp_serverinfo(account, conf.debug,
4189 &errmsg, &errstr)) != EX_OK)
4190 {
4191 if (errstr)
4192 {
4193 print_error("%s", sanitize_string(errstr));
4194 }
4195 if (errmsg)
4196 {
4197 lp = errmsg;
4198 while (!list_is_empty(lp))
4199 {
4200 lp = lp->next;
4201 print_error(_("server message: %s"),
4202 sanitize_string(lp->data));
4203 }
4204 }
4205 }
4206 }
4207 else /* rmqs */
4208 {
4209 if ((error_code = msmtp_rmqs(account, conf.debug, conf.rmqs_argument,
4210 &errmsg, &errstr)) != EX_OK)
4211 {
4212 if (errstr)
4213 {
4214 print_error("%s", sanitize_string(errstr));
4215 }
4216 if (errmsg)
4217 {
4218 lp = errmsg;
4219 while (!list_is_empty(lp))
4220 {
4221 lp = lp->next;
4222 print_error(_("server message: %s"),
4223 sanitize_string(lp->data));
4224 }
4225 }
4226 }
4227 }
4228
4229
4230 exit:
4231
4232 /* clean up */
4233 if (header_tmpfile)
4234 {
4235 fclose(header_tmpfile);
4236 }
4237 if (prepend_header_tmpfile)
4238 {
4239 fclose(prepend_header_tmpfile);
4240 }
4241 free(loaded_system_conffile);
4242 free(loaded_user_conffile);
4243 #ifdef HAVE_TLS
4244 if (tls_lib_initialized)
4245 {
4246 mtls_lib_deinit();
4247 }
4248 #endif /* HAVE_TLS */
4249 if (net_lib_initialized)
4250 {
4251 net_lib_deinit();
4252 }
4253 if (account_list)
4254 {
4255 list_xfree(account_list, account_free);
4256 }
4257 account_free(conf.cmdline_account);
4258 account_free(account);
4259 if (conf.recipients)
4260 {
4261 list_xfree(conf.recipients, free);
4262 }
4263 free(errstr);
4264 if (errmsg)
4265 {
4266 list_xfree(errmsg, free);
4267 }
4268
4269 return error_code;
4270 }
4271