summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd/bounce.c
diff options
context:
space:
mode:
authorGilles Chehade <gilles@cvs.openbsd.org>2009-08-06 13:40:46 +0000
committerGilles Chehade <gilles@cvs.openbsd.org>2009-08-06 13:40:46 +0000
commit2ae4b5918b8e7e071b3421e081923a1f8d357c56 (patch)
treea9345247824966cb257b493c0a151b01bb024bfa /usr.sbin/smtpd/bounce.c
parent939e6d47367841cb1f3ca05dbfb46c0f17c07331 (diff)
This commit reworks the entire mailer daemon support to actually make it
work for real. As an added bonus, it simplifies it, makes it follow the same code path as regular messages and kills quite some code from mta, mda and store. There's still some work needed but the most painful part is behind us now ;) ok jacekm@
Diffstat (limited to 'usr.sbin/smtpd/bounce.c')
-rw-r--r--usr.sbin/smtpd/bounce.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/usr.sbin/smtpd/bounce.c b/usr.sbin/smtpd/bounce.c
new file mode 100644
index 00000000000..360bfe18402
--- /dev/null
+++ b/usr.sbin/smtpd/bounce.c
@@ -0,0 +1,177 @@
+/* $OpenBSD: bounce.c,v 1.1 2009/08/06 13:40:45 gilles Exp $ */
+
+/*
+ * Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/tree.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <err.h>
+#include <event.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "smtpd.h"
+
+void
+bounce_process(struct smtpd *env, struct message *message)
+{
+ imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_SMTP_ENQUEUE, 0, 0, -1,
+ message, sizeof(*message));
+}
+
+int
+bounce_session(struct smtpd *env, int fd, struct message *messagep)
+{
+ char *buf, *lbuf;
+ size_t len;
+ FILE *fp;
+ enum session_state state = S_INIT;
+
+ fp = fdopen(fd, "r+");
+ if (fp == NULL)
+ goto fail;
+
+ lbuf = NULL;
+ while ((buf = fgetln(fp, &len))) {
+ if (buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
+ else {
+ if ((lbuf = malloc(len + 1)) == NULL)
+ err(1, "malloc");
+ memcpy(lbuf, buf, len);
+ lbuf[len] = '\0';
+ buf = lbuf;
+ }
+ if (! bounce_session_switch(env, fp, &state, buf, messagep))
+ goto fail;
+ }
+ free(lbuf);
+
+ fclose(fp);
+ return 1;
+fail:
+ if (fp != NULL)
+ fclose(fp);
+ else
+ close(fd);
+ return 0;
+}
+
+int
+bounce_session_switch(struct smtpd *env, FILE *fp, enum session_state *state, char *line,
+ struct message *messagep)
+{
+ switch (*state) {
+ case S_INIT:
+ if (strncmp(line, "220 ", 4) != 0)
+ return 0;
+ fprintf(fp, "HELO %s\r\n", env->sc_hostname);
+ *state = S_GREETED;
+ break;
+
+ case S_GREETED:
+ if (strncmp(line, "250 ", 4) != 0)
+ return 0;
+
+ fprintf(fp, "MAIL FROM: <MAILER-DAEMON@%s>\r\n", env->sc_hostname);
+ *state = S_MAIL;
+ break;
+
+ case S_MAIL:
+ if (strncmp(line, "250 ", 4) != 0)
+ return 0;
+
+ fprintf(fp, "RCPT TO: <%s@%s>\r\n", messagep->sender.user,
+ messagep->sender.domain);
+ *state = S_RCPT;
+ break;
+
+ case S_RCPT:
+ if (strncmp(line, "250 ", 4) != 0)
+ return 0;
+
+ fprintf(fp, "DATA\r\n");
+ *state = S_DATA;
+ break;
+
+ case S_DATA: {
+ int msgfd;
+ FILE *srcfp;
+
+ if (strncmp(line, "354 ", 4) != 0)
+ return 0;
+
+ msgfd = queue_open_message_file(messagep->message_id);
+ if (msgfd == -1)
+ return 0;
+
+ srcfp = fdopen(msgfd, "r");
+ if (srcfp == NULL) {
+ close(msgfd);
+ return 0;
+ }
+
+ fprintf(fp, "From: Mailer Daemon <MAILER-DAEMON@%s>\r\n",
+ env->sc_hostname);
+ fprintf(fp, "To: %s@%s\r\n",
+ messagep->sender.user, messagep->sender.domain);
+ fprintf(fp, "Subject: Delivery attempt failure\r\n");
+ fprintf(fp, "\r\n");
+
+ fprintf(fp, "Hi !\r\n");
+ fprintf(fp, "This is the MAILER-DAEMON, please DO NOT REPLY t this e-mail.\r\n");
+ fprintf(fp, "An error has occurred while attempting to deliver a message.\r\n");
+ fprintf(fp, "\r\n");
+ fprintf(fp, "Below is a copy of the original message:\r\n\r\n");
+
+ if (! file_copy_session(env, fp, srcfp)) {
+ return 0;
+ }
+
+ fprintf(fp, ".\r\n");
+
+ *state = S_DONE;
+ break;
+ }
+ case S_DONE:
+ if (strncmp(line, "250 ", 4) != 0)
+ return 0;
+
+ fprintf(fp, "QUIT\r\n");
+ *state = S_QUIT;
+ break;
+
+ case S_QUIT:
+ if (strncmp(line, "221 ", 4) != 0)
+ return 0;
+
+ break;
+
+ default:
+ errx(1, "bounce_session_switch: unknown state.");
+ }
+
+ fflush(fp);
+ return 1;
+}