~ubuntu-branches/ubuntu/hoary/postfix/hoary-security

« back to all changes in this revision

Viewing changes to src/global/abounce.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-10-06 11:50:33 UTC
  • Revision ID: james.westby@ubuntu.com-20041006115033-ooo6yfg6kmoteu04
Tags: upstream-2.1.3
ImportĀ upstreamĀ versionĀ 2.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*++
 
2
/* NAME
 
3
/*      abounce 3
 
4
/* SUMMARY
 
5
/*      asynchronous bounce/defer service client
 
6
/* SYNOPSIS
 
7
/*      #include <abounce.h>
 
8
/*
 
9
/*      void    abounce_flush(flags, queue, id, encoding, sender,
 
10
/*                              callback, context)
 
11
/*      int     flags;
 
12
/*      const char *queue;
 
13
/*      const char *id;
 
14
/*      const char *encoding;
 
15
/*      const char *sender;
 
16
/*      void    (*callback)(int status, char *context);
 
17
/*      char    *context;
 
18
/*
 
19
/*      void    abounce_flush_verp(flags, queue, id, encoding,
 
20
/*                              sender, verp, callback, context)
 
21
/*      int     flags;
 
22
/*      const char *queue;
 
23
/*      const char *id;
 
24
/*      const char *encoding;
 
25
/*      const char *sender;
 
26
/*      const char *verp;
 
27
/*      void    (*callback)(int status, char *context);
 
28
/*      char    *context;
 
29
/*
 
30
/*      void    adefer_flush(flags, queue, id, encoding, sender,
 
31
/*                              callback, context)
 
32
/*      int     flags;
 
33
/*      const char *queue;
 
34
/*      const char *id;
 
35
/*      const char *encoding;
 
36
/*      const char *sender;
 
37
/*      void    (*callback)(int status, char *context);
 
38
/*      char    *context;
 
39
/*
 
40
/*      void    adefer_flush_verp(flags, queue, id, encoding,
 
41
/*                              sender, verp, callback, context)
 
42
/*      int     flags;
 
43
/*      const char *queue;
 
44
/*      const char *id;
 
45
/*      const char *encoding;
 
46
/*      const char *sender;
 
47
/*      const char *verp;
 
48
/*      void    (*callback)(int status, char *context);
 
49
/*      char    *context;
 
50
/*
 
51
/*      void    adefer_warn(flags, queue, id, encoding, sender,
 
52
/*                              callback, context)
 
53
/*      int     flags;
 
54
/*      const char *queue;
 
55
/*      const char *id;
 
56
/*      const char *encoding;
 
57
/*      const char *sender;
 
58
/*      void    (*callback)(int status, char *context);
 
59
/*      char    *context;
 
60
/* DESCRIPTION
 
61
/*      This module implements an asynchronous interface to the
 
62
/*      bounce/defer service for submitting sender notifications
 
63
/*      without waiting for completion of the request.
 
64
/*
 
65
/*      abounce_flush() bounces the specified message to
 
66
/*      the specified sender, including the bounce log that was
 
67
/*      built with bounce_append().
 
68
/*
 
69
/*      abounce_flush_verp() is like abounce_flush() but sends
 
70
/*      one VERP style notification per undeliverable recipient.
 
71
/*
 
72
/*      adefer_flush() bounces the specified message to
 
73
/*      the specified sender, including the defer log that was
 
74
/*      built with defer_append().
 
75
/*      adefer_flush() requests that the deferred recipients are deleted
 
76
/*      from the original queue file.
 
77
/*
 
78
/*      adefer_flush_verp() is like adefer_flush() but sends
 
79
/*      one VERP style notification per undeliverable recipient.
 
80
/*
 
81
/*      adefer_warn() sends a "mail is delayed" notification to
 
82
/*      the specified sender, including the defer log that was
 
83
/*      built with defer_append().
 
84
/*
 
85
/*      Arguments:
 
86
/* .IP flags
 
87
/*      The bitwise OR of zero or more of the following (specify
 
88
/*      BOUNCE_FLAG_NONE to request no special processing):
 
89
/* .RS
 
90
/* .IP BOUNCE_FLAG_CLEAN
 
91
/*      Delete the bounce log in case of an error (as in: pretend
 
92
/*      that we never even tried to bounce this message).
 
93
/* .IP BOUNCE_FLAG_COPY
 
94
/*      Request that a postmaster copy is sent.
 
95
/* .RE
 
96
/* .IP queue
 
97
/*      The message queue name of the original message file.
 
98
/* .IP id
 
99
/*      The message queue id if the original message file. The bounce log
 
100
/*      file has the same name as the original message file.
 
101
/* .IP encoding
 
102
/*      The body content encoding: MAIL_ATTR_ENC_{7BIT,8BIT,NONE}.
 
103
/* .IP sender
 
104
/*      The sender envelope address.
 
105
/* .IP verp
 
106
/*      VERP delimiter characters.
 
107
/* .IP callback
 
108
/*      Name of a routine that receives the notification status as
 
109
/*      documented for bounce_flush() or defer_flush().
 
110
/* .IP context
 
111
/*      Application-specific context that is passed through to the
 
112
/*      callback routine. Use proper casts or the world will come
 
113
/*      to an end.
 
114
/* DIAGNOSTICS
 
115
/*      In case of success, these functions log the action, and return a
 
116
/*      zero result via the callback routine. Otherwise, the functions
 
117
/*      return a non-zero result via the callback routine, and when
 
118
/*      BOUNCE_FLAG_CLEAN is disabled, log that message delivery is deferred.
 
119
/* LICENSE
 
120
/* .ad
 
121
/* .fi
 
122
/*      The Secure Mailer license must be distributed with this software.
 
123
/* AUTHOR(S)
 
124
/*      Wietse Venema
 
125
/*      IBM T.J. Watson Research
 
126
/*      P.O. Box 704
 
127
/*      Yorktown Heights, NY 10598, USA
 
128
/*--*/
 
