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