From 765763cfefcaf450299a0eb098cc611b4df48906 Mon Sep 17 00:00:00 2001
From: Sergey Poznyakoff <gray@Pirx.gnu.org.ua>
Date: Sat, 13 Jun 2009 09:25:35 +0300
Subject: [PATCH] Implement discard mailer

* include/sm/das.h (DA_IDX_DISCARD): New index.
* include/sm/mta.h (DISCARD_MT): New define.
* smar/rcpt.c: Handle "discard:" keyword in mailertable.
* qmgr/sched.c (qmgr_sched_dlvry): Handle DA_IDX_DISCARD
mailers.
---
 include/sm/das.h |    1 +
 include/sm/mta.h |    1 +
 qmgr/sched.c     |   26 ++++++++++++++++++++++++--
 smar/rcpt.c      |   28 ++++++++++++++++++++++++++++
 4 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/include/sm/das.h b/include/sm/das.h
index 1602d19..94bd603 100644
--- a/include/sm/das.h
+++ b/include/sm/das.h
@@ -29,6 +29,7 @@
 #define DA_IDX_ESMTP		0	/* MUST be 0: default */
 #define DA_IDX_LMTP_UNIX	1	/* lmtp over UNIX domain socket */
 #define DA_IDX_LMTP_INET	2	/* lmtp over inet(v4) socket */
+#define DA_IDX_DISCARD          3       /* Bitbucket mailer */
 
 #if DA_IDX_ESMTP != 0
  ERROR: DA_IDX_ESMTP_ != 0
diff --git a/include/sm/mta.h b/include/sm/mta.h
index 99a4c96..fea5a7f 100644
--- a/include/sm/mta.h
+++ b/include/sm/mta.h
@@ -227,6 +227,7 @@ typedef struct in_addr	sm_host_T, *sm_host_P;
 #endif
 #define LMTP_IPV4_S2	"[127.0.0.255]"
 #define LMTP_MT		"lmtp:"
+#define DISCARD_MT      "discard:"
 
 /* default log level */
 #define SM_LOG_LEVEL	99999
diff --git a/qmgr/sched.c b/qmgr/sched.c
index 54d3aee..3918523 100644
--- a/qmgr/sched.c
+++ b/qmgr/sched.c
@@ -1617,8 +1617,30 @@ so they are counted in qda...
 				aq_rcpt_nxt->aqr_last_try = time_now;
 			}
 
-			/* Send task to DA */
-			ret = sm_rcbcom_endrep(&qsc_ctx->qsc_com, qsc_ctx->qsc_com.rcbcom_tsk, true /* XXX HACK */, &rcbe);
+			/* NOTE: The SAME_TRANSACTION macro used in the
+			   above loop ensures that all recipients within a
+			   single transaction have the same aqr_da_idx. */
+			if (aq_rcpt->aqr_da_idx == DA_IDX_DISCARD) {
+				sm_log_write(qmgr_ctx->qmgr_lctx,
+					     QM_LCAT_SCHED, QM_LMOD_SCHED,
+					     SM_LOG_INFO, 9,
+					     "func=qmgr_sched_dlvry, ss_ta=%s, da_sess=%s, da_ta=%s, rcpt=%@S, status=discarded"
+				, aq_rcpt->aqr_ss_ta_id
+				, dadb_entry->dadbe_da_se_id
+				, dadb_entry->dadbe_da_ta_id
+			        , aq_rcpt->aqr_pa);
+
+				AQR_SET_FLAG(aq_rcpt, AQR_FL_SCHED);
+				aq_rcpt->aqr_last_try = time_now;
+				ret = qda_update_ta_stat(
+					qmgr_ctx, dadb_entry->dadbe_da_ta_id,
+					SM_SUCCESS,
+					0, qsc_ctx->qsc_dadb_ctx,
+					dadb_entry, aq_ta, NULL,
+					NULL, THR_NO_LOCK);
+			} else
+				/* Send task to DA */
+				ret = sm_rcbcom_endrep(&qsc_ctx->qsc_com, qsc_ctx->qsc_com.rcbcom_tsk, true /* XXX HACK */, &rcbe);
 			if (sm_is_err(ret)) {
 				aq_rcpt_P aq_rcpt_r;
 
diff --git a/smar/rcpt.c b/smar/rcpt.c
index d5601a0..b64fd8c 100644
--- a/smar/rcpt.c
+++ b/smar/rcpt.c
@@ -1505,6 +1505,34 @@ SMAR_LEV_DPRINTF(4, (SMAR_DEBFP, "sev=DBG, func=smar_rcpt_rslv, pa=%S, arr_ret=%
 		}
 		gotport = false;
 
+#define DISCARD_MT_LEN     (sizeof(DISCARD_MT) - 1)
+		if (ipv4s != NULL
+		    && strncmp(ipv4s, DISCARD_MT, DISCARD_MT_LEN) == 0) {
+			sm_rcb_P rcb;
+			
+			smar_rcpt->arr_da = DA_IDX_DISCARD;
+			SMARR_SET_FLAG(smar_rcpt, SMARR_FL_GOTMT);
+			sm_log_write(smar_ctx->smar_lctx,
+				AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
+				SM_LOG_INFO, 10,
+				"sev=INFO, func=smar_rcpt_rslv, status=resolved, pa=%S, mailer=discard",
+				smar_rcpt->arr_pa);
+
+			ret = smar_rcpt_re_ipv4(smar_rcpt, 1,
+						smar_rcpts->arrs_resolved == 0);
+			if (sm_is_err(ret)) {
+				sm_log_write(smar_ctx->smar_lctx,
+					AR_LCAT_RESOLVER, AR_LMOD_RESOLVER,
+					     SM_LOG_ERROR, 0,
+					     "sev=ERROR, func=smar_rcpt_rslv, called=resolved, pa=%S, mailer=discard, ret=%m",
+					     smar_rcpt->arr_pa, ret);
+				SMARRS_SET_FLAG(smar_rcpts, SMARRS_FL_ERCB);
+				/* XXX need more cleanup? */
+				goto error;
+			}
+			goto endcom;
+		}
+		
 		if (ipv4s != NULL && '{' == *ipv4s && sm_str_getlen(mtstr) > 2) {
 			ar_mtcnf_T ar_mtcnf;
 			uint u;
-- 
1.6.0