129
 
 
130
/* System library. */
 
131
 
 
132
#include <sys_defs.h>
 
133
 
 
134
/* Utility library. */
 
135
 
 
136
#include <msg.h>
 
137
#include <mymalloc.h>
 
138
#include <events.h>
 
139
#include <vstream.h>
 
140
 
 
141
/* Global library. */
 
142
 
 
143
#include <mail_params.h>
 
144
#include <mail_proto.h>
 
145
#include <abounce.h>
 
146
 
 
147
/* Application-specific. */
 
148
 
 
149
 /*
 
150
  * Each bounce/defer flush/warn request is implemented by sending the
 
151
  * request to the bounce/defer server, and by creating a pseudo thread that
 
152
  * suspends itself until the server replies (or dies). Upon wakeup, the
 
153
  * pseudo thread delivers the request completion status to the application
 
154
  * and destroys itself. The structure below maintains all the necessary
 
155
  * request state while the pseudo thread is suspended.
 
156
  */
 
157
typedef struct {
 
158
    int     command;                    /* bounce request type */
 
159
    int     flags;                      /* bounce options */
 
160
    char   *id;                         /* queue ID for logging */
 
161
    ABOUNCE_FN callback;                /* application callback */
 
162
    char   *context;                    /* application context */
 
163
    VSTREAM *fp;                        /* server I/O handle */
 
164
} ABOUNCE;
 
165
 
 
166
/* abounce_done - deliver status to application and clean up pseudo thread */
 
167
 
 
168
static void abounce_done(ABOUNCE *ap, int status)
 
169
{
 
170
    (void) vstream_fclose(ap->fp);
 
171
    if (status != 0 && (ap->flags & BOUNCE_FLAG_CLEAN) == 0)
 
172
        msg_info("%s: status=deferred (%s failed)", ap->id,
 
173
                 ap->command == BOUNCE_CMD_FLUSH ? "bounce" :
 
174
                 ap->command == BOUNCE_CMD_WARN ? "delay warning" :
 
175
                 "whatever");
 
176
    ap->callback(status, ap->context);
 
177
    myfree(ap->id);
 
178
    myfree((char *) ap);
 
179
}
 
180
 
 
181
/* abounce_event - resume pseudo thread after server reply event */
 
182
 
 
183
static void abounce_event(int unused_event, char *context)
 
184
{
 
185
    ABOUNCE *ap = (ABOUNCE *) context;
 
186
    int     status;
 
187
 
 
188
    event_disable_readwrite(vstream_fileno(ap->fp));
 
189
    abounce_done(ap, attr_scan(ap->fp, ATTR_FLAG_STRICT,
 
190
                               ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
 
191
                               ATTR_TYPE_END) == 1 ? status : -1);
 
192
}
 
193
 
 
194
/* abounce_request_verp - suspend pseudo thread until server reply event */
 
195
 
 
196
static void abounce_request_verp(const char *class, const char *service,
 
197
                                         int command, int flags,
 
198
                                         const char *queue, const char *id,
 
199
                                         const char *encoding,
 
200
                                         const char *sender,
 
201
                                         const char *verp,
 
202
                                         ABOUNCE_FN callback,
 
203
                                         char *context)
 
