BUG/MEDIUM: checks: Avoid having an associated server for email checks.

When using a check to send email, avoid having an associated server, so that
we don't modify the server state if we fail to send an email.
Also revert back to initialize the check status to HCHK_STATUS_INI, now that
set_server_check_status() stops early if there's no server, we shouldn't
get in a mail loop anymore.

This should be backported to 1.9.
diff --git a/src/checks.c b/src/checks.c
index edb61b4..1a81ccd 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -236,6 +236,11 @@
 	if (check->result == CHK_RES_NEUTRAL)
 		return;
 
+	/* If the check was really just sending a mail, it won't have an
+	 * associated server, so we're done now.
+	 */
+	if (!s)
+	    return;
 	report = 0;
 
 	switch (check->result) {
@@ -681,7 +686,8 @@
 		 * might be due to a server IP change.
 		 * Let's trigger a DNS resolution if none are currently running.
 		 */
-		dns_trigger_resolution(check->server->dns_requester);
+		if (check->server)
+			dns_trigger_resolution(check->server->dns_requester);
 
 	}
 	else if ((conn->flags & (CO_FL_CONNECTED|CO_FL_WAIT_L6_CONN)) == CO_FL_WAIT_L6_CONN) {
@@ -711,13 +717,20 @@
 {
 	struct check *check = ctx;
 	struct conn_stream *cs = check->cs;
+	struct email_alertq *q = container_of(check, typeof(*q), check);
 
 	if (!(check->wait_list.events & SUB_RETRY_SEND))
 		wake_srv_chk(cs);
 	if (!(check->wait_list.events & SUB_RETRY_RECV)) {
-		HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
+		if (check->server)
+			HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
+		else
+			HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock);
 		__event_srv_chk_r(cs);
-		HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
+		if (check->server)
+			HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
+		else
+			HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock);
 	}
 	return NULL;
 }
@@ -1394,9 +1407,13 @@
 {
 	struct connection *conn = cs->conn;
 	struct check *check = cs->data;
+	struct email_alertq *q = container_of(check, typeof(*q), check);
 	int ret = 0;
 
-	HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
+	if (check->server)
+		HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
+	else
+		HA_SPIN_LOCK(EMAIL_ALERTS_LOCK, &q->lock);
 
 	/* we may have to make progress on the TCP checks */
 	if (check->type == PR_O2_TCPCHK_CHK) {
@@ -1433,7 +1450,10 @@
 		ret = -1;
 	}
 
-	HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
+	if (check->server)
+		HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
+	else
+		HA_SPIN_UNLOCK(EMAIL_ALERTS_LOCK, &q->lock);
 
 	/* if a connection got replaced, we must absolutely prevent the connection
 	 * handler from touching its fd, and perform the FD polling updates ourselves
@@ -2131,7 +2151,8 @@
 	int ret;
 	int expired = tick_is_expired(t->expire, now_ms);
 
-	HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
+	if (check->server)
+		HA_SPIN_LOCK(SERVER_LOCK, &check->server->lock);
 	if (!(check->state & CHK_ST_INPROGRESS)) {
 		/* no check currently running */
 		if (!expired) /* woke up too early */
@@ -2257,34 +2278,39 @@
 			conn = NULL;
 		}
 
-		if (check->result == CHK_RES_FAILED) {
-			/* a failure or timeout detected */
-			check_notify_failure(check);
-		}
-		else if (check->result == CHK_RES_CONDPASS) {
-			/* check is OK but asks for stopping mode */
-			check_notify_stopping(check);
-		}
-		else if (check->result == CHK_RES_PASSED) {
-			/* a success was detected */
-			check_notify_success(check);
+		if (check->server) {
+			if (check->result == CHK_RES_FAILED) {
+				/* a failure or timeout detected */
+				check_notify_failure(check);
+			}
+			else if (check->result == CHK_RES_CONDPASS) {
+				/* check is OK but asks for stopping mode */
+				check_notify_stopping(check);
+			}
+			else if (check->result == CHK_RES_PASSED) {
+				/* a success was detected */
+				check_notify_success(check);
+			}
 		}
 		task_set_affinity(t, MAX_THREADS_MASK);
 		check->state &= ~CHK_ST_INPROGRESS;
 
-		rv = 0;
-		if (global.spread_checks > 0) {
-			rv = srv_getinter(check) * global.spread_checks / 100;
-			rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0)));
+		if (check->server) {
+			rv = 0;
+			if (global.spread_checks > 0) {
+				rv = srv_getinter(check) * global.spread_checks / 100;
+				rv -= (int) (2 * rv * (rand() / (RAND_MAX + 1.0)));
+			}
+			t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(check) + rv));
 		}
-		t->expire = tick_add(now_ms, MS_TO_TICKS(srv_getinter(check) + rv));
 	}
 
  reschedule:
 	while (tick_is_expired(t->expire, now_ms))
 		t->expire = tick_add(t->expire, MS_TO_TICKS(check->inter));
  out_unlock:
-	HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
+	if (check->server)
+		HA_SPIN_UNLOCK(SERVER_LOCK, &check->server->lock);
 	return t;
 }
 
@@ -2760,7 +2786,7 @@
 			conn = cs->conn;
 			/* Maybe there were an older connection we were waiting on */
 			check->wait_list.events = 0;
-			conn->target = &s->obj_type;
+			conn->target = s ? &s->obj_type : &proxy->obj_type;
 
 			/* no client address */
 			clear_addr(&conn->addr.from);
@@ -3173,9 +3199,8 @@
 			alert = LIST_NEXT(&q->email_alerts, typeof(alert), list);
 			LIST_DEL(&alert->list);
 			t->expire             = now_ms;
-			check->server         = alert->srv;
 			check->tcpcheck_rules = &alert->tcpcheck_rules;
-			check->status         = HCHK_STATUS_UNKNOWN; // the UNKNOWN status is used to exit set_server_check_status(.) early
+			check->status         = HCHK_STATUS_INI;
 			check->state         |= CHK_ST_ENABLED;
 		}
 
@@ -3230,7 +3255,6 @@
 		check->xprt = mailer->xprt;
 		check->addr = mailer->addr;
 		check->port = get_host_port(&mailer->addr);
-		//check->server = s;
 
 		if ((t = task_new(MAX_THREADS_MASK)) == NULL) {
 			memprintf(err, "out of memory while allocating mailer alerts task");