/* Module to send mail using a "sendmail" program.
*
* IRC Services is copyright (c) 1996-2007 Andrew Church.
* E-mail: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file COPYING for
* details.
*/
#include "services.h"
#include "modules.h"
#include "conffile.h"
#include "language.h"
#include "mail.h"
#include "mail-local.h"
#include <sys/wait.h> /* for WIFEXITED(), etc. */
/*************************************************************************/
static Module *module;
static char *SendmailPath;
static Module *module_mail_main;
static typeof(low_send) *low_send_p;
/*************************************************************************/
/***************************** Mail sending ******************************/
/*************************************************************************/
static int send_sendmail(const char *from, const char *fromname,
const char *to, const char *subject, const char *body)
{
FILE *pipe;
char cmd[PATH_MAX+4];
char buf[BUFSIZE], *s;
int res;
time_t t;
snprintf(cmd, sizeof(cmd), "%s -t", SendmailPath);
pipe = popen(cmd, "w");
if (!pipe) {
module_log_perror("Unable to execute %s", SendmailPath);
return -1;
}
/* Quote all double-quotes in from-name string */
if (*fromname) {
s = buf;
while (s < buf+sizeof(buf)-2 && *fromname) {
if (*fromname == '"')
*s++ = '\\';
*s++ = *fromname++;
}
*s = 0;
fprintf(pipe, "From: %s <%s>\n", buf, from);
} else {
fprintf(pipe, "From: %s\n", from);
}
time(&t);
if (!strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S", gmtime(&t)))
strscpy(buf, "Thu, 1 Jan 1970 00:00:00", sizeof(buf));
fprintf(pipe, "To: %s\nSubject: %s\nDate: %s +0000\n\n%s\n",
to, subject, buf, body);
res = pclose(pipe);
if (res == -1) {
module_log_perror("pclose() failed");
} else if (res != 0) {
if (debug >= 2)
module_log("debug: sendmail exit code = %04X\n", res);
module_log("%s exited with %s %d%s", SendmailPath,
WIFEXITED(res) ? "code" : "signal",
WIFEXITED(res) ? WEXITSTATUS(res) : WTERMSIG(res),
WIFEXITED(res) && WEXITSTATUS(res)==127 ? " (unable to execute program?)" : "");
return -1;
}
return 0;
}
/*************************************************************************/
/***************************** Module stuff ******************************/
/*************************************************************************/
const int32 module_version = MODULE_VERSION_CODE;
static int do_SendmailPath(const char *filename, int linenum, char *param);
ConfigDirective module_config[] = {
{ "SendmailPath", { { CD_FUNC, CF_DIRREQ, do_SendmailPath } } },
{ NULL }
};
/*************************************************************************/
static int do_SendmailPath(const char *filename, int linenum, char *param)
{
static char *new_SendmailPath = NULL;
if (filename) {
/* Check parameter for validity and save */
if (*param != '/') {
config_error(filename, linenum,
"SendmailPath value must begin with a slash (`/')");
return 0;
}
free(new_SendmailPath);
new_SendmailPath = strdup(param);
if (!new_SendmailPath) {
config_error(filename, linenum, "Out of memory");
return 0;
}
} else if (linenum == CDFUNC_SET) {
/* Copy new values to config variables and clear */
if (new_SendmailPath) { /* paranoia */
free(SendmailPath);
SendmailPath = new_SendmailPath;
} else {
free(new_SendmailPath);
}
new_SendmailPath = NULL;
} else if (linenum == CDFUNC_DECONFIG) {
/* Reset to defaults */
free(SendmailPath);
SendmailPath = NULL;
}
return 1;
}
/*************************************************************************/
static int do_load_module(Module *mod, const char *modname)
{
if (strcmp(modname, "mail/main") == 0) {
module_mail_main = mod;
low_send_p = get_module_symbol(mod, "low_send");
if (low_send_p)
*low_send_p = send_sendmail;
else
module_log("Unable to find `low_send' symbol, cannot send mail");
}
return 0;
}
/*************************************************************************/
static int do_unload_module(Module *mod)
{
if (mod == module_mail_main) {
if (low_send_p)
*low_send_p = NULL;
low_send_p = NULL;
module_mail_main = NULL;
}
return 0;
}
/*************************************************************************/
int init_module(Module *module_)
{
Module *tmpmod;
module = module_;
if (!add_callback(NULL, "load module", do_load_module)
|| !add_callback(NULL, "unload module", do_unload_module)
) {
module_log("Unable to add callbacks");
exit_module(0);
return 0;
}
tmpmod = find_module("mail/main");
if (tmpmod)
do_load_module(tmpmod, "mail/main");
return 1;
}
/*************************************************************************/
int exit_module(int shutdown_unused)
{
#ifdef CLEAN_COMPILE
shutdown_unused = shutdown_unused;
#endif
if (module_mail_main)
do_unload_module(module_mail_main);
remove_callback(NULL, "unload module", do_unload_module);
remove_callback(NULL, "load module", do_load_module);
return 1;
}
/*************************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1