summaryrefslogtreecommitdiffstats
path: root/src/global/sent.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/global/sent.c')
-rw-r--r--src/global/sent.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/global/sent.c b/src/global/sent.c
new file mode 100644
index 0000000..c81cceb
--- /dev/null
+++ b/src/global/sent.c
@@ -0,0 +1,176 @@
+/*++
+/* NAME
+/* sent 3
+/* SUMMARY
+/* log that a message was or could be sent
+/* SYNOPSIS
+/* #include <sent.h>
+/*
+/* int sent(flags, queue_id, stats, recipient, relay, dsn)
+/* int flags;
+/* const char *queue_id;
+/* MSG_STATS *stats;
+/* RECIPIENT *recipient;
+/* const char *relay;
+/* DSN *dsn;
+/* DESCRIPTION
+/* sent() logs that a message was successfully delivered,
+/* updates the address verification service, or updates a
+/* sender-requested message delivery record. The
+/* flags argument determines the action.
+/*
+/* Arguments:
+/* .IP flags
+/* Zero or more of the following:
+/* .RS
+/* .IP SENT_FLAG_NONE
+/* The message is a normal delivery request.
+/* .IP DEL_REQ_FLAG_MTA_VRFY
+/* The message is an MTA-requested address verification probe.
+/* Update the address verification database.
+/* .IP DEL_REQ_FLAG_USR_VRFY
+/* The message is a user-requested address expansion probe.
+/* Update the message delivery record.
+/* .IP DEL_REQ_FLAG_RECORD
+/* This is a normal message with logged delivery. Update the
+/* the message delivery record.
+/* .RE
+/* .IP queue_id
+/* The message queue id.
+/* .IP stats
+/* Time stamps from different message delivery stages
+/* and session reuse count.
+/* .IP recipient
+/* Recipient information. See recipient_list(3).
+/* .IP relay
+/* Name of the host we're talking to.
+/* .IP dsn
+/* Delivery status. See dsn(3). The action is ignored in case
+/* of a probe message. Otherwise, "delivered" is assumed when
+/* no action is specified.
+/* DIAGNOSTICS
+/* A non-zero result means the operation failed.
+/*
+/* Fatal: out of memory.
+/* BUGS
+/* Should be replaced by routines with an attribute-value based
+/* interface instead of an interface that uses a rigid argument list.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+
+/* Global library. */
+
+#define DSN_INTERN
+#include <mail_params.h>
+#include <verify.h>
+#include <log_adhoc.h>
+#include <trace.h>
+#include <defer.h>
+#include <sent.h>
+#include <dsn_util.h>
+#include <dsn_mask.h>
+
+/* Application-specific. */
+
+/* sent - log that a message was or could be sent */
+
+int sent(int flags, const char *id, MSG_STATS *stats,
+ RECIPIENT *recipient, const char *relay,
+ DSN *dsn)
+{
+ DSN my_dsn = *dsn;
+ DSN *dsn_res;
+ int status;
+
+ /*
+ * Sanity check.
+ */
+ if (my_dsn.status[0] != '2' || !dsn_valid(my_dsn.status)) {
+ msg_warn("sent: ignoring dsn code \"%s\"", my_dsn.status);
+ my_dsn.status = "2.0.0";
+ }
+
+ /*
+ * DSN filter (Postfix 3.0).
+ */
+ if (delivery_status_filter != 0
+ && (dsn_res = dsn_filter_lookup(delivery_status_filter, &my_dsn)) != 0)
+ my_dsn = *dsn_res;
+
+ /*
+ * MTA-requested address verification information is stored in the verify
+ * service database.
+ */
+ if (flags & DEL_REQ_FLAG_MTA_VRFY) {
+ my_dsn.action = "deliverable";
+ status = verify_append(id, stats, recipient, relay, &my_dsn,
+ DEL_RCPT_STAT_OK);
+ return (status);
+ }
+
+ /*
+ * User-requested address verification information is logged and mailed
+ * to the requesting user.
+ */
+ if (flags & DEL_REQ_FLAG_USR_VRFY) {
+ my_dsn.action = "deliverable";
+ status = trace_append(flags, id, stats, recipient, relay, &my_dsn);
+ return (status);
+ }
+
+ /*
+ * Normal mail delivery. May also send a delivery record to the user.
+ */
+ else {
+
+ /* Readability macros: record all deliveries, or the delayed ones. */
+#define REC_ALL_SENT(flags) (flags & DEL_REQ_FLAG_RECORD)
+#define REC_DLY_SENT(flags, rcpt) \
+ ((flags & DEL_REQ_FLAG_REC_DLY_SENT) \
+ && (rcpt->dsn_notify == 0 || (rcpt->dsn_notify & DSN_NOTIFY_DELAY)))
+
+ if (my_dsn.action == 0 || my_dsn.action[0] == 0)
+ my_dsn.action = "delivered";
+
+ if (((REC_ALL_SENT(flags) == 0 && REC_DLY_SENT(flags, recipient) == 0)
+ || trace_append(flags, id, stats, recipient, relay, &my_dsn) == 0)
+ && ((recipient->dsn_notify & DSN_NOTIFY_SUCCESS) == 0
+ || trace_append(flags, id, stats, recipient, relay, &my_dsn) == 0)) {
+ log_adhoc(id, stats, recipient, relay, &my_dsn, "sent");
+ status = 0;
+ } else {
+ VSTRING *junk = vstring_alloc(100);
+
+ vstring_sprintf(junk, "%s: %s service failed",
+ id, var_trace_service);
+ my_dsn.reason = vstring_str(junk);
+ my_dsn.status = "4.3.0";
+ status = defer_append(flags, id, stats, recipient, relay, &my_dsn);
+ vstring_free(junk);
+ }
+ return (status);
+ }
+}