}
static void
+rspamd_milter_remove_header_safe (struct rspamd_milter_session *session,
+ const gchar *key, gint nhdr)
+{
+ gint saved_nhdr, i;
+ gpointer found;
+ GString *hname, *hvalue;
+ struct rspamd_milter_private *priv = session->priv;
+
+ found = g_hash_table_lookup (priv->headers, key);
+
+ if (found) {
+ saved_nhdr = GPOINTER_TO_INT (found);
+
+ hname = g_string_new (key);
+ hvalue = g_string_new ("");
+
+ if (nhdr >= 1) {
+ rspamd_milter_send_action (session,
+ RSPAMD_MILTER_CHGHEADER,
+ nhdr, hname, hvalue);
+ }
+ else if (nhdr == 0) {
+ /* We need to clear all headers */
+ for (i = 1; i <= saved_nhdr; i ++) {
+ rspamd_milter_send_action (session,
+ RSPAMD_MILTER_CHGHEADER,
+ i, hname, hvalue);
+ }
+ }
+ else {
+ /* Remove from the end */
+ if (nhdr >= -saved_nhdr) {
+ rspamd_milter_send_action (session,
+ RSPAMD_MILTER_CHGHEADER,
+ saved_nhdr + nhdr + 1, hname, hvalue);
+ }
+ }
+
+ g_string_free (hname, TRUE);
+ g_string_free (hvalue, TRUE);
+ }
+}
+
+/*
+ * Returns `TRUE` if action has been processed internally by this function
+ */
+static gboolean
rspamd_milter_process_milter_block (struct rspamd_milter_session *session,
- const ucl_object_t *obj)
+ const ucl_object_t *obj, gint action)
{
const ucl_object_t *elt, *cur, *cur_elt;
ucl_object_iter_t it;
- struct rspamd_milter_private *priv = session->priv;
GString *hname, *hvalue;
- gint nhdr, saved_nhdr, i;
- gpointer found;
if (obj && ucl_object_type (obj) == UCL_OBJECT) {
elt = ucl_object_lookup (obj, "remove_headers");
while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
if (ucl_object_type (cur) == UCL_INT) {
- nhdr = ucl_object_toint (cur);
-
- found = g_hash_table_lookup (priv->headers,
- ucl_object_key (cur));
-
- if (found) {
- saved_nhdr = GPOINTER_TO_INT (found);
-
- hname = g_string_new (ucl_object_key (cur));
- hvalue = g_string_new ("");
-
- if (nhdr >= 1) {
- rspamd_milter_send_action (session,
- RSPAMD_MILTER_CHGHEADER,
- nhdr, hname, hvalue);
- }
- else if (nhdr == 0) {
- /* We need to clear all headers */
- for (i = 1; i <= saved_nhdr; i ++) {
- rspamd_milter_send_action (session,
- RSPAMD_MILTER_CHGHEADER,
- i, hname, hvalue);
- }
- }
- else {
- /* Remove from the end */
- if (nhdr >= -saved_nhdr) {
- rspamd_milter_send_action (session,
- RSPAMD_MILTER_CHGHEADER,
- saved_nhdr + nhdr + 1, hname, hvalue);
- }
- }
-
- g_string_free (hname, TRUE);
- g_string_free (hvalue, TRUE);
- }
+ rspamd_milter_remove_header_safe (session,
+ ucl_object_key (cur),
+ ucl_object_toint (cur));
}
}
}
}
}
}
+
+ if (action == METRIC_ACTION_ADD_HEADER) {
+ elt = ucl_object_lookup (obj, "spam_header");
+
+ if (elt) {
+ if (ucl_object_type (elt) == UCL_STRING) {
+ rspamd_milter_remove_header_safe (session,
+ milter_ctx->spam_header,
+ 0);
+
+ hname = g_string_new (milter_ctx->spam_header);
+ hvalue = g_string_new (ucl_object_tostring (elt));
+ rspamd_milter_send_action (session, RSPAMD_MILTER_CHGHEADER,
+ (guint32)1, hname, hvalue);
+ g_string_free (hname, TRUE);
+ g_string_free (hvalue, TRUE);
+ rspamd_milter_send_action (session, RSPAMD_MILTER_ACCEPT);
+
+ return TRUE;
+ }
+ else if (ucl_object_type (elt) == UCL_OBJECT) {
+ it = NULL;
+
+ while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
+ rspamd_milter_remove_header_safe (session,
+ ucl_object_key (cur),
+ 0);
+
+ hname = g_string_new (ucl_object_key (cur));
+ hvalue = g_string_new (ucl_object_tostring (cur));
+ rspamd_milter_send_action (session, RSPAMD_MILTER_CHGHEADER,
+ (guint32) 1, hname, hvalue);
+ g_string_free (hname, TRUE);
+ g_string_free (hvalue, TRUE);
+ }
+
+ rspamd_milter_send_action (session, RSPAMD_MILTER_ACCEPT);
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
}
void
gint action = METRIC_ACTION_REJECT;
rspamd_fstring_t *xcode = NULL, *rcode = NULL, *reply = NULL;
GString *hname, *hvalue;
+ gboolean processed = FALSE;
if (results == NULL) {
msg_err_milter ("cannot find scan results, tempfail");
elt = ucl_object_lookup (results, "milter");
if (elt) {
- rspamd_milter_process_milter_block (session, elt);
+ processed = rspamd_milter_process_milter_block (session, elt, action);
}
/* DKIM-Signature */
g_string_free (hvalue, TRUE);
}
+ if (processed) {
+ goto cleanup;
+ }
+
switch (action) {
case METRIC_ACTION_REJECT:
rcode = rspamd_fstring_new_init (RSPAMD_MILTER_RCODE_REJECT,
break;
case METRIC_ACTION_ADD_HEADER:
+ /* Remove existing headers */
+ rspamd_milter_remove_header_safe (session,
+ milter_ctx->spam_header,
+ 0);
+
hname = g_string_new (milter_ctx->spam_header);
- /* TODO: Perhaps, we can customize it as well */
hvalue = g_string_new ("Yes");
-
- /* TODO: We to track headers to make it work fine */
rspamd_milter_send_action (session, RSPAMD_MILTER_CHGHEADER,
(guint32)1, hname, hvalue);
g_string_free (hname, TRUE);
break;
}
+cleanup:
rspamd_fstring_free (rcode);
rspamd_fstring_free (xcode);
rspamd_fstring_free (reply);