]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: mailers: remove native mailers support
authorAurelien DARRAGON <adarragon@haproxy.com>
Mon, 23 Jun 2025 20:32:08 +0000 (22:32 +0200)
committerAurelien DARRAGON <adarragon@haproxy.com>
Tue, 24 Jun 2025 08:55:58 +0000 (10:55 +0200)
As mentioned in 2.8 announce on the mailing list [1] and on the wiki [2]
native mailers were deprecated and planned for removal in 3.3. Now is
the time to drop the legacy code for native mailers which is based on a
tcpcheck "hack" and cannot be maintained. Lua mailers should be used as
a drop in replacement. Indeed, "mailers" and associated config directives
are preserved because mailers config is exposed to Lua, which helps smoothing
the transition from native mailers to Lua based ones.

As a reminder, to keep mailers configuration working as before without
making changes to the config file, simply add the line below to the global
section:

       lua-load examples/lua/mailers.lua

mailers.lua script (provided in the git repository, adjust path as needed)
may be customized by users familiar with Lua, by default it emulates the
behavior of the native (now removed) mailers.

[1]: https://www.mail-archive.com/haproxy@formilux.org/msg43600.html
[2]: https://github.com/haproxy/wiki/wiki/Breaking-changes

doc/lua-api/index.rst
examples/lua/mailers.lua
include/haproxy/mailers-t.h
include/haproxy/mailers.h
include/haproxy/thread-t.h
src/check.c
src/hlua.c
src/mailers.c
src/server.c
src/thread.c

index 347de92a0c5f2a00b64d8066e0d86b9bcd5fa5a0..7f96274522b7e15b9b559bf81232b603ae303c1e 100644 (file)
@@ -1089,19 +1089,6 @@ Core class
     perform the heavy job in a dedicated task and allow remaining events to be
     processed more quickly.
 
-.. js:function:: core.disable_legacy_mailers()
-
-  **LEGACY**
-
-  **context**: body, init
-
-  Disable the sending of email alerts through the legacy email sending
-  function when mailers are used in the configuration.
-
-  Use this when sending email alerts directly from lua.
-
-  :see: :js:func:`Proxy.get_mailers()`
-
 .. _proxy_class:
 
 Proxy class
@@ -1247,10 +1234,6 @@ ProxyMailers class
 
   This class provides mailers config for a given proxy.
 
-  If sending emails directly from lua, please consider
-  :js:func:`core.disable_legacy_mailers()` to disable the email sending from
-  haproxy. (Or email alerts will be sent twice...)
-
 .. js:attribute:: ProxyMailers.track_server_health
 
   Boolean set to true if the option "log-health-checks" is configured on
index 47a83560610f05eaf6527ca363b684343d0b070f..b1201fffd58308c5e46362a681c793781cf6a9e0 100644 (file)
@@ -3,7 +3,7 @@
 -- Provides a pure lua alternative to tcpcheck mailers.
 --
 -- To be loaded using "lua-load" from haproxy configuration to handle
