/*
Copyright (C) 1999-2004 IC & S dbmail@ic-s.nl
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 (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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: forward.c 2357 2006-11-06 15:13:18Z leander $
*
* takes care of forwarding mail to an external address */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "db.h"
#include "dbmail.h"
#include "debug.h"
#include "forward.h"
#include "list.h"
/* For each of the addresses or programs in targets,
* send out a copy of the message pointed to by msgidnr.
*
* Returns 0 if all went well, -1 if there was an error.
* FIXME: there is no detail in the error reporting,
* so there's no way to tell *which* targets failed...
* */
int forward(u64_t msgidnr, struct list *targets, const char *from,
const char *header, u64_t headersize UNUSED)
{
struct element *target = NULL;
char *command = NULL;
char *escaped_from = NULL;
char *escaped_to = NULL;
size_t command_len = 0;
FILE *pipe = NULL;
int err;
field_t sendmail;
char timestr[50];
time_t td;
struct tm tm;
time(&td); /* get time */
tm = *localtime(&td); /* get components */
strftime(timestr, sizeof(timestr), "%a %b %e %H:%M:%S %Y", &tm);
GetConfigValue("SENDMAIL", "SMTP", sendmail);
if (sendmail[0] == '\0')
trace(TRACE_FATAL,
"%s,%s: SENDMAIL not configured (see config file). "
"Stop.", __FILE__, __func__);
trace(TRACE_INFO,
"%s,%s: delivering to [%ld] external addresses",
__FILE__, __func__, list_totalnodes(targets));
if (!msgidnr) {
trace(TRACE_ERROR,
"%s,%s: got NULL as message id number",
__FILE__, __func__);
return -1;
}
target = list_getstart(targets);
while (target != NULL) {
if ((((char *) target->data)[0] == '|')
|| (((char *) target->data)[0] == '!')) {
/* external pipe command */
command_len = strlen((char *) (target->data)) + 1;
command = dm_malloc(command_len * sizeof(char));
if (!command) {
trace(TRACE_ERROR,
"%s,%s: out of memory",
__FILE__, __func__);
return -1;
}
/* skip the pipe (|) sign */
strncpy(command, (char *) (target->data) + 1, command_len);
} else {
escaped_from = dm_shellesc(from);
if (!escaped_from) {
trace(TRACE_ERROR,
"%s,%s: out of memory",
__FILE__, __func__);
return -1;
}
escaped_to = dm_shellesc((char *) (target->data));
if (!escaped_to) {
trace(TRACE_ERROR,
"%s,%s: out of memory",
__FILE__, __func__);
return -1;
}
/* pipe to sendmail */
command_len = strlen(sendmail) + strlen(" -f ") +
strlen(escaped_from) + strlen (" ") +
strlen(escaped_to) + 1;
command = dm_malloc(command_len * sizeof(char));
if (!command) {
trace(TRACE_ERROR,
"%s,%s: out of memory",
__FILE__, __func__);
return -1;
}
trace(TRACE_DEBUG,
"%s,%s: allocated memory for external "
"command call", __FILE__, __func__);
snprintf(command, command_len, "%s -f %s %s", sendmail, escaped_from, escaped_to);
}
trace(TRACE_INFO, "%s,%s: opening pipe to command %s",
__FILE__, __func__, command);
pipe = popen(command, "w"); /* opening pipe */
dm_free(command);
command = NULL;
if (pipe != NULL) {
trace(TRACE_DEBUG,
"%s,%s: call to popen() successfully "
"opened pipe [%d]", __FILE__, __func__,
fileno(pipe));
if (((char *) target->data)[0] == '!') {
/* ! tells us to prepend an mbox style header in this pipe */
trace(TRACE_DEBUG,
"%s,%s: appending mbox style from "
"header to pipe returnpath : %s",
__FILE__, __func__, from);
/* format: From<space>address<space><space>Date */
fprintf(pipe, "From %s %s\n", from,
timestr);
}
trace(TRACE_INFO,
"%s,%s: sending message id number [%llu] "
"to forward pipe", __FILE__, __func__,
msgidnr);
err = ferror(pipe);
trace(TRACE_DEBUG, "%s,%s: ferror reports"
" %d, feof reports %d on pipe %d", __FILE__,
__func__, err, feof(pipe), fileno(pipe));
if (!err) {
if (msgidnr != 0) {
trace(TRACE_DEBUG,
"%s,%s: sending lines from "
"message %llu on pipe %d",
__FILE__, __func__,
msgidnr, fileno(pipe));
db_send_message_lines(pipe,
msgidnr, -2,
1);
} else {
/* only send the headers if there
* is no message to send. */
trace(TRACE_DEBUG,
"%s,%s: writing header to "
"pipe", __FILE__,
__func__);
fprintf(pipe, "%s", header);
}
}
trace(TRACE_DEBUG, "%s,%s: closing pipes",
__FILE__, __func__);
if (!ferror(pipe)) {
pclose(pipe);
trace(TRACE_DEBUG,
"%s,%s: pipe closed",
__FILE__, __func__);
} else {
trace(TRACE_ERROR,
"%s,%s: error on pipe",
__FILE__, __func__);
}
} else {
trace(TRACE_ERROR,
"%s,%s: Could not open pipe to [%s]",
__FILE__, __func__, sendmail);
}
target = target->nextnode;
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1