chiark / gitweb /
Use system sendmail if available (rather than SMTP over TCP)
authorRichard Kettlewell <rjk@greenend.org.uk>
Sun, 1 Jun 2008 14:15:28 +0000 (15:15 +0100)
committerRichard Kettlewell <rjk@greenend.org.uk>
Sun, 1 Jun 2008 14:15:28 +0000 (15:15 +0100)
CHANGES.html
README
configure.ac
doc/disorder_config.5.in
lib/Makefile.am
lib/configuration.c
lib/configuration.h
lib/defs.c
lib/defs.h
lib/sendmail.c
scripts/sedfiles.make

index 9a60a44..a0dad8e 100644 (file)
@@ -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).</p>
 
+  <p>Mail is now sent via the system sendmail program, though it remains
+  possible to use TCP to connect to an SMTP server.  See <tt>sendmail</tt> and
+  <tt>smtp_server</tt> in disorder_config(5).</p>
+  
 </div>
 
 </div>
diff --git a/README b/README
index d9bdde9..8aa4ccd 100644 (file)
--- 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
 
index 3459400..18380c0 100644 (file)
@@ -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
index 952b2b9..ea3a4bf 100644 (file)
@@ -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.
index ba53792..ce28475 100644 (file)
@@ -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
index c66f66b..241d101 100644 (file)
@@ -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 */
index 51dc835..cc7e1e3 100644 (file)
@@ -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;
 
index 084bf0a..67f7951 100644 (file)
@@ -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.
index 94f7059..73d633e 100644 (file)
@@ -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 */
 
index 8f75343..12291b8 100644 (file)
@@ -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;
 }
 
index cbae8c1..5b7a649 100644 (file)
@@ -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 \