--- email-alerts directly from lua and disable legacy tcpcheck implementation.
+-- email-alerts directly from lua
 
 local SYSLOG_LEVEL = {
        ["EMERG"] = 0,
@@ -364,10 +364,6 @@ local function srv_event_add(event, data)
        mailers_track_server_events(data.reference)
 end
 
-
--- disable legacy email-alerts since email-alerts will be sent from lua directly
-core.disable_legacy_mailers()
-
 -- event subscriptions are purposely performed in an init function to prevent
 -- email alerts from being generated too early (when process is starting up)
 core.register_init(function()
index 5df95a977de67d6c8b4fdca84e7bfae3c1b55a41..44f50fdf902dfd33713ea7a05dc543b2b49ef009 100644 (file)
@@ -71,20 +71,5 @@ struct mailers {
        } timeout;
 };
 
-struct email_alert {
-       struct list list;
-       struct tcpcheck_rules rules;
-       struct server *srv;
-};
-
-struct email_alertq {
-       struct list email_alerts;
-       struct check check;             /* Email alerts are implemented using existing check
-                                        * code even though they are not checks. This structure
-                                        * is as a parameter to the check code.
-                                        * Each check corresponds to a mailer */
-       __decl_thread(HA_SPINLOCK_T lock);
-};
-
 #endif /* _HAPROXY_MAILERS_T_H */
 
index ad5fd437f6b67969e0dff79ccff0ec3597d9b63f..509224ac6fa591f4e7cd2c530f2ffe43efcbc901 100644 (file)
 #include <haproxy/server-t.h>
 
 extern struct mailers *mailers;
-extern int send_email_disabled;
 
 int init_email_alert(struct mailers *mailers, struct proxy *p, char **err);
 void free_email_alert(struct proxy *p);
-void send_email_alert(struct server *s, int priority, const char *format, ...)
-       __attribute__ ((format(printf, 3, 4)));
-
 
 #endif /* _HAPROXY_MAILERS_H */
index 0d8cf3b39adf89b36360c58e7db867ee77e9ca59..2c99a4cb98194e3c94c2545a9042afd9b9a7c515 100644 (file)
@@ -201,7 +201,6 @@ enum lock_label {
        SPOE_APPLET_LOCK,
        DNS_LOCK,
        PID_LIST_LOCK,
-       EMAIL_ALERTS_LOCK,
        PIPES_LOCK,
        TLSKEYS_REF_LOCK,
        AUTH_LOCK,
index f202131675c59ef15b7bf9465dacdb3c922d9f08..2689eddc07cd6d864441f09e82674494d3fa1746 100644 (file)
@@ -190,19 +190,16 @@ static void check_trace(enum trace_level level, uint64_t mask,
        if (!check || src->verbosity < CHK_VERB_CLEAN)
                return;
 
-       if (srv) {
-               chunk_appendf(&trace_buf, " : [%c] SRV=%s",
-                             ((check->type == PR_O2_EXT_CHK) ? 'E' : (check->state & CHK_ST_AGENT ? 'A' : 'H')),
-                             srv->id);
+       BUG_ON(!srv);
+       chunk_appendf(&trace_buf, " : [%c] SRV=%s",
+                     ((check->type == PR_O2_EXT_CHK) ? 'E' : (check->state & CHK_ST_AGENT ? 'A' : 'H')),
+                     srv->id);
 
-               chunk_appendf(&trace_buf, " status=%d/%d %s exp=%d",
-                             (check->health >= check->rise) ? check->health - check->rise + 1 : check->health,
-                             (check->health >= check->rise) ? check->fall : check->rise,
-                             (check->health >= check->rise) ? (srv->uweight ? "UP" : "DRAIN") : "DOWN",
-                             (check->task->expire ? TICKS_TO_MS(check->task->expire - now_ms) : 0));
-       }
-       else
-               chunk_appendf(&trace_buf, " : [EMAIL]");
+       chunk_appendf(&trace_buf, " status=%d/%d %s exp=%d",
+                     (check->health >= check->rise) ? check->health - check->rise + 1 : check->health,
+                     (check->health >= check->rise) ? check->fall : check->rise,
+                     (check->health >= check->rise) ? (srv->uweight ? "UP" : "DRAIN") : "DOWN",
+                     (check->task->expire ? TICKS_TO_MS(check->task->expire - now_ms) : 0));
 
        switch (check->result) {
        case CHK_RES_NEUTRAL: res = "-";     break;
@@ -564,7 +561,6 @@ void set_server_check_status(struct check *check, short status, const char *desc
 
                ha_warning("%s.\n", trash.area);
                send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.area);
-               send_email_alert(s, LOG_INFO, "%s", trash.area);
        }
 }
 
@@ -1057,17 +1053,15 @@ int wake_srv_chk(struct stconn *sc)
 {
        struct connection *conn;
        struct check *check = __sc_check(sc);
-       struct email_alertq *q = container_of(check, typeof(*q), check);
        int ret = 0;
 
+       BUG_ON(!check->server);
+
        TRACE_ENTER(CHK_EV_HCHK_WAKE, check);
        if (check->result != CHK_RES_UNKNOWN)
                goto end;
 
-       if (check->server)
-               HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
-       else
-               HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock);
+       HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
 
        /* we may have to make progress on the TCP checks */
        ret = tcpcheck_main(check);
@@ -1099,10 +1093,7 @@ int wake_srv_chk(struct stconn *sc)
                task_queue(check->task);
        }
 
-       if (check->server)
-               HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
-       else
-               HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock);
+       HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
 
   end:
        TRACE_LEAVE(CHK_EV_HCHK_WAKE, check);
