/*
* This file is part of DisOrder
- * Copyright (C) 2007 Richard Kettlewell
+ * Copyright (C) 2007-2008 Richard Kettlewell
*
* 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
* USA
*/
-#include <config.h>
-#include "types.h"
+#include "common.h"
-#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/socket.h>
#include "hostname.h"
#include "sendmail.h"
#include "base64.h"
+#include "wstat.h"
/** @brief Get a server response
* @param tag Server name
* @param recipient Recipient address
* @param subject Subject string
* @param encoding Body encoding
- * @param body_type Content-type of body
+ * @param content_type Content-type of body
* @param body Text of body (encoded, but \n for newline)
* @return 0 on success, non-0 on error
*/
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")))
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;
}