1 Description: Implement double-bounce handling via an external program.
2 Implement double-bounce handling via an external program, controlled
3 by the DBOUNCEPROG config parameter.
4 Enable this handling by default, using the dbounce-simple-safecat
5 helper installed by the package.
6 Unfortunately, Simon Schubert <corecode@dragonflybsd.org> did not
7 accept this part of my changes to dma in issue 1321.
8 Origin: other: http://svn.ringlet.net/svn/ringlet/mail/dma/
9 Bug: http://bugs.dragonflybsd.org/issue1321
10 Author: Peter Pentchev <roam@ringlet.net>
11 Last-Update: 2010-07-27
16 config.authpath= data;
17 else if (strcmp(word, "CERTFILE") == 0 && data != NULL)
18 config.certfile = data;
19 + else if (strcmp(word, "DBOUNCEPROG") == 0 && data != NULL)
20 + config.dbounceprog = data;
21 else if (strcmp(word, "MAILNAME") == 0 && data != NULL)
22 config.mailname = data;
23 else if (strcmp(word, "MAILNAMEFILE") == 0 && data != NULL)
29 This option is handy if you are behind a dialup line.
30 +.It Ic DBOUNCEPROG Xo
31 +(string, default=dbounce-simple-safecat)
33 +Comment if you want the default behavior of
35 +upon double bounces - just abort the delivery.
36 +Otherwise, specify the name or full path to a program that will process
37 +the bounced bounce message.
39 +The program will be invoked with several command-line options:
45 +.Ar bounced@email.address
51 (boolean, default=commented)
54 (e.g.\& user@localhost) so you have to rewrite your outgoing email
55 address to a valid address.
57 +.Xr dbounce-simple-safecat 1 ,
67 + const char *dbounceprog;
69 const char *mailnamefile;
74 # behind a dialup line. You have to submit your mails manually with dma -q
77 +# The double-bounce handler program. Leave this blank if you like dma's
78 +# default behavior of simply aborting the delivery, or specify the name or
79 +# full path to a program that will process the double-bounce message.
80 +# NOTE: on Debian systems this is handled via debconf!
81 +DBOUNCEPROG dbounce-simple-safecat
83 # Uncomment if you want the bounce message to include the complete original
84 # message, not just the headers.
92 +#include <sys/types.h>
93 +#include <sys/wait.h>
103 struct queue bounceq;
110 + size_t i, pos, bufsize;
113 + struct sigaction sa;
115 /* Don't bounce bounced mails */
116 if (it->sender[0] == 0) {
117 - syslog(LOG_INFO, "can not bounce a bounce message, discarding");
119 + syslog(LOG_INFO, "%s: bounce delivery failed, double-bouncing",
121 + if (config.dbounceprog == NULL) {
122 + syslog(LOG_CRIT, "%s: delivery panic: can't bounce a bounce and no double-bounce program defined in the config file",
126 + if (pipe(pipefd) == -1) {
127 + syslog(LOG_ERR, "%s: double-bounce: cannot pipe for the double-bounce program: %m",
131 + bzero(&sa, sizeof(sa));
132 + sa.sa_flags = SA_NOCLDSTOP;
133 + sa.sa_handler = SIG_DFL;
134 + if (sigaction(SIGCHLD, &sa, NULL) == -1) {
135 + syslog(LOG_ERR, "%s: double-bounce: cannot set signal action: %m",
141 + syslog(LOG_ERR, "%s: double-bounce: cannot fork for the double-bounce program: %m",
144 + } else if (child == 0) {
146 + dup2(pipefd[1], STDIN_FILENO);
147 + dup2(pipefd[1], STDOUT_FILENO);
148 + dup2(pipefd[1], STDERR_FILENO);
149 + execlp(config.dbounceprog, config.dbounceprog,
150 + "-t", "dma", "-a", it->addr, "-i", it->queueid,
151 + "-f", it->queuefn, NULL);
152 + err(1, "Could not execute %s", config.dbounceprog);
160 + if (pos == bufsize) {
164 + nsize = bufsize + BUF_SIZE;
165 + nbuf = realloc(buf, nsize);
166 + if (nbuf == NULL) {
168 + syslog(LOG_ERR, "%s: double-bounce failed: could not allocate %lu bytes of memory: %m", it->queueid, (unsigned long)nsize);
174 + n = read(pipefd[0], buf + pos, bufsize - pos);
177 + syslog(LOG_ERR, "%s: double-bounce failed: could not read the output of the double-bounce program: %m", it->queueid);
179 + } else if (n == 0) {
185 + for (i = 0; i < pos; i++)
189 + * The order of the reallocation and reading above
190 + * guarantees that we have at least one more byte available
191 + * in buf[] after pos.
195 + if (waitpid(child, &status, 0) == -1) {
196 + syslog(LOG_ERR, "%s: double-bounce deferred: could not fetch the result from child process %ld: %m; child process output: %s",
197 + it->queueid, (long)child, buf);
199 + } else if (WIFSIGNALED(status)) {
200 + syslog(LOG_ERR, "%s: double-bounce deferred: child process %ld died from signal %d; child process output: %s",
201 + it->queueid, (long)child, WTERMSIG(status), buf);
203 + } else if (!WIFEXITED(status)) {
204 + syslog(LOG_ERR, "%s: double-bounce deferred: child process %ld got an unexpected waitpid code of %d; child process output: %s",
205 + it->queueid, (long)child, status, buf);
207 + } else if (WEXITSTATUS(status) != 0) {
208 + syslog(LOG_ERR, "%s: double-bounce deferred: child process %ld exited with code %d; child process output: %s",
209 + it->queueid, (long)child, (int)WEXITSTATUS(status), buf);
212 + syslog(LOG_ERR, "%s: double-bounce succeeded, message passed to handler `%s': %s",
213 + it->queueid, config.dbounceprog, buf);
218 bzero(&bounceq, sizeof(bounceq));