index 8e1a54d3a5be513a5481acbec6c6d42a74ff3ee7..25df956907063ed4a349d9a667d9ac8fbed65374 100644 (file)
@@ -2384,21 +2384,6 @@ __LJMP static int hlua_core_get_var(lua_State *L)
        return MAY_LJMP(hlua_smp2lua(L, &smp));
 }
 
-/* This function disables the sending of email through the
- * legacy email sending function which is implemented using
- * checks.
- *
- * It may not be used during runtime.
- */
-__LJMP static int hlua_disable_legacy_mailers(lua_State *L)
-{
-       if (hlua_gethlua(L))
-               WILL_LJMP(luaL_error(L, "disable_legacy_mailers: "
-                                       "not available outside of init or body context"));
-       send_email_disabled = 1;
-       return 0;
-}
-
 /* A class is a lot of memory that contain data. This data can be a table,
  * an integer or user data. This data is associated with a metatable. This
  * metatable have an original version registered in the global context with
@@ -14123,7 +14108,6 @@ lua_State *hlua_init_state(int thread_num)
        hlua_class_function(L, "Warning", hlua_log_warning);
        hlua_class_function(L, "Alert", hlua_log_alert);
        hlua_class_function(L, "done", hlua_done);
-       hlua_class_function(L, "disable_legacy_mailers", hlua_disable_legacy_mailers);
        hlua_fcn_reg_core_fcn(L);
 
        lua_setglobal(L, "core");
index 1e61842f4f73c338283cde5b7c11a942f066b64b..7d3fe38391fd7758825c82dcef8d8efefbe59621 100644 (file)
 
 #include <haproxy/action-t.h>
 #include <haproxy/api.h>
-#include <haproxy/check.h>
 #include <haproxy/errors.h>
-#include <haproxy/list.h>
 #include <haproxy/mailers.h>
-#include <haproxy/pool.h>
 #include <haproxy/proxy.h>
 #include <haproxy/server-t.h>
 #include <haproxy/task.h>
-#include <haproxy/tcpcheck.h>
-#include <haproxy/thread.h>
 #include <haproxy/time.h>
 #include <haproxy/tools.h>
 
 
 struct mailers *mailers = NULL;
 
-/* Set to 1 to disable email sending through checks even if the
- * mailers are configured to do so. (e.g.: disable from lua)
- */
-int send_email_disabled = 0;
-
-DECLARE_STATIC_POOL(pool_head_email_alert,   "email_alert",   sizeof(struct email_alert));
-
-/****************************** Email alerts ******************************/
-/* NOTE: It may be pertinent to use an applet to handle email alerts      */
-/*        instead of a tcp-check ruleset                                  */
-/**************************************************************************/
-void email_alert_free(struct email_alert *alert)
-{
-       struct tcpcheck_rule *rule, *back;
-
-       if (!alert)
-               return;
-
-       if (alert->rules.list) {
-               list_for_each_entry_safe(rule, back, alert->rules.list, list) {
-                       LIST_DELETE(&rule->list);
-                       free_tcpcheck(rule, 1);
-               }
-               free_tcpcheck_vars(&alert->rules.preset_vars);
-               ha_free(&alert->rules.list);
-       }
-       pool_free(pool_head_email_alert, alert);
-}
-
-static struct task *process_email_alert(struct task *t, void *context, unsigned int state)
-{
-       struct check        *check = context;
-       struct email_alertq *q;
-       struct email_alert  *alert;
-
-       q = container_of(check, typeof(*q), check);
-
-       HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock);
-       while (1) {
-               if (!(check->state & CHK_ST_ENABLED)) {
-                       if (LIST_ISEMPTY(&q->email_alerts)) {
-                               /* All alerts processed, queue the task */
-                               t->expire = TICK_ETERNITY;
-                               task_queue(t);
-                               goto end;
-                       }
-
-                       alert = LIST_NEXT(&q->email_alerts, typeof(alert), list);
-                       LIST_DELETE(&alert->list);
-                       t->expire             = tick_add(now_ms, 0);
-                       check->tcpcheck_rules = &alert->rules;
-                       check->status         = HCHK_STATUS_INI;
-                       check->state         |= CHK_ST_ENABLED;
-               }
-
-               process_chk(t, context, state);
-               if (check->state & CHK_ST_INPROGRESS)
-                       break;
-
-               alert = container_of(check->tcpcheck_rules, typeof(*alert), rules);
-               email_alert_free(alert);
-               check->tcpcheck_rules = NULL;
-               check->server         = NULL;
-               check->state         &= ~CHK_ST_ENABLED;
-       }
-  end:
-       HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock);
-       return t;
-}
-
 /* Initializes mailer alerts for the proxy <p> using <mls> parameters.
  *
  * The function returns 1 in success case, otherwise, it returns 0 and err is
@@ -108,73 +33,11 @@ static struct task *process_email_alert(struct task *t, void *context, unsigned
  */
 int init_email_alert(struct mailers *mls, struct proxy *p, char **err)
 {
-       struct mailer       *mailer;
-       struct email_alertq *queues;
-       const char          *err_str;
-       int                  i = 0;
-
-       if (!send_email_disabled)
-               ha_warning("Legacy mailers used by %s '%s' will not be supported anymore in version 3.3. You should use Lua to send email-alerts, see 'examples/lua/mailers.lua' file.\n",
-                          proxy_type_str(p), p->id);
-
-       if ((queues = calloc(mls->count, sizeof(*queues))) == NULL) {
-               memprintf(err, "out of memory while allocating mailer alerts queues");
-               goto fail_no_queue;
-       }
-
-       for (mailer = mls->mailer_list; mailer; i++, mailer = mailer->next) {
-               struct email_alertq *q     = &queues[i];
-               struct check        *check = &q->check;
-               struct task         *t;
-
-               LIST_INIT(&q->email_alerts);
-               HA_SPIN_INIT(&q->lock);
-               check->obj_type = OBJ_TYPE_CHECK;
-               check->inter = mls->timeout.mail;
-               check->rise = DEF_AGENT_RISETIME;
-               check->proxy = p;
-               check->fall = DEF_AGENT_FALLTIME;
-               if ((err_str = init_check(check, PR_O2_TCPCHK_CHK))) {
-                       memprintf(err, "%s", err_str);
-                       goto error;
-               }
-
-               check->xprt = mailer->xprt;
-               check->addr = mailer->addr;
-               check->port = get_host_port(&mailer->addr);
-
-               if ((t = task_new_anywhere()) == NULL) {
-                       memprintf(err, "out of memory while allocating mailer alerts task");
-                       goto error;
-               }
-
-               check->task = t;
-               t->process = process_email_alert;
-               t->context = check;
-
-               /* check this in one ms */
-               t->expire    = TICK_ETERNITY;
-               check->start = now_ns;
-               task_queue(t);
-       }
-
        mls->users++;
        free(p->email_alert.mailers.name);
        p->email_alert.mailers.m = mls;
        p->email_alert.flags |= PR_EMAIL_ALERT_RESOLVED;
-       p->email_alert.queues    = queues;
        return 0;
-
-  error:
-       for (i = 0; i < mls->count; i++) {
-               struct email_alertq *q     = &queues[i];
-               struct check        *check = &q->check;
-
-               free_check(check);
-       }
-       free(queues);
-  fail_no_queue:
-       return 1;
 }
 
 void free_email_alert(struct proxy *p)
