diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index b5900cd83692075183e3ce1ba34dbc4ea9983012..43ab0ae97898b9a75ab8eafa7f131630b08f7ce2 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -1746,20 +1746,20 @@ static BOOL ftp_hacklog(char* prot, char* user, char* text, char* host, union xp
 /* Consecutive failed login (possible password hack) attempt tracking		*/
 /****************************************************************************/
 
-static BOOL badlogin(SOCKET sock, CRYPT_SESSION sess, ulong* login_attempts, char* user, char* passwd, char* host, union xp_sockaddr* addr)
+static BOOL badlogin(SOCKET sock, CRYPT_SESSION sess, ulong* login_attempts
+	,char* user, char* passwd, client_t* client, union xp_sockaddr* addr)
 {
 	ulong count;
-	char	host_ip[INET6_ADDRSTRLEN];
 
 	if(addr!=NULL) {
-		count=loginFailure(startup->login_attempt_list, addr, "FTP", user, passwd);
+		count=loginFailure(startup->login_attempt_list, addr, client->protocol, user, passwd);
+		mqtt_user_login_fail(&mqtt, client, user);
 		if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold)
-			ftp_hacklog("FTP LOGIN", user, passwd, host, addr);
+			ftp_hacklog("FTP LOGIN", user, passwd, client->host, addr);
 		if(startup->login_attempt.filter_threshold && count>=startup->login_attempt.filter_threshold) {
 			char reason[128];
 			SAFEPRINTF(reason, "- TOO MANY CONSECUTIVE FAILED LOGIN ATTEMPTS (%lu)", count);
-			inet_addrtop(addr, host_ip, sizeof(host_ip));
-			filter_ip(&scfg, "FTP", reason, host, host_ip, user, /* fname: */NULL);
+			filter_ip(&scfg, client->protocol, reason, client->host, client->addr, user, /* fname: */NULL);
 		}
 		if(count > *login_attempts)
 			*login_attempts=count;
@@ -2140,7 +2140,7 @@ static void ctrl_thread(void* arg)
 	long		timeleft;
 	ulong		l;
 	ulong		login_attempts=0;
-	ulong		avail;	/* disk space */
+	uint64_t	avail;	/* disk space */
 	ulong		count;
 	BOOL		detail;
 	BOOL		success;
@@ -2461,7 +2461,7 @@ static void ctrl_thread(void* arg)
 					lprintf(LOG_WARNING,"%04d !UNKNOWN USER: '%s' (password: %s)",sock,user.alias,p);
 				else
 					lprintf(LOG_WARNING,"%04d !UNKNOWN USER: '%s'",sock,user.alias);
-				if(badlogin(sock, sess, &login_attempts, user.alias, p, host_name, &ftp.client_addr))
+				if(badlogin(sock, sess, &login_attempts, user.alias, p, &client, &ftp.client_addr))
 					break;
 				continue;
 			}
@@ -2531,7 +2531,7 @@ static void ctrl_thread(void* arg)
 					lprintf(LOG_WARNING,"%04d <%s> !FAILED Password attempt"
 						,sock, user.alias);
 				user.number=0;
-				if(badlogin(sock, sess, &login_attempts, user.alias, password, host_name, &ftp.client_addr))
+				if(badlogin(sock, sess, &login_attempts, user.alias, password, &client, &ftp.client_addr))
 					break;
 				continue;
 			}
@@ -3050,9 +3050,9 @@ static void ctrl_thread(void* arg)
 			else
 				avail=getfreediskspace(scfg.data_dir,0);	/* Change to temp_dir? */
 			if(l && l>avail)
-				sockprintf(sock,sess,"504 Only %lu bytes available.",avail);
+				sockprintf(sock,sess,"504 Only %" PRIu64 " bytes available.",avail);
 			else
-				sockprintf(sock,sess,"200 %lu bytes available.",avail);
+				sockprintf(sock,sess,"200 %" PRIu64 " bytes available.",avail);
 			continue;
 		}
 
