From: Richard Kettlewell Date: Sun, 1 Jun 2008 14:15:28 +0000 (+0100) Subject: Use system sendmail if available (rather than SMTP over TCP) X-Git-Tag: 4.0~44 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/commitdiff_plain/2eee4b0cd743865445a5023e8c10467cdc9b350e Use system sendmail if available (rather than SMTP over TCP) --- diff --git a/CHANGES.html b/CHANGES.html index 9a60a44..a0dad8e 100644 --- a/CHANGES.html +++ b/CHANGES.html @@ -126,6 +126,10 @@ span.command { is possible to define macros to avoid repetition, and the documentation is less monolithic (see disorder.cgi(8) as a starting point).

+

Mail is now sent via the system sendmail program, though it remains + possible to use TCP to connect to an SMTP server. See sendmail and + smtp_server in disorder_config(5).

+ diff --git a/README b/README index d9bdde9..8aa4ccd 100644 --- a/README +++ b/README @@ -204,9 +204,15 @@ You need to configure a number of things to make this work: mail_sender webmaster@example.com - By default the web interface sends mail by connecting to the SMTP port of - 127.0.0.1. You can override this with the smtp_server directive, for - exampler: + By default the web interface sends mail via the system sendmail executable + (typically /usr/sbin/sendmail or /usr/lib/sendmail). You can override this + with the sendmail directive, for example: + + sendmail /usr/sbin/my-sendmail + + The executable you choose must support the -bs option. Alternatively you + can tell it to connect to an SMTP server via TCP, with the smtp_server + directive. For example: smtp_server mail.example.com diff --git a/configure.ac b/configure.ac index 3459400..18380c0 100644 --- a/configure.ac +++ b/configure.ac @@ -221,6 +221,8 @@ missing_functions="" AC_DEFINE(_GNU_SOURCE, 1, [required for e.g. strsignal]) +AC_PATH_PROG([SENDMAIL],[sendmail],[none],[$PATH:/usr/sbin:/usr/lib]) + # Macs might have libraries under fink's root AC_PATH_PROG([FINK],[fink],[none],[$PATH:/sw/bin]) if test "x$FINK" != xnone; then diff --git a/doc/disorder_config.5.in b/doc/disorder_config.5.in index 952b2b9..ea3a4bf 100644 --- a/doc/disorder_config.5.in +++ b/doc/disorder_config.5.in @@ -725,6 +725,12 @@ This must be set if you have online registration enabled. Specifies the maximum refresh period in seconds. Default 15. .TP +.B sendmail \fIPATH\fR +The path to the Sendmail executable. +This must support the \fB-bs\fR option (Postfix, Exim and Sendmail should all +work). +The default is the sendmail executable found at compile time. +.TP .B short_display \fICHARACTERS\fR Defines the maximum number of characters to include in a \fBshort\fR name part. @@ -733,6 +739,7 @@ Default 30. .B smtp_server \fIHOSTNAME\fR The hostname (or address) of the SMTP server to use for sending mail. The default is 127.0.0.1. +If \fBsendmail\fR is set then that is used instead. .TP .B transform \fITYPE\fR \fIREGEXP\fR \fISUBST\fR [\fICONTEXT\fR [\fIREFLAGS\fR]] Determines how names are sorted and displayed in track choice displays. diff --git a/lib/Makefile.am b/lib/Makefile.am index ba53792..ce28475 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -112,6 +112,7 @@ definitions.h: Makefile echo "#define SBINDIR \"${sbindir}/\"" >> $@.new echo "#define BINDIR \"${bindir}/\"" >> $@.new echo "#define FINKBINDIR \"${finkbindir}/\"" >> $@.new + echo "#define SENDMAIL \"${SENDMAIL}\"" >> $@.new @if cmp $@.new $@; then \ echo rm -f $@.new; rm -f $@.new; else \ echo mv $@.new $@; mv $@.new $@; fi diff --git a/lib/configuration.c b/lib/configuration.c index c66f66b..241d101 100644 --- a/lib/configuration.c +++ b/lib/configuration.c @@ -962,6 +962,7 @@ static const struct conf conf[] = { { C2(restrict, restrictions), &type_restrict, validate_any }, { C(sample_format), &type_sample_format, validate_sample_format }, { C(scratch), &type_string_accum, validate_isreg }, + { C(sendmail), &type_string, validate_isabspath }, { C(short_display), &type_integer, validate_positive }, { C(signal), &type_signal, validate_any }, { C(smtp_server), &type_string, validate_any }, @@ -1190,6 +1191,8 @@ static struct config *config_default(void) { c->dbversion = 2; c->cookie_login_lifetime = 86400; c->cookie_key_lifetime = 86400 * 7; + if(sendmail_binary[0] && strcmp(sendmail_binary, "none")) + c->sendmail = xstrdup(sendmail_binary); c->smtp_server = xstrdup("127.0.0.1"); c->new_max = 100; c->reminder_interval = 600; /* 10m */ diff --git a/lib/configuration.h b/lib/configuration.h index 51dc835..cc7e1e3 100644 --- a/lib/configuration.h +++ b/lib/configuration.h @@ -272,6 +272,9 @@ struct config { /** @brief Default rights for a new user */ char *default_rights; + /** @brief Path to sendmail executable */ + char *sendmail; + /** @brief SMTP server for sending mail */ char *smtp_server; diff --git a/lib/defs.c b/lib/defs.c index 084bf0a..67f7951 100644 --- a/lib/defs.c +++ b/lib/defs.c @@ -49,6 +49,9 @@ const char bindir[] = BINDIR; /** @brief System binary directory */ const char sbindir[] = SBINDIR; +/** @brief System sendmail executable */ +const char sendmail_binary[] = SENDMAIL; + /** @brief Fink binary directory * * Meaningless if not on a Mac. diff --git a/lib/defs.h b/lib/defs.h index 94f7059..73d633e 100644 --- a/lib/defs.h +++ b/lib/defs.h @@ -30,6 +30,7 @@ extern const char pkgdatadir[]; extern const char bindir[]; extern const char sbindir[]; extern const char finkbindir[]; +extern const char sendmail_binary[]; #endif /* DEFS_H */ diff --git a/lib/sendmail.c b/lib/sendmail.c index 8f75343..12291b8 100644 --- a/lib/sendmail.c +++ b/lib/sendmail.c @@ -37,6 +37,7 @@ #include "hostname.h" #include "sendmail.h" #include "base64.h" +#include "wstat.h" /** @brief Get a server response * @param tag Server name @@ -206,6 +207,7 @@ int sendmail(const char *sender, char *tag; int fdin, fdout, rc; FILE *in, *out; + pid_t pid = -1; static const struct addrinfo pref = { .ai_flags = 0, @@ -215,20 +217,45 @@ int sendmail(const char *sender, }; /* Find the SMTP server */ - a.n = 2; - a.s = s; - s[0] = config->smtp_server; - s[1] = (char *)"smtp"; - if(!(ai = get_address(&a, &pref, &tag))) - return -1; - fdin = xsocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if(connect(fdin, ai->ai_addr, ai->ai_addrlen) < 0) { - error(errno, "error connecting to %s", tag); - xclose(fdin); - return -1; + if(config->sendmail && config->sendmail[0]) { + int inpipe[2], outpipe[2]; + + /* If it's a path name, use -bs mode. Exim, Postfix and Sendmail all claim + * to support this. */ + xpipe(inpipe); /* sendmail's stdin */ + xpipe(outpipe); /* sendmail's stdout */ + if(!(pid = xfork())) { + exitfn = _exit; + signal(SIGPIPE, SIG_DFL); + xdup2(inpipe[0], 0); + xclose(inpipe[1]); + xclose(outpipe[0]); + xdup2(outpipe[1], 1); + execlp(config->sendmail, + config->sendmail, "-bs", (char *)0); + fatal(errno, "executing %s", config->sendmail); + } + xclose(inpipe[0]); + xclose(outpipe[1]); + fdin = outpipe[0]; /* read from sendmail's stdout */ + fdout = inpipe[1]; /* write to sendmail's stdin */ + tag = config->sendmail; + } else { + a.n = 2; + a.s = s; + s[0] = config->smtp_server; + s[1] = (char *)"smtp"; + if(!(ai = get_address(&a, &pref, &tag))) + return -1; + fdin = xsocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if(connect(fdin, ai->ai_addr, ai->ai_addrlen) < 0) { + error(errno, "error connecting to %s", tag); + xclose(fdin); + return -1; + } + if((fdout = dup(fdin)) < 0) + fatal(errno, "error calling dup2"); } - if((fdout = dup(fdin)) < 0) - fatal(errno, "error calling dup2"); if(!(in = fdopen(fdin, "rb"))) fatal(errno, "error calling fdopen"); if(!(out = fdopen(fdout, "wb"))) @@ -237,6 +264,19 @@ int sendmail(const char *sender, encoding, content_type, body); fclose(in); fclose(out); + if(pid != -1) { + int w; + + while(waitpid(pid, &w, 0) < 0 && errno == EINTR) + ; + if(w < 0) + fatal(errno, "error calling waitpid"); + if(w) { + error(0, "%s -bs: %s", config->sendmail, wstat(w)); + if(!rc) + rc = -1; + } + } return rc; } diff --git a/scripts/sedfiles.make b/scripts/sedfiles.make index cbae8c1..5b7a649 100644 --- a/scripts/sedfiles.make +++ b/scripts/sedfiles.make @@ -25,6 +25,7 @@ $(SEDFILES) : % : %.in Makefile -e 's!pkgconfdir!${sysconfdir}/disorder!g;' \ -e 's!pkgstatedir!${localstatedir}/disorder!g;' \ -e 's!pkgdatadir!${pkgdatadir}!g;' \ + -e 's!SENDMAIL!${SENDMAIL}!g;' \ -e 's!_version_!${VERSION}!g;' \ < $< > $@.new @if test -x $<; then \