diff --git a/src/sbbs3/scfg/scfgsub.c b/src/sbbs3/scfg/scfgsub.c
index 9659d7e0650fbad9e71b4d6b8c06bf0bddf9e365..9508c901ac536f3938e801f1395493604ceed1f6 100644
--- a/src/sbbs3/scfg/scfgsub.c
+++ b/src/sbbs3/scfg/scfgsub.c
@@ -292,8 +292,10 @@ void sub_cfg(int grpnum)
 			SAFECOPY(cfg.sub[subnum[i]]->lname,str);
 			SAFECOPY(cfg.sub[subnum[i]]->sname,str2);
 			SAFECOPY(cfg.sub[subnum[i]]->qwkname,code);
-			if(strchr(str,'.') && strchr(str,' ')==NULL)
+			if(strchr(str,'.') && strchr(str,' ')==NULL) {
 				SAFECOPY(cfg.sub[subnum[i]]->newsgroup,str);
+				make_newsgroup_name(cfg.sub[subnum[i]]->newsgroup);
+			}
 			uifc.changes = TRUE;
 			continue;
 		}
@@ -353,9 +355,10 @@ void sub_cfg(int grpnum)
 			else
 				SAFEPRINTF(area_tag, "[%s]", sub_area_tag(&cfg, cfg.sub[i], tmp, sizeof(tmp)));
 			char newsgroup_name[sizeof(cfg.sub[i]->newsgroup) + 2];
-			if(cfg.sub[i]->newsgroup[0])
+			if(cfg.sub[i]->newsgroup[0]) {
 				SAFECOPY(newsgroup_name, cfg.sub[i]->newsgroup);
-			else
+				make_newsgroup_name(newsgroup_name);
+			} else
 				SAFEPRINTF(newsgroup_name, "[%s]", sub_newsgroup_name(&cfg, cfg.sub[i], tmp, sizeof(tmp)));
 			snprintf(opt[n++], MAX_OPLN, "%-27.27s%s","Long Name",cfg.sub[i]->lname);
 			snprintf(opt[n++], MAX_OPLN, "%-27.27s%s","Short Name",cfg.sub[i]->sname);
@@ -476,10 +479,13 @@ void sub_cfg(int grpnum)
 						"is configured here, a name will be automatically generated from the\n"
 						"Sub-board's Short Name and message group's Short Name.\n"
 						"\n"
-						"This name should ~ not ~ contain spaces."
+						"A newsgroup name (per RFC 5536) may ~ only ~ contain the characters:\n"
+						"    [`a-z`], [`A-Z`], [`0-9`], '`+`', '`_`', '`-`', and '`.`'.\n"
+						"A newsgroup name may not begin or end with a '`.`'.\n"
 					;
-					uifc.input(WIN_MID|WIN_SAV,0,17,""
-						,cfg.sub[i]->newsgroup,sizeof(cfg.sub[i]->newsgroup)-1,K_EDIT);
+					if(uifc.input(WIN_MID|WIN_SAV,0,17,""
+						,cfg.sub[i]->newsgroup,sizeof(cfg.sub[i]->newsgroup)-1,K_EDIT) > 0)
+						make_newsgroup_name(cfg.sub[i]->newsgroup);
 					break;
 				case 5:
 					uifc.helpbuf=
diff --git a/src/sbbs3/scfglib1.c b/src/sbbs3/scfglib1.c
index 740603d9db3408757b4a05a101c68baa53df85e4..03453d7763b9e89e039e19cc73fb6a60f5f29bc6 100644
--- a/src/sbbs3/scfglib1.c
+++ b/src/sbbs3/scfglib1.c
@@ -26,6 +26,7 @@
 #include "findstr.h"
 #include "ini_file.h"
 #include "sockwrap.h"	 // IPPORT_MQTT
+#include "str_util.h"
 
 bool allocerr(char* error, size_t maxerrlen, const char* fname, const char *item, size_t size)
 {
@@ -934,37 +935,11 @@ faddr_t* nearest_sysfaddr(scfg_t* cfg, faddr_t* addr)
 
 char* sub_newsgroup_name(scfg_t* cfg, sub_t* sub, char* str, size_t size)
 {
-	memset(str, 0, size);
 	if(sub->newsgroup[0])
-		strncpy(str, sub->newsgroup, size - 1);
-	else {
-		snprintf(str, size - 1, "%s.%s", cfg->grp[sub->grp]->sname, sub->sname);
-		/*
-		 * From RFC5536:
-		 * newsgroup-name  =  component *( "." component )
-		 * component       =  1*component-char
-		 * component-char  =  ALPHA / DIGIT / "+" / "-" / "_"
-		 */
-		if (str[0] == '.')
-			str[0] = '_';
-		size_t c;
-		for(c = 0; str[c] != 0; c++) {
-			/* Legal characters */
-			if ((str[c] >= 'A' && str[c] <= 'Z')
-					|| (str[c] >= 'a' && str[c] <= 'z')
-					|| (str[c] >= '0' && str[c] <= '9')
-					|| str[c] == '+'
-					|| str[c] == '-'
-					|| str[c] == '_'
-					|| str[c] == '.')
-				continue;
-			str[c] = '_';
-		}
-		c--;
-		if (str[c] == '.')
-			str[c] = '_';
-	}
-	return str;
+		strlcpy(str, sub->newsgroup, size);
+	else
+		snprintf(str, size, "%s.%s", cfg->grp[sub->grp]->sname, sub->sname);
+	return make_newsgroup_name(str);
 }
 
 char* sub_area_tag(scfg_t* cfg, sub_t* sub, char* str, size_t size)