The following diff introduces the junk action which allows builtin
filters to junk a session or transaction.
The following would junk a session if it doesn't have rdns when it
reaches the helo filtering hook:
match "check-rdns" phase helo match !rdns junk
Currently this is not doable so builtin filters may only accept or
throw away a session or transaction, whereas with this diff you'll
be able to automatically classify in Junk folder with the junk mda
option:
action "local_users" maildir junk
This also allows simplifying proc filters that want to junk as the
current method requires registering for data-line and injecting an
X-Spam: Yes header, while this can now be handled by returning the
junk filter response at any phase and letting smtpd prefill header
Index: lka_filter.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/lka_filter.c,v
retrieving revision 1.44
diff -u -p -r1.44 lka_filter.c
--- lka_filter.c 29 Aug 2019 08:49:55 -0000 1.44
+++ lka_filter.c 2 Sep 2019 20:04:37 -0000
@@ -56,6 +56,7 @@ static int filter_builtins_mail_from(str
static int filter_builtins_rcpt_to(struct filter_session *, struct filter
*, uint64_t, const char *);
static void filter_result_proceed(uint64_t);
+static void filter_result_junk(uint64_t);
static void filter_result_rewrite(uint64_t, const char *);
static void filter_result_reject(uint64_t, const char *);
static void filter_result_disconnect(uint64_t, const char *);
@@ -479,6 +480,11 @@ lka_filter_process_response(const char *
fatalx("Unexpected parameter after proceed: %s", line);
filter_protocol_next(token, reqid, 0);
return;
+ } else if (strcmp(response, "junk") == 0) {
+ if (parameter != NULL)
+ fatalx("Unexpected parameter after junk: %s", line);
+ filter_result_junk(reqid);
+ return;
} else {
if (parameter == NULL)
fatalx("Missing parameter: %s", line);
@@ -574,6 +580,15 @@ filter_protocol_internal(struct filter_s
filter_result_disconnect(reqid,
filter->config->disconnect);
return;
}
+ else if (filter->config->junk) {
+ log_trace(TRACE_FILTERS, "%016"PRIx64" filters protocol
phase=%s, "
+ "resume=%s, action=junk, filter=%s, query=%s",
+ fs->id, phase_name, resume ? "y" : "n",
+ filter->name,
+ param);
+ filter_result_junk(reqid);
+ return;
+ }
else {
log_trace(TRACE_FILTERS, "%016"PRIx64" filters protocol
phase=%s, "
"resume=%s, action=reject, filter=%s, query=%s,
response=%s",
@@ -759,6 +774,15 @@ filter_result_proceed(uint64_t reqid)
m_create(p_pony, IMSG_FILTER_SMTP_PROTOCOL, 0, 0, -1);
m_add_id(p_pony, reqid);
m_add_int(p_pony, FILTER_PROCEED);
+ m_close(p_pony);
+}
+
+static void
+filter_result_junk(uint64_t reqid)
+{
+ m_create(p_pony, IMSG_FILTER_SMTP_PROTOCOL, 0, 0, -1);
+ m_add_id(p_pony, reqid);
+ m_add_int(p_pony, FILTER_JUNK);
m_close(p_pony);
}
Index: lka_report.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/lka_report.c,v
retrieving revision 1.27
diff -u -p -r1.27 lka_report.c
--- lka_report.c 29 Aug 2019 07:23:18 -0000 1.27
+++ lka_report.c 2 Sep 2019 20:04:38 -0000
@@ -428,6 +428,9 @@ lka_report_smtp_filter_response(const ch
case FILTER_PROCEED:
response_name = "proceed";
break;
+ case FILTER_JUNK:
+ response_name = "junk";
+ break;
case FILTER_REWRITE:
response_name = "rewrite";
break;
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/parse.y,v
retrieving revision 1.259
diff -u -p -r1.259 parse.y
--- parse.y 25 Aug 2019 03:40:45 -0000 1.259
+++ parse.y 2 Sep 2019 20:04:38 -0000
@@ -1297,6 +1297,9 @@ REJECT STRING {
| REWRITE STRING {
filter_config->rewrite = $2;
}
+| JUNK {
+ filter_config->junk = 1;
+}
;
filter_phase_check_fcrdns:
Index: smtp_session.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/smtp_session.c,v
retrieving revision 1.408
diff -u -p -r1.408 smtp_session.c
--- smtp_session.c 28 Aug 2019 15:50:36 -0000 1.408
+++ smtp_session.c 2 Sep 2019 20:04:39 -0000
@@ -126,6 +126,8 @@ struct smtp_tx {
int rcvcount;
int has_date;
int has_message_id;
+
+ uint8_t junk;
};
struct smtp_session {
@@ -154,6 +156,8 @@ struct smtp_session {
enum smtp_command last_cmd;
enum filter_phase filter_phase;
const char *filter_param;
+
+ uint8_t junk;
};
#define ADVERTISE_TLS(s) \
@@ -970,7 +974,8 @@ smtp_session_imsg(struct mproc *p, struc
m_msg(&m, imsg);
m_get_id(&m, &reqid);
m_get_int(&m, &filter_response);
- if (filter_response != FILTER_PROCEED)
+ if (filter_response != FILTER_PROCEED &&
+ filter_response != FILTER_JUNK)
m_get_string(&m, &filter_param);
else
filter_param = NULL;
@@ -998,9 +1003,17 @@ smtp_session_imsg(struct mproc *p, struc
smtp_proceed_rollback(s, NULL);
break;
+
+ case FILTER_JUNK:
+ if (s->tx)
+ s->tx->junk = 1;
+ else
+ s->junk = 1;
+ /* fallthrough */
+
case FILTER_PROCEED:
filter_param = s->filter_param;
- /* fallthrough*/
+ /* fallthrough */
case FILTER_REWRITE:
report_smtp_filter_response("smtp-in", s->id,
s->filter_phase,
@@ -2815,6 +2828,9 @@ smtp_message_begin(struct smtp_tx *tx)
smtp_reply(s, "354 Enter mail, end with \".\""
" on a line by itself");
+ if (s->junk || (s->tx && s->tx->junk))
+ m_printf(tx, "X-Spam: Yes\n");
+
m_printf(tx, "Received: ");
if (!(s->listener->flags & F_MASK_SOURCE)) {
m_printf(tx, "from %s (%s [%s])",
Index: smtpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/smtpd.conf.5,v
retrieving revision 1.221
diff -u -p -r1.221 smtpd.conf.5
--- smtpd.conf.5 17 Aug 2019 14:43:21 -0000 1.221
+++ smtpd.conf.5 2 Sep 2019 20:04:39 -0000
@@ -348,6 +348,15 @@ to disconnect session with
Phase and matching conditions are documented in a specific section,
see
.Sx BUILTIN FILTERING .
+.It Ic filter Ar filter-name Ic phase Ar phase-name Ic match Ar conditions Ic
junk
+Register builtin filter
+.Ar filter-name
+matching
+.Ar conditions
+to mark a session or a transaction as junk.
+Phase and matching conditions are documented in a specific section,
+see
+.Sx BUILTIN FILTERING .
.It Ic filter Ar filter-name Ic phase Ar phase-name Ic match Ar conditions Ic
reject Ar message
Register builtin filter
.Ar filter-name
Index: smtpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/smtpd.h,v
retrieving revision 1.633
diff -u -p -r1.633 smtpd.h
--- smtpd.h 28 Aug 2019 15:50:36 -0000 1.633
+++ smtpd.h 2 Sep 2019 20:04:40 -0000
@@ -1046,6 +1046,7 @@ struct filter_config {
char *reject;
char *disconnect;
char *rewrite;
+ uint8_t junk;
char *proc;
const char **chain;
@@ -1095,6 +1096,7 @@ enum filter_status {
FILTER_REWRITE,
FILTER_REJECT,
FILTER_DISCONNECT,
+ FILTER_JUNK,
};
enum ca_resp_status {