it appears to be because the restrictions can't be used
for whitelisting. File: smtpd/smtpd_check.c.
+20030920
+
+ Bugfix: LDAP client update by by Victor Duchovni, Morgan
+ Stanley. Files: README_FILES/LDAP_README, util/dict_ldap.c.
+
+ Bugfix: after returning too old mail, the bounce daemon
+ now deletes recipients from the original queue file, to
+ avoid repeated bounce notifications when the queue manager
+ is restarted. Files: bounce/*.[hc], global/bounce_log.[hc],
+ global/{bounce,defer}.[hc] and everything that invokes
+ these routines including queue manager and delivery agents.
+
Open problems:
High: when virtual aliasing is turned off after content
filtering, local submissions may escape virtual aliasing.
- Med: qmgr should not exit while an asynchronous bounce
- request is in progress; this can result in multiple
- non-delivery notifications.
-
Low: qmgr_move should not reset time stamps on queue files
without shared lock (i.e. not open by a delivery agent).
server_host (localhost)
The name of the host running the LDAP server, e.g.
server_host = ldap.your.com
- It should be possible with all the libraries mentioned above to
- specify multiple servers separated by spaces, with the libraries
- trying them in order should the first one fail. It should also
- be possible to give each server in the list a different port, by
- naming them like "ldap.your.com:1444".
+ It should be possible with all the libraries mentioned above
+ to specify multiple servers, with the libraries trying them in
+ order should the first one fail. It should also be possible to
+ give each server in the list a different port, by naming them
+ like "ldap.your.com:1444".
With OpenLDAP, LDAP URLs can be used to request connection
over UNIX domain sockets (ldapi://%2Fsome%2Fpath) or LDAP SSL
-<html> <head> </head> <body> <pre>
+<html> <body> <pre>
BOUNCE(8) BOUNCE(8)
<b>NAME</b>
will have to change in order to easily support standard
delivery status notifications.
-<b>CONFIGURATION</b> <b>PARAMETERS</b>
+<b>CONFIGURATION PARAMETERS</b>
The following <b>main.cf</b> parameters are especially relevant
to this program. See the Postfix <b>main.cf</b> file for syntax
- details and for default values. Use the <b>postfix</b> <b>reload</b>
+ details and for default values. Use the <b>postfix reload</b>
command after a configuration change.
- <b>bounce</b><i>_</i><b>notice</b><i>_</i><b>recipient</b>
+ <b>bounce_notice_recipient</b>
The recipient of single bounce postmaster notices.
- <b>2bounce</b><i>_</i><b>notice</b><i>_</i><b>recipient</b>
+ <b>2bounce_notice_recipient</b>
The recipient of double bounce postmaster notices.
- <b>delay</b><i>_</i><b>notice</b><i>_</i><b>recipient</b>
+ <b>delay_notice_recipient</b>
The recipient of "delayed mail" postmaster notices.
- <b>bounce</b><i>_</i><b>size</b><i>_</i><b>limit</b>
+ <b>bounce_size_limit</b>
Limit the amount of original message context that
is sent in a non-delivery notification.
- <b>backwards</b><i>_</i><b>bounce</b><i>_</i><b>logfile</b><i>_</i><b>compatibility</b>
+ <b>backwards_bounce_logfile_compatibility</b>
Controls whether the logfile will be readable by
old Postfix versions that used the ad-hoc logfile
- format of <i>&</i>lt;<i>address&</i>gt;<i>:</i> <i>text</i>.
+ format of <i>&</i>lt;<i>address&</i>gt;<i>: text</i>.
- <b>mail</b><i>_</i><b>name</b>
+ <b>mail_name</b>
Use this mail system name in the introductory text
at the start of a bounce message.
- <b>notify</b><i>_</i><b>classes</b>
+ <b>notify_classes</b>
Notify the postmaster of bounced mail when this
parameter includes the <b>bounce</b> class. For privacy
reasons, the message body is not included.
-<b>SEE</b> <b>ALSO</b>
+<b>SEE ALSO</b>
<a href="master.8.html">master(8)</a> process manager
<a href="qmgr.8.html">qmgr(8)</a> queue manager
syslogd(8) system logging
-<html> <head> </head> <body> <pre>
+<html> <body> <pre>
ERROR(8) ERROR(8)
<b>NAME</b>
<b>DIAGNOSTICS</b>
Problems and transactions are logged to <b>syslogd</b>(8).
- Depending on the setting of the <b>notify</b><i>_</i><b>classes</b> parameter,
+ Depending on the setting of the <b>notify_classes</b> parameter,
the postmaster is notified of bounces and of other trou-
ble.
<b>BUGS</b>
-<b>CONFIGURATION</b> <b>PARAMETERS</b>
+<b>CONFIGURATION PARAMETERS</b>
The following <b>main.cf</b> parameters are especially relevant
to this program. See the Postfix <b>main.cf</b> file for syntax
- details and for default values. Use the <b>postfix</b> <b>reload</b>
+ details and for default values. Use the <b>postfix reload</b>
command after a configuration change.
<b>Miscellaneous</b>
- <b>bounce</b><i>_</i><b>notice</b><i>_</i><b>recipient</b>
+ <b>bounce_notice_recipient</b>
Postmaster for bounce error notices.
- <b>notify</b><i>_</i><b>classes</b>
+ <b>notify_classes</b>
When this parameter includes the <b>bounce</b> class, send
mail to the postmaster with the headers of the
bounced mail.
-<b>SEE</b> <b>ALSO</b>
+<b>SEE ALSO</b>
<a href="bounce.8.html">bounce(8)</a> non-delivery status reports
<a href="master.8.html">master(8)</a> process manager
<a href="qmgr.8.html">qmgr(8)</a> queue manager
-<html> <head> </head> <body> <pre>
+<html> <body> <pre>
PIPE(8) PIPE(8)
<b>NAME</b>
-<html> <head> </head> <body> <pre>
-
+<html> <body> <pre>
POSTKICK(1) POSTKICK(1)
<b>NAME</b>
postkick - kick a Postfix service
<b>SYNOPSIS</b>
- <b>postkick</b> [<b>-c</b> <i>config_dir</i>] [<b>-v</b>] <i>class</i> <i>service</i> <i>request</i>
+ <b>postkick</b> [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<b>-v</b>] <i>class service request</i>
<b>DESCRIPTION</b>
The <b>postkick</b> command sends <i>request</i> to the specified <i>ser-</i>
Options:
- <b>-c</b> <i>config_dir</i>
+ <b>-c</b> <i>config</i><b>_</b><i>dir</i>
Read the <b>main.cf</b> configuration file in the named
directory instead of the default configuration
directory.
stream.
<b>ENVIRONMENT</b>
- <b>MAIL</b><i>_</i><b>CONFIG</b>
+ <b>MAIL_CONFIG</b>
Directory with Postfix configuration files.
- <b>MAIL</b><i>_</i><b>VERBOSE</b>
+ <b>MAIL_VERBOSE</b>
Enable verbose logging for debugging purposes.
-<b>CONFIGURATION</b> <b>PARAMETERS</b>
+<b>CONFIGURATION PARAMETERS</b>
The following <b>main.cf</b> parameters are especially relevant
to this program. See the Postfix <b>main.cf</b> file for syntax
details and for default values.
- <b>queue</b><i>_</i><b>directory</b>
+ <b>queue_directory</b>
Location of the Postfix queue, and of the local IPC
communication endpoints.
-<b>SEE</b> <b>ALSO</b>
+<b>SEE ALSO</b>
<a href="qmgr.8.html">qmgr(8)</a> queue manager trigger protocol
<a href="pickup.8.html">pickup(8)</a> local pickup daemon
P.O. Box 704
Yorktown Heights, NY 10598, USA
- 1
-
+ POSTKICK(1)
</pre> </body> </html>
bounce_notify_service.o: ../../include/cleanup_user.h
bounce_notify_service.o: ../../include/mail_addr.h
bounce_notify_service.o: ../../include/mail_error.h
+bounce_notify_service.o: ../../include/bounce.h
+bounce_notify_service.o: ../../include/deliver_request.h
+bounce_notify_service.o: ../../include/recipient_list.h
bounce_notify_service.o: bounce_service.h
bounce_notify_service.o: ../../include/bounce_log.h
bounce_notify_util.o: bounce_notify_util.c
bounce_notify_util.o: ../../include/iostuff.h
bounce_notify_util.o: ../../include/attr.h
bounce_notify_util.o: ../../include/lex_822.h
+bounce_notify_util.o: ../../include/deliver_completed.h
bounce_notify_util.o: bounce_service.h
bounce_notify_verp.o: bounce_notify_verp.c
bounce_notify_verp.o: ../../include/sys_defs.h
bounce_notify_verp.o: ../../include/mail_addr.h
bounce_notify_verp.o: ../../include/mail_error.h
bounce_notify_verp.o: ../../include/verp_sender.h
+bounce_notify_verp.o: ../../include/bounce.h
+bounce_notify_verp.o: ../../include/deliver_request.h
+bounce_notify_verp.o: ../../include/recipient_list.h
bounce_notify_verp.o: bounce_service.h
bounce_notify_verp.o: ../../include/bounce_log.h
bounce_one_service.o: bounce_one_service.c
bounce_one_service.o: ../../include/cleanup_user.h
bounce_one_service.o: ../../include/mail_addr.h
bounce_one_service.o: ../../include/mail_error.h
-bounce_one_service.o: bounce_service.h
+bounce_one_service.o: ../../include/bounce.h
+bounce_one_service.o: ../../include/deliver_request.h
bounce_one_service.o: ../../include/vstring.h
+bounce_one_service.o: ../../include/recipient_list.h
+bounce_one_service.o: bounce_service.h
bounce_one_service.o: ../../include/bounce_log.h
bounce_trace_service.o: bounce_trace_service.c
bounce_trace_service.o: ../../include/sys_defs.h
static int bounce_append_proto(char *service_name, VSTREAM *client)
{
+ char *myname = "bounce_append_proto";
int flags;
+ long offset;
/*
* Read the and validate the client request.
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_rcpt,
ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient,
+ ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &offset,
ATTR_TYPE_STR, MAIL_ATTR_STATUS, dsn_status,
ATTR_TYPE_STR, MAIL_ATTR_ACTION, dsn_action,
ATTR_TYPE_STR, MAIL_ATTR_WHY, why,
- ATTR_TYPE_END) != 7) {
+ ATTR_TYPE_END) != 8) {
msg_warn("malformed request");
return (-1);
}
return (-1);
}
if (msg_verbose)
- msg_info("bounce_append_proto: service=%s id=%s org_to=%s to=%s stat=%s act=%s why=%s",
- service_name, STR(queue_id), STR(orig_rcpt),
- STR(recipient), STR(dsn_status),
+ msg_info("%s: flags=0x%x service=%s id=%s org_to=%s to=%s off=%ld stat=%s act=%s why=%s",
+ myname, flags, service_name, STR(queue_id), STR(orig_rcpt),
+ STR(recipient), offset, STR(dsn_status),
STR(dsn_action), STR(why));
/*
/*
* Execute the request.
*/
- return (bounce_append_service(service_name, STR(queue_id),
- STR(orig_rcpt), STR(recipient),
+ return (bounce_append_service(flags, service_name, STR(queue_id),
+ STR(orig_rcpt), STR(recipient), offset,
STR(dsn_status), STR(dsn_action),
STR(why)));
}
/* bounce_notify_proto - bounce_notify server protocol */
static int bounce_notify_proto(char *service_name, VSTREAM *client,
- int (*service) (char *, char *, char *, char *, char *))
+ int (*service) (int, char *, char *, char *, char *, char *))
{
+ char *myname = "bounce_notify_proto";
int flags;
/*
return (-1);
}
if (msg_verbose)
- msg_info("bounce_notify_proto: service=%s queue=%s id=%s encoding=%s sender=%s",
- service_name, STR(queue_name), STR(queue_id),
+ msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s sender=%s",
+ myname, flags, service_name, STR(queue_name), STR(queue_id),
STR(encoding), STR(sender));
/*
/*
* Execute the request.
*/
- return (service(service_name, STR(queue_name),
+ return (service(flags, service_name, STR(queue_name),
STR(queue_id), STR(encoding),
STR(sender)));
}
return (-1);
}
if (msg_verbose)
- msg_info("%s: service=%s queue=%s id=%s encoding=%s sender=%s delim=%s",
- myname, service_name, STR(queue_name), STR(queue_id),
+ msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s sender=%s delim=%s",
+ myname, flags, service_name, STR(queue_name), STR(queue_id),
STR(encoding), STR(sender), STR(verp_delims));
/*
*/
if (!*STR(sender) || !strcasecmp(STR(sender), mail_addr_double_bounce())) {
msg_warn("request to send VERP-style notification of bounced mail");
- return (bounce_notify_service(service_name, STR(queue_name),
+ return (bounce_notify_service(flags, service_name, STR(queue_name),
STR(queue_id), STR(encoding),
STR(sender)));
} else
- return (bounce_notify_verp(service_name, STR(queue_name),
+ return (bounce_notify_verp(flags, service_name, STR(queue_name),
STR(queue_id), STR(encoding),
STR(sender), STR(verp_delims)));
}
static int bounce_one_proto(char *service_name, VSTREAM *client)
{
- int unused_flags;
+ char *myname = "bounce_one_proto";
+ int flags;
+ long offset;
/*
* Read and validate the client request.
*/
if (mail_command_server(client,
- ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &unused_flags,
+ ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags,
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding,
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_rcpt,
ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient,
+ ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &offset,
ATTR_TYPE_STR, MAIL_ATTR_STATUS, dsn_status,
ATTR_TYPE_STR, MAIL_ATTR_ACTION, dsn_action,
ATTR_TYPE_STR, MAIL_ATTR_WHY, why,
- ATTR_TYPE_END) != 10) {
+ ATTR_TYPE_END) != 11) {
msg_warn("malformed request");
return (-1);
}
return (-1);
}
if (msg_verbose)
- msg_info("bounce_one_proto: queue=%s id=%s encoding=%s sender=%s orig_to=%s to=%s stat=%s act=%s why=%s",
- STR(queue_name), STR(queue_id), STR(encoding),
- STR(sender), STR(orig_rcpt), STR(recipient),
+ msg_info("%s: flags=0x%x queue=%s id=%s encoding=%s sender=%s orig_to=%s to=%s off=%ld stat=%s act=%s why=%s",
+ myname, flags, STR(queue_name), STR(queue_id), STR(encoding),
+ STR(sender), STR(orig_rcpt), STR(recipient), offset,
STR(dsn_status), STR(dsn_action), STR(why));
/*
* Execute the request.
*/
- return (bounce_one_service(STR(queue_name), STR(queue_id), STR(encoding),
- STR(sender), STR(orig_rcpt), STR(recipient),
- STR(dsn_status), STR(dsn_action), STR(why)));
+ return (bounce_one_service(flags, STR(queue_name), STR(queue_id),
+ STR(encoding), STR(sender), STR(orig_rcpt),
+ STR(recipient), offset, STR(dsn_status),
+ STR(dsn_action), STR(why)));
}
/* bounce_service - parse bounce command type and delegate */
* Read and validate the first parameter of the client request. Let the
* request-specific protocol routines take care of the remainder.
*/
-#define REALLY_BOUNCE 1
-#define JUST_WARN 0
-
if (attr_scan(client, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
ATTR_TYPE_NUM, MAIL_ATTR_NREQ, &command, 0) != 1) {
msg_warn("malformed request");
/* SYNOPSIS
/* #include "bounce_service.h"
/*
-/* int bounce_append_service(queue_id, orig_rcpt, recipient,
+/* int bounce_append_service(flags, queue_id, orig_rcpt, recipient,
/* status, action, why)
+/* int flags;
/* char *queue_id;
/* char *orig_rcpt;
/* char *recipient;
/* bounce_append_service - append bounce log */
-int bounce_append_service(char *service, char *queue_id,
+int bounce_append_service(int unused_flags, char *service, char *queue_id,
char *orig_rcpt, char *recipient,
- char *status, char *action,
+ long offset, char *status, char *action,
char *why)
{
VSTRING *in_buf = vstring_alloc(100);
if (*orig_rcpt && strcasecmp(recipient, orig_rcpt) != 0)
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_ORCPT,
printable(vstring_str(quote_822_local(in_buf, orig_rcpt)), '?'));
+ if (offset > 0)
+ vstream_fprintf(log, "%s=%ld\n", MAIL_ATTR_OFFSET, offset);
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_STATUS, printable(status, '?'));
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_ACTION, printable(action, '?'));
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_WHY, printable(why, '?'));
/* SYNOPSIS
/* #include "bounce_service.h"
/*
-/* int bounce_notify_service(queue_name, queue_id, encoding,
+/* int bounce_notify_service(flags, queue_name, queue_id, encoding,
/* sender)
+/* int flags;
/* char *queue_name;
/* char *queue_id;
/* char *encoding;
#include <post_mail.h>
#include <mail_addr.h>
#include <mail_error.h>
+#include <bounce.h>
/* Application-specific. */
/* bounce_notify_service - send a bounce */
-int bounce_notify_service(char *service, char *queue_name,
+int bounce_notify_service(int flags, char *service, char *queue_name,
char *queue_id, char *encoding,
char *recipient)
{
}
}
+ /*
+ * Optionally, delete the recipients from the queue file.
+ */
+ if (bounce_status == 0 && (flags & BOUNCE_FLAG_DELRCPT))
+ bounce_delrcpt(bounce_info);
+
/*
* Examine the completion status. Delete the bounce log file only when
* the bounce was posted successfully, and only if we are bouncing for
/* VSTREAM *fp;
/* BOUNCE_INFO *bounce_info;
/* int headers_only;
+/*
+/* void bounce_delrcpt(bounce_info)
+/* BOUNCE_INFO *bounce_info;
+/*
+/* void bounce_delrcpt_one(bounce_info)
+/* BOUNCE_INFO *bounce_info;
/* DESCRIPTION
/* This module implements the grunt work of sending a non-delivery
/* notification. A bounce is sent in a form that satisfies RFC 1894
/* bounce_original() starts a message/rfc822 or headers/rfc822
/* message segment and sends the original message, either full or
/* message headers only.
+/*
+/* bounce_delrcpt() deletes recipients in the logfile from the original
+/* queue file.
+/*
+/* bounce_delrcpt_one() deletes one recipient from the original
+/* queue file.
/* DIAGNOSTICS
/* Fatal error: error opening existing file. Warnings: corrupt
/* message file. A corrupt message is saved to the "corrupt"
#include <mail_date.h>
#include <mail_proto.h>
#include <lex_822.h>
+#include <deliver_completed.h>
/* Application-specific. */
/* XXX Future: sender+recipient after message content. */
if (VSTRING_LEN(bounce_info->sender) == 0)
msg_warn("%s: no sender before message content record",
- bounce_info->queue_id);
+ bounce_info->queue_id);
bounce_info->orig_offs = vstream_ftell(bounce_info->orig_fp);
break;
}
const char *encoding,
const char *orig_recipient,
const char *recipient,
+ long offset,
const char *dsn_status,
const char *dsn_action,
const char *why)
*/
#define REALLY_BOUNCE 1
- log_handle = bounce_log_forge(orig_recipient, recipient, dsn_status,
+ log_handle = bounce_log_forge(orig_recipient, recipient, offset, dsn_status,
dsn_action, why);
bounce_info = bounce_mail_alloc("none", queue_name, queue_id,
encoding, REALLY_BOUNCE, log_handle);
return (status);
}
+
+/* bounce_delrcpt - delete recipients from original queue file */
+
+int bounce_delrcpt(BOUNCE_INFO *bounce_info)
+{
+ if (bounce_info->orig_fp != 0
+ && bounce_info->log_handle != 0
+ && bounce_log_rewind(bounce_info->log_handle) == 0)
+ while (bounce_log_read(bounce_info->log_handle) != 0)
+ if (bounce_info->log_handle->rcpt_offset > 0)
+ deliver_completed(bounce_info->orig_fp,
+ bounce_info->log_handle->rcpt_offset);
+}
+
+/* bounce_delrcpt_one - delete one recipient from original queue file */
+
+int bounce_delrcpt_one(BOUNCE_INFO *bounce_info)
+{
+ if (bounce_info->orig_fp != 0
+ && bounce_info->log_handle != 0
+ && bounce_info->log_handle->rcpt_offset > 0)
+ deliver_completed(bounce_info->orig_fp,
+ bounce_info->log_handle->rcpt_offset);
+}
/* SYNOPSIS
/* #include "bounce_service.h"
/*
-/* int bounce_notify_verp(service, queue_name, queue_id, sender,
+/* int bounce_notify_verp(flags, service, queue_name, queue_id, sender,
/* verp_delims)
+/* int flags;
/* char *queue_name;
/* char *queue_id;
/* char *sender;
#include <mail_addr.h>
#include <mail_error.h>
#include <verp_sender.h>
+#include <bounce.h>
/* Application-specific. */
/* bounce_notify_verp - send a bounce */
-int bounce_notify_verp(char *service, char *queue_name,
+int bounce_notify_verp(int flags, char *service, char *queue_name,
char *queue_id, char *encoding,
- char *recipient,
- char *verp_delims)
+ char *recipient, char *verp_delims)
{
char *myname = "bounce_notify_verp";
BOUNCE_INFO *bounce_info;
break;
/*
- * Mark this recipient as done.
+ * Optionally, mark this recipient as done.
*/
- bounce_log_delrcpt(bounce_info->log_handle);
+ if (flags & BOUNCE_FLAG_DELRCPT)
+ bounce_delrcpt_one(bounce_info);
/*
* Optionally, send a postmaster notice.
/* SYNOPSIS
/* #include "bounce_service.h"
/*
-/* int bounce_one_service(queue_name, queue_id, encoding,
+/* int bounce_one_service(flags, queue_name, queue_id, encoding,
/* orig_sender, orig_recipient,
/* status, why)
+/* int flags;
/* char *queue_name;
/* char *queue_id;
/* char *encoding;
#include <post_mail.h>
#include <mail_addr.h>
#include <mail_error.h>
+#include <bounce.h>
/* Application-specific. */
/* bounce_one_service - send a bounce for one recipient */
-int bounce_one_service(char *queue_name, char *queue_id, char *encoding,
- char *orig_sender, char *orig_recipient,
- char *recipient, char *dsn_status,
- char *dsn_action, char *why)
+int bounce_one_service(int flags, char *queue_name, char *queue_id,
+ char *encoding, char *orig_sender,
+ char *orig_recipient, char *recipient,
+ long offset, char *dsn_status,
+ char *dsn_action, char *why)
{
BOUNCE_INFO *bounce_info;
int bounce_status = 1;
*/
bounce_info = bounce_mail_one_init(queue_name, queue_id,
encoding, orig_recipient,
- recipient, dsn_status,
+ recipient, offset, dsn_status,
dsn_action, why);
#define NULL_SENDER MAIL_ADDR_EMPTY /* special address */
}
}
+ /*
+ * Optionally, delete the recipient from the queue file.
+ */
+ if (bounce_status == 0 && (flags & BOUNCE_FLAG_DELRCPT))
+ bounce_delrcpt_one(bounce_info);
+
/*
* Cleanup.
*/
/*
* bounce_append_service.c
*/
-extern int bounce_append_service(char *, char *, char *, char *, char *, char *, char *);
+extern int bounce_append_service(int, char *, char *, char *, char *, long, char *, char *, char *);
/*
* bounce_notify_service.c
*/
-extern int bounce_notify_service(char *, char *, char *, char *, char *);
+extern int bounce_notify_service(int, char *, char *, char *, char *, char *);
/*
* bounce_warn_service.c
*/
-extern int bounce_warn_service(char *, char *, char *, char *, char *);
+extern int bounce_warn_service(int, char *, char *, char *, char *, char *);
/*
* bounce_trace_service.c
*/
-extern int bounce_trace_service(char *, char *, char *, char *, char *);
+extern int bounce_trace_service(int, char *, char *, char *, char *, char *);
/*
* bounce_notify_verp.c
*/
-extern int bounce_notify_verp(char *, char *, char *, char *, char *, char *);
+extern int bounce_notify_verp(int, char *, char *, char *, char *, char *, char *);
/*
* bounce_one_service.c
*/
-extern int bounce_one_service(char *, char *, char *, char *, char *, char *, char *, char *, char *);
+extern int bounce_one_service(int, char *, char *, char *, char *, char *, char *, long, char *, char *, char *);
/*
* bounce_cleanup.c
} BOUNCE_INFO;
extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, const char *, int);
-extern BOUNCE_INFO *bounce_mail_one_init(const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *);
+extern BOUNCE_INFO *bounce_mail_one_init(const char *, const char *, const char *, const char *, const char *, long, const char *, const char *, const char *);
extern void bounce_mail_free(BOUNCE_INFO *);
extern int bounce_header(VSTREAM *, BOUNCE_INFO *, const char *);
extern int bounce_boilerplate(VSTREAM *, BOUNCE_INFO *);
extern int bounce_recipient_dsn(VSTREAM *, BOUNCE_INFO *);
extern int bounce_diagnostic_dsn(VSTREAM *, BOUNCE_INFO *);
extern int bounce_original(VSTREAM *, BOUNCE_INFO *, int);
+extern int bounce_delrcpt(BOUNCE_INFO *);
+extern int bounce_delrcpt_one(BOUNCE_INFO *);
#define BOUNCE_MSG_FAIL 0
#define BOUNCE_MSG_WARN 1
/* SYNOPSIS
/* #include "bounce_service.h"
/*
-/* int bounce_trace_service(queue_name, queue_id, encoding, sender)
+/* int bounce_trace_service(flags, queue_name, queue_id, encoding, sender)
+/* int flags;
/* char *queue_name;
/* char *queue_id;
/* char *encoding;
/* bounce_trace_service - send a delivery status notice */
-int bounce_trace_service(char *service, char *queue_name,
+int bounce_trace_service(int unused_flags, char *service, char *queue_name,
char *queue_id, char *encoding,
char *recipient)
{
/* SYNOPSIS
/* #include "bounce_service.h"
/*
-/* int bounce_warn_service(queue_name, queue_id, encoding, sender)
+/* int bounce_warn_service(flags, queue_name, queue_id, encoding, sender)
+/* int flags;
/* char *queue_name;
/* char *queue_id;
/* char *encoding;
/* bounce_warn_service - send a delayed mail notice */
-int bounce_warn_service(char *service, char *queue_name,
+int bounce_warn_service(int unused_flags, char *service, char *queue_name,
char *queue_id, char *encoding,
char *recipient)
{
if (bounce_append(BOUNCE_FLAG_CLEAN, state->queue_id,
state->recip ? state->recip : "unknown",
state->recip ? state->recip : "unknown",
- "cleanup", state->time,
+ (long) 0, "cleanup", state->time,
"%s", state->reason ? state->reason :
cleanup_strerror(state->errs)) == 0
&& bounce_flush(BOUNCE_FLAG_CLEAN, state->queue_name,
rcpt = request->rcpt_list.info + nrcpt;
if (rcpt->offset >= 0) {
status = bounce_append(BOUNCE_FLAGS(request), request->queue_id,
- rcpt->orig_addr, rcpt->address, "none",
- request->arrival_time,
+ rcpt->orig_addr, rcpt->address,
+ rcpt->offset, "none", request->arrival_time,
"%s", request->nexthop);
if (status == 0)
deliver_completed(src, rcpt->offset);
/* SYNOPSIS
/* #include <bounce.h>
/*
-/* int bounce_append(flags, id, orig_rcpt, recipient, relay,
+/* int bounce_append(flags, id, orig_rcpt, recipient, offset, relay,
/* entry, format, ...)
/* int flags;
/* const char *id;
/* const char *orig_rcpt;
/* const char *recipient;
+/* long offset;
/* const char *relay;
/* time_t entry;
/* const char *format;
/*
-/* int vbounce_append(flags, id, orig_rcpt, recipient, relay,
+/* int vbounce_append(flags, id, orig_rcpt, recipient, offset, relay,
/* entry, format, ap)
/* int flags;
/* const char *id;
/* const char *orig_rcpt;
/* const char *recipient;
+/* long offset;
/* const char *relay;
/* time_t entry;
/* const char *format;
/* const char *sender;
/*
/* int bounce_one(flags, queue, id, encoding, sender, orig_rcpt,
-/* recipient, relay, entry, format, ...)
+/* recipient, offset, relay, entry, format, ...)
/* int flags;
/* const char *queue;
/* const char *id;
/* const char *encoding;
/* const char *sender;
+/* const char *orig_rcpt;
/* const char *recipient;
+/* long offset;
/* const char *relay;
/* time_t entry;
/* const char *format;
/*
/* int vbounce_one(flags, queue, id, encoding, sender, orig_rcpt,
-/* recipient, relay, entry, format, ap)
+/* recipient, offset, relay, entry, format, ap)
/* int flags;
/* const char *queue;
/* const char *id;
/* const char *sender;
/* const char *orig_rcpt;
/* const char *recipient;
+/* long offset;
/* const char *relay;
/* time_t entry;
/* const char *format;
/* .IP recipient
/* Recipient address that the message could not be delivered to.
/* This information is used for syslogging only.
+/* .IP offset
+/* Queue file offset of recipient record.
/* .IP format
/* The reason for non-delivery.
/* .IP ap
/* bounce_append - append reason to per-message bounce log */
int bounce_append(int flags, const char *id, const char *orig_rcpt,
- const char *recipient, const char *relay,
+ const char *recipient, long offset, const char *relay,
time_t entry, const char *fmt,...)
{
va_list ap;
va_start(ap, fmt);
status = vbounce_append(flags, id, orig_rcpt, recipient,
- relay, entry, fmt, ap);
+ offset, relay, entry, fmt, ap);
va_end(ap);
return (status);
}
/* vbounce_append - append bounce reason to per-message log */
int vbounce_append(int flags, const char *id, const char *orig_rcpt,
- const char *recipient, const char *relay,
+ const char *recipient, long offset, const char *relay,
time_t entry, const char *fmt, va_list ap)
{
int status;
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_rcpt,
ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient,
+ ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, offset,
ATTR_TYPE_STR, MAIL_ATTR_STATUS, dsn_code,
ATTR_TYPE_STR, MAIL_ATTR_ACTION, dsn_action,
ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why),
entry, log_status, fmt, ap);
status = (var_soft_bounce ? -1 : 0);
} else if ((flags & BOUNCE_FLAG_CLEAN) == 0) {
- status = defer_append(flags, id, orig_rcpt, recipient, relay,
- entry, "%s or %s service failure",
+ status = defer_append(flags, id, orig_rcpt, recipient, offset,
+ relay, entry, "%s or %s service failure",
var_bounce_service, var_trace_service);
} else {
status = -1;
int bounce_one(int flags, const char *queue, const char *id,
const char *encoding, const char *sender,
const char *orig_rcpt, const char *recipient,
- const char *relay, time_t entry,
+ long offset, const char *relay, time_t entry,
const char *fmt,...)
{
va_list ap;
va_start(ap, fmt);
status = vbounce_one(flags, queue, id, encoding, sender, orig_rcpt,
- recipient, relay, entry, fmt, ap);
+ recipient, offset, relay, entry, fmt, ap);
va_end(ap);
return (status);
}
int vbounce_one(int flags, const char *queue, const char *id,
const char *encoding, const char *sender,
const char *orig_rcpt, const char *recipient,
- const char *relay, time_t entry,
+ long offset, const char *relay, time_t entry,
const char *fmt, va_list ap)
{
int status;
*/
else if (var_soft_bounce) {
return (vbounce_append(flags, id, orig_rcpt, recipient,
- relay, entry, fmt, ap));
+ offset, relay, entry, fmt, ap));
}
/*
ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_rcpt,
ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient,
+ ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, offset,
ATTR_TYPE_STR, MAIL_ATTR_STATUS, "5.0.0",
ATTR_TYPE_STR, MAIL_ATTR_ACTION, "failed",
ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why),
entry, "bounced", fmt, ap);
status = 0;
} else if ((flags & BOUNCE_FLAG_CLEAN) == 0) {
- status = defer_append(flags, id, orig_rcpt, recipient, relay,
- entry, "%s or %s service failure",
+ status = defer_append(flags, id, orig_rcpt, recipient, offset,
+ relay, entry, "%s or %s service failure",
var_bounce_service, var_trace_service);
} else {
status = -1;
/*
* Client interface.
*/
-extern int PRINTFLIKE(7, 8) bounce_append(int, const char *,
+extern int PRINTFLIKE(8, 9) bounce_append(int, const char *,
const char *, const char *,
- const char *, time_t,
+ long, const char *, time_t,
const char *,...);
-extern int vbounce_append(int, const char *, const char *, const char *,
+extern int vbounce_append(int, const char *, const char *, const char *, long,
const char *, time_t, const char *, va_list);
extern int bounce_flush(int, const char *, const char *, const char *, const char *);
-extern int PRINTFLIKE(10, 11) bounce_one(int, const char *, const char *,
+extern int PRINTFLIKE(11, 12) bounce_one(int, const char *, const char *,
const char *, const char *,
const char *, const char *,
- const char *, time_t,
+ long, const char *, time_t,
const char *,...);
extern int vbounce_one(int, const char *, const char *, const char *,
- const char *, const char *, const char *,
+ const char *, const char *, const char *, long,
const char *, time_t, const char *, va_list);
/*
*/
#define BOUNCE_FLAG_NONE 0 /* no flags up */
#define BOUNCE_FLAG_CLEAN (1<<0) /* remove log on error */
+#define BOUNCE_FLAG_DELRCPT (1<<1) /* delete recipient from queue file */
/*
* Backwards compatibility.
/* /* public members... */
/* const char *recipient;
/* const char *orig_rcpt;
+/* long rcpt_offset;
/* const char *dsn_status;
/* const char *dsn_action;
/* const char *text;
/* BOUNCE_LOG *bounce_log_read(bp)
/* BOUNCE_LOG *bp;
/*
-/* BOUNCE_LOG *bounce_log_delrcpt(bp)
-/* BOUNCE_LOG *bp;
-/*
/* void bounce_log_rewind(bp)
/* BOUNCE_LOG *bp;
/*
-/* BOUNCE_LOG *bounce_log_forge(orig_rcpt, recipient, dsn_status,
-/* dsn_action, why)
+/* BOUNCE_LOG *bounce_log_forge(orig_rcpt, recipient, rcpt_offset,
+/* dsn_status, dsn_action, why)
/* const char *orig_rcpt;
/* const char *recipient;
+/* long rcpt_offset;
/* const char *dsn_status;
/* const char *dsn_action;
/* const char *why;
/* bounce_log_read() returns a null pointer when no recipient was read,
/* otherwise it returns its argument.
/*
-/* bounce_log_delrcpt() marks the last accessed recipient record as
-/* "deleted". This requires that the logfile is opened for update.
-/*
/* bounce_log_rewind() is a helper that seeks to the first recipient
/* in an open bounce or defer logfile (skipping over recipients that
/* are marked as done). The result is 0 in case of success, -1 in case
/* .IP orig_rcpt
/* Null pointer or the original recipient address in RFC 822
/* external form.
+/* .IP rcpt_offset
+/* Queue file offset of recipient record.
/* .IP text
/* The text that explains why the recipient was undeliverable.
/* .IP dsn_status
#include <string.h>
#include <ctype.h>
#include <unistd.h>
+#include <stdlib.h>
/* Utility library. */
VSTRING *buf,
VSTRING *orcp_buf,
VSTRING *rcpt_buf,
+ long rcpt_offset,
VSTRING *status_buf,
const char *compat_status,
VSTRING *action_buf,
const char *compat_action,
- VSTRING *text_buf,
- long offset)
+ VSTRING *text_buf)
{
BOUNCE_LOG *bp;
bp->buf = buf;
SET_BUFFER(bp, orcp_buf, orig_rcpt);
SET_BUFFER(bp, rcpt_buf, recipient);
+ bp->rcpt_offset = rcpt_offset;
SET_BUFFER(bp, status_buf, dsn_status);
bp->compat_status = compat_status;
SET_BUFFER(bp, action_buf, dsn_action);
bp->compat_action = compat_action;
SET_BUFFER(bp, text_buf, text);
- bp->offset = offset;
return (bp);
}
vstring_alloc(100), /* buffer */
vstring_alloc(10), /* orig_rcpt */
vstring_alloc(10), /* recipient */
+ (long) 0, /* offset */
vstring_alloc(10), /* dsn_status */
STREQ(queue_name, MAIL_QUEUE_DEFER) ?
"4.0.0" : "5.0.0", /* compatibility */
vstring_alloc(10), /* dsn_action */
STREQ(queue_name, MAIL_QUEUE_DEFER) ?
"delayed" : "failed", /* compatibility */
- vstring_alloc(10), /* text */
- 0)); /* offset */
+ vstring_alloc(10))); /* text */
}
}
char *text;
char *cp;
int state;
- long offset;
/*
* Our trivial logfile parser state machine.
*/
#define START 0 /* still searching */
#define FOUND 1 /* in logfile entry */
-#define SKIP 2 /* in deleted entry */
/*
* Initialize.
state = START;
bp->recipient = "(unavailable)";
bp->orig_rcpt = 0;
+ bp->rcpt_offset = 0;
bp->dsn_status = "(unavailable)";
bp->dsn_action = "(unavailable)";
bp->text = "(unavailable)";
* With backwards compatibility, we even have old format followed by new
* format within the same logfile entry!
*/
- while ((offset = vstream_ftell(bp->fp)),
- (vstring_get_nonl(bp->buf, bp->fp) != VSTREAM_EOF)) {
+ while ((vstring_get_nonl(bp->buf, bp->fp) != VSTREAM_EOF)) {
/*
* Logfile entries are separated by blank lines. Even the old ad-hoc
continue;
}
- /*
- * Skip over deleted logfile entries.
- */
- if (state == SKIP)
- continue;
-
/*
* Sanitize. XXX This needs to be done more carefully with new-style
* logfile entries.
*/
cp = printable(STR(bp->buf), '?');
- /*
- * Skip over deleted recipients.
- */
- if (*cp == BOUNCE_LOG_STAT_DELETED) {
- state = SKIP;
- continue;
- }
-
- /*
- * Save the first record offset of this logfile entry so that it can
- * be marked as deleted.
- */
- if (state == START) {
+ if (state == START)
state = FOUND;
- bp->offset = offset;
- }
/*
* New style logfile entries are in "name = value" format.
} else if (STREQ(name, MAIL_ATTR_ORCPT)) {
bp->orig_rcpt = STR(vstring_strcpy(bp->orcp_buf, *value ?
value : "(MAILER-DAEMON)"));
+ } else if (STREQ(name, MAIL_ATTR_OFFSET)) {
+ bp->rcpt_offset = atol(value);
} else if (STREQ(name, MAIL_ATTR_STATUS)) {
bp->dsn_status = STR(vstring_strcpy(bp->status_buf, value));
} else if (STREQ(name, MAIL_ATTR_ACTION)) {
return (0);
}
-/* bounce_log_delrcpt - mark recipient record as deleted */
-
-BOUNCE_LOG *bounce_log_delrcpt(BOUNCE_LOG *bp)
-{
- long current_offset;
-
- current_offset = vstream_ftell(bp->fp);
- if (vstream_fseek(bp->fp, bp->offset, SEEK_SET) < 0)
- msg_fatal("bounce logfile %s seek error: %m", VSTREAM_PATH(bp->fp));
- VSTREAM_PUTC(BOUNCE_LOG_STAT_DELETED, bp->fp);
- if (vstream_fseek(bp->fp, current_offset, SEEK_SET) < 0)
- msg_fatal("bounce logfile %s seek error: %m", VSTREAM_PATH(bp->fp));
- return (bp);
-}
-
/* bounce_log_forge - forge one recipient status record */
BOUNCE_LOG *bounce_log_forge(const char *orig_rcpt, const char *recipient,
- const char *dsn_status, const char *dsn_action,
- const char *text)
+ long rcpt_offset, const char *dsn_status,
+ const char *dsn_action, const char *text)
{
return (bounce_log_init((VSTREAM *) 0,
(VSTRING *) 0,
SAVE_TO_VSTRING(orig_rcpt),
SAVE_TO_VSTRING(recipient),
+ rcpt_offset,
SAVE_TO_VSTRING(dsn_status),
"(unavailable)",
SAVE_TO_VSTRING(dsn_action),
"(unavailable)",
- SAVE_TO_VSTRING(text),
- 0));
+ SAVE_TO_VSTRING(text)));
}
/* bounce_log_close - close bounce reader stream */
/* Public. */
const char *recipient; /* final recipient */
const char *orig_rcpt; /* original recipient */
+ long rcpt_offset; /* queue file offset */
const char *dsn_status; /* dsn code */
const char *dsn_action; /* dsn action */
const char *text; /* descriptive text */
- long offset; /* start of current record */
} BOUNCE_LOG;
extern BOUNCE_LOG *bounce_log_open(const char *, const char *, int, int);
extern BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *);
extern BOUNCE_LOG *bounce_log_delrcpt(BOUNCE_LOG *);
-extern BOUNCE_LOG *bounce_log_forge(const char *, const char *, const char *, const char *, const char *);
+extern BOUNCE_LOG *bounce_log_forge(const char *, const char *, long, const char *, const char *, const char *);
extern int bounce_log_close(BOUNCE_LOG *);
#define bounce_log_rewind(bp) vstream_fseek((bp)->fp, 0L, SEEK_SET)
-#define BOUNCE_LOG_STAT_DELETED 'D' /* deleted record */
-
/* LICENSE
/* .ad
/* .fi
/* SYNOPSIS
/* #include <defer.h>
/*
-/* int defer_append(flags, id, orig_rcpt, recipient, relay,
+/* int defer_append(flags, id, orig_rcpt, recipient, offset, relay,
/* entry, format, ...)
/* int flags;
/* const char *id;
/* const char *orig_rcpt;
/* const char *recipient;
+/* long offset;
/* const char *relay;
/* time_t entry;
/* const char *format;
/*
-/* int vdefer_append(flags, id, orig_rcpt, recipient, relay,
+/* int vdefer_append(flags, id, orig_rcpt, recipient, offset, relay,
/* entry, format, ap)
/* int flags;
/* const char *id;
/* const char *orig_rcpt;
/* const char *recipient;
+/* long offset;
/* const char *relay;
/* time_t entry;
/* const char *format;
/* .IP recipient
/* A recipient address that is being deferred. The domain part
/* of the address is marked dead (for a limited amount of time).
+/* .IP offset
+/* Queue file offset of recipient record.
/* .IP encoding
/* The body content encoding: MAIL_ATTR_ENC_{7BIT,8BIT,NONE}.
/* .IP sender
/* defer_append - defer message delivery */
int defer_append(int flags, const char *id, const char *orig_rcpt,
- const char *recipient, const char *relay,
+ const char *recipient, long offset, const char *relay,
time_t entry, const char *fmt,...)
{
va_list ap;
va_start(ap, fmt);
status = vdefer_append(flags, id, orig_rcpt, recipient,
- relay, entry, fmt, ap);
+ offset, relay, entry, fmt, ap);
va_end(ap);
return (status);
}
/* vdefer_append - defer delivery of queue file */
int vdefer_append(int flags, const char *id, const char *orig_rcpt,
- const char *recipient, const char *relay,
+ const char *recipient, long offset, const char *relay,
time_t entry, const char *fmt, va_list ap)
{
const char *rcpt_domain;
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id,
ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_rcpt,
ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient,
+ ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, offset,
ATTR_TYPE_STR, MAIL_ATTR_STATUS, "4.0.0",
ATTR_TYPE_STR, MAIL_ATTR_ACTION, "delayed",
ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why),
int defer_flush(int flags, const char *queue, const char *id,
const char *encoding, const char *sender)
{
+ flags |= BOUNCE_FLAG_DELRCPT;
+
if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
/*
* External interface.
*/
-extern int PRINTFLIKE(7, 8) defer_append(int, const char *, const char *,
- const char *, const char *, time_t,
+extern int PRINTFLIKE(8, 9) defer_append(int, const char *,
+ const char *, const char *,
+ long, const char *, time_t,
const char *,...);
-extern int vdefer_append(int, const char *, const char *, const char *,
+extern int vdefer_append(int, const char *, const char *, const char *, long,
const char *, time_t, const char *, va_list);
extern int defer_flush(int, const char *, const char *, const char *, const char *);
/* char *var_queue_dir;
/* int var_use_limit;
/* int var_idle_limit;
+/* int var_event_drain;
/* int var_bundle_rcpt;
/* char *var_procname;
/* int var_pid;
char *var_command_dir;
char *var_queue_dir;
int var_use_limit;
+int var_event_drain;
int var_idle_limit;
int var_bundle_rcpt;
char *var_procname;
0,
};
static CONFIG_TIME_TABLE time_defaults[] = {
+ VAR_EVENT_DRAIN, DEF_EVENT_DRAIN, &var_event_drain, 1, 0,
VAR_MAX_IDLE, DEF_MAX_IDLE, &var_idle_limit, 1, 0,
VAR_IPC_TIMEOUT, DEF_IPC_TIMEOUT, &var_ipc_timeout, 1, 0,
VAR_IPC_IDLE, DEF_IPC_IDLE, &var_ipc_idle_limit, 1, 0,
#define DEF_MAX_IDLE "100s"
extern int var_idle_limit;
+ /*
+ * Any subsystem: default amount of time a mail subsystem waits for
+ * application events to drain.
+ */
+#define VAR_EVENT_DRAIN "application_event_drain_time"
+#define DEF_EVENT_DRAIN "100s"
+extern int var_event_drain;
+
/*
* Any subsystem: default amount of time a mail subsystem keeps an internal
* IPC connection before closing it because it is idle for too much time.
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
-#define MAIL_RELEASE_DATE "20030919"
+#define MAIL_RELEASE_DATE "20030920"
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
/* SYNOPSIS
/* #include <sent.h>
/*
-/* int sent(flags, queue_id, orig_rcpt, recipient, relay,
+/* int sent(flags, queue_id, orig_rcpt, recipient, offset, relay,
/* entry, format, ...)
/* int flags;
/* const char *queue_id;
/* const char *orig_rcpt;
/* const char *recipient;
+/* long offset;
/* const char *relay;
/* time_t entry;
/* const char *format;
/*
-/* int vsent(flags, queue_id, orig_rcpt, recipient, relay,
+/* int vsent(flags, queue_id, orig_rcpt, recipient, offset, relay,
/* entry, format, ap)
/* int flags;
/* const char *queue_id;
/* const char *orig_rcpt;
/* const char *recipient;
+/* long offset;
/* const char *relay;
/* time_t entry;
/* const char *format;
/* specify a null string or a null pointer.
/* .IP recipient
/* The recipient address.
+/* .IP offset
+/* Queue file offset of the recipient record.
/* .IP relay
/* Name of the host we're talking to.
/* .IP entry
/* sent - log that a message was sent */
int sent(int flags, const char *id, const char *orig_rcpt,
- const char *recipient, const char *relay,
+ const char *recipient, long offset, const char *relay,
time_t entry, const char *fmt,...)
{
va_list ap;
int status;
va_start(ap, fmt);
- status = vsent(flags, id, orig_rcpt, recipient, relay, entry, fmt, ap);
+ status = vsent(flags, id, orig_rcpt, recipient,
+ offset, relay, entry, fmt, ap);
va_end(ap);
return (status);
}
/* vsent - log that a message was sent */
int vsent(int flags, const char *id, const char *orig_rcpt,
- const char *recipient, const char *relay,
+ const char *recipient, long offset, const char *relay,
time_t entry, const char *fmt, va_list ap)
{
int status;
entry, "sent", fmt, ap);
status = 0;
} else {
- status = defer_append(flags, id, orig_rcpt, recipient,
+ status = defer_append(flags, id, orig_rcpt, recipient, offset,
relay, entry, "%s: %s service failed",
id, var_trace_service);
}
*/
#define SENT_FLAG_NONE (0)
-extern int PRINTFLIKE(7, 8) sent(int, const char *, const char *, const char *,
- const char *, time_t, const char *,...);
-extern int vsent(int, const char *, const char *, const char *, const char *,
- time_t, const char *, va_list);
+extern int PRINTFLIKE(8, 9) sent(int, const char *, const char *, const char *,
+ long, const char *, time_t, const char *,...);
+extern int vsent(int, const char *, const char *, const char *, long,
+ const char *, time_t, const char *, va_list);
/* LICENSE
/* .ad
if (DEL_REQ_TRACE_ONLY(request->flags)
&& sent(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, rcpt->orig_addr,
- rcpt->address, session->namaddr,
- request->arrival_time, "%s",
+ rcpt->address, rcpt->offset,
+ session->namaddr, request->arrival_time,
+ "%s",
translit(resp->str, "\n", " ")) == 0) {
if (request->flags & DEL_REQ_FLAG_SUCCESS)
deliver_completed(state->src, rcpt->offset);
if (rcpt->offset) {
if (sent(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, rcpt->orig_addr,
- rcpt->address, session->namaddr,
+ rcpt->address, rcpt->offset,
+ session->namaddr,
request->arrival_time,
"%s", resp->str) == 0) {
if (request->flags & DEL_REQ_FLAG_SUCCESS)
continue;
status = (soft_error ? defer_append : bounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
- rcpt->orig_addr, rcpt->address,
+ rcpt->orig_addr, rcpt->address, rcpt->offset,
session ? session->namaddr : "none",
request->arrival_time, "%s", vstring_str(why));
if (status == 0) {
continue;
status = (LMTP_SOFT(code) ? defer_append : bounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
- rcpt->orig_addr, rcpt->address,
+ rcpt->orig_addr, rcpt->address, rcpt->offset,
session->namaddr, request->arrival_time,
"%s", vstring_str(why));
if (status == 0) {
va_start(ap, format);
status = (LMTP_SOFT(code) ? vdefer_append : vbounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
- rcpt->orig_addr, rcpt->address,
+ rcpt->orig_addr, rcpt->address, rcpt->offset,
session->namaddr, request->arrival_time, format, ap);
va_end(ap);
if (status == 0) {
state->status |= defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id,
rcpt->orig_addr, rcpt->address,
- session->namaddr,
+ rcpt->offset, session->namaddr,
request->arrival_time,
"%s", vstring_str(why));
}
forward_init();
state.msg_attr.orig_rcpt = rcpt->orig_addr;
state.msg_attr.recipient = rcpt->address;
+ state.msg_attr.rcpt_offset = rcpt->offset;
rcpt_stat = deliver_recipient(state, usr_attr);
rcpt_stat |= forward_finish(rqst, state.msg_attr, rcpt_stat);
if (rcpt_stat == 0 && (rqst->flags & DEL_REQ_FLAG_SUCCESS))
char *sender; /* taken from envelope */
char *orig_rcpt; /* from submission */
char *recipient; /* taken from resolver */
+ long rcpt_offset; /* taken from resolver */
char *domain; /* recipient domain */
char *local; /* recipient full localpart */
char *user; /* recipient localpart, base name */
#define BOUNCE_FLAGS(request) DEL_REQ_TRACE_FLAGS((request)->flags)
#define BOUNCE_ATTR(attr) attr.queue_id, attr.orig_rcpt, attr.recipient, \
- attr.relay, attr.arrival_time
+ attr.rcpt_offset, attr.relay, \
+ attr.arrival_time
#define BOUNCE_ONE_ATTR(attr) attr.queue_name, attr.queue_id, attr.encoding, \
attr.sender, attr.orig_rcpt, \
- attr.recipient, attr.relay, \
- attr.arrival_time
-#define SENT_ATTR(attr) attr.queue_id, attr.orig_rcpt, attr.recipient, \
+ attr.recipient, attr.rcpt_offset, \
attr.relay, attr.arrival_time
+#define SENT_ATTR(attr) attr.queue_id, attr.orig_rcpt, attr.recipient, \
+ attr.rcpt_offset, attr.relay, \
+ attr.arrival_time
#define OPENED_ATTR(attr) attr.queue_id, attr.sender
#define COPY_ATTR(attr) attr.sender, attr.orig_rcpt, attr.delivered, \
attr.fp
va_start(ap, format);
status = vbounce_append(message->tflags, message->queue_id,
- recipient->orig_rcpt, recipient->address, "none",
- message->arrival_time, format, ap);
+ recipient->orig_rcpt, recipient->address,
+ recipient->offset, "none", message->arrival_time,
+ format, ap);
va_end(ap);
if (status == 0)
*/
message->flags |= defer_append(message->tflags, message->queue_id,
recipient->orig_rcpt, recipient->address,
- "none", message->arrival_time, "%s", reason);
+ recipient->offset, "none",
+ message->arrival_time, "%s", reason);
}
if (strncasecmp(STR(reply.recipient), var_double_bounce_sender,
len) == 0
&& !var_double_bounce_sender[len]) {
- status = sent(message->tflags, message->queue_id, recipient->orig_rcpt,
- recipient->address, "none", message->arrival_time,
+ status = sent(message->tflags, message->queue_id,
+ recipient->orig_rcpt, recipient->address,
+ recipient->offset, "none", message->arrival_time,
"undeliverable postmaster notification discarded");
if (status == 0) {
deliver_completed(message->fp, recipient->offset);
rcpt = request->rcpt_list.info + n;
status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, rcpt->orig_addr,
- rcpt->address, service,
+ rcpt->address, rcpt->offset, service,
request->arrival_time, "%s", request->nexthop);
if (status == 0 && (request->flags & DEL_REQ_FLAG_SUCCESS))
deliver_completed(src, rcpt->offset);
rcpt = request->rcpt_list.info + n;
status = bounce_append(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, rcpt->orig_addr,
- rcpt->address, service,
+ rcpt->address, rcpt->offset, service,
request->arrival_time, "%s", why);
if (status == 0)
deliver_completed(src, rcpt->offset);
rcpt = request->rcpt_list.info + n;
result |= defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, rcpt->orig_addr,
- rcpt->address, service,
+ rcpt->address, rcpt->offset, service,
request->arrival_time, "%s", why);
}
break;
rcpt = request->rcpt_list.info + n;
status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, rcpt->orig_addr,
- rcpt->address, service,
+ rcpt->address, rcpt->offset, service,
request->arrival_time,
"delivers to command: %s", attr.command[0]);
if (status == 0 && (request->flags & DEL_REQ_FLAG_SUCCESS))
class, service);
exit(1);
} else {
- event_drain();
+ event_drain(var_event_drain);
exit(0);
}
}
va_start(ap, format);
status = vbounce_append(message->tflags, message->queue_id,
- recipient->orig_rcpt, recipient->address, "none",
- message->arrival_time, format, ap);
+ recipient->orig_rcpt, recipient->address,
+ recipient->offset, "none", message->arrival_time,
+ format, ap);
va_end(ap);
if (status == 0)
*/
message->flags |= defer_append(message->tflags, message->queue_id,
recipient->orig_rcpt, recipient->address,
- "none", message->arrival_time, "%s", reason);
+ recipient->offset, "none",
+ message->arrival_time, "%s", reason);
}
if (strncasecmp(STR(reply.recipient), var_double_bounce_sender,
len) == 0
&& !var_double_bounce_sender[len]) {
- status = sent(message->tflags, message->queue_id, recipient->orig_rcpt,
- recipient->address, "none", message->arrival_time,
+ status = sent(message->tflags, message->queue_id,
+ recipient->orig_rcpt, recipient->address,
+ recipient->offset, "none", message->arrival_time,
"undeliverable postmaster notification discarded");
if (status == 0) {
deliver_completed(message->fp, recipient->offset);
if (DEL_REQ_TRACE_ONLY(request->flags)
&& sent(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, rcpt->orig_addr,
- rcpt->address, session->namaddr,
- request->arrival_time, "%s",
+ rcpt->address, rcpt->offset,
+ session->namaddr, request->arrival_time,
+ "%s",
translit(resp->str, "\n", " ")) == 0) {
if (request->flags & DEL_REQ_FLAG_SUCCESS)
deliver_completed(state->src, rcpt->offset);
if (rcpt->offset) {
if (sent(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, rcpt->orig_addr,
- rcpt->address,
+ rcpt->address, rcpt->offset,
session->namaddr,
request->arrival_time,
"%s", resp->str) == 0) {
continue;
status = (soft_error ? defer_append : bounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
- rcpt->orig_addr, rcpt->address,
+ rcpt->orig_addr, rcpt->address, rcpt->offset,
session ? session->namaddr : "none",
request->arrival_time, "%s", vstring_str(why));
if (status == 0) {
continue;
status = (SMTP_SOFT(code) ? defer_append : bounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
- rcpt->orig_addr, rcpt->address,
+ rcpt->orig_addr, rcpt->address, rcpt->offset,
session->namaddr, request->arrival_time,
"%s", vstring_str(why));
if (status == 0) {
va_start(ap, format);
status = (SMTP_SOFT(code) ? vdefer_append : vbounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
- rcpt->orig_addr, rcpt->address,
+ rcpt->orig_addr, rcpt->address, rcpt->offset,
session->namaddr, request->arrival_time, format, ap);
va_end(ap);
if (status == 0) {
state->status |= defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id,
rcpt->orig_addr, rcpt->address,
- session->namaddr,
+ rcpt->offset, session->namaddr,
request->arrival_time,
"%s", vstring_str(why));
}
}
if (dns_status != DNS_OK) {
msg_warn("Unable to look up %s host for %s", dns_strtype(type),
- domain && domain[1] ? domain : reply_name);
+ domain && domain[1] ? domain : name);
return (SMTPD_CHECK_DUNNO);
}
/* .PP
/* Configuration parameters:
/* .IP server_host
-/* Blank-separated list of hosts at which all LDAP queries are directed.
+/* List of hosts at which all LDAP queries are directed.
/* The host names can also be LDAP URLs if the LDAP client library used
/* is OpenLDAP.
/* .IP server_port
VSTRING *keybuf = vstring_alloc(10);
char *key;
int len;
+
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
int sslon = dict_ldap->start_tls || dict_ldap->ldap_ssl;
+
+#endif
LDAP_CONN *conn;
#define ADDSTR(vp, s) vstring_memcat((vp), (s), strlen((s))+1)
{
char *myname = "dict_ldap_open";
DICT_LDAP *dict_ldap;
-
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(LDAP_OPT_NETWORK_TIMEOUT)
VSTRING *url_list;
- char *s,
- *h;
-
-#endif
+ char *s;
+ char *h;
char *server_host;
CFG_PARSER parser;
char *domainlist;
dict_ldap->version = LDAP_VERSION2;
}
-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(LDAP_OPT_NETWORK_TIMEOUT)
+#if defined(LDAP_API_FEATURE_X_OPENLDAP)
+ dict_ldap->ldap_ssl = 0;
+#endif
- /*
- * Convert (host, port) pairs to LDAP URLs
- */
url_list = vstring_alloc(32);
s = server_host;
- dict_ldap->ldap_ssl = 0;
- while ((h = mystrtok(&s, " \t")) != NULL) {
+ while ((h = mystrtok(&s, " \t\n\r,")) != NULL) {
+#if defined(LDAP_API_FEATURE_X_OPENLDAP)
+
+ /*
+ * Convert (host, port) pairs to LDAP URLs
+ */
if (ldap_is_ldap_url(h)) {
LDAPURLDesc *url_desc;
int rc;
vstring_sprintf_append(url_list, " ldap://%s:%d", h,
dict_ldap->server_port);
}
+#else
+ vstring_sprintf_append(url_list, " %s", h);
+#endif
}
dict_ldap->server_host = mystrdup(vstring_str(url_list) + 1);
+#if defined(LDAP_API_FEATURE_X_OPENLDAP)
+
/*
* With URL scheme, clear port to normalize connection cache key
*/
- dict_ldap->server_port = 0;
+ dict_ldap->server_port = LDAP_PORT;
if (msg_verbose)
msg_info("%s: %s server_host URL is %s", myname, ldapsource,
dict_ldap->server_host);
+#endif
myfree(server_host);
vstring_free(url_list);
-#else
- dict_ldap->server_host = server_host;
-#endif
/*
* Scope handling thanks to Carsten Hoeger of SuSE.
/* void event_disable_readwrite(fd)
/* int fd;
/*
-/* void event_drain()
+/* void event_drain(time_limit)
+/* int time_limit;
/* DESCRIPTION
/* This module delivers I/O and timer events.
/* Multiple I/O streams and timers can be monitored simultaneously.
/* I/O event requests.
/*
/* event_drain() repeatedly calls event_loop() until no more timer
-/* events or I/O events are pending. This routine must not be called
-/* from an event_whatever() callback routine.
+/* events or I/O events are pending or until the time limit is reached.
+/* This routine must not be called from an event_whatever() callback
+/* routine.
/* DIAGNOSTICS
/* Panics: interface violations. Fatal errors: out of memory,
/* system call failure. Warnings: the number of available
/* event_drain - loop until all pending events are done */
-void event_drain(void)
+void event_drain(int time_limit)
{
fd_set zero_mask;
+ time_t max_time;
if (EVENT_INIT_NEEDED())
return;
FD_ZERO(&zero_mask);
- while (event_timer_head.pred != event_timer_head.succ
- || memcmp(&zero_mask, &event_xmask, sizeof(zero_mask)) != 0)
- event_loop(-1);
+ max_time = event_present + time_limit;
+ while (event_present < max_time
+ && (event_timer_head.pred != event_timer_head.succ
+ || memcmp(&zero_mask, &event_xmask, sizeof(zero_mask)) != 0))
+ event_loop(1);
}
/* event_enable_read - enable read events */
extern time_t event_request_timer(EVENT_NOTIFY_TIME, char *, int);
extern int event_cancel_timer(EVENT_NOTIFY_TIME, char *);
extern void event_loop(int);
-extern void event_drain(void);
+extern void event_drain(int);
/*
* Event codes.
char *sender; /* taken from envelope */
char *orig_rcpt; /* taken from sender */
char *recipient; /* taken from resolver */
+ long rcpt_offset; /* taken from resolver */
char *user; /* recipient lookup handle */
char *delivered; /* for loop detection */
char *relay; /* relay host */
#define BOUNCE_FLAGS(request) DEL_REQ_TRACE_FLAGS((request)->flags)
#define BOUNCE_ATTR(attr) attr.queue_id, attr.orig_rcpt, attr.recipient, \
- attr.relay, attr.arrival_time
+ attr.rcpt_offset, attr.relay, \
+ attr.arrival_time
#define SENT_ATTR(attr) attr.queue_id, attr.orig_rcpt, attr.recipient, \
- attr.relay, attr.arrival_time
+ attr.rcpt_offset, attr.relay, \
+ attr.arrival_time
#define COPY_ATTR(attr) attr.sender, attr.orig_rcpt, attr.delivered, \
attr.fp