diff --git a/src/sbbs3/login.cpp b/src/sbbs3/login.cpp
index 4625a068475d07e7675a7d51e81a74237a598b03..c90d8d18ec8d07c5e8d6d65bb768d5cc3fb2334e 100644
--- a/src/sbbs3/login.cpp
+++ b/src/sbbs3/login.cpp
@@ -143,6 +143,7 @@ void sbbs_t::badlogin(const char* user, const char* passwd, const char* protocol
 	socklen_t addr_len = sizeof(*addr);
 	SAFEPRINTF(reason,"%s LOGIN", protocol);
 	count=loginFailure(startup->login_attempt_list, addr, protocol, user, passwd);
+	mqtt_user_login_fail(mqtt, &client, user);
 	if(user!=NULL && startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold) {
 		getnameinfo(&addr->addr, addr_len, host_name, sizeof(host_name), NULL, 0, NI_NAMEREQD);
 		::hacklog(&cfg, mqtt, reason, user, passwd, host_name, addr);
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index 7199c24e5d33db04232615876f4be21fc8e2dbf0..0efc81b7e01fc0154906e77bc8b3f9a08f482248 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -967,34 +967,34 @@ static u_long resolve_ip(const char *inaddr)
 /* A successful login from the same host resets the counter.				*/
 /****************************************************************************/
 
-static void badlogin(SOCKET sock, CRYPT_SESSION sess, const char* prot, const char* resp, char* user, char* passwd, char* host, union xp_sockaddr* addr)
+static void badlogin(SOCKET sock, CRYPT_SESSION sess, const char* resp
+	,char* user, char* passwd, client_t* client, union xp_sockaddr* addr)
 {
 	char	reason[128];
-	char	ip[INET6_ADDRSTRLEN];
 	ulong	count;
 	
 	if(user == NULL)
 		user = "<unspecified>";
 
 	if(addr!=NULL) {
-		SAFEPRINTF(reason,"%s LOGIN", prot);
-		count=loginFailure(startup->login_attempt_list, addr, prot, user, passwd);
+		SAFEPRINTF(reason,"%s LOGIN", client->protocol);
+		count=loginFailure(startup->login_attempt_list, addr, client->protocol, user, passwd);
+		mqtt_user_login_fail(&mqtt, client, user);
 		if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold) {
-			hacklog(&scfg, &mqtt, reason, user, passwd, host, addr);
+			hacklog(&scfg, &mqtt, reason, user, passwd, client->host, addr);
 #ifdef _WIN32
 			if(startup->sound.hack[0] && !sound_muted(&scfg)) 
 				PlaySound(startup->sound.hack, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 		}
-		inet_addrtop(addr, ip, sizeof(ip));
 		if(startup->login_attempt.filter_threshold && count>=startup->login_attempt.filter_threshold) {
 			SAFEPRINTF(reason, "- TOO MANY CONSECUTIVE FAILED LOGIN ATTEMPTS (%lu)", count);
-			filter_ip(&scfg, (char*)prot, reason ,host, ip, user, /* fname: */NULL);
+			filter_ip(&scfg, client->protocol, reason, client->host, client->addr, user, /* fname: */NULL);
 		}
 	}
 
 	mswait(startup->login_attempt.delay);
-	sockprintf(sock,prot,sess, "%s", resp);
+	sockprintf(sock, client->protocol, sess, "%s", resp);
 }
 
 static void pop3_thread(void* arg)
@@ -1305,7 +1305,7 @@ static void pop3_thread(void* arg)
 			else
 				lprintf(LOG_NOTICE,"%04d %s [%s] !UNKNOWN USER: '%s'"
 					,socket, client.protocol, host_ip, username);
-			badlogin(socket, session, client.protocol, pop_auth_error, username, password, host_name, &pop3.client_addr);
+			badlogin(socket, session, pop_auth_error, username, password, &client, &pop3.client_addr);
 			break;
 		}
 		if((i=getuserdat(&scfg, &user))!=0) {
@@ -1316,7 +1316,7 @@ static void pop3_thread(void* arg)
 		if(user.misc&(DELETED|INACTIVE)) {
 			lprintf(LOG_NOTICE,"%04d %s [%s] !DELETED or INACTIVE user #%u (%s)"
 				,socket, client.protocol, host_ip, user.number, username);
-			badlogin(socket, session, client.protocol, pop_auth_error, username, password, NULL, NULL);
+			badlogin(socket, session, pop_auth_error, username, password, &client, NULL);
 			break;
 		}
 		if(apop) {
@@ -1332,7 +1332,7 @@ static void pop3_thread(void* arg)
 				lprintf(LOG_DEBUG,"%04d !POP3 calc digest: %s",socket,str);
 				lprintf(LOG_DEBUG,"%04d !POP3 resp digest: %s",socket,response);
 #endif
-				badlogin(socket, session, client.protocol, pop_auth_error, username, response, host_name, &pop3.client_addr);
+				badlogin(socket, session, pop_auth_error, username, response, &client, &pop3.client_addr);
 				break;
 			}
 		} else if(stricmp(password,user.pass)) {
@@ -1342,7 +1342,7 @@ static void pop3_thread(void* arg)
 			else
 				lprintf(LOG_NOTICE,"%04d %s [%s] !FAILED Password attempt for user %s"
 					,socket, client.protocol, host_ip, username);
-			badlogin(socket, session, client.protocol, pop_auth_error, username, password, host_name, &pop3.client_addr);
+			badlogin(socket, session, pop_auth_error, username, password, &client, &pop3.client_addr);
 			break;
 		}
 
@@ -3991,8 +3991,12 @@ static void smtp_thread(void* arg)
 					}
 					lprintf(LOG_INFO,"%04d %s %s Added message header #%u from %s to %s"
 						,socket, client.protocol, client_id, newmsg.hdr.number, sender_info, rcpt_info);
