diff --git a/src/sbbs3/atcodes.cpp b/src/sbbs3/atcodes.cpp
index 4001bd9d404786bdf44b5392f9f87e356902ade9..d109abfdcf85895eb6cc5fab53d675bf50515c53 100644
--- a/src/sbbs3/atcodes.cpp
+++ b/src/sbbs3/atcodes.cpp
@@ -61,6 +61,7 @@ int sbbs_t::show_atcode(const char *instr)
 	bool	zero_padded=false;
 	bool	truncated = true;
 	bool	doubled = false;
+	long	pmode = 0;
 	const char *cp;
 
 	SAFECOPY(str,instr);
@@ -96,7 +97,7 @@ int sbbs_t::show_atcode(const char *instr)
 		*p=0;
 	}
 
-	cp=atcode(sp,str2,sizeof(str2));
+	cp = atcode(sp, str2, sizeof(str2), &pmode);
 	if(cp==NULL)
 		return(0);
 
@@ -111,32 +112,38 @@ int sbbs_t::show_atcode(const char *instr)
 				disp_len = (cols - 1) - column;
 		}
 	}
+	if(pmode & P_UTF8) {
+		if(term_supports(UTF8))
+			disp_len += strlen(cp) - utf8_str_total_width(cp);
+		else
+			disp_len += strlen(cp) - utf8_str_count_width(cp, /* min: */1, /* max: */2);
+	}
 	if(padded_left)
-		bprintf("%-*.*s",disp_len,disp_len,cp);
+		bprintf(pmode, "%-*.*s",disp_len,disp_len,cp);
 	else if(padded_right)
-		bprintf("%*.*s",disp_len,disp_len,cp);
+		bprintf(pmode, "%*.*s",disp_len,disp_len,cp);
 	else if(centered) {
 		int vlen = strlen(cp);
 		if(vlen < disp_len) {
 			int left = (disp_len - vlen) / 2;
-			bprintf("%*s%-*s", left, "", disp_len - left, cp);
+			bprintf(pmode, "%*s%-*s", left, "", disp_len - left, cp);
 		} else
-			bprintf("%.*s", disp_len, cp);
+			bprintf(pmode, "%.*s", disp_len, cp);
 	} else if(doubled) {
 		wide(cp);
 	} else if(zero_padded) {
 		int vlen = strlen(cp);
 		if(vlen < disp_len)
-			bprintf("%-.*s%s", (int)(disp_len - strlen(cp)), "0000000000", cp);
+			bprintf(pmode, "%-.*s%s", (int)(disp_len - strlen(cp)), "0000000000", cp);
 		else
-			bprintf("%.*s", disp_len, cp);
+			bprintf(pmode, "%.*s", disp_len, cp);
 	} else
-		bprintf("%.*s", disp_len, cp);
+		bprintf(pmode, "%.*s", disp_len, cp);
 
 	return(len);
 }
 
-const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen)
+const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen, long* pmode)
 {
 	char*	tp = NULL;
 	uint	i;
@@ -1112,6 +1119,8 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen)
 
 	/* Message header codes */
 	if(!strcmp(sp,"MSG_TO") && current_msg!=NULL && current_msg_to!=NULL) {
+		if(pmode != NULL)
+			*pmode |= (current_msg->hdr.auxattr & MSG_HFIELDS_UTF8);
 		if(current_msg->to_ext!=NULL)
 			safe_snprintf(str,maxlen,"%s #%s",current_msg_to,current_msg->to_ext);
 		else if(current_msg->to_net.addr != NULL) {
@@ -1122,8 +1131,11 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen)
 			return(current_msg_to);
 		return(str);
 	}