@@ -185,159 +48,3 @@ void free_email_alert(struct proxy *p)
        ha_free(&p->email_alert.to);
        ha_free(&p->email_alert.myhostname);
 }
-
-static int enqueue_one_email_alert(struct proxy *p, struct server *s,
-                                  struct email_alertq *q, const char *msg)
-{
-       struct email_alert   *alert;
-       struct tcpcheck_rule *tcpcheck;
-       struct check *check = &q->check;
-
-       if ((alert = pool_alloc(pool_head_email_alert)) == NULL)
-               goto error;
-       LIST_INIT(&alert->list);
-       alert->rules.flags = TCPCHK_RULES_TCP_CHK;
-       alert->rules.list = calloc(1, sizeof(*alert->rules.list));
-       if (!alert->rules.list)
-               goto error;
-       LIST_INIT(alert->rules.list);
-       LIST_INIT(&alert->rules.preset_vars); /* unused for email alerts */
-       alert->srv = s;
-
-       if ((tcpcheck = pool_zalloc(pool_head_tcpcheck_rule)) == NULL)
-               goto error;
-       tcpcheck->action       = TCPCHK_ACT_CONNECT;
-       tcpcheck->comment      = NULL;
-
-       LIST_APPEND(alert->rules.list, &tcpcheck->list);
-
-       if (!add_tcpcheck_expect_str(&alert->rules, "220 "))
-               goto error;
-
-       {
-               const char * const strs[4] = { "HELO ", p->email_alert.myhostname, "\r\n" };
-               if (!add_tcpcheck_send_strs(&alert->rules, strs))
-                       goto error;
-       }
-
-       if (!add_tcpcheck_expect_str(&alert->rules, "250 "))
-               goto error;
-
-       {
-               const char * const strs[4] = { "MAIL FROM:<", p->email_alert.from, ">\r\n" };
-               if (!add_tcpcheck_send_strs(&alert->rules, strs))
-                       goto error;
-       }
-
-       if (!add_tcpcheck_expect_str(&alert->rules, "250 "))
-               goto error;
-
-       {
-               const char * const strs[4] = { "RCPT TO:<", p->email_alert.to, ">\r\n" };
-               if (!add_tcpcheck_send_strs(&alert->rules, strs))
-                       goto error;
-       }
-
-       if (!add_tcpcheck_expect_str(&alert->rules, "250 "))
-               goto error;
-
-       {
-               const char * const strs[2] = { "DATA\r\n" };
-               if (!add_tcpcheck_send_strs(&alert->rules, strs))
-                       goto error;
-       }
-
-       if (!add_tcpcheck_expect_str(&alert->rules, "354 "))
-               goto error;
-
-       {
-               struct tm tm;
-               char datestr[48];
-               const char * const strs[18] = {
-                       "From: ", p->email_alert.from, "\r\n",
-                       "To: ", p->email_alert.to, "\r\n",
-                       "Date: ", datestr, "\r\n",
-                       "Subject: [HAProxy Alert] ", msg, "\r\n",
-                       "\r\n",
-                       msg, "\r\n",
-                       "\r\n",
-                       ".\r\n",
-                       NULL
-               };
-
-               get_localtime(date.tv_sec, &tm);
-
-               if (strftime(datestr, sizeof(datestr), "%a, %d %b %Y %T %z (%Z)", &tm) == 0) {
-                       goto error;
-               }
-
-               if (!add_tcpcheck_send_strs(&alert->rules, strs))
-                       goto error;
-       }
-
-       if (!add_tcpcheck_expect_str(&alert->rules, "250 "))
-               goto error;
-
-       {
-               const char * const strs[2] = { "QUIT\r\n" };
-               if (!add_tcpcheck_send_strs(&alert->rules, strs))
-                       goto error;
-       }
-
-       if (!add_tcpcheck_expect_str(&alert->rules, "221 "))
-               goto error;
-
-       HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock);
-       task_wakeup(check->task, TASK_WOKEN_MSG);
-       LIST_APPEND(&q->email_alerts, &alert->list);
-       HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock);
-       return 1;
-
-error:
-       email_alert_free(alert);
-       return 0;
-}
-
-static void enqueue_email_alert(struct proxy *p, struct server *s, const char *msg)
-{
-       int i;
-       struct mailer *mailer;
-
-       for (i = 0, mailer = p->email_alert.mailers.m->mailer_list;
-            i < p->email_alert.mailers.m->count; i++, mailer = mailer->next) {
-               if (!enqueue_one_email_alert(p, s, &p->email_alert.queues[i], msg)) {
-                       ha_alert("Email alert [%s] could not be enqueued: out of memory\n", p->id);
-                       return;
-               }
-       }
-
-       return;
-}
-
-/*
- * Send email alert if configured.
- */
-void send_email_alert(struct server *s, int level, const char *format, ...)
-{
-       va_list argp;
-       char buf[1024];
-       int len;
-       struct proxy *p = s->proxy;
-
-       if (send_email_disabled)
-               return;
-
-       if (!p->email_alert.mailers.m || level > p->email_alert.level || format == NULL)
-               return;
-
-       va_start(argp, format);
-       len = vsnprintf(buf, sizeof(buf), format, argp);
-       va_end(argp);
-
-       if (len < 0 || len >= sizeof(buf)) {
-               ha_alert("Email alert [%s] could not format message\n", p->id);
-               return;
-       }
-
-       enqueue_email_alert(p, s, buf);
-}
index 45b079e9df053ad5a757d69b8146f0dd1e611cbb..294ba7e9926ecab21e21b492e69471db68819bdc 100644 (file)
@@ -6592,8 +6592,6 @@ static int _srv_update_status_op(struct server *s, enum srv_op_st_chg_cause caus
                        log_level = srv_was_stopping ? LOG_NOTICE : LOG_ALERT;
                        send_log(s->proxy, log_level, "%s.\n",
                                 tmptrash->area);
-                       send_email_alert(s, log_level, "%s",
-                                        tmptrash->area);
                        free_trash_chunk(tmptrash);
                }
        }