-					if(relay_user.number!=0)
+					if(relay_user.number!=0) {
 						user_sent_email(&scfg, &relay_user, 1, usernum==1);
+						lprintf(LOG_DEBUG, "%04d %s %s #%u sent %u email messages today (of %u max), %u total"
+							,socket, client.protocol, client_id, relay_user.number
+							,relay_user.etoday, scfg.level_emailperday[relay_user.level], relay_user.emails);
+					}
 
 					if(nettype == NET_FIDO && scfg.netmail_sem[0])
 						ftouch(mailcmdstr(scfg.netmail_sem
@@ -4139,27 +4143,27 @@ static void smtp_thread(void* arg)
 				sockprintf(socket,client.protocol,session,"334 VXNlcm5hbWU6");	/* Base64-encoded "Username:" */
 				if((rd=sockreadline(socket, client.protocol, session, buf, sizeof(buf)))<1) {
 					lprintf(LOG_WARNING,"%04d %s %s !Missing AUTH LOGIN username argument", socket, client.protocol, client_id);
-					badlogin(socket, session, client.protocol, badarg_rsp, NULL, NULL, host_name, &smtp.client_addr);
+					badlogin(socket, session, badarg_rsp, NULL, NULL, &client, &smtp.client_addr);
 					continue;
 				}
 				if(startup->options&MAIL_OPT_DEBUG_RX_RSP) 
 					lprintf(LOG_DEBUG,"%04d %s %s RX: %s", socket, client.protocol, client_id, buf);
 				if(b64_decode(user_name,sizeof(user_name),buf,rd)<1 || str_has_ctrl(user_name)) {
 					lprintf(LOG_WARNING,"%04d %s %s !Bad AUTH LOGIN username argument", socket, client.protocol, client_id);
-					badlogin(socket, session, client.protocol, badarg_rsp, NULL, NULL, host_name, &smtp.client_addr);
+					badlogin(socket, session, badarg_rsp, NULL, NULL, &client, &smtp.client_addr);
 					continue;
 				}
 				sockprintf(socket,client.protocol,session,"334 UGFzc3dvcmQ6");	/* Base64-encoded "Password:" */
 				if((rd=sockreadline(socket, client.protocol, session, buf, sizeof(buf)))<1) {
 					lprintf(LOG_WARNING,"%04d %s %s !Missing AUTH LOGIN password argument", socket, client.protocol, client_id);
-					badlogin(socket, session, client.protocol, badarg_rsp, user_name, NULL, host_name, &smtp.client_addr);
+					badlogin(socket, session, badarg_rsp, user_name, NULL, &client, &smtp.client_addr);
 					continue;
 				}
 				if(startup->options&MAIL_OPT_DEBUG_RX_RSP) 
 					lprintf(LOG_DEBUG,"%04d %s %s RX: %s", socket, client.protocol, client_id, buf);
 				if(b64_decode(user_pass,sizeof(user_pass),buf,rd)<1 || str_has_ctrl(user_pass)) {
 					lprintf(LOG_WARNING,"%04d %s %s !Bad AUTH LOGIN password argument", socket, client.protocol, client_id);
-					badlogin(socket, session, client.protocol, badarg_rsp, user_name, NULL, host_name, &smtp.client_addr);
+					badlogin(socket, session, badarg_rsp, user_name, NULL, &client, &smtp.client_addr);
 					continue;
 				}
 			} else {	/* AUTH PLAIN b64(<username>\0<user-id>\0<password>) */
@@ -4167,13 +4171,13 @@ static void smtp_thread(void* arg)
 				SKIP_WHITESPACE(p);
 				if(*p==0) {
 					lprintf(LOG_WARNING,"%04d %s %s !Missing AUTH PLAIN argument", socket, client.protocol, client_id);
-					badlogin(socket, session, client.protocol, badarg_rsp, NULL, NULL, host_name, &smtp.client_addr);
+					badlogin(socket, session, badarg_rsp, NULL, NULL, &client, &smtp.client_addr);
 					continue;
 				}
 				ZERO_VAR(tmp);
 				if(b64_decode(tmp,sizeof(tmp),p,strlen(p))<1 || str_has_ctrl(tmp)) {
 					lprintf(LOG_WARNING,"%04d %s %s !Bad AUTH PLAIN argument", socket, client.protocol, client_id);
-					badlogin(socket, session, client.protocol, badarg_rsp, NULL, NULL, host_name, &smtp.client_addr);
+					badlogin(socket, session, badarg_rsp, NULL, NULL, &client, &smtp.client_addr);
 					continue;
 				}
 				p=tmp;
@@ -4181,7 +4185,7 @@ static void smtp_thread(void* arg)
 				p++;			/* skip NULL */
 				if(*p==0) {
 					lprintf(LOG_WARNING,"%04d %s %s !Missing AUTH PLAIN user-id argument", socket, client.protocol, client_id);
-					badlogin(socket, session, client.protocol, badarg_rsp, NULL, NULL, host_name, &smtp.client_addr);
+					badlogin(socket, session, badarg_rsp, NULL, NULL, &client, &smtp.client_addr);
 					continue;
 				}
 				SAFECOPY(user_name,p);
@@ -4189,7 +4193,7 @@ static void smtp_thread(void* arg)
 				p++;			/* skip NULL */
 				if(*p==0) {
 					lprintf(LOG_WARNING,"%04d %s %s !Missing AUTH PLAIN password argument", socket, client.protocol, client_id);
-					badlogin(socket, session, client.protocol, badarg_rsp, user_name, NULL, host_name, &smtp.client_addr);
+					badlogin(socket, session, badarg_rsp, user_name, NULL, &client, &smtp.client_addr);
 					continue;
 				}
 				SAFECOPY(user_pass,p);
@@ -4202,19 +4206,19 @@ static void smtp_thread(void* arg)
 				else
 					lprintf(LOG_WARNING,"%04d %s %s !UNKNOWN USER: '%s'"
 						,socket, client.protocol, client_id, user_name);
-				badlogin(socket, session, client.protocol, badauth_rsp, user_name, user_pass, host_name, &smtp.client_addr);
+				badlogin(socket, session, badauth_rsp, user_name, user_pass, &client, &smtp.client_addr);
 				break;
 			}
 			if((i=getuserdat(&scfg, &relay_user))!=0) {
 				lprintf(LOG_ERR,"%04d %s %s !ERROR %d getting data on user (%s)"
 					,socket, client.protocol, client_id, i, user_name);
-				badlogin(socket, session, client.protocol, badauth_rsp, NULL, NULL, NULL, NULL);
+				badlogin(socket, session, badauth_rsp, NULL, NULL, &client, NULL);
 				break;
 			}
 			if(relay_user.misc&(DELETED|INACTIVE)) {
 				lprintf(LOG_WARNING,"%04d %s %s !DELETED or INACTIVE user #%u (%s)"
 					,socket, client.protocol, client_id, relay_user.number, user_name);
-				badlogin(socket, session, client.protocol, badauth_rsp, NULL, NULL, NULL, NULL);
+				badlogin(socket, session, badauth_rsp, NULL, NULL, &client, NULL);
 				break;
 			}
 			if(stricmp(user_pass,relay_user.pass)) {
@@ -4224,7 +4228,7 @@ static void smtp_thread(void* arg)
 				else
 					lprintf(LOG_WARNING,"%04d %s %s !FAILED Password attempt for user %s"
 						,socket, client.protocol, client_id, user_name);
-				badlogin(socket, session, client.protocol, badauth_rsp, user_name, user_pass, host_name, &smtp.client_addr);
+				badlogin(socket, session, badauth_rsp, user_name, user_pass, &client, &smtp.client_addr);
 				break;
 			}
 
@@ -4285,19 +4289,19 @@ static void smtp_thread(void* arg)
 			if((relay_user.number = find_login_id(&scfg, user_name))==0) {
 				lprintf(LOG_WARNING,"%04d %s %s !UNKNOWN USER: '%s'"
 					,socket, client.protocol, client_id, user_name);
-				badlogin(socket, session, client.protocol, badauth_rsp, user_name, NULL, host_name, &smtp.client_addr);
+				badlogin(socket, session, badauth_rsp, user_name, NULL, &client, &smtp.client_addr);
 				break;
 			}
 			if((i=getuserdat(&scfg, &relay_user))!=0) {
 				lprintf(LOG_ERR,"%04d %s %s !ERROR %d getting data on user (%s)"
 					,socket, client.protocol, client_id, i, user_name);
-				badlogin(socket, session, client.protocol, badauth_rsp, NULL, NULL, NULL, NULL);
+				badlogin(socket, session, badauth_rsp, NULL, NULL, &client, NULL);
 				break;
 			}
 			if(relay_user.misc&(DELETED|INACTIVE)) {
 				lprintf(LOG_WARNING,"%04d %s %s !DELETED or INACTIVE user #%u (%s)"
 					,socket, client.protocol, client_id, relay_user.number, user_name);
-				badlogin(socket, session, client.protocol, badauth_rsp, NULL, NULL, NULL, NULL);
+				badlogin(socket, session, badauth_rsp, NULL, NULL, &client, NULL);
 				break;
 			}
 			/* Calculate correct response */
@@ -4322,7 +4326,7 @@ static void smtp_thread(void* arg)
 				lprintf(LOG_DEBUG,"%04d !SMTP resp digest: %s"
 					,socket,p);
 #endif
-				badlogin(socket, session, client.protocol, badauth_rsp, user_name, p, host_name, &smtp.client_addr);
+				badlogin(socket, session, badauth_rsp, user_name, p, &client, &smtp.client_addr);
 				break;
 			}
 
