#include "config.h"
#include <netdb.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "conn/lib.h"
#include "gui/lib.h"
#include "smtp.h"
#include "send/lib.h"
#include "mutt_account.h"
#include "mutt_globals.h"
#include "mutt_socket.h"
#include "progress.h"
#include <sasl/sasl.h>
#include <sasl/saslutil.h>
#include "options.h"
Go to the source code of this file.
|
static bool | valid_smtp_code (char *buf, size_t buflen, int *n) |
| Is the is a valid SMTP return code? More...
|
|
static int | smtp_get_resp (struct SmtpAccountData *adata) |
| Read a command response from the SMTP server. More...
|
|
static int | smtp_rcpt_to (struct SmtpAccountData *adata, const struct AddressList *al) |
| Set the recipient to an Address. More...
|
|
static int | smtp_data (struct SmtpAccountData *adata, const char *msgfile) |
| Send data to an SMTP server. More...
|
|
static const char * | smtp_get_field (enum ConnAccountField field, void *gf_data) |
| Get connection login credentials - Implements ConnAccount::get_field() More...
|
|
static int | smtp_fill_account (struct SmtpAccountData *adata, struct ConnAccount *cac) |
| Create ConnAccount object from SMTP Url. More...
|
|
static int | smtp_helo (struct SmtpAccountData *adata, bool esmtp) |
| Say hello to an SMTP Server. More...
|
|
static int | smtp_auth_sasl (struct SmtpAccountData *adata, const char *mechlist) |
| Authenticate using SASL. More...
|
|
static int | smtp_auth_oauth (struct SmtpAccountData *adata, const char *method) |
| Authenticate an SMTP connection using OAUTHBEARER. More...
|
|
static int | smtp_auth_plain (struct SmtpAccountData *adata, const char *method) |
| Authenticate using plain text. More...
|
|
static int | smtp_auth_login (struct SmtpAccountData *adata, const char *method) |
| Authenticate using plain text. More...
|
|
bool | smtp_auth_is_valid (const char *authenticator) |
| Check if string is a valid smtp authentication method. More...
|
|
static int | smtp_authenticate (struct SmtpAccountData *adata) |
| Authenticate to an SMTP server. More...
|
|
static int | smtp_open (struct SmtpAccountData *adata, bool esmtp) |
| Open an SMTP Connection. More...
|
|
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, struct ConfigSubset *sub) |
| Send a message using SMTP. More...
|
|
Send email to an SMTP server
- Authors
- Michael R. Elkins
- Brendan Cully
- Pietro Cerutti
- Copyright
- This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
Definition in file smtp.c.
◆ smtp_success
#define smtp_success |
( |
|
x | ) |
((x) / 100 == 2) |
◆ SMTP_READY
◆ SMTP_CONTINUE
#define SMTP_CONTINUE 354 |
◆ SMTP_ERR_READ
◆ SMTP_ERR_WRITE
#define SMTP_ERR_WRITE -3 |
◆ SMTP_ERR_CODE
◆ SMTP_PORT
◆ SMTPS_PORT
◆ SMTP_AUTH_SUCCESS
#define SMTP_AUTH_SUCCESS 0 |
◆ SMTP_AUTH_UNAVAIL
#define SMTP_AUTH_UNAVAIL 1 |
◆ SMTP_AUTH_FAIL
#define SMTP_AUTH_FAIL -1 |
◆ SMTP_CAP_NO_FLAGS
#define SMTP_CAP_NO_FLAGS 0 |
No flags are set.
Definition at line 80 of file smtp.c.
◆ SMTP_CAP_STARTTLS
#define SMTP_CAP_STARTTLS (1 << 0) |
Server supports STARTTLS command.
Definition at line 81 of file smtp.c.
◆ SMTP_CAP_AUTH
#define SMTP_CAP_AUTH (1 << 1) |
Server supports AUTH command.
Definition at line 82 of file smtp.c.
◆ SMTP_CAP_DSN
#define SMTP_CAP_DSN (1 << 2) |
Server supports Delivery Status Notification.
Definition at line 83 of file smtp.c.
◆ SMTP_CAP_EIGHTBITMIME
#define SMTP_CAP_EIGHTBITMIME (1 << 3) |
Server supports 8-bit MIME content.
Definition at line 84 of file smtp.c.
◆ SMTP_CAP_SMTPUTF8
#define SMTP_CAP_SMTPUTF8 (1 << 4) |
Server accepts UTF-8 strings.
Definition at line 85 of file smtp.c.
◆ SMTP_CAP_ALL
#define SMTP_CAP_ALL ((1 << 5) - 1) |
◆ SmtpCapFlags
◆ valid_smtp_code()
static bool valid_smtp_code |
( |
char * |
buf, |
|
|
size_t |
buflen, |
|
|
int * |
n |
|
) |
| |
|
static |
Is the is a valid SMTP return code?
- Parameters
-
[in] | buf | String to check |
[in] | buflen | Length of string |
[out] | n | Numeric value of code |
- Return values
-
Definition at line 126 of file smtp.c.
◆ smtp_get_resp()
Read a command response from the SMTP server.
- Parameters
-
- Return values
-
0 | Success (2xx code) or continue (354 code) |
-1 | Write error, or any other response code |
Definition at line 147 of file smtp.c.
160 const char *s = buf + 4;
181 }
while (buf[3] ==
'-');
◆ smtp_rcpt_to()
static int smtp_rcpt_to |
( |
struct SmtpAccountData * |
adata, |
|
|
const struct AddressList * |
al |
|
) |
| |
|
static |
Set the recipient to an Address.
- Parameters
-
adata | SMTP Account data |
al | AddressList to use |
- Return values
-
Definition at line 197 of file smtp.c.
214 snprintf(buf,
sizeof(buf),
"RCPT TO:<%s> NOTIFY=%s\r\n", a->
mailbox, c_dsn_notify);
216 snprintf(buf,
sizeof(buf),
"RCPT TO:<%s>\r\n", a->
mailbox);
◆ smtp_data()
static int smtp_data |
( |
struct SmtpAccountData * |
adata, |
|
|
const char * |
msgfile |
|
) |
| |
|
static |
Send data to an SMTP server.
- Parameters
-
adata | SMTP Account data |
msgfile | Filename containing data |
- Return values
-
Definition at line 234 of file smtp.c.
242 FILE *fp = fopen(msgfile,
"r");
245 mutt_error(
_(
"SMTP session failed: unable to open %s"), msgfile);
252 snprintf(buf,
sizeof(buf),
"DATA\r\n");
265 while (fgets(buf,
sizeof(buf) - 1, fp))
268 term = buflen && buf[buflen - 1] ==
'\n';
269 if (term && ((buflen == 1) || (buf[buflen - 2] !=
'\r')))
270 snprintf(buf + buflen - 1,
sizeof(buf) - buflen + 1,
"\r\n");
286 if (!term && buflen &&
◆ smtp_get_field()
static const char* smtp_get_field |
( |
enum ConnAccountField |
field, |
|
|
void * |
gf_data |
|
) |
| |
|
static |
Get connection login credentials - Implements ConnAccount::get_field()
Definition at line 308 of file smtp.c.
329 const char *c_smtp_oauth_refresh_command =
331 return c_smtp_oauth_refresh_command;
◆ smtp_fill_account()
Create ConnAccount object from SMTP Url.
- Parameters
-
- Return values
-
Definition at line 346 of file smtp.c.
375 static unsigned short SmtpPort = 0;
378 struct servent *service = getservbyname(
"smtp",
"tcp");
380 SmtpPort = ntohs(service->s_port);
385 cac->
port = SmtpPort;
◆ smtp_helo()
Say hello to an SMTP Server.
- Parameters
-
adata | SMTP Account data |
esmtp | If true, use ESMTP |
- Return values
-
Definition at line 400 of file smtp.c.
414 if (c_ssl_force_tls || (c_ssl_starttls !=
MUTT_NO))
420 snprintf(buf,
sizeof(buf),
"%s %s\r\n", esmtp ?
"EHLO" :
"HELO", adata->
fqdn);
◆ smtp_auth_sasl()
static int smtp_auth_sasl |
( |
struct SmtpAccountData * |
adata, |
|
|
const char * |
mechlist |
|
) |
| |
|
static |
Authenticate using SASL.
- Parameters
-
adata | SMTP Account data |
mechlist | List of mechanisms to use |
- Return values
-
Definition at line 437 of file smtp.c.
439 sasl_conn_t *saslconn = NULL;
440 sasl_interact_t *interaction = NULL;
441 const char *mech = NULL;
442 const char *data = NULL;
453 rc = sasl_client_start(saslconn, mechlist, &interaction, &data, &len, &mech);
454 if (rc == SASL_INTERACT)
456 }
while (rc == SASL_INTERACT);
458 if ((rc != SASL_OK) && (rc != SASL_CONTINUE))
461 sasl_dispose(&saslconn);
471 bufsize =
MAX((len * 2), 1024);
474 snprintf(buf, bufsize,
"AUTH %s", mech);
500 if (sasl_decode64(buf + 4, strlen(buf + 4), buf, bufsize - 1, &len) != SASL_OK)
508 saslrc = sasl_client_step(saslconn, buf, len, &interaction, &data, &len);
509 if (saslrc == SASL_INTERACT)
511 }
while (saslrc == SASL_INTERACT);
515 if ((len * 2) > bufsize)
520 if (sasl_encode64(data, len, buf, bufsize, &len) != SASL_OK)
527 }
while (rc ==
SMTP_READY && saslrc != SASL_FAIL);
537 sasl_dispose(&saslconn);
◆ smtp_auth_oauth()
static int smtp_auth_oauth |
( |
struct SmtpAccountData * |
adata, |
|
|
const char * |
method |
|
) |
| |
|
static |
Authenticate an SMTP connection using OAUTHBEARER.
- Parameters
-
adata | SMTP Account data |
method | Authentication method (not used) |
- Return values
-
Definition at line 549 of file smtp.c.
561 size_t ilen = strlen(oauthbearer) + 30;
563 snprintf(ibuf, ilen,
"AUTH OAUTHBEARER %s\r\n", oauthbearer);
◆ smtp_auth_plain()
static int smtp_auth_plain |
( |
struct SmtpAccountData * |
adata, |
|
|
const char * |
method |
|
) |
| |
|
static |
Authenticate using plain text.
- Parameters
-
adata | SMTP Account data |
method | Authentication method (not used) |
- Return values
-
Definition at line 584 of file smtp.c.
603 if (snprintf(buf + len,
sizeof(buf) - len,
"\r\n") != 2)
◆ smtp_auth_login()
static int smtp_auth_login |
( |
struct SmtpAccountData * |
adata, |
|
|
const char * |
method |
|
) |
| |
|
static |
Authenticate using plain text.
- Parameters
-
adata | SMTP Account data |
method | Authentication method (not used) |
- Return values
-
Definition at line 630 of file smtp.c.
634 char b64[1024] = { 0 };
635 char buf[1024] = { 0 };
658 size_t len = snprintf(buf,
sizeof(buf),
"%s", adata->
conn->
account.
user);
660 snprintf(buf,
sizeof(buf),
"%s\r\n", b64);
676 snprintf(buf,
sizeof(buf),
"%s\r\n", b64);
693 mutt_error(
_(
"%s authentication failed"),
"LOGIN");
◆ smtp_auth_is_valid()
bool smtp_auth_is_valid |
( |
const char * |
authenticator | ) |
|
Check if string is a valid smtp authentication method.
- Parameters
-
authenticator | Authenticator string to check |
- Return values
-
bool | True if argument is a valid auth method |
Validate whether an input string is an accepted smtp authentication method as defined by smtp_authenticators.
Definition at line 717 of file smtp.c.
◆ smtp_authenticate()
Authenticate to an SMTP server.
- Parameters
-
- Return values
-
Definition at line 735 of file smtp.c.
739 const struct Slist *c_smtp_authenticators =
741 if (c_smtp_authenticators && (c_smtp_authenticators->
count > 0))
771 mutt_error(
_(
"SMTP authentication requires SASL"));
◆ smtp_open()
Open an SMTP Connection.
- Parameters
-
adata | SMTP Account data |
esmtp | If true, use ESMTP |
- Return values
-
Definition at line 799 of file smtp.c.
822 else if (c_ssl_force_tls)
843 mutt_error(
_(
"Could not negotiate TLS connection"));
858 mutt_error(
_(
"SMTP server does not support authentication"));
◆ mutt_smtp_send()
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, |
|
|
struct ConfigSubset * |
sub |
|
) |
| |
Send a message using SMTP.
- Parameters
-
- Return values
-
Definition at line 880 of file smtp.c.
886 const char *envfrom = NULL;
895 const struct Address *c_envelope_from_address =
900 if (c_envelope_from_address)
901 envfrom = c_envelope_from_address->
mailbox;
928 int len = snprintf(buf,
sizeof(buf),
"MAIL FROM:<%s>", envfrom);
935 len += snprintf(buf + len,
sizeof(buf) - len,
" RET=%s", c_dsn_return);
940 snprintf(buf + len,
sizeof(buf) - len,
" SMTPUTF8");
◆ smtp_authenticators
const struct SmtpAuth smtp_authenticators[] |
|
static |
Initial value:
Accepted authentication methods.
Definition at line 700 of file smtp.c.
@ MUTT_PROGRESS_NET
Progress tracks bytes, according to $net_inc
Login details for a remote server.
static bool valid_smtp_code(char *buf, size_t buflen, int *n)
Is the is a valid SMTP return code?
QuadOption
Possible values for a quad-option.
const char * fqdn
Fully-qualified domain name.
const char * auth_mechs
Allowed authorisation mechanisms.
int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
Wrapper for sasl_client_new()
@ MUTT_ACCT_TYPE_SMTP
Smtp Account.
int mutt_account_fromurl(struct ConnAccount *cac, const struct Url *url)
Fill ConnAccount with information from url.
static int smtp_auth_oauth(struct SmtpAccountData *adata, const char *method)
Authenticate an SMTP connection using OAUTHBEARER.
#define SMTP_AUTH_UNAVAIL
@ LL_DEBUG3
Log at debug level 3.
struct ConnAccount account
Account details: username, password, etc.
int mutt_sasl_interact(sasl_interact_t *interaction)
Perform an SASL interaction with the user.
const char *(* get_field)(enum ConnAccountField field, void *gf_data)
Function to get some login credentials.
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
void mutt_socket_empty(struct Connection *conn)
Clear out any queued data.
int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
Read a line from a socket.
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
#define TAILQ_EMPTY(head)
#define TAILQ_FOREACH(var, head, field)
int mutt_socket_close(struct Connection *conn)
Close a socket.
enum UrlScheme scheme
Scheme, e.g. U_SMTPS.
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.
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
char * mutt_str_dup(const char *str)
Copy a string, safely.
@ LL_DEBUG1
Log at debug level 1.
void * gf_data
Private data to pass to get_field()
#define mutt_socket_readln(buf, buflen, conn)
SMTP authentication multiplexor.
static int smtp_data(struct SmtpAccountData *adata, const char *msgfile)
Send data to an SMTP server.
#define SMTP_CAP_DSN
Server supports Delivery Status Notification.
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
#define SMTP_CAP_AUTH
Server supports AUTH command.
struct Url * url_parse(const char *src)
Fill in Url.
#define mutt_array_size(x)
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
#define STAILQ_FOREACH(var, head, field)
#define SMTP_CAP_STARTTLS
Server supports STARTTLS command.
static int smtp_helo(struct SmtpAccountData *adata, bool esmtp)
Say hello to an SMTP Server.
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
static int smtp_auth_login(struct SmtpAccountData *adata, const char *method)
Authenticate using plain text.
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
static int smtp_fill_account(struct SmtpAccountData *adata, struct ConnAccount *cac)
Create ConnAccount object from SMTP Url.
char * mutt_strn_cat(char *d, size_t l, const char *s, size_t sl)
Concatenate two strings.
#define SMTP_CAP_EIGHTBITMIME
Server supports 8-bit MIME content.
void mutt_progress_init(struct Progress *progress, const char *msg, enum ProgressType type, size_t size)
Set up a progress bar.
#define TAILQ_FIRST(head)
void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
Set up an SASL connection.
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
@ U_SMTPS
Url is smtps://.
const char * method
Name of authentication method supported, NULL means variable.
void mutt_account_unsetpass(struct ConnAccount *cac)
Unset ConnAccount's password.
struct Connection * conn
Server Connection.
static int smtp_authenticate(struct SmtpAccountData *adata)
Authenticate to an SMTP server.
size_t mutt_b64_encode(const char *in, size_t inlen, char *out, size_t outlen)
Convert raw bytes to null-terminated base64 string.
@ MUTT_CA_HOST
Server name.
A parsed URL proto://user:password@host:port/path?a=1&b=2
struct ConfigSubset * sub
Config scope.
void url_free(struct Url **ptr)
Free the contents of a URL.
SmtpCapFlags capabilities
Server capabilities.
int(* authenticate)(struct SmtpAccountData *adata, const char *method)
Authenticate an SMTP connection.
#define mutt_socket_send(conn, buf)
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
static int smtp_open(struct SmtpAccountData *adata, bool esmtp)
Open an SMTP Connection.
unsigned char type
Connection type, e.g. MUTT_ACCT_TYPE_IMAP.
#define mutt_debug(LEVEL,...)
@ MUTT_NO
User answered 'No', or assume 'No'.
static int smtp_auth_plain(struct SmtpAccountData *adata, const char *method)
Authenticate using plain text.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
#define MUTT_ACCT_USER
User field has been set.
MuttAccountFlags flags
Which fields are initialised, e.g. MUTT_ACCT_USER.
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
#define SMTP_AUTH_SUCCESS
static const struct SmtpAuth smtp_authenticators[]
Accepted authentication methods.
char * mailbox
Mailbox and host address.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
@ MUTT_CA_LOGIN
Login name.
#define MUTT_ACCT_SSL
Account uses SSL/TLS.
bool mutt_addrlist_uses_unicode(const struct AddressList *al)
Do any of a list of addresses use Unicode characters.
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
int mutt_socket_open(struct Connection *conn)
Simple wrapper.
unsigned short port
Port to connect to.
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
WHERE char * ShortHostname
Short version of the hostname.
static const char * smtp_get_field(enum ConnAccountField field, void *gf_data)
Get connection login credentials - Implements ConnAccount::get_field()
static int smtp_rcpt_to(struct SmtpAccountData *adata, const struct AddressList *al)
Set the recipient to an Address.
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
const struct Slist * cs_subset_slist(const struct ConfigSubset *sub, const char *name)
Get a string-list config item by name.
char * mutt_account_getoauthbearer(struct ConnAccount *cac)
Get an OAUTHBEARER token.
#define SMTP_CAP_SMTPUTF8
Server accepts UTF-8 strings.
void mutt_progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
static size_t plen
Length of cached packet.
#define MUTT_SOCK_LOG_FULL
const char * service
Name of the service, e.g. "imap".
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
int mutt_ssl_starttls(struct Connection *conn)
Negotiate TLS over an already opened connection.
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
bool mutt_addr_uses_unicode(const char *str)
Does this address use Unicode character.
#define mutt_message(...)
static int smtp_auth_sasl(struct SmtpAccountData *adata, const char *mechlist)
Authenticate using SASL.
struct Connection * mutt_conn_find(const struct ConnAccount *cac)
Find a connection from a list.
unsigned int ssf
Security strength factor, in bits (see below)
@ LL_DEBUG2
Log at debug level 2.
@ MUTT_CA_OAUTH_CMD
OAuth refresh command.
#define SMTP_CAP_NO_FLAGS
No flags are set.
static int smtp_get_resp(struct SmtpAccountData *adata)
Read a command response from the SMTP server.
int mutt_account_getpass(struct ConnAccount *cac)
Fetch password into ConnAccount, if necessary.
#define mutt_socket_send_d(conn, buf, dbg)
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)