-	if(!strcmp(sp,"MSG_TO_NAME") && current_msg_to!=NULL)
+	if(!strcmp(sp,"MSG_TO_NAME") && current_msg_to!=NULL) {
+		if(pmode != NULL && current_msg != NULL)
+			*pmode |= (current_msg->hdr.auxattr & MSG_HFIELDS_UTF8);
 		return(current_msg_to);
+	}
 	if(!strcmp(sp,"MSG_TO_EXT") && current_msg!=NULL) {
 		if(current_msg->to_ext==NULL)
 			return(nulstr);
@@ -1144,6 +1156,8 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen)
 	if(!strcmp(sp,"MSG_FROM") && current_msg != NULL && current_msg_from != NULL) {
 		if(current_msg->hdr.attr&MSG_ANONYMOUS && !SYSOP)
 			return(text[Anonymous]);
+		if(pmode != NULL)
+			*pmode |= (current_msg->hdr.auxattr & MSG_HFIELDS_UTF8);
 		if(current_msg->from_ext!=NULL)
 			safe_snprintf(str,maxlen,"%s #%s",current_msg_from,current_msg->from_ext);
 		else if(current_msg->from_net.addr != NULL) {
@@ -1157,6 +1171,8 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen)
 	if(!strcmp(sp,"MSG_FROM_NAME") && current_msg_from!=NULL) {
 		if(current_msg->hdr.attr&MSG_ANONYMOUS && !SYSOP)
 			return(text[Anonymous]);
+		if(pmode != NULL && current_msg != NULL)
+			*pmode |= (current_msg->hdr.auxattr & MSG_HFIELDS_UTF8);
 		return(current_msg_from);
 	}
 	if(!strcmp(sp,"MSG_FROM_EXT") && current_msg!=NULL) {
@@ -1176,8 +1192,11 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen)
 			return nulstr;
 		return(smb_nettype((enum smb_net_type)current_msg->from_net.type));
 	}
-	if(!strcmp(sp,"MSG_SUBJECT") && current_msg_subj != NULL)
+	if(!strcmp(sp,"MSG_SUBJECT") && current_msg_subj != NULL) {
+		if(pmode != NULL && current_msg != NULL)
+			*pmode |= (current_msg->hdr.auxattr & MSG_HFIELDS_UTF8);
 		return(current_msg_subj);
+	}
 	if(!strcmp(sp,"MSG_SUMMARY") && current_msg!=NULL)
 		return(current_msg->summary==NULL ? nulstr : current_msg->summary);
 	if(!strcmp(sp,"MSG_TAGS") && current_msg!=NULL)
diff --git a/src/sbbs3/getmsg.cpp b/src/sbbs3/getmsg.cpp
index ab1edfff17833b20bb942b37aeefa3b3fa3fe873..0069028a993766f4f8fa0c5dc2fbceac04fc77ed 100644
--- a/src/sbbs3/getmsg.cpp
+++ b/src/sbbs3/getmsg.cpp
@@ -118,6 +118,18 @@ void sbbs_t::show_msgattr(smbmsg_t* msg)
 		);
 }
 
+/* Returns a CP437 text.dat string converted to UTF-8, when appropriate */
+const char* sbbs_t::msghdr_text(const smbmsg_t* msg, uint index)
+{
+	if(msg == NULL || !(msg->hdr.auxattr & MSG_HFIELDS_UTF8))
+		return text[index];
+
+	if(cp437_to_utf8_str(text[index], msghdr_utf8_text, sizeof(msghdr_utf8_text), /* min-char-val: */'\x80') < 1)
+		return text[index];
+
+	return msghdr_utf8_text;
+}
+
 /****************************************************************************/
 /* Displays a message header to the screen                                  */
 /****************************************************************************/