diff --git a/src/sbbs3/mqtt.c b/src/sbbs3/mqtt.c
index cff196994c819c1936d5b20e124cfa55a18044fb..9270fcb5698d1fd4f1a7a032fb75f05672c423e1 100644
--- a/src/sbbs3/mqtt.c
+++ b/src/sbbs3/mqtt.c
@@ -687,6 +687,29 @@ int mqtt_client_on(struct mqtt* mqtt, BOOL on, int sock, client_t* client, BOOL
 	return result;
 }
 
+int mqtt_user_login_fail(struct mqtt* mqtt, client_t* client, const char* username)
+{
+	char str[128];
+	char topic[128];
+
+	if(mqtt == NULL || mqtt->cfg == NULL || client == NULL)
+		return MQTT_FAILURE;
+
+	if(!mqtt->cfg->mqtt.enabled)
+		return MQTT_SUCCESS;
+
+	if(client->protocol == NULL || username == NULL)
+		return MQTT_FAILURE;
+	snprintf(topic, sizeof(topic), "login_fail/%s", client->protocol);
+	strlwr(topic);
+	snprintf(str, sizeof(str), "%s\t%s\t%s"
+		,username
+		,client->addr
+		,client->host
+		);
+	return mqtt_pub_timestamped_msg(mqtt, TOPIC_BBS_ACTION, topic, time(NULL), str);
+}
+
 int mqtt_user_login(struct mqtt* mqtt, client_t* client)
 {
 	char str[128];
diff --git a/src/sbbs3/mqtt.h b/src/sbbs3/mqtt.h
index 8b1598767d62a650898067dc39b9676ad0895b8a..e225672c068d2891a6478fd81f31bb969cbb20c8 100644
--- a/src/sbbs3/mqtt.h
+++ b/src/sbbs3/mqtt.h
@@ -97,6 +97,7 @@ DLLEXPORT int mqtt_thread_stop(struct mqtt*);
 DLLEXPORT int mqtt_client_on(struct mqtt*, BOOL on, int sock, client_t* client, BOOL update);
 DLLEXPORT int mqtt_client_max(struct mqtt*, ulong count);
 DLLEXPORT int mqtt_client_count(struct mqtt*);
+DLLEXPORT int mqtt_user_login_fail(struct mqtt*, client_t*, const char* username);
 DLLEXPORT int mqtt_user_login(struct mqtt*, client_t*);
 DLLEXPORT int mqtt_user_logout(struct mqtt*, client_t*, time_t);
 DLLEXPORT int mqtt_file_upload(struct mqtt*, user_t*, file_t*, off_t size, client_t*);
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index ce0b2aca25ed1d6071f6af12ddc2f797b6818e26..4c7efa8216b7814701d702ab5ef57f46e8237067 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -333,25 +333,24 @@ js_log(JSContext *cx, uintN argc, jsval *arglist)
     return(JS_TRUE);
 }
 