204
{
 
205
    ABOUNCE *ap;
 
206
 
 
207
    /*
 
208
     * Save pseudo thread state. Connect to the server. Send the request and
 
209
     * suspend the pseudo thread until the server replies (or dies).
 
210
     */
 
211
    ap = (ABOUNCE *) mymalloc(sizeof(*ap));
 
212
    ap->command = command;
 
213
    ap->flags = flags;
 
214
    ap->id = mystrdup(id);
 
215
    ap->callback = callback;
 
216
    ap->context = context;
 
217
    ap->fp = mail_connect_wait(class, service);
 
218
 
 
219
    if (attr_print(ap->fp, ATTR_FLAG_NONE,
 
220
                   ATTR_TYPE_NUM, MAIL_ATTR_NREQ, command,
 
221
                   ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
 
222
                   ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
 
223
                   ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
 
224
                   ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding,
 
225
                   ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
 
226
                   ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp,
 
227
                   ATTR_TYPE_END) == 0
 
228
        && vstream_fflush(ap->fp) == 0) {
 
229
        event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap);
 
230
    } else {
 
231
        abounce_done(ap, -1);
 
232
    }
 
233
}
 
234
 
 
235
/* abounce_flush_verp - asynchronous bounce flush */
 
236
 
 
237
void    abounce_flush_verp(int flags, const char *queue, const char *id,
 
238
                                   const char *encoding, const char *sender,
 
239
                                   const char *verp, ABOUNCE_FN callback,
 
240
                                   char *context)
 
241
{
 
242
    abounce_request_verp(MAIL_CLASS_PRIVATE, var_bounce_service,
 
243
                         BOUNCE_CMD_VERP, flags, queue, id, encoding,
 
244
                         sender, verp, callback, context);
 
245
}
 
246
 
 
247
/* adefer_flush_verp - asynchronous defer flush */
 
248
 
 
249
void    adefer_flush_verp(int flags, const char *queue, const char *id,
 
250
                                  const char *encoding, const char *sender,
 
251
                                  const char *verp, ABOUNCE_FN callback,
 
252
                                  char *context)
 
253
{
 
254
    flags |= BOUNCE_FLAG_DELRCPT;
 
255
    abounce_request_verp(MAIL_CLASS_PRIVATE, var_defer_service,
 
256
                         BOUNCE_CMD_VERP, flags, queue, id, encoding,
 
257
                         sender, verp, callback, context);
 
258
}
 
259
 
 
260
/* abounce_request - suspend pseudo thread until server reply event */
 
261
 
 
262
static void abounce_request(const char *class, const char *service,
 
263
                                    int command, int flags,
 
264
                                    const char *queue, const char *id,
 
265
                                    const char *encoding, const char *sender,
 
266
                                    ABOUNCE_FN callback, char *context)
 
267
{
 
268
    ABOUNCE *ap;
 
269
 
 
270
    /*
 
271
     * Save pseudo thread state. Connect to the server. Send the request and
 
272
     * suspend the pseudo thread until the server replies (or dies).
 
273
     */
 
274
    ap = (ABOUNCE *) mymalloc(sizeof(*ap));
 
275
    ap->command = command;
 
276
    ap->flags = flags;
 
277
    ap->id = mystrdup(id);
 
278
    ap->callback = callback;
 
279
    ap->context = context;
 
280
    ap->fp = mail_connect_wait(class, service);
 
281
 
 
282
    if (attr_print(ap->fp, ATTR_FLAG_NONE,
 
283
                   ATTR_TYPE_NUM, MAIL_ATTR_NREQ, command,
 
284
                   ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
 
285
                   ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue,
 
286
                   ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
 
287
                   ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding,
 
288
                   ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
 
289
                   ATTR_TYPE_END) == 0
 
290
        && vstream_fflush(ap->fp) == 0) {
 
291
        event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap);
 
292
    } else {
 
293
        abounce_done(ap, -1);
 
294
    }
 
295
}
 
296
 
 
297
/* abounce_flush - asynchronous bounce flush */
 
298
 
 
299
void    abounce_flush(int flags, const char *queue, const char *id,
 
300
                              const char *encoding, const char *sender,
 
301
                              ABOUNCE_FN callback, char *context)
 
302
{
 
303
    abounce_request(MAIL_CLASS_PRIVATE, var_bounce_service, BOUNCE_CMD_FLUSH,
 
304
                    flags, queue, id, encoding, sender, callback, context);
 
305
}
 
306
 
 
307
/* adefer_flush - asynchronous defer flush */
 
308
 
 
309
void    adefer_flush(int flags, const char *queue, const char *id,
 
310
                             const char *encoding, const char *sender,
 
311
                             ABOUNCE_FN callback, char *context)
 
312
{
 
313
    flags |= BOUNCE_FLAG_DELRCPT;
 
314
    abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_FLUSH,
 
315
                    flags, queue, id, encoding, sender, callback, context);
 
316
}
 
317
 
 
318
/* adefer_warn - send copy of defer log to sender as warning bounce */
 
319
 
 
320
void    adefer_warn(int flags, const char *queue, const char *id,
 
321
                            const char *encoding, const char *sender,
 
322
                            ABOUNCE_FN callback, char *context)
 
323
{
 
324
    abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_WARN,
 
325
                    flags, queue, id, encoding, sender, callback, context);
 
326
}