@@ -6657,8 +6655,6 @@ static int _srv_update_status_op(struct server *s, enum srv_op_st_chg_cause caus
                        ha_warning("%s.\n", tmptrash->area);
                        send_log(s->proxy, LOG_NOTICE, "%s.\n",
                                 tmptrash->area);
-                       send_email_alert(s, LOG_NOTICE, "%s",
-                                        tmptrash->area);
                        free_trash_chunk(tmptrash);
                }
        }
@@ -6918,8 +6914,6 @@ static int _srv_update_status_adm(struct server *s, enum srv_adm_st_chg_cause ca
                                        ha_warning("%s.\n", tmptrash->area);
                                        send_log(s->proxy, LOG_NOTICE, "%s.\n",
                                                 tmptrash->area);
-                                       send_email_alert(s, LOG_NOTICE, "%s",
-                                                        tmptrash->area);
                                }
                                free_trash_chunk(tmptrash);
                        }
index 0bdb0f94d728c946e838435975a1c71c62a66906..8c0c5c2940f1b15070051e405df46852ed4a38ff 100644 (file)
@@ -421,7 +421,6 @@ const char *lock_label(enum lock_label label)
        case SPOE_APPLET_LOCK:     return "SPOE_APPLET";
        case DNS_LOCK:             return "DNS";
        case PID_LIST_LOCK:        return "PID_LIST";
-       case EMAIL_ALERTS_LOCK:    return "EMAIL_ALERTS";
        case PIPES_LOCK:           return "PIPES";
        case TLSKEYS_REF_LOCK:     return "TLSKEYS_REF";
        case AUTH_LOCK:            return "AUTH";