Commit 4ff42217 authored by Brendan Cully's avatar Brendan Cully

This patch adds ESMTP relay support to mutt.

To use, set $smtp_url to the address of your smtp relay, in the form:

smtp[s]://[user[:password]@]host[:port]/

where port defaults to 25 for smtp and 465 for smtps.

You can also set $smtp_authenticators to control which methods mutt
will attempt to use during authentication. See $imap_authenticators
for details.
parent 5c8b3868
......@@ -60,7 +60,7 @@ CPPFLAGS=@CPPFLAGS@ -I$(includedir)
EXTRA_mutt_SOURCES = account.c md5c.c mutt_sasl.c mutt_socket.c mutt_ssl.c \
mutt_tunnel.c pop.c pop_auth.c pop_lib.c smime.c pgp.c pgpinvoke.c pgpkey.c \
pgplib.c sha1.c pgpmicalg.c gnupgparse.c resize.c dotlock.c remailer.c \
browser.h mbyte.h remailer.h url.h \
smtp.c browser.h mbyte.h remailer.h url.h \
crypt-mod-pgp-classic.c crypt-mod-smime-classic.c \
pgppacket.c mutt_idna.h hcache.h hcache.c bcache.c bcache.h mutt_ssl_gnutls.c \
crypt-gpgme.c crypt-mod-pgp-gpgme.c crypt-mod-smime-gpgme.c \
......
......@@ -123,6 +123,16 @@ void mutt_account_tourl (ACCOUNT* account, ciss_url_t* url)
}
#endif
#ifdef USE_SMTP
if (account->type == M_ACCT_TYPE_SMTP)
{
if (account->flags & M_ACCT_SSL)
url->scheme = U_SMTPS;
else
url->scheme = U_SMTP;
}
#endif
url->host = account->host;
if (account->flags & M_ACCT_PORT)
url->port = account->port;
......
......@@ -28,7 +28,8 @@ enum
{
M_ACCT_TYPE_NONE = 0,
M_ACCT_TYPE_IMAP,
M_ACCT_TYPE_POP
M_ACCT_TYPE_POP,
M_ACCT_TYPE_SMTP
};
/* account flags */
......
......@@ -573,6 +573,13 @@ AC_ARG_ENABLE(imap, AC_HELP_STRING([--enable-imap], [Enable IMAP support]),
])
AM_CONDITIONAL(BUILD_IMAP, test x$need_imap = xyes)
AC_ARG_ENABLE(smtp, AC_HELP_STRING([--enable-smtp], [include internal SMTP relay support]),
[if test $enableval = yes; then
AC_DEFINE(USE_SMTP, 1, [Include internal SMTP relay support])
MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS smtp.o"
need_socket="yes"
fi])
if test x"$need_imap" = xyes -o x"$need_pop" = xyes ; then
MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS bcache.o"
fi
......
......@@ -115,6 +115,10 @@ WHERE char *Sendmail;
WHERE char *Shell;
WHERE char *Signature;
WHERE char *SimpleSearch;
#if USE_SMTP
WHERE char *SmtpUrl INITVAL (NULL);
WHERE char *SmtpAuthenticators INITVAL (NULL);
#endif /* USE_SMTP */
WHERE char *Spoolfile;
WHERE char *SpamSep;
#if defined(USE_SSL)
......
......@@ -92,6 +92,9 @@ struct option_t
# ifndef USE_POP
# define USE_POP
# endif
# ifndef USE_SMTP
# define USE_SMTP
# endif
# ifndef USE_SSL_OPENSSL
# define USE_SSL_OPENSSL
# endif
......@@ -2550,6 +2553,34 @@ struct option_t MuttVars[] = {
** messages from the current folder. The default is to pause one second, so
** a value of zero for this option suppresses the pause.
*/
#if USE_SMTP
{ "smtp_url", DT_STR, R_NONE, UL &SmtpUrl, UL 0 },
/*
** .pp
** Defines the SMTP ``smart'' host where sent messages should relayed for
** delivery. This should take the form of an SMTP URL, eg:
** .pp
** smtp[s]://[user[:pass]@]host[:port]/
** .pp
** Setting this variable overrides the value of the ``$$sendmail''
** variable.
*/
# ifdef USE_SASL
{ "smtp_authenticators", DT_STR, R_NONE, UL &SmtpAuthenticators, UL 0 },
/*
** .pp
** This is a colon-delimited list of authentication methods mutt may
** attempt to use to log in to an SMTP server, in the order mutt should
** try them. Authentication methods are any SASL mechanism, eg
** 'digest-md5', 'gssapi' or 'cram-md5'.
** This parameter is case-insensitive. If this parameter is unset
** (the default) mutt will try all available methods, in order from
** most-secure to least-secure.
** .pp
** Example: set smtp_authenticators="digest-md5:cram-md5"
*/
# endif /* USE_SASL */
#endif /* USE_SMTP */
{ "sort", DT_SORT, R_INDEX|R_RESORT, UL &Sort, SORT_DATE },
/*
** .pp
......@@ -2945,7 +2976,10 @@ struct option_t MuttVars[] = {
/*
** .pp
** Controls whether mutt writes out the Bcc header when preparing
** messages to be sent. Exim users may wish to unset this.
** messages to be sent. Exim users may wish to unset this. If mutt
** is set to deliver directly via SMTP (see ``$$smtp_url''), this
** option does nothing: mutt will never write out the BCC header
** in this case.
*/
/*--*/
{ NULL }
......
......@@ -257,6 +257,12 @@ static void show_version (void)
"-USE_IMAP "
#endif
#ifdef USE_SMTP
"+USE_SMTP "
#else
"-USE_SMTP "
#endif
#ifdef USE_GSS
"+USE_GSS "
#else
......
......@@ -182,42 +182,44 @@ int mutt_sasl_client_new (CONNECTION* conn, sasl_conn_t** saslconn)
case M_ACCT_TYPE_POP:
service = "pop";
break;
case M_ACCT_TYPE_SMTP:
service = "smtp";
break;
default:
dprint (1, (debugfile, "mutt_sasl_client_new: account type unset\n"));
mutt_error (_("Unknown SASL profile"));
return -1;
}
size = sizeof (local);
if (getsockname (conn->fd, (struct sockaddr *)&local, &size)){
dprint (1, (debugfile, "mutt_sasl_client_new: getsockname for local failed\n"));
if (getsockname (conn->fd, (struct sockaddr *)&local, &size)) {
mutt_error (_("SASL failed to get local IP address"));
return -1;
}
else
if (iptostring((struct sockaddr *)&local, size, iplocalport, IP_PORT_BUFLEN) != SASL_OK){
dprint (1, (debugfile, "mutt_sasl_client_new: iptostring for local failed\n"));
if (iptostring((struct sockaddr *)&local, size, iplocalport, IP_PORT_BUFLEN) != SASL_OK) {
mutt_error (_("SASL failed to parse local IP address"));
return -1;
}
size = sizeof (remote);
if (getpeername (conn->fd, (struct sockaddr *)&remote, &size)){
dprint (1, (debugfile, "mutt_sasl_client_new: getsockname for remote failed\n"));
mutt_error (_("SASL failed to get remote IP address"));
return -1;
}
else
if (iptostring((struct sockaddr *)&remote, size, ipremoteport, IP_PORT_BUFLEN) != SASL_OK){
dprint (1, (debugfile, "mutt_sasl_client_new: iptostring for remote failed\n"));
mutt_error (_("SASL failed to parse remote IP address"));
return -1;
}
dprint(1,(debugfile, "local ip: %s, remote ip:%s\n", iplocalport, ipremoteport));
dprint(2, (debugfile, "local ip: %s, remote ip:%s\n", iplocalport, ipremoteport));
rc = sasl_client_new (service, conn->account.host, iplocalport, ipremoteport,
mutt_sasl_get_callbacks (&conn->account), 0, saslconn);
if (rc != SASL_OK)
{
dprint (1, (debugfile,
"mutt_sasl_client_new: Error allocating SASL connection\n"));
mutt_error (_("Error allocating SASL connection"));
return -1;
}
......@@ -227,8 +229,7 @@ int mutt_sasl_client_new (CONNECTION* conn, sasl_conn_t** saslconn)
secprops.maxbufsize = M_SASL_MAXBUF;
if (sasl_setprop (*saslconn, SASL_SEC_PROPS, &secprops) != SASL_OK)
{
dprint (1, (debugfile,
"mutt_sasl_client_new: Error setting security properties\n"));
mutt_error (_("Error setting SASL security properties"));
return -1;
}
......@@ -238,13 +239,13 @@ int mutt_sasl_client_new (CONNECTION* conn, sasl_conn_t** saslconn)
dprint (2, (debugfile, "External SSF: %d\n", conn->ssf));
if (sasl_setprop (*saslconn, SASL_SSF_EXTERNAL, &(conn->ssf)) != SASL_OK)
{
dprint (1, (debugfile, "mutt_sasl_client_new: Error setting external properties\n"));
mutt_error (_("Error setting SASL external security strength"));
return -1;
}
dprint (2, (debugfile, "External authentication name: %s\n", conn->account.user));
if (sasl_setprop (*saslconn, SASL_AUTH_EXTERNAL, conn->account.user) != SASL_OK)
{
dprint (1, (debugfile, "mutt_sasl_client_new: Error setting external properties\n"));
{
mutt_error (_("Error setting SASL external user name"));
return -1;
}
}
......
......@@ -340,6 +340,10 @@ int mutt_save_attachment (FILE *, BODY *, char *, int, HEADER *);
int _mutt_save_message (HEADER *, CONTEXT *, int, int, int);
int mutt_save_message (HEADER *, int, int, int, int *);
int mutt_search_command (int, int);
#ifdef USE_SMTP
int mutt_smtp_send (const ADDRESS *, const ADDRESS *, const ADDRESS *,
const ADDRESS *, const char *, int);
#endif
int mutt_strwidth (const char *);
int mutt_compose_menu (HEADER *, char *, size_t, HEADER *);
int mutt_thread_set_flag (HEADER *, int, int, int);
......
......@@ -960,18 +960,30 @@ static int send_message (HEADER *msg)
char tempfile[_POSIX_PATH_MAX];
FILE *tempfp;
int i;
#ifdef USE_SMTP
short old_write_bcc;
#endif
/* Write out the message in MIME form. */
mutt_mktemp (tempfile);
if ((tempfp = safe_fopen (tempfile, "w")) == NULL)
return (-1);
#ifdef USE_SMTP
old_write_bcc = option (OPTWRITEBCC);
if (SmtpUrl)
unset_option (OPTWRITEBCC);
#endif
#ifdef MIXMASTER
mutt_write_rfc822_header (tempfp, msg->env, msg->content, 0, msg->chain ? 1 : 0);
#endif
#ifndef MIXMASTER
mutt_write_rfc822_header (tempfp, msg->env, msg->content, 0, 0);
#endif
#ifdef USE_SMTP
if (old_write_bcc)
set_option (OPTWRITEBCC);
#endif
fputc ('\n', tempfp); /* tie off the header. */
......@@ -994,8 +1006,16 @@ static int send_message (HEADER *msg)
return mix_send_message (msg->chain, tempfile);
#endif
#if USE_SMTP
if (SmtpUrl)
return mutt_smtp_send (msg->env->from, msg->env->to, msg->env->cc,
msg->env->bcc, tempfile,
(msg->content->encoding == ENC8BIT));
#endif /* USE_SMTP */
i = mutt_invoke_sendmail (msg->env->from, msg->env->to, msg->env->cc,
msg->env->bcc, tempfile, (msg->content->encoding == ENC8BIT));
msg->env->bcc, tempfile,
(msg->content->encoding == ENC8BIT));
return (i);
}
......
......@@ -2361,6 +2361,12 @@ static int _mutt_bounce_message (FILE *fp, HEADER *h, ADDRESS *to, const char *r
mutt_copy_bytes (fp, f, h->content->length);
fclose (f);
#if USE_SMTP
if (SmtpUrl)
ret = mutt_smtp_send (env_from, to, NULL, NULL, tempfile,
h->content->encoding == ENC8BIT);
else
#endif /* USE_SMTP */
ret = mutt_invoke_sendmail (env_from, to, NULL, NULL, tempfile,
h->content->encoding == ENC8BIT);
}
......@@ -2611,7 +2617,7 @@ int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int post,
rewind (tempfp);
while (fgets (sasha, sizeof (sasha), tempfp) != NULL)
lines++;
fprintf (msg->fp, "Content-Length: " OFF_T_FMT "\n", ftello (tempfp));
fprintf (msg->fp, "Content-Length: " OFF_T_FMT "\n", (LOFF_T) ftell (tempfp));
fprintf (msg->fp, "Lines: %d\n\n", lines);
/* copy the body and clean up */
......
This diff is collapsed.
......@@ -37,10 +37,12 @@ static struct mapping_t UrlMap[] =
{ "file", U_FILE },
{ "imap", U_IMAP },
{ "imaps", U_IMAPS },
{ "pop", U_POP },
{ "pops", U_POPS },
{ "pop", U_POP },
{ "pops", U_POPS },
{ "mailto", U_MAILTO },
{ NULL, U_UNKNOWN}
{ "smtp", U_SMTP },
{ "smtps", U_SMTPS },
{ NULL, U_UNKNOWN }
};
......
......@@ -8,6 +8,8 @@ typedef enum url_scheme
U_POPS,
U_IMAP,
U_IMAPS,
U_SMTP,
U_SMTPS,
U_MAILTO,
U_UNKNOWN
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment