diff --git a/exec/load/smbdefs.js b/exec/load/smbdefs.js
index 87074140aeadb80818913a389deda50c69ab87ab..c1389184991a96029cf04bb01da3a1e7c910d9f5 100644
--- a/exec/load/smbdefs.js
+++ b/exec/load/smbdefs.js
@@ -69,6 +69,7 @@ const MSG_KILLFILE			= (1<<3);	// Delete file(s) when sent
 const MSG_RECEIPTREQ		= (1<<4);	// Return receipt requested
 const MSG_CONFIRMREQ		= (1<<5);	// Confirmation receipt requested
 const MSG_NODISP			= (1<<6);	// Msg may not be displayed to user
+const MSG_FIXED_FORMAT		= (1<<7);   // Pre-formatted message body text
 const MSG_HFIELDS_UTF8		= (1<<13);	// Message header fields are UTF-8 encoded
 const POLL_CLOSED			= (1<<24);	// Closed to voting
 const POLL_RESULTS_MASK		= (3<<30);	// 4 possible values:
diff --git a/exec/postmeme.js b/exec/postmeme.js
index 7ec8b8c158ee91030838809cc4eeb0db3f6e0314..7c29f88254bb906838659b9a21b20b3bd00ca116 100755
--- a/exec/postmeme.js
+++ b/exec/postmeme.js
@@ -27,7 +27,7 @@ if (!msg)
 var sub = msg_area.sub[bbs.cursub_code];
 console.print(format(bbs.text("Posting"), sub.grp_name, sub.description));
 
-var hdr = { from_ext: user.number, from:  sub.settings & SUB_NAME ? user.name : user.alias };
+var hdr = { auxattr: MSG_FIXED_FORMAT, from_ext: user.number, from:  sub.settings & SUB_NAME ? user.name : user.alias };
 console.print(bbs.text("PostTo"));
 hdr.to = console.getstr("All", LEN_ALIAS, K_EDIT | K_LINE | K_AUTODEL);
 if (console.aborted || !hdr.to)
diff --git a/exec/postmsg.js b/exec/postmsg.js
index 9dec58235c1679a6f3bd56f0cfcf9e3200085bc5..0085dbd549da80bfffe29a108a8c73635fc9d624 100644
--- a/exec/postmsg.js
+++ b/exec/postmsg.js
@@ -25,6 +25,7 @@ function usage()
 	print("\t-T<date/time> set message date and time in string format supported by JS Date()");
 	print("\t-d            use default values (no prompt) for to, from, and subject");
 	print("\t-F            set file request attribute flag");
+	print("\t-P            set message format to 'Fixed' (pre-formatted text)");
 	print();
 	print("Note: You may need to enclose multi-word options in quotes (e.g. \"-fMy Name\")");
 	print();
