Attached is Michael Elkins' SMTP relay patch patch.me.smtp.3 ported to 1.5.10. I've replaced smtp_host with smtp_url so you can override the port, and because I intend to add AUTH and TLS support to it shortly. It's such a tiny patch that I have a hard time considering it to be bloat, and if it isn't very full-featured, nothing stops you from using the standard process-based interface. Apologies in advance if this starts a flamefest.
diff -r 31066b9fe2ab Makefile.am --- a/Makefile.am Tue Sep 6 23:47:38 2005 +++ b/Makefile.am Tue Sep 6 11:35:18 2005 @@ -61,7 +61,7 @@ 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.c mutt_ssl_gnutls.c \ crypt-gpgme.c crypt-mod-pgp-gpgme.c crypt-mod-smime-gpgme.c diff -r 31066b9fe2ab account.h --- a/account.h Tue Sep 6 23:47:38 2005 +++ b/account.h Tue Sep 6 11:35:18 2005 @@ -28,7 +28,8 @@ { M_ACCT_TYPE_NONE = 0, M_ACCT_TYPE_IMAP, - M_ACCT_TYPE_POP + M_ACCT_TYPE_POP, + M_ACCT_TYPE_SMTP }; /* account flags */ diff -r 31066b9fe2ab configure.in --- a/configure.in Tue Sep 6 23:47:38 2005 +++ b/configure.in Tue Sep 6 11:35:18 2005 @@ -512,6 +512,13 @@ fi ]) 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]) dnl -- end socket dependencies -- diff -r 31066b9fe2ab globals.h --- a/globals.h Tue Sep 6 23:47:38 2005 +++ b/globals.h Tue Sep 6 11:35:18 2005 @@ -108,6 +108,9 @@ WHERE char *Shell; WHERE char *Signature; WHERE char *SimpleSearch; +#if USE_SMTP +WHERE char *SmtpUrl; +#endif /* USE_SMTP */ WHERE char *Spoolfile; WHERE char *SpamSep; #if defined(USE_SSL) || defined(USE_GNUTLS) diff -r 31066b9fe2ab init.h --- a/init.h Tue Sep 6 23:47:38 2005 +++ b/init.h Tue Sep 6 11:35:18 2005 @@ -91,6 +91,9 @@ # endif # ifndef USE_POP # define USE_POP +# endif +# ifndef USE_SMTP +# define USE_SMTP # endif # ifndef USE_SSL # define USE_SSL @@ -2486,6 +2489,19 @@ ** 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, NULL }, + /* + ** .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://[user[:pass]@]host[:port]/ + ** .pp + ** Setting this variable overrides the value of the ``$$sendmail'' + ** variable. + */ +#endif /* USE_SMTP */ { "sort", DT_SORT, R_INDEX|R_RESORT, UL &Sort, SORT_DATE }, /* ** .pp diff -r 31066b9fe2ab mutt_socket.h --- a/mutt_socket.h Tue Sep 6 23:47:38 2005 +++ b/mutt_socket.h Tue Sep 6 11:35:18 2005 @@ -56,7 +56,7 @@ int mutt_socket_readchar (CONNECTION *conn, char *c); #define mutt_socket_readln(A,B,C) mutt_socket_readln_d(A,B,C,M_SOCK_LOG_CMD) int mutt_socket_readln_d (char *buf, size_t buflen, CONNECTION *conn, int dbg); -#define mutt_socket_write(A,B) mutt_socket_write_d(A,B,M_SOCK_LOG_CMD); +#define mutt_socket_write(A,B) mutt_socket_write_d(A,B,M_SOCK_LOG_CMD) int mutt_socket_write_d (CONNECTION *conn, const char *buf, int dbg); /* stupid hack for imap_logout_all */ diff -r 31066b9fe2ab protos.h --- a/protos.h Tue Sep 6 23:47:38 2005 +++ b/protos.h Tue Sep 6 11:35:18 2005 @@ -342,6 +342,9 @@ 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 (ADDRESS *, ADDRESS *, ADDRESS *, ADDRESS *, const char *); +#endif int mutt_strwidth (const char *); int mutt_compose_menu (HEADER *, char *, size_t, HEADER *); int mutt_thread_set_flag (HEADER *, int, int, int); diff -r 31066b9fe2ab send.c --- a/send.c Tue Sep 6 23:47:38 2005 +++ b/send.c Tue Sep 6 11:35:18 2005 @@ -990,6 +990,12 @@ 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); +#endif /* USE_SMTP */ + i = mutt_invoke_sendmail (msg->env->from, msg->env->to, msg->env->cc, msg->env->bcc, tempfile, (msg->content->encoding == ENC8BIT)); return (i); diff -r 31066b9fe2ab sendlib.c --- a/sendlib.c Tue Sep 6 23:47:38 2005 +++ b/sendlib.c Tue Sep 6 11:35:18 2005 @@ -2169,6 +2169,11 @@ 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); + else +#endif /* USE_SMTP */ ret = mutt_invoke_sendmail (env_from, to, NULL, NULL, tempfile, h->content->encoding == ENC8BIT); } diff -r 31066b9fe2ab url.c --- a/url.c Tue Sep 6 23:47:38 2005 +++ b/url.c Tue Sep 6 11:35:18 2005 @@ -37,10 +37,11 @@ { "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 }, + { NULL, U_UNKNOWN } }; diff -r 31066b9fe2ab url.h --- a/url.h Tue Sep 6 23:47:38 2005 +++ b/url.h Tue Sep 6 11:35:18 2005 @@ -8,6 +8,7 @@ U_POPS, U_IMAP, U_IMAPS, + U_SMTP, U_MAILTO, U_UNKNOWN } diff -r 31066b9fe2ab smtp.c --- /dev/null Tue Sep 6 23:47:38 2005 +++ b/smtp.c Tue Sep 6 11:35:18 2005 @@ -0,0 +1,239 @@ +/* mutt - text oriented MIME mail user agent + * Copyright (C) 2002 Michael R. Elkins <me@xxxxxxxx> + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + */ + +/* This file contains code for direct SMTP delivery of email messages. */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mutt.h" +#include "mutt_socket.h" + +#include <netdb.h> + +#define smtp_success(x) ((x)/100 == 2) +#define smtp_continue 354 + +#define smtp_err_read -2 +#define smtp_err_write -3 + +#define SMTP_PORT 25 + +static int smtp_fill_account (ACCOUNT *account); + +/* Reads a command response from the SMTP server. + * Returns: + * 0 on success (2xx code) or continue (354 code) + * -1 write error, or any other response code + */ +static int +smtp_get_resp (CONNECTION * conn) +{ + int n; + char buf[1024]; + + n = mutt_socket_readln (buf, sizeof (buf), conn); + if (n == -1) + return smtp_err_read; + n = atoi (buf); + if (smtp_success (n) || n == smtp_continue) + return 0; + mutt_error (_("SMTP session failed: %s"), buf); + return -1; +} + +static int +smtp_rcpt_to (CONNECTION * conn, ADDRESS * a) +{ + char buf[1024]; + int r; + + while (a) + { + snprintf (buf, sizeof (buf), "RCPT TO: <%s>\r\n", a->mailbox); + if (mutt_socket_write (conn, buf) == -1) + return smtp_err_write; + if ((r = smtp_get_resp (conn))) + return r; + a = a->next; + } + return 0; +} + +static int +smtp_data (CONNECTION * conn, const char *msgfile) +{ + FILE *fp = 0; + char buf[1024]; + int r; + + fp = fopen (msgfile, "r"); + if (!fp) + { + mutt_error ("SMTP session failed: unable to open %s", msgfile); + return -1; + } + + snprintf (buf, sizeof (buf), "DATA\r\n"); + if (mutt_socket_write (conn, buf) == -1) + { + fclose (fp); + return smtp_err_write; + } + if ((r = smtp_get_resp (conn))) + { + fclose (fp); + return r; + } + + while (fgets (buf, sizeof (buf), fp)) + { + if (buf[0] == '.') + if (mutt_socket_write (conn, ".") == -1) + { + fclose (fp); + return smtp_err_write; + } + if (mutt_socket_write (conn, buf) == -1) + { + fclose (fp); + return smtp_err_write; + } + } + fclose (fp); + + /* terminate the message body */ + if (mutt_socket_write (conn, ".\r\n") == -1) + return smtp_err_write; + + if ((r = smtp_get_resp (conn))) + return r; + + return 0; +} + +int +mutt_smtp_send (ADDRESS * from, ADDRESS * to, ADDRESS * cc, ADDRESS * bcc, + const char *msgfile) +{ + CONNECTION *conn; + ACCOUNT account; + int ret = -1; + char buf[1024]; + + if (smtp_fill_account (&account) < 0) + return ret; + + if (!(conn = mutt_conn_find (NULL, &account))) + return -1; + + do + { + if (mutt_socket_open (conn)) + break; + + /* get greeting string */ + if ((ret = smtp_get_resp (conn))) + break; + + /* send our greeting */ + snprintf (buf, sizeof (buf), "HELO %s\r\n", Hostname); + /* XXX there should probably be a wrapper in mutt_socket.c that + * repeatedly calls conn->write until all data is sent. This + * currently doesn't check for a short write. + */ + if (mutt_socket_write (conn, buf) == -1) + { + ret = smtp_err_write; + break; + } + if ((ret = smtp_get_resp (conn))) + break; + + /* send the sender's address */ + snprintf (buf, sizeof (buf), "MAIL FROM: <%s>\r\n", from->mailbox); + if (mutt_socket_write (conn, buf) == -1) + { + ret = smtp_err_write; + break; + } + if ((ret = smtp_get_resp (conn))) + break; + + /* send the recipient list */ + if ((ret = smtp_rcpt_to (conn, to)) || (ret = smtp_rcpt_to (conn, cc)) + || (ret = smtp_rcpt_to (conn, bcc))) + break; + + /* send the message data */ + if ((ret = smtp_data (conn, msgfile))) + break; + + mutt_socket_write (conn, "QUIT\r\n"); + + ret = 0; + } + while (0); + + if (conn) + mutt_socket_free (conn); + + if (ret == smtp_err_read) + mutt_error (_("SMTP session failed: read error")); + else if (ret == smtp_err_write) + mutt_error (_("SMTP session failed: write error")); + + return ret; +} + +static int smtp_fill_account (ACCOUNT *account) +{ + static unsigned short SmtpPort = 0; + + struct servent* service; + ciss_url_t url; + char* urlstr; + + if (!SmtpPort) + { + service = getservbyname ("smtp", "tcp"); + if (service) + SmtpPort = ntohs (service->s_port); + else + SmtpPort = SMTP_PORT; + dprint (3, (debugfile, "Using default SMTP port %d\n", SmtpPort)); + } + + account->flags = 0; + account->port = SmtpPort; + account->type = M_ACCT_TYPE_SMTP; + + urlstr = safe_strdup (SmtpUrl); + url_parse_ciss (&url, SmtpUrl); + if (url.scheme != U_SMTP || mutt_account_fromurl (account, &url) < 0) + { + FREE (&urlstr); + mutt_error (_("Invalid SMTP URL: %s"), SmtpUrl); + mutt_sleep (1); + return -1; + } + + FREE (&urlstr); + return 0; +}
Attachment:
pgpKQzTw0kxY8.pgp
Description: PGP signature