NeoMutt  2018-07-16 +2481-68dcde
Teaching an old dog new tricks
DOXYGEN
smtp.c
Go to the documentation of this file.
1 
31 /* This file contains code for direct SMTP delivery of email messages. */
32 
33 #include "config.h"
34 #include <netdb.h>
35 #include <netinet/in.h>
36 #include <stdbool.h>
37 #include <stdint.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <sys/stat.h>
41 #include <unistd.h>
42 #include "mutt/mutt.h"
43 #include "address/lib.h"
44 #include "config/lib.h"
45 #include "email/lib.h"
46 #include "conn/conn.h"
47 #include "mutt.h"
48 #include "globals.h"
49 #include "mutt_account.h"
50 #include "mutt_socket.h"
51 #include "options.h"
52 #include "progress.h"
53 #include "sendlib.h"
54 #ifdef USE_SASL
55 #include <sasl/sasl.h>
56 #include <sasl/saslutil.h>
57 #endif
58 
59 /* These Config Variables are only used in smtp.c */
61 
62 #define smtp_success(x) ((x) / 100 == 2)
63 #define SMTP_READY 334
64 #define SMTP_CONTINUE 354
65 
66 #define SMTP_ERR_READ -2
67 #define SMTP_ERR_WRITE -3
68 #define SMTP_ERR_CODE -4
69 
70 #define SMTP_PORT 25
71 #define SMTPS_PORT 465
72 
73 #define SMTP_AUTH_SUCCESS 0
74 #define SMTP_AUTH_UNAVAIL 1
75 #define SMTP_AUTH_FAIL -1
76 
77 // clang-format off
81 typedef uint8_t SmtpCapFlags;
82 #define SMTP_CAP_NO_FLAGS 0
83 #define SMTP_CAP_STARTTLS (1 << 0)
84 #define SMTP_CAP_AUTH (1 << 1)
85 #define SMTP_CAP_DSN (1 << 2)
86 #define SMTP_CAP_EIGHTBITMIME (1 << 3)
87 #define SMTP_CAP_SMTPUTF8 (1 << 4)
88 
89 #define SMTP_CAP_ALL ((1 << 5) - 1)
90 // clang-format on
91 
92 static char *AuthMechs = NULL;
94 
102 static bool valid_smtp_code(char *buf, size_t buflen, int *n)
103 {
104  char code[4];
105 
106  if (buflen < 4)
107  return false;
108  code[0] = buf[0];
109  code[1] = buf[1];
110  code[2] = buf[2];
111  code[3] = '\0';
112  if (mutt_str_atoi(code, n) < 0)
113  return false;
114  return true;
115 }
116 
123 static int smtp_get_resp(struct Connection *conn)
124 {
125  int n;
126  char buf[1024];
127 
128  do
129  {
130  n = mutt_socket_readln(buf, sizeof(buf), conn);
131  if (n < 4)
132  {
133  /* read error, or no response code */
134  return SMTP_ERR_READ;
135  }
136  const char *s = buf + 4; /* Skip the response code and the space/dash */
137  size_t plen;
138 
139  if (mutt_str_startswith(s, "8BITMIME", CASE_IGNORE))
141  else if ((plen = mutt_str_startswith(s, "AUTH ", CASE_IGNORE)))
142  {
144  FREE(&AuthMechs);
145  AuthMechs = mutt_str_strdup(s + plen);
146  }
147  else if (mutt_str_startswith(s, "DSN", CASE_IGNORE))
149  else if (mutt_str_startswith(s, "STARTTLS", CASE_IGNORE))
151  else if (mutt_str_startswith(s, "SMTPUTF8", CASE_IGNORE))
153 
154  if (!valid_smtp_code(buf, n, &n))
155  return SMTP_ERR_CODE;
156 
157  } while (buf[3] == '-');
158 
159  if (smtp_success(n) || (n == SMTP_CONTINUE))
160  return 0;
161 
162  mutt_error(_("SMTP session failed: %s"), buf);
163  return -1;
164 }
165 
173 static int smtp_rcpt_to(struct Connection *conn, const struct AddressList *al)
174 {
175  if (!al)
176  return 0;
177 
178  struct Address *a = NULL;
179  TAILQ_FOREACH(a, al, entries)
180  {
181  /* weed out group mailboxes, since those are for display only */
182  if (!a->mailbox || a->group)
183  {
184  continue;
185  }
186  char buf[1024];
188  snprintf(buf, sizeof(buf), "RCPT TO:<%s> NOTIFY=%s\r\n", a->mailbox, C_DsnNotify);
189  else
190  snprintf(buf, sizeof(buf), "RCPT TO:<%s>\r\n", a->mailbox);
191  if (mutt_socket_send(conn, buf) == -1)
192  return SMTP_ERR_WRITE;
193  int rc = smtp_get_resp(conn);
194  if (rc != 0)
195  return rc;
196  }
197 
198  return 0;
199 }
200 
208 static int smtp_data(struct Connection *conn, const char *msgfile)
209 {
210  char buf[1024];
211  struct Progress progress;
212  struct stat st;
213  int rc, term = 0;
214  size_t buflen = 0;
215 
216  FILE *fp = fopen(msgfile, "r");
217  if (!fp)
218  {
219  mutt_error(_("SMTP session failed: unable to open %s"), msgfile);
220  return -1;
221  }
222  stat(msgfile, &st);
223  unlink(msgfile);
224  mutt_progress_init(&progress, _("Sending message..."), MUTT_PROGRESS_NET, st.st_size);
225 
226  snprintf(buf, sizeof(buf), "DATA\r\n");
227  if (mutt_socket_send(conn, buf) == -1)
228  {
229  mutt_file_fclose(&fp);
230  return SMTP_ERR_WRITE;
231  }
232  rc = smtp_get_resp(conn);
233  if (rc != 0)
234  {
235  mutt_file_fclose(&fp);
236  return rc;
237  }
238 
239  while (fgets(buf, sizeof(buf) - 1, fp))
240  {
241  buflen = mutt_str_strlen(buf);
242  term = buflen && buf[buflen - 1] == '\n';
243  if (term && ((buflen == 1) || (buf[buflen - 2] != '\r')))
244  snprintf(buf + buflen - 1, sizeof(buf) - buflen + 1, "\r\n");
245  if (buf[0] == '.')
246  {
247  if (mutt_socket_send_d(conn, ".", MUTT_SOCK_LOG_FULL) == -1)
248  {
249  mutt_file_fclose(&fp);
250  return SMTP_ERR_WRITE;
251  }
252  }
253  if (mutt_socket_send_d(conn, buf, MUTT_SOCK_LOG_FULL) == -1)
254  {
255  mutt_file_fclose(&fp);
256  return SMTP_ERR_WRITE;
257  }
258  mutt_progress_update(&progress, ftell(fp), -1);
259  }
260  if (!term && buflen && (mutt_socket_send_d(conn, "\r\n", MUTT_SOCK_LOG_FULL) == -1))
261  {
262  mutt_file_fclose(&fp);
263  return SMTP_ERR_WRITE;
264  }
265  mutt_file_fclose(&fp);
266 
267  /* terminate the message body */
268  if (mutt_socket_send(conn, ".\r\n") == -1)
269  return SMTP_ERR_WRITE;
270 
271  rc = smtp_get_resp(conn);
272  if (rc != 0)
273  return rc;
274 
275  return 0;
276 }
277 
283 static bool address_uses_unicode(const char *a)
284 {
285  if (!a)
286  return false;
287 
288  while (*a)
289  {
290  if ((unsigned char) *a & (1 << 7))
291  return true;
292  a++;
293  }
294 
295  return false;
296 }
297 
303 static bool addresses_use_unicode(const struct AddressList *al)
304 {
305  if (!al)
306  {
307  return false;
308  }
309 
310  struct Address *a = NULL;
311  TAILQ_FOREACH(a, al, entries)
312  {
313  if (a->mailbox && !a->group && address_uses_unicode(a->mailbox))
314  return true;
315  }
316  return false;
317 }
318 
325 static int smtp_fill_account(struct ConnAccount *account)
326 {
327  account->flags = 0;
328  account->port = 0;
329  account->type = MUTT_ACCT_TYPE_SMTP;
330 
331  struct Url *url = url_parse(C_SmtpUrl);
332  if (!url || ((url->scheme != U_SMTP) && (url->scheme != U_SMTPS)) ||
333  !url->host || (mutt_account_fromurl(account, url) < 0))
334  {
335  url_free(&url);
336  mutt_error(_("Invalid SMTP URL: %s"), C_SmtpUrl);
337  return -1;
338  }
339 
340  if (url->scheme == U_SMTPS)
341  account->flags |= MUTT_ACCT_SSL;
342 
343  if (account->port == 0)
344  {
345  if (account->flags & MUTT_ACCT_SSL)
346  account->port = SMTPS_PORT;
347  else
348  {
349  static unsigned short SmtpPort = 0;
350  if (SmtpPort == 0)
351  {
352  struct servent *service = getservbyname("smtp", "tcp");
353  if (service)
354  SmtpPort = ntohs(service->s_port);
355  else
356  SmtpPort = SMTP_PORT;
357  mutt_debug(LL_DEBUG3, "Using default SMTP port %d\n", SmtpPort);
358  }
359  account->port = SmtpPort;
360  }
361  }
362 
363  url_free(&url);
364  return 0;
365 }
366 
374 static int smtp_helo(struct Connection *conn, bool esmtp)
375 {
376  Capabilities = 0;
377 
378  if (!esmtp)
379  {
380  /* if TLS or AUTH are requested, use EHLO */
381  if (conn->account.flags & MUTT_ACCT_USER)
382  esmtp = true;
383 #ifdef USE_SSL
384  if (C_SslForceTls || (C_SslStarttls != MUTT_NO))
385  esmtp = true;
386 #endif
387  }
388 
389  const char *fqdn = mutt_fqdn(false);
390  if (!fqdn)
391  fqdn = NONULL(ShortHostname);
392 
393  char buf[1024];
394  snprintf(buf, sizeof(buf), "%s %s\r\n", esmtp ? "EHLO" : "HELO", fqdn);
395  /* XXX there should probably be a wrapper in mutt_socket.c that
396  * repeatedly calls conn->write until all data is sent. This
397  * currently doesn't check for a short write. */
398  if (mutt_socket_send(conn, buf) == -1)
399  return SMTP_ERR_WRITE;
400  return smtp_get_resp(conn);
401 }
402 
403 #ifdef USE_SASL
404 
411 static int smtp_auth_sasl(struct Connection *conn, const char *mechlist)
412 {
413  sasl_conn_t *saslconn = NULL;
414  sasl_interact_t *interaction = NULL;
415  const char *mech = NULL;
416  const char *data = NULL;
417  unsigned int len;
418  char *buf = NULL;
419  size_t bufsize = 0;
420  int rc, saslrc;
421 
422  if (mutt_sasl_client_new(conn, &saslconn) < 0)
423  return SMTP_AUTH_FAIL;
424 
425  do
426  {
427  rc = sasl_client_start(saslconn, mechlist, &interaction, &data, &len, &mech);
428  if (rc == SASL_INTERACT)
429  mutt_sasl_interact(interaction);
430  } while (rc == SASL_INTERACT);
431 
432  if ((rc != SASL_OK) && (rc != SASL_CONTINUE))
433  {
434  mutt_debug(LL_DEBUG2, "%s unavailable\n", mech);
435  sasl_dispose(&saslconn);
436  return SMTP_AUTH_UNAVAIL;
437  }
438 
439  if (!OptNoCurses)
440  mutt_message(_("Authenticating (%s)..."), mech);
441 
442  bufsize = MAX((len * 2), 1024);
443  buf = mutt_mem_malloc(bufsize);
444 
445  snprintf(buf, bufsize, "AUTH %s", mech);
446  if (len)
447  {
448  mutt_str_strcat(buf, bufsize, " ");
449  if (sasl_encode64(data, len, buf + mutt_str_strlen(buf),
450  bufsize - mutt_str_strlen(buf), &len) != SASL_OK)
451  {
452  mutt_debug(LL_DEBUG1, "#1 error base64-encoding client response\n");
453  goto fail;
454  }
455  }
456  mutt_str_strcat(buf, bufsize, "\r\n");
457 
458  do
459  {
460  if (mutt_socket_send(conn, buf) < 0)
461  goto fail;
462  rc = mutt_socket_readln_d(buf, bufsize, conn, MUTT_SOCK_LOG_FULL);
463  if (rc < 0)
464  goto fail;
465  if (!valid_smtp_code(buf, rc, &rc))
466  goto fail;
467 
468  if (rc != SMTP_READY)
469  break;
470 
471  if (sasl_decode64(buf + 4, strlen(buf + 4), buf, bufsize - 1, &len) != SASL_OK)
472  {
473  mutt_debug(LL_DEBUG1, "error base64-decoding server response\n");
474  goto fail;
475  }
476 
477  do
478  {
479  saslrc = sasl_client_step(saslconn, buf, len, &interaction, &data, &len);
480  if (saslrc == SASL_INTERACT)
481  mutt_sasl_interact(interaction);
482  } while (saslrc == SASL_INTERACT);
483 
484  if (len)
485  {
486  if ((len * 2) > bufsize)
487  {
488  bufsize = len * 2;
489  mutt_mem_realloc(&buf, bufsize);
490  }
491  if (sasl_encode64(data, len, buf, bufsize, &len) != SASL_OK)
492  {
493  mutt_debug(LL_DEBUG1, "#2 error base64-encoding client response\n");
494  goto fail;
495  }
496  }
497  mutt_str_strfcpy(buf + len, "\r\n", bufsize - len);
498  } while (rc == SMTP_READY && saslrc != SASL_FAIL);
499 
500  if (smtp_success(rc))
501  {
502  mutt_sasl_setup_conn(conn, saslconn);
503  FREE(&buf);
504  return SMTP_AUTH_SUCCESS;
505  }
506 
507 fail:
508  sasl_dispose(&saslconn);
509  FREE(&buf);
510  return SMTP_AUTH_FAIL;
511 }
512 #endif
513 
519 static int smtp_auth_oauth(struct Connection *conn)
520 {
521  mutt_message(_("Authenticating (OAUTHBEARER)..."));
522 
523  /* We get the access token from the smtp_oauth_refresh_command */
524  char *oauthbearer = mutt_account_getoauthbearer(&conn->account);
525  if (!oauthbearer)
526  return SMTP_AUTH_FAIL;
527 
528  size_t ilen = strlen(oauthbearer) + 30;
529  char *ibuf = mutt_mem_malloc(ilen);
530  snprintf(ibuf, ilen, "AUTH OAUTHBEARER %s\r\n", oauthbearer);
531 
532  int rc = mutt_socket_send(conn, ibuf);
533  FREE(&oauthbearer);
534  FREE(&ibuf);
535 
536  if (rc == -1)
537  return SMTP_AUTH_FAIL;
538  if (smtp_get_resp(conn) != 0)
539  return SMTP_AUTH_FAIL;
540 
541  return SMTP_AUTH_SUCCESS;
542 }
543 
550 static int smtp_auth_plain(struct Connection *conn)
551 {
552  char buf[1024];
553 
554  /* Get username and password. Bail out of any can't be retrieved. */
555  if ((mutt_account_getuser(&conn->account) < 0) ||
556  (mutt_account_getpass(&conn->account) < 0))
557  {
558  goto error;
559  }
560 
561  /* Build the initial client response. */
562  size_t len = mutt_sasl_plain_msg(buf, sizeof(buf), "AUTH PLAIN", conn->account.user,
563  conn->account.user, conn->account.pass);
564 
565  /* Terminate as per SMTP protocol. Bail out if there's no room left. */
566  if (snprintf(buf + len, sizeof(buf) - len, "\r\n") != 2)
567  {
568  goto error;
569  }
570 
571  /* Send request, receive response (with a check for OK code). */
572  if ((mutt_socket_send(conn, buf) < 0) || smtp_get_resp(conn))
573  {
574  goto error;
575  }
576 
577  /* If we got here, auth was successful. */
578  return 0;
579 
580 error:
581  mutt_error(_("SASL authentication failed"));
582  return -1;
583 }
584 
591 static int smtp_auth(struct Connection *conn)
592 {
593  int r = SMTP_AUTH_UNAVAIL;
594 
595  if (C_SmtpAuthenticators)
596  {
597  struct ListNode *np = NULL;
598  STAILQ_FOREACH(np, &C_SmtpAuthenticators->head, entries)
599  {
600  mutt_debug(LL_DEBUG2, "Trying method %s\n", np->data);
601 
602  if (strcmp(np->data, "oauthbearer") == 0)
603  {
604  r = smtp_auth_oauth(conn);
605  }
606  else if (strcmp(np->data, "plain") == 0)
607  {
608  r = smtp_auth_plain(conn);
609  }
610  else
611  {
612 #ifdef USE_SASL
613  r = smtp_auth_sasl(conn, np->data);
614 #else
615  mutt_error(_("SMTP authentication method %s requires SASL"), np->data);
616  continue;
617 #endif
618  }
619 
620  if ((r == SMTP_AUTH_FAIL) && (C_SmtpAuthenticators->count > 1))
621  {
622  mutt_error(_("%s authentication failed, trying next method"), np->data);
623  }
624  else if (r != SMTP_AUTH_UNAVAIL)
625  break;
626  }
627  }
628  else
629  {
630 #ifdef USE_SASL
631  r = smtp_auth_sasl(conn, AuthMechs);
632 #else
633  mutt_error(_("SMTP authentication requires SASL"));
634  r = SMTP_AUTH_UNAVAIL;
635 #endif
636  }
637 
638  if (r != SMTP_AUTH_SUCCESS)
640 
641  if (r == SMTP_AUTH_FAIL)
642  {
643  mutt_error(_("SASL authentication failed"));
644  }
645  else if (r == SMTP_AUTH_UNAVAIL)
646  {
647  mutt_error(_("No authenticators available"));
648  }
649 
650  return (r == SMTP_AUTH_SUCCESS) ? 0 : -1;
651 }
652 
660 static int smtp_open(struct Connection *conn, bool esmtp)
661 {
662  int rc;
663 
664  if (mutt_socket_open(conn))
665  return -1;
666 
667  /* get greeting string */
668  rc = smtp_get_resp(conn);
669  if (rc != 0)
670  return rc;
671 
672  rc = smtp_helo(conn, esmtp);
673  if (rc != 0)
674  return rc;
675 
676 #ifdef USE_SSL
677  enum QuadOption ans = MUTT_NO;
678  if (conn->ssf)
679  ans = MUTT_NO;
680  else if (C_SslForceTls)
681  ans = MUTT_YES;
682  else if ((Capabilities & SMTP_CAP_STARTTLS) &&
684  _("Secure connection with TLS?"))) == MUTT_ABORT))
685  {
686  return -1;
687  }
688 
689  if (ans == MUTT_YES)
690  {
691  if (mutt_socket_send(conn, "STARTTLS\r\n") < 0)
692  return SMTP_ERR_WRITE;
693  rc = smtp_get_resp(conn);
694  if (rc != 0)
695  return rc;
696 
697  if (mutt_ssl_starttls(conn))
698  {
699  mutt_error(_("Could not negotiate TLS connection"));
700  return -1;
701  }
702 
703  /* re-EHLO to get authentication mechanisms */
704  rc = smtp_helo(conn, esmtp);
705  if (rc != 0)
706  return rc;
707  }
708 #endif
709 
710  if (conn->account.flags & MUTT_ACCT_USER)
711  {
712  if (!(Capabilities & SMTP_CAP_AUTH))
713  {
714  mutt_error(_("SMTP server does not support authentication"));
715  return -1;
716  }
717 
718  return smtp_auth(conn);
719  }
720 
721  return 0;
722 }
723 
735 int mutt_smtp_send(const struct AddressList *from, const struct AddressList *to,
736  const struct AddressList *cc, const struct AddressList *bcc,
737  const char *msgfile, bool eightbit)
738 {
739  struct Connection *conn = NULL;
740  struct ConnAccount account;
741  const char *envfrom = NULL;
742  char buf[1024];
743  int rc = -1;
744 
745  /* it might be better to synthesize an envelope from from user and host
746  * but this condition is most likely arrived at accidentally */
748  envfrom = C_EnvelopeFromAddress->mailbox;
749  else if (from && !TAILQ_EMPTY(from))
750  envfrom = TAILQ_FIRST(from)->mailbox;
751  else
752  {
753  mutt_error(_("No from address given"));
754  return -1;
755  }
756 
757  if (smtp_fill_account(&account) < 0)
758  return rc;
759 
760  conn = mutt_conn_find(NULL, &account);
761  if (!conn)
762  return -1;
763 
764  do
765  {
766  /* send our greeting */
767  rc = smtp_open(conn, eightbit);
768  if (rc != 0)
769  break;
770  FREE(&AuthMechs);
771 
772  /* send the sender's address */
773  int len = snprintf(buf, sizeof(buf), "MAIL FROM:<%s>", envfrom);
774  if (eightbit && (Capabilities & SMTP_CAP_EIGHTBITMIME))
775  {
776  mutt_str_strncat(buf, sizeof(buf), " BODY=8BITMIME", 15);
777  len += 14;
778  }
780  len += snprintf(buf + len, sizeof(buf) - len, " RET=%s", C_DsnReturn);
782  (address_uses_unicode(envfrom) || addresses_use_unicode(to) ||
784  {
785  snprintf(buf + len, sizeof(buf) - len, " SMTPUTF8");
786  }
787  mutt_str_strncat(buf, sizeof(buf), "\r\n", 3);
788  if (mutt_socket_send(conn, buf) == -1)
789  {
790  rc = SMTP_ERR_WRITE;
791  break;
792  }
793  rc = smtp_get_resp(conn);
794  if (rc != 0)
795  break;
796 
797  /* send the recipient list */
798  if ((rc = smtp_rcpt_to(conn, to)) || (rc = smtp_rcpt_to(conn, cc)) ||
799  (rc = smtp_rcpt_to(conn, bcc)))
800  {
801  break;
802  }
803 
804  /* send the message data */
805  rc = smtp_data(conn, msgfile);
806  if (rc != 0)
807  break;
808 
809  mutt_socket_send(conn, "QUIT\r\n");
810 
811  rc = 0;
812  } while (false);
813 
814  mutt_socket_close(conn);
815  FREE(&conn);
816 
817  if (rc == SMTP_ERR_READ)
818  mutt_error(_("SMTP session failed: read error"));
819  else if (rc == SMTP_ERR_WRITE)
820  mutt_error(_("SMTP session failed: write error"));
821  else if (rc == SMTP_ERR_CODE)
822  mutt_error(_("Invalid server response"));
823 
824  return rc;
825 }
Progress tracks bytes, according to C_NetInc.
Definition: progress.h:42
WHERE char * C_SmtpUrl
Config: (smtp) Url of the SMTP server.
Definition: globals.h:147
static int smtp_auth_plain(struct Connection *conn)
Authenticate using plain text.
Definition: smtp.c:550
#define NONULL(x)
Definition: string2.h:37
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:262
static int smtp_helo(struct Connection *conn, bool esmtp)
Say hello to an SMTP Server.
Definition: smtp.c:374
#define TAILQ_FIRST(head)
Definition: queue.h:717
struct ConnAccount account
Definition: connection.h:36
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
#define mutt_socket_send(conn, buf)
Definition: mutt_socket.h:38
unsigned int ssf
security strength factor, in bits
Definition: connection.h:37
#define SMTP_CAP_STARTTLS
Server supports STARTTLS command.
Definition: smtp.c:83
Structs that make up an email.
User aborted the question (with Ctrl-G)
Definition: quad.h:37
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3331
#define mutt_message(...)
Definition: logging.h:83
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:66
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
enum UrlScheme scheme
Scheme, e.g. U_SMTPS.
Definition: url.h:68
static size_t plen
Length of cached packet.
Definition: pgppacket.c:38
An open network connection (socket)
Definition: connection.h:34
#define SMTP_CAP_SMTPUTF8
Server accepts UTF-8 strings.
Definition: smtp.c:87
char user[128]
Definition: connaccount.h:33
#define _(a)
Definition: message.h:28
size_t mutt_sasl_plain_msg(char *buf, size_t buflen, const char *cmd, const char *authz, const char *user, const char *pass)
Construct a base64 encoded SASL PLAIN message.
Definition: sasl_plain.c:54
An email address.
Definition: address.h:34
int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
wrapper for sasl_client_new
Definition: sasl.c:534
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:46
#define SMTP_AUTH_SUCCESS
Definition: smtp.c:73
char * mailbox
Mailbox and host address.
Definition: address.h:37
void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
Set up an SASL connection.
Definition: sasl.c:678
struct Slist * C_SmtpAuthenticators
Config: (smtp) List of allowed authentication methods.
Definition: smtp.c:60
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
String list.
Definition: slist.h:43
WHERE bool C_SslForceTls
Config: (ssl) Require TLS encryption for all connections.
Definition: globals.h:241
#define MUTT_SOCK_LOG_FULL
Definition: mutt_socket.h:32
char * mutt_str_strncat(char *d, size_t l, const char *s, size_t sl)
Concatenate two strings.
Definition: string.c:424
A progress bar.
Definition: progress.h:48
Convenience wrapper for the config headers.
int mutt_socket_open(struct Connection *conn)
Simple wrapper.
Definition: socket.c:74
Hundreds of global variables to back the user variables.
Email Address Handling.
#define MAX(a, b)
Definition: memory.h:30
static int smtp_open(struct Connection *conn, bool esmtp)
Open an SMTP Connection.
Definition: smtp.c:660
void mutt_progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:212
static int smtp_auth(struct Connection *conn)
Authenticate to an SMTP server.
Definition: smtp.c:591
Log at debug level 2.
Definition: logging.h:57
struct ListHead head
Definition: slist.h:45
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:150
char pass[256]
Definition: connaccount.h:35
#define mutt_socket_send_d(conn, buf, dbg)
Definition: mutt_socket.h:39
static SmtpCapFlags Capabilities
Definition: smtp.c:93
Progress bar.
char * mutt_account_getoauthbearer(struct ConnAccount *account)
Get an OAUTHBEARER token.
Definition: mutt_account.c:348
int mutt_account_getpass(struct ConnAccount *account)
Fetch password into ConnAccount, if necessary.
Definition: mutt_account.c:289
#define SMTP_ERR_WRITE
Definition: smtp.c:67
int mutt_ssl_starttls(struct Connection *conn)
Negotiate TLS over an already opened connection.
Definition: ssl.c:1444
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#define SMTP_PORT
Definition: smtp.c:70
size_t count
Definition: slist.h:46
unsigned short port
Definition: connaccount.h:37
ConnAccount object used by POP and IMAP.
static bool address_uses_unicode(const char *a)
Do any addresses use Unicode.
Definition: smtp.c:283
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
Url is smtps://.
Definition: url.h:43
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
int mutt_account_getuser(struct ConnAccount *account)
Retrieve username into ConnAccount, if necessary.
Definition: mutt_account.c:208
static int smtp_get_resp(struct Connection *conn)
Read a command response from the SMTP server.
Definition: smtp.c:123
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
unsigned char type
Connection type, e.g. MUTT_ACCT_TYPE_IMAP.
Definition: connaccount.h:38
char * host
Host.
Definition: url.h:71
Ignore case when comparing strings.
Definition: string2.h:68
#define SMTP_ERR_READ
Definition: smtp.c:66
#define SMTP_READY
Definition: smtp.c:63
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
void mutt_progress_init(struct Progress *progress, const char *msg, enum ProgressType type, size_t size)
Set up a progress bar.
Definition: progress.c:153
#define smtp_success(x)
Definition: smtp.c:62
Login details for a remote server.
Definition: connaccount.h:31
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:95
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2527
WHERE char * C_DsnReturn
Config: What to send as a notification of message delivery or delay.
Definition: globals.h:113
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
#define mutt_socket_readln(buf, buflen, conn)
Definition: mutt_socket.h:37
#define SMTP_ERR_CODE
Definition: smtp.c:68
char * mutt_str_strcat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:395
#define SMTP_AUTH_UNAVAIL
Definition: smtp.c:74
char * data
String.
Definition: list.h:35
static int smtp_auth_sasl(struct Connection *conn, const char *mechlist)
Authenticate using SASL.
Definition: smtp.c:411
Log at debug level 1.
Definition: logging.h:56
bool group
Group mailbox?
Definition: address.h:38
static int smtp_fill_account(struct ConnAccount *account)
Create ConnAccount object from SMTP Url.
Definition: smtp.c:325
static bool valid_smtp_code(char *buf, size_t buflen, int *n)
Is the is a valid SMTP return code?
Definition: smtp.c:102
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
#define SMTP_CONTINUE
Definition: smtp.c:64
WHERE struct Address * C_EnvelopeFromAddress
Config: Manually set the sender for outgoing messages.
Definition: globals.h:98
uint8_t SmtpCapFlags
typedef SmtpCapFlags - SMTP server capabilities
Definition: smtp.c:81
#define SMTP_CAP_EIGHTBITMIME
Server supports 8-bit MIME content.
Definition: smtp.c:86
Connection Library.
static bool addresses_use_unicode(const struct AddressList *al)
Do any of a list of addresses use Unicode.
Definition: smtp.c:303
void url_free(struct Url **u)
Free the contents of a URL.
Definition: url.c:288
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:50
#define FREE(x)
Definition: memory.h:40
static int smtp_rcpt_to(struct Connection *conn, const struct AddressList *al)
Set the recipient to an Address.
Definition: smtp.c:173
Url is smtp://.
Definition: url.h:42
int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
Read a line from a socket.
Definition: socket.c:242
#define MUTT_ACCT_SSL
Account uses SSL/TLS.
Definition: mutt_account.h:64
Smtp Account.
Definition: mutt_account.h:54
int mutt_smtp_send(const struct AddressList *from, const struct AddressList *to, const struct AddressList *cc, const struct AddressList *bcc, const char *msgfile, bool eightbit)
Send a message using SMTP.
Definition: smtp.c:735
Handling of global boolean variables.
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Miscellaneous functions for sending an email.
#define SMTPS_PORT
Definition: smtp.c:71
#define TAILQ_EMPTY(head)
Definition: queue.h:715
NeoMutt connections.
int mutt_account_fromurl(struct ConnAccount *account, const struct Url *url)
Fill ConnAccount with information from url.
Definition: mutt_account.c:109
A List node for strings.
Definition: list.h:33
#define SMTP_CAP_AUTH
Server supports AUTH command.
Definition: smtp.c:84
Convenience wrapper for the library headers.
static char * AuthMechs
Definition: smtp.c:92
#define SMTP_AUTH_FAIL
Definition: smtp.c:75
static int smtp_auth_oauth(struct Connection *conn)
Authenticate an SMTP connection using OAUTHBEARER.
Definition: smtp.c:519
WHERE char * C_DsnNotify
Config: Request notification for message delivery or delay.
Definition: globals.h:112
Log at debug level 3.
Definition: logging.h:58
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
static int smtp_data(struct Connection *conn, const char *msgfile)
Send data to an SMTP server.
Definition: smtp.c:208
WHERE unsigned char C_SslStarttls
Config: (ssl) Use STARTTLS on servers advertising the capability.
Definition: globals.h:193
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
Definition: connaccount.h:39
#define MUTT_ACCT_USER
User field has been set.
Definition: mutt_account.h:61
int mutt_sasl_interact(sasl_interact_t *interaction)
Perform an SASL interaction with the user.
Definition: sasl.c:645
void mutt_account_unsetpass(struct ConnAccount *account)
Unset ConnAccount&#39;s password.
Definition: mutt_account.c:332
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:161
struct Connection * mutt_conn_find(const struct Connection *start, const struct ConnAccount *account)
Find a connection from a list.
Definition: mutt_socket.c:84
#define SMTP_CAP_DSN
Server supports Delivery Status Notification.
Definition: smtp.c:85