@@ -53,6 +54,9 @@ for(var i in argv) {
 				case 'F':
 					hdrs.auxattr = MSG_FILEREQUEST;
 					break;
+				case 'P':
+					hdrs.auxattr = MSG_FIXED_FORMAT;
+					break;
 				case 'e':
 					if(val.length)
 						hdrs.from_ext = val;
diff --git a/src/sbbs3/atcodes.cpp b/src/sbbs3/atcodes.cpp
index c4695252894eb642e95388ea9919ab6cdd64c610..99acd663462caeefee236c5698fc87574dcb52ed 100644
--- a/src/sbbs3/atcodes.cpp
+++ b/src/sbbs3/atcodes.cpp
@@ -2109,7 +2109,7 @@ const char* sbbs_t::atcode(const char* sp, char* str, size_t maxlen, int* pmode,
 		return str;
 	}
 	if (!strcmp(sp, "MSG_AUXATTR") && current_msg != NULL) {
-		safe_snprintf(str, maxlen, "%s%s%s%s%s%s%s"
+		safe_snprintf(str, maxlen, "%s%s%s%s%s%s%s%s"
 		              , current_msg->hdr.auxattr & MSG_FILEREQUEST   ? "FileRequest  "   :nulstr
 		              , current_msg->hdr.auxattr & MSG_FILEATTACH    ? "FileAttach  "    :nulstr
 		              , current_msg->hdr.auxattr & MSG_MIMEATTACH    ? "MimeAttach  "    :nulstr
@@ -2117,6 +2117,7 @@ const char* sbbs_t::atcode(const char* sp, char* str, size_t maxlen, int* pmode,
 		              , current_msg->hdr.auxattr & MSG_RECEIPTREQ    ? "ReceiptReq  "    :nulstr
 		              , current_msg->hdr.auxattr & MSG_CONFIRMREQ    ? "ConfirmReq  "    :nulstr
 		              , current_msg->hdr.auxattr & MSG_NODISP        ? "DontDisplay  "   :nulstr
+		              , current_msg->hdr.auxattr & MSG_FIXED_FORMAT  ? "FixedFormat "    :nulstr
 		              );
 		return str;
 	}
diff --git a/src/sbbs3/getmsg.cpp b/src/sbbs3/getmsg.cpp
index 06930d68ae348c523293d8b48aaa33e50c8692e6..3d82178926239cf056d1d9b83e902065bb37d936 100644
--- a/src/sbbs3/getmsg.cpp
+++ b/src/sbbs3/getmsg.cpp
@@ -101,7 +101,7 @@ void sbbs_t::show_msgattr(const smbmsg_t* msg)
 	              );
 
 	char auxattr_str[64];
-	safe_snprintf(auxattr_str, sizeof(auxattr_str), "%s%s%s%s%s%s%s"
+	safe_snprintf(auxattr_str, sizeof(auxattr_str), "%s%s%s%s%s%s%s%s"
 	              , auxattr & MSG_FILEREQUEST? "FileRequest  "   :nulstr
 	              , auxattr & MSG_FILEATTACH ? "FileAttach  "    :nulstr
 	              , auxattr & MSG_MIMEATTACH ? "MimeAttach  "    :nulstr
@@ -109,6 +109,7 @@ void sbbs_t::show_msgattr(const smbmsg_t* msg)
 	              , auxattr & MSG_RECEIPTREQ ? "ReceiptReq  "    :nulstr
 	              , auxattr & MSG_CONFIRMREQ ? "ConfirmReq  "    :nulstr
 	              , auxattr & MSG_NODISP     ? "DontDisplay  "   :nulstr
+	              , auxattr & MSG_FIXED_FORMAT ? "FixedFormat "  :nulstr
 	              );
 
 	char netattr_str[64];
@@ -347,6 +348,8 @@ bool sbbs_t::show_msg(smb_t* smb, smbmsg_t* msg, int p_mode, post_t* post)
 	}
 	if (console & CON_RAW_IN)
 		p_mode = P_NOATCODES;
+	else if (msg->hdr.auxattr & MSG_FIXED_FORMAT)
+		p_mode &= ~(P_WORDWRAP | P_MARKUP);
 	putmsg(p, p_mode, msg->columns);
 	smb_freemsgtxt(txt);
 	if (term->column)
diff --git a/src/sbbs3/msgtoqwk.cpp b/src/sbbs3/msgtoqwk.cpp
index 3a9194015af451b3fad182b781b8b89c8cc89fb1..34383fed3ca6a9489d80ed81e93efeec2f82ea84 100644
--- a/src/sbbs3/msgtoqwk.cpp
+++ b/src/sbbs3/msgtoqwk.cpp
@@ -123,6 +123,7 @@ int sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, int mode, smb_t* smb
 		fprintf(hdrs, "Utf8 = %s\n"
 		        , ((smb_msg_is_utf8(msg) || (msg->hdr.auxattr & MSG_HFIELDS_UTF8)) && (mode & QM_UTF8))
 		        ? "true" : "false");
+		fprintf(hdrs, "Format = %s\n", (msg->hdr.auxattr & MSG_FIXED_FORMAT) ? "fixed" : "flowed");
 
 		/* Message-IDs */
 		fprintf(hdrs, "%s: %s\n", smb_hfieldtype(RFC822MSGID), msgid);
diff --git a/src/sbbs3/postmsg.cpp b/src/sbbs3/postmsg.cpp
index 23624007bb940a299a0c2e241c3a247475ea47b7..eb2cca5e5c5cf295a5d14b9f159064c25098b405 100644
--- a/src/sbbs3/postmsg.cpp
+++ b/src/sbbs3/postmsg.cpp
@@ -78,6 +78,7 @@ bool sbbs_t::postmsg(int subnum, int wm_mode, smb_t* resmb, smbmsg_t* remsg)
 	char*       msgbuf = NULL;
 	uint16_t    xlat;
 	ushort      msgattr = 0;
+	uint32_t    auxattr = (console & CON_RAW_IN) ? MSG_FIXED_FORMAT : 0;
 	int         i, storage;
 	int         dupechk_hashes;
 	int         length;
@@ -285,6 +286,7 @@ bool sbbs_t::postmsg(int subnum, int wm_mode, smb_t* resmb, smbmsg_t* remsg)
 
 	memset(&msg, 0, sizeof(msg));
 	msg.hdr.attr = msgattr;
+	msg.hdr.auxattr = auxattr;
 	msg.hdr.when_written = smb_when(time(NULL), sys_timezone(&cfg));
 	msg.hdr.when_imported.time = time32(NULL);
 	msg.hdr.when_imported.zone = msg.hdr.when_written.zone;
diff --git a/src/sbbs3/qwktomsg.cpp b/src/sbbs3/qwktomsg.cpp
index 5533e852103987cf95fa295ca067a1207a0b59c4..657d3910c2889034b19d8c039a781afcc9246e97 100644
--- a/src/sbbs3/qwktomsg.cpp
+++ b/src/sbbs3/qwktomsg.cpp
@@ -42,6 +42,10 @@ static bool qwk_parse_header_list(sbbs_t* sbbs, uint confnum, smbmsg_t* msg, str
 		if (stricmp(value, "true") == 0)
 			msg->hdr.auxattr |= MSG_HFIELDS_UTF8;
 	}
+	if ((p = iniPopKey(headers, ROOT_SECTION, "format", value)) != NULL) {
+		if (stricmp(value, "fixed") == 0)
+			msg->hdr.auxattr |= MSG_FIXED_FORMAT;
+	}
 
 	if ((p = iniPopKey(headers, ROOT_SECTION, "WhenWritten", value)) != NULL) {
 		xpDateTime_t dt = isoDateTimeStr_parse(p);
diff --git a/src/sbbs3/sbbsecho.c b/src/sbbs3/sbbsecho.c
index 318c9068ac8547508877f273beb119eea5adfcfb..637f1ede318d149bb84501690b435fb0cd8273e8 100644
--- a/src/sbbs3/sbbsecho.c
+++ b/src/sbbs3/sbbsecho.c
@@ -1215,6 +1215,7 @@ int create_netmail(const char *to, const smbmsg_t* msg, const char *subject, con
 				charset = FIDO_CHARSET_CP437;
 		}
 		fprintf(fp, "\1CHRS: %s\r", charset);
+		fprintf(fp, "\1FORMAT: %s\r", (msg->hdr.auxattr & MSG_FIXED_FORMAT) ? "fixed" : "flowed");
 		if (msg->editor != NULL)
 			fprintf(fp, "\1NOTE: %s\r", msg->editor);
 		if (subject != msg->subj)
@@ -3643,6 +3644,15 @@ int fmsgtosmsg(char* fbuf, fmsghdr_t* hdr, uint usernumber, uint subnum)
 					smb_hfield_bin(&msg, SMB_COLUMNS, columns);
 			}
 
+			else if (!strncmp(fbuf + l + 1, "FORMAT:", 7)) {   /* SBBSecho */
+				l += 8;
+				while (l < length && fbuf[l] == ' ') l++;
+				m = l;
+				while (m < length && fbuf[m] != '\r') m++;
+				if (strnicmp(fbuf + l, "fixed", m - l) == 0)
+					msg.hdr.auxattr |= MSG_FIXED_FORMAT;
+			}
+
 			else if (!strncmp(fbuf + l + 1, "BBSID:", 6)) {
 				l += 7;
 				while (l < length && fbuf[l] <= ' ' && fbuf[l] >= 0) l++;
@@ -5158,6 +5168,7 @@ ulong export_echomail(const char* sub_code, const nodecfg_t* nodecfg, bool resca
 					charset = FIDO_CHARSET_CP437;
 			}
 			f += sprintf(fmsgbuf + f, "\1CHRS: %s\r", charset);
+			f += sprintf(fmsgbuf + f, "\1FORMAT: %s\r", (msg.hdr.auxattr & MSG_FIXED_FORMAT) ? "fixed" : "flowed");
 			if (msg.editor != NULL)
 				f += sprintf(fmsgbuf + f, "\1NOTE: %s\r", msg.editor);
 
diff --git a/src/sbbs3/sbbsecho.h b/src/sbbs3/sbbsecho.h
index c52ea28e3312a4709bda89ce56eac3c160fed3c9..48590fe0ea8686977106b7ec5656e576a59a6389 100644
--- a/src/sbbs3/sbbsecho.h
+++ b/src/sbbs3/sbbsecho.h
@@ -28,7 +28,7 @@
 #include "ini_file.h"
 
 #define SBBSECHO_VERSION_MAJOR      3
-#define SBBSECHO_VERSION_MINOR      24
+#define SBBSECHO_VERSION_MINOR      25
 
 #define SBBSECHO_PRODUCT_CODE       0x12FF  /* from http://ftsc.org/docs/ftscprod.013 */
 
diff --git a/src/smblib/smbdefs.h b/src/smblib/smbdefs.h
index 14cac0032467f9e97f0f77af60272ad30d29975c..d1f5808ea16df08977749af8557964af51ff9697 100644
--- a/src/smblib/smbdefs.h
+++ b/src/smblib/smbdefs.h
@@ -304,6 +304,7 @@ typedef unsigned char uchar;
 #define MSG_RECEIPTREQ      (1 << 4)      /* Return receipt requested */
 #define MSG_CONFIRMREQ      (1 << 5)      /* Confirmation receipt requested */
 #define MSG_NODISP          (1 << 6)      /* Msg may not be displayed to user */
+#define MSG_FIXED_FORMAT    (1 << 7)      /* Preformatted message body text */
 #define MSG_HFIELDS_UTF8    (1 << 13)     /* Message header fields are UTF-8 encoded */
 #define POLL_CLOSED         (1 << 24)     /* Closed to voting */
 #define POLL_RESULTS_MASK   (3U << 30)    /* 4 possible values: */
diff --git a/src/smblib/smbstr.c b/src/smblib/smbstr.c
index d1fcc70296de2ae45d4d41078d6f39ffbb3df95e..577e6dd7fa9d0fcec7912d2147ea7b4dbf8faa89 100644
--- a/src/smblib/smbstr.c
+++ b/src/smblib/smbstr.c
@@ -483,6 +483,7 @@ char* smb_auxattrstr(int32_t attr, char* outstr, size_t maxlen)
 	MSG_ATTR_CHECK(attr, RECEIPTREQ);
 	MSG_ATTR_CHECK(attr, CONFIRMREQ);
 	MSG_ATTR_CHECK(attr, NODISP);
+	MSG_ATTR_CHECK(attr, FIXED_FORMAT);
 	MSG_ATTR_CHECK(attr, HFIELDS_UTF8);
 	if (attr & POLL_CLOSED)
 		sprintf(str + strlen(str), "%sPOLL-CLOSED", str[0] == 0 ? "" : ", ");