X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/5aff007d8fcfb4c6cc3c3627ae15f45562db7a0d..4265e5d362914f3732b4035dcf67162e525e0142:/lib/sendmail.c diff --git a/lib/sendmail.c b/lib/sendmail.c index 95ad2a1..a01b9d3 100644 --- a/lib/sendmail.c +++ b/lib/sendmail.c @@ -2,26 +2,28 @@ * This file is part of DisOrder * Copyright (C) 2007-2008 Richard Kettlewell * - * This program is free software; you can redistribute it and/or modify + * 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 + * the Free Software Foundation, either version 3 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. - * + * + * 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-1307 - * USA + * along with this program. If not, see . */ +/** @file lib/sendmail.c + * @brief Sending email + * + * Can send email either via a local MTA or by connecting to an SMTP TCP port. + * The former is preferred as there is a strong implication that the local MTA + * will queue for you than some random TCP SMTP server you found. + */ +#include "common.h" -#include -#include "types.h" - -#include #include #include #include @@ -39,6 +41,7 @@ #include "hostname.h" #include "sendmail.h" #include "base64.h" +#include "wstat.h" /** @brief Get a server response * @param tag Server name @@ -123,7 +126,7 @@ static int sendmailfp(const char *tag, FILE *in, FILE *out, time_t now; char date[128]; - time(&now); + xtime(&now); gmtime_r(&now, &ut); strftime(date, sizeof date, "%a, %d %b %Y %H:%M:%S +0000", &ut); gcry_create_nonce(idbuf, sizeof idbuf); @@ -208,33 +211,55 @@ int sendmail(const char *sender, char *tag; int fdin, fdout, rc; FILE *in, *out; + pid_t pid = -1; static const struct addrinfo pref = { - 0, - PF_INET, - SOCK_STREAM, - IPPROTO_TCP, - 0, - 0, - 0, - 0 + .ai_flags = 0, + .ai_family = PF_INET, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, }; /* 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"))) @@ -243,6 +268,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) + info("warning: %s -bs: %s", config->sendmail, wstat(w)); + /* Not fatal - we determine success/failure from the SMTP conversation. + * Some MTAs exit nonzero if you don't QUIT, which is just stupidly + * picky. */ + } return rc; }