]> git.ipfire.org Git - people/ms/dma.git/blob - patches/11-double-bounce.patch
Really fix the build on the GNU Hurd.
[people/ms/dma.git] / patches / 11-double-bounce.patch
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
12
13 --- a/conf.c
14 +++ b/conf.c
15 @@ -256,6 +256,8 @@
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)
24 --- a/dma.8
25 +++ b/dma.8
26 @@ -240,6 +240,26 @@
27 .Fl q
28 option.
29 This option is handy if you are behind a dialup line.
30 +.It Ic DBOUNCEPROG Xo
31 +(string, default=dbounce-simple-safecat)
32 +.Xc
33 +Comment if you want the default behavior of
34 +.Nm
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.
38 +.Pp
39 +The program will be invoked with several command-line options:
40 +.Pp
41 +.Nm dbounce
42 +.Fl t
43 +.Ar dma
44 +.Fl a
45 +.Ar bounced@email.address
46 +.Fl i
47 +.Ar queueid
48 +.Fl f
49 +.Ar messagefile
50 .It Ic FULLBOUNCE Xo
51 (boolean, default=commented)
52 .Xc
53 @@ -270,6 +290,7 @@
54 (e.g.\& user@localhost) so you have to rewrite your outgoing email
55 address to a valid address.
56 .Sh SEE ALSO
57 +.Xr dbounce-simple-safecat 1 ,
58 .Xr mailaddr 7 ,
59 .Xr mailwrapper 8 ,
60 .Xr sendmail 8
61 --- a/dma.h
62 +++ b/dma.h
63 @@ -111,6 +111,7 @@
64 const char *authpath;
65 const char *certfile;
66 int features;
67 + const char *dbounceprog;
68 const char *mailname;
69 const char *mailnamefile;
70
71 --- a/dma.conf
72 +++ b/dma.conf
73 @@ -43,6 +43,12 @@
74 # behind a dialup line. You have to submit your mails manually with dma -q
75 #DEFER
76
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
82 +
83 # Uncomment if you want the bounce message to include the complete original
84 # message, not just the headers.
85 #FULLBOUNCE
86 --- a/mail.c
87 +++ b/mail.c
88 @@ -32,7 +32,12 @@
89 * SUCH DAMAGE.
90 */
91
92 +#include <sys/types.h>
93 +#include <sys/wait.h>
94 +
95 +#include <err.h>
96 #include <errno.h>
97 +#include <signal.h>
98 #include <syslog.h>
99 #include <unistd.h>
100
101 @@ -43,13 +48,114 @@
102 {
103 struct queue bounceq;
104 char line[1000];
105 - size_t pos;
106 int error;
107 + int pipefd[2];
108 + pid_t child;
109 + char *buf;
110 + size_t i, pos, bufsize;
111 + ssize_t n;
112 + int status;
113 + struct sigaction sa;
114
115 /* Don't bounce bounced mails */
116 if (it->sender[0] == 0) {
117 - syslog(LOG_INFO, "can not bounce a bounce message, discarding");
118 - exit(1);
119 + syslog(LOG_INFO, "%s: bounce delivery failed, double-bouncing",
120 + it->queueid);
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",
123 + it->queueid);
124 + exit(1);
125 + }
126 + if (pipe(pipefd) == -1) {
127 + syslog(LOG_ERR, "%s: double-bounce: cannot pipe for the double-bounce program: %m",
128 + it->queueid);
129 + exit(1);
130 + }
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",
136 + it->queueid);
137 + exit(1);
138 + }
139 + child = fork();
140 + if (child == -1) {
141 + syslog(LOG_ERR, "%s: double-bounce: cannot fork for the double-bounce program: %m",
142 + it->queueid);
143 + exit(1);
144 + } else if (child == 0) {
145 + close(pipefd[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);
153 + /* NOTREACHED */
154 + }
155 +
156 + close(pipefd[1]);
157 + buf = NULL;
158 + pos = bufsize = 0;
159 + while (1) {
160 + if (pos == bufsize) {
161 + char *nbuf;
162 + size_t nsize;
163 +
164 + nsize = bufsize + BUF_SIZE;
165 + nbuf = realloc(buf, nsize);
166 + if (nbuf == NULL) {
167 + free(buf);
168 + syslog(LOG_ERR, "%s: double-bounce failed: could not allocate %lu bytes of memory: %m", it->queueid, (unsigned long)nsize);
169 + exit(1);
170 + }
171 + buf = nbuf;
172 + bufsize = nsize;
173 + }
174 + n = read(pipefd[0], buf + pos, bufsize - pos);
175 + if (n < 0) {
176 + free(buf);
177 + syslog(LOG_ERR, "%s: double-bounce failed: could not read the output of the double-bounce program: %m", it->queueid);
178 + exit(1);
179 + } else if (n == 0) {
180 + break;
181 + } else {
182 + pos += n;
183 + }
184 + }
185 + for (i = 0; i < pos; i++)
186 + if (buf[i] < 32)
187 + buf[i] = '_';
188 + /*
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.
192 + */
193 + buf[pos] = '\0';
194 +
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);
198 + exit(1);
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);
202 + exit(1);
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);
206 + exit(1);
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);
210 + exit(1);
211 + }
212 + syslog(LOG_ERR, "%s: double-bounce succeeded, message passed to handler `%s': %s",
213 + it->queueid, config.dbounceprog, buf);
214 + delqueue(it);
215 + exit(0);
216 }
217
218 bzero(&bounceq, sizeof(bounceq));