@@ -128,6 +140,7 @@ void sbbs_t::show_msghdr(smb_t* smb, smbmsg_t* msg, const char* subject, const c
 	char	*sender=NULL;
 	int 	i;
 	smb_t	saved_smb = this->smb;
+	long	pmode = 0;
 
 	if(smb != NULL)
 		this->smb = *smb;	// Needed for @-codes and JS bbs.smb_* properties
@@ -136,6 +149,8 @@ void sbbs_t::show_msghdr(smb_t* smb, smbmsg_t* msg, const char* subject, const c
 		current_msg_subj = msg->subj;
 		current_msg_from = msg->from;
 		current_msg_to = msg->to;
+		if(msg->hdr.auxattr & MSG_HFIELDS_UTF8)
+			pmode |= P_UTF8;
 	}
 	if(subject != NULL)
 		current_msg_subj = subject;
@@ -153,13 +168,13 @@ void sbbs_t::show_msghdr(smb_t* smb, smbmsg_t* msg, const char* subject, const c
 	}
 	msghdr_tos = tos;
 	if(!menu("msghdr", P_NOERROR)) {
-		bprintf(text[MsgSubj], current_msg_subj);
+		bprintf(pmode, msghdr_text(msg, MsgSubj), current_msg_subj);
 		if(msg->tags && *msg->tags)
 			bprintf(text[MsgTags], msg->tags);
 		if(msg->hdr.attr || msg->hdr.netattr || msg->hdr.auxattr)
 			show_msgattr(msg);
 		if(current_msg_to != NULL && *current_msg_to != 0) {
-			bprintf(text[MsgTo], current_msg_to);
+			bprintf(pmode, msghdr_text(msg, MsgTo), current_msg_to);
 			if(msg->to_net.addr!=NULL)
 				bprintf(text[MsgToNet],smb_netaddrstr(&msg->to_net,str));
 			if(msg->to_ext)
@@ -168,7 +183,7 @@ void sbbs_t::show_msghdr(smb_t* smb, smbmsg_t* msg, const char* subject, const c
 		if(msg->cc_list != NULL)
 			bprintf(text[MsgCarbonCopyList], msg->cc_list);
 		if(current_msg_from != NULL && (!(msg->hdr.attr&MSG_ANONYMOUS) || SYSOP)) {
-			bprintf(text[MsgFrom], current_msg_from);
+			bprintf(pmode, msghdr_text(msg, MsgFrom), current_msg_from);
 			if(msg->from_ext)
 				bprintf(text[MsgFromExt],msg->from_ext);
 			if(msg->from_net.addr!=NULL && (current_msg_from == NULL || strchr(current_msg_from,'@')==NULL))
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 06e4afde63743a4ae6087b7b30b1bc7d81b25c8e..73f7ac3869fc7a8aa9dcfc96792731f849e6d05a 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -688,6 +688,8 @@ public:
 	void	show_msghdr(smb_t*, smbmsg_t*, const char *subj = NULL, const char* from = NULL, const char* to = NULL);
 	bool	show_msg(smb_t*, smbmsg_t*, long p_mode = 0, post_t* post = NULL);
 	bool	msgtotxt(smb_t*, smbmsg_t*, const char *fname, bool header = true, ulong gettxt_mode = GETMSGTXT_ALL);
+	const char* msghdr_text(const smbmsg_t*, uint index);
+	char	msghdr_utf8_text[128];
 	ulong	getlastmsg(uint subnum, uint32_t *ptr, time_t *t);
 	time_t	getmsgtime(uint subnum, ulong ptr);
 	ulong	getmsgnum(uint subnum, time_t t);
@@ -787,7 +789,7 @@ public:
 
 	/* atcodes.cpp */
 	int		show_atcode(const char *code);
-	const char*	atcode(char* sp, char* str, size_t maxlen);
+	const char*	atcode(char* sp, char* str, size_t maxlen, long* pmode = NULL);
 
 	/* getnode.cpp */
 	int		getsmsg(int usernumber, bool clearline = false);
diff --git a/src/sbbs3/writemsg.cpp b/src/sbbs3/writemsg.cpp
index 415fc33eb84ca234dd89e6414af682b318d44216..37f183c3ead5a4c26d0fc75762a5d44e5e97de03 100644
--- a/src/sbbs3/writemsg.cpp
+++ b/src/sbbs3/writemsg.cpp
@@ -749,7 +749,10 @@ void sbbs_t::editor_info_to_msg(smbmsg_t* msg, const char* editor, const char* c
 
 	if(editor == NULL || useron_xedit == 0 || (cfg.xedit[useron_xedit - 1]->misc&SAVECOLUMNS))
 		smb_hfield_bin(msg, SMB_COLUMNS, cols);
-}
+
+	if(!str_is_ascii(msg->subj) && utf8_str_is_valid(msg->subj))
+		msg->hdr.auxattr |= MSG_HFIELDS_UTF8;
+}  
 
 /****************************************************************************/
 /****************************************************************************/