/*
+ * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>.
* Copyright (c) 2008 The DragonFly Project. All rights reserved.
*
* This code is derived from software contributed to The DragonFly Project
- * by Simon 'corecode' Schubert <corecode@fs.ei.tum.de>.
+ * by Simon Schubert <2@0x2c.org>.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
/* Don't bounce bounced mails */
if (it->sender[0] == 0) {
syslog(LOG_INFO, "can not bounce a bounce message, discarding");
- exit(1);
+ exit(EX_SOFTWARE);
}
bzero(&bounceq, sizeof(bounceq));
LIST_INIT(&bounceq.queue);
bounceq.sender = "";
- if (add_recp(&bounceq, it->sender, 1) != 0)
+ if (add_recp(&bounceq, it->sender, EXPAND_WILDCARD) != 0)
goto fail;
if (newspoolf(&bounceq) != 0)
error = fprintf(bounceq.mailf,
"Received: from MAILER-DAEMON\n"
"\tid %s\n"
- "\tby %s (%s)\n"
+ "\tby %s (%s);\n"
"\t%s\n"
"X-Original-To: <%s>\n"
"From: MAILER-DAEMON <>\n"
fail:
syslog(LOG_CRIT, "error creating bounce: %m");
delqueue(it);
- exit(1);
+ exit(EX_IOERR);
}
struct parse_state {
case ',':
case ';':
+ /*
+ * Next address, copy previous one.
+ * However, we might be directly after
+ * a <address>, or have two consecutive
+ * commas.
+ * Skip the comma unless there is
+ * really something to copy.
+ */
+ if (ps->pos == 0)
+ goto skip;
s++;
goto newaddr;
ps->pos = 0;
addr = strdup(ps->addr);
if (addr == NULL)
- errlog(1, NULL);
+ errlog(EX_SOFTWARE, NULL);
- if (add_recp(queue, addr, 1) != 0)
- errlogx(1, "invalid recipient `%s'", addr);
+ if (add_recp(queue, addr, EXPAND_WILDCARD) != 0)
+ errlogx(EX_DATAERR, "invalid recipient `%s'", addr);
goto again;
}
int had_from = 0;
int had_messagid = 0;
int had_date = 0;
+ int had_last_line = 0;
int nocopy = 0;
parse_state.state = NONE;
"Received: from %s (uid %d)\n"
"\t(envelope-from %s)\n"
"\tid %s\n"
- "\tby %s (%s)\n"
+ "\tby %s (%s);\n"
"\t%s\n",
- username, getuid(),
+ username, useruid,
queue->sender,
queue->id,
hostname(), VERSION,
return (-1);
while (!feof(stdin)) {
- if (fgets(line, sizeof(line), stdin) == NULL)
+ if (fgets(line, sizeof(line) - 1, stdin) == NULL)
break;
+ if (had_last_line)
+ errlogx(EX_DATAERR, "bad mail input format:"
+ " from %s (uid %d) (envelope-from %s)",
+ username, useruid, queue->sender);
linelen = strlen(line);
if (linelen == 0 || line[linelen - 1] != '\n') {
- errno = EINVAL; /* XXX mark permanent errors */
- return (-1);
+ /*
+ * This line did not end with a newline character.
+ * If we fix it, it better be the last line of
+ * the file.
+ */
+ line[linelen] = '\n';
+ line[linelen + 1] = 0;
+ had_last_line = 1;
}
if (!had_headers) {
/*
if (parse_state.state != NONE) {
if (parse_addrs(&parse_state, line, queue) < 0) {
- errlogx(1, "invalid address in header\n");
+ errlogx(EX_DATAERR, "invalid address in header\n");
/* NOTREACHED */
}
}
strprefixcmp(line, "Bcc:") == 0)) {
parse_state.state = START;
if (parse_addrs(&parse_state, line, queue) < 0) {
- errlogx(1, "invalid address in header\n");
+ errlogx(EX_DATAERR, "invalid address in header\n");
/* NOTREACHED */
}
}
snprintf(line, sizeof(line), "Message-Id: <%"PRIxMAX".%s.%"PRIxMAX"@%s>\n",
(uintmax_t)time(NULL),
queue->id,
- random(),
+ (uintmax_t)random(),
hostname());
} else if (!had_from) {
had_from = 1;