-static void badlogin(SOCKET sock, char* prot, char* user, char* passwd, char* host, union xp_sockaddr* addr)
+static void badlogin(SOCKET sock, char* user, char* passwd, client_t* client, union xp_sockaddr* addr)
 {
 	char reason[128];
-	char addr_ip[INET6_ADDRSTRLEN];
 	ulong count;
 
-	SAFEPRINTF(reason,"%s LOGIN", prot);
-	count=loginFailure(startup->login_attempt_list, addr, prot, user, passwd);
+	SAFEPRINTF(reason,"%s LOGIN", client->protocol);
+	count=loginFailure(startup->login_attempt_list, addr, client->protocol, user, passwd);
+	mqtt_user_login_fail(&mqtt, client, user);
 	if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold) {
-		hacklog(&scfg, &mqtt, reason, user, passwd, host, addr);
+		hacklog(&scfg, &mqtt, reason, user, passwd, client->host, addr);
 #ifdef _WIN32
 		if(startup->sound.hack[0] && !sound_muted(&scfg))
 			PlaySound(startup->sound.hack, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 	}
 	if(startup->login_attempt.filter_threshold && count>=startup->login_attempt.filter_threshold) {
-		inet_addrtop(addr, addr_ip, sizeof(addr_ip));
 		SAFEPRINTF(reason, "- TOO MANY CONSECUTIVE FAILED LOGIN ATTEMPTS (%lu)", count);
-		filter_ip(&scfg, prot, reason, host, addr_ip, user, /* fname: */NULL);
+		filter_ip(&scfg, client->protocol, reason, client->host, client->addr, user, /* fname: */NULL);
 	}
 
 	mswait(startup->login_attempt.delay);
@@ -400,7 +399,7 @@ js_login(JSContext *cx, uintN argc, jsval *arglist)
 	if(getuserdat(&scfg,&client->user)!=0) {
 		lprintf(LOG_NOTICE,"%04d %s !USER NOT FOUND: '%s'"
 			,client->socket,client->service->protocol,user);
-		badlogin(client->socket, client->service->protocol, user, pass, client->client->host, &client->addr);
+		badlogin(client->socket, user, pass, client->client, &client->addr);
 		JS_RESUMEREQUEST(cx, rc);
 		return(JS_TRUE);
 	}
@@ -416,7 +415,7 @@ js_login(JSContext *cx, uintN argc, jsval *arglist)
 	if(client->user.pass[0] && (pass == NULL || stricmp(client->user.pass,pass))) { /* Wrong password */
 		lprintf(LOG_WARNING,"%04d %s !INVALID PASSWORD ATTEMPT FOR USER: %s"
 			,client->socket,client->service->protocol,client->user.alias);
-		badlogin(client->socket, client->service->protocol, user, pass, client->client->host, &client->addr);
+		badlogin(client->socket, user, pass, client->client, &client->addr);
 		JS_RESUMEREQUEST(cx, rc);
 		return(JS_TRUE);
 	}
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 48a15321c1306cc4c3d8b6c24a7fc059cdb5525f..b8234c148a44691484c679705ef6bc3209f551c0 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -1868,16 +1868,16 @@ static BOOL digest_authentication(http_session_t* session, int auth_allowed, use
 	return(TRUE);
 }
 
-static void badlogin(SOCKET sock, const char* prot, const char* user, const char* passwd, const char* host, union xp_sockaddr* addr)
+static void badlogin(SOCKET sock, const char* user, const char* passwd, client_t* client, union xp_sockaddr* addr)
 {
 	char reason[128];
-	char addrstr[INET6_ADDRSTRLEN];
 	ulong count;
 
-	SAFEPRINTF(reason,"%s LOGIN", prot);
-	count=loginFailure(startup->login_attempt_list, addr, prot, user, passwd);
+	SAFEPRINTF(reason,"%s LOGIN", client->protocol);
+	count=loginFailure(startup->login_attempt_list, addr, client->protocol, user, passwd);
+	mqtt_user_login_fail(&mqtt, client, user);
 	if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold) {
-		hacklog(&scfg, &mqtt, reason, user, passwd, host, addr);
+		hacklog(&scfg, &mqtt, reason, user, passwd, client->host, addr);
 #ifdef _WIN32
 		if(startup->sound.hack[0] && !sound_muted(&scfg))
 			PlaySound(startup->sound.hack, NULL, SND_ASYNC|SND_FILENAME);
@@ -1885,8 +1885,8 @@ static void badlogin(SOCKET sock, const char* prot, const char* user, const char
 	}
 	if(startup->login_attempt.filter_threshold && count>=startup->login_attempt.filter_threshold) {
 		SAFEPRINTF(reason, "- TOO MANY CONSECUTIVE FAILED LOGIN ATTEMPTS (%lu)", count);
-		filter_ip(&scfg, prot, reason
-			,host, inet_addrtop(addr, addrstr, sizeof(addrstr)), user, /* fname: */NULL);
+		filter_ip(&scfg, client->protocol, reason
+			,client->host, client->addr, user, /* fname: */NULL);
 	}
 	if(count>1)
 		mswait(startup->login_attempt.delay);
@@ -1995,7 +1995,7 @@ static BOOL check_ars(http_session_t * session)
 				else
 					lprintf(LOG_WARNING,"%04d !BASIC AUTHENTICATION FAILURE for user '%s'"
 						,session->socket,session->req.auth.username);
-				badlogin(session->socket,session->client.protocol, session->req.auth.username, session->req.auth.password, session->host_name, &session->addr);
+				badlogin(session->socket, session->req.auth.username, session->req.auth.password, &session->client, &session->addr);
 				return(FALSE);
 			}
 			break;
@@ -2005,7 +2005,7 @@ static BOOL check_ars(http_session_t * session)
 			if(!digest_authentication(session, auth_allowed, thisuser, &reason)) {
 				lprintf(LOG_NOTICE,"%04d !DIGEST AUTHENTICATION FAILURE (reason: %s) for user '%s'"
 						,session->socket,reason,session->req.auth.username);
-				badlogin(session->socket,session->client.protocol, session->req.auth.username, "<digest>", session->host_name, &session->addr);
+				badlogin(session->socket, session->req.auth.username, "<digest>", &session->client, &session->addr);
 				return(FALSE);
 			}
 			break;
@@ -5579,7 +5579,7 @@ js_login(JSContext *cx, uintN argc, jsval *arglist)
 			rc=JS_SUSPENDREQUEST(cx);
 			lprintf(LOG_WARNING,"%04d !INVALID PASSWORD ATTEMPT FOR USER: '%s'"
 				,session->socket,user.alias);
-			badlogin(session->socket,session->client.protocol, username, password, session->host_name, &session->addr);
+			badlogin(session->socket, username, password, &session->client, &session->addr);
 			JS_RESUMEREQUEST(cx, rc);
 			return(JS_TRUE);
 		}
@@ -6186,7 +6186,7 @@ static void respond(http_session_t * session)
 				e = 1;
 			lprintf(LOG_INFO, "%04d Sent file: %s (%"PRIdOFF" bytes, %ld cps)"
 				,session->socket, session->req.physical_path, snt, (long)(snt / e));
-			if(session->parsed_vpath == PARSED_VPATH_FULL) {
+			if(session->parsed_vpath == PARSED_VPATH_FULL && session->file.name != NULL) {
 				user_downloaded_file(&scfg, &session->user, &session->client, session->file.dir, session->file.name, snt);
 				mqtt_file_download(&mqtt, &session->user, &session->file, snt, &session->client);
 			}