diff --git a/src/sbbs3/getmail.c b/src/sbbs3/getmail.c
index 2dc5b48ce1081375dfa37da126d666b5ee5674bb..2da5ddd5ea5e91acefc5c02d786e8adb0c2ae857 100644
--- a/src/sbbs3/getmail.c
+++ b/src/sbbs3/getmail.c
@@ -92,9 +92,11 @@ BOOL DLLCALL delfattach(scfg_t* cfg, smbmsg_t* msg)
 		sp=strrchr(tp,'/');              /* sp is slash pointer */
 		if(!sp) sp=strrchr(tp,'\\');
 		if(sp) tp=sp+1;
-		SAFEPRINTF2(path, "%s/%s", dir, tp);
-		if(remove(path) != 0)
-			return FALSE;
+		if(strcspn(tp, ILLEGAL_FILENAME_CHARS) == strlen(tp)) {
+			SAFEPRINTF2(path, "%s/%s", dir, tp);
+			if(remove(path) != 0)
+				return FALSE;
+		}
 		if(!p)
 			break;
 		tp=p+1; 
diff --git a/src/sbbs3/getmsg.cpp b/src/sbbs3/getmsg.cpp
index 2216cb79b84b10f0382ae1239f4e0a612375a17b..7b59ce3f1155b09690ffd1e4ecbc96b2206416e8 100644
--- a/src/sbbs3/getmsg.cpp
+++ b/src/sbbs3/getmsg.cpp
@@ -405,58 +405,60 @@ void sbbs_t::download_msg_attachments(smb_t* smb, smbmsg_t* msg, bool del)
 			tp=getfname(tp);
 			file_t	fd;
 			fd.dir=cfg.total_dirs+1;			/* temp dir for file attachments */
-			padfname(tp,fd.name);
-			SAFEPRINTF3(fpath,"%sfile/%04u.in/%s"  /* path is path/fname */
-				,cfg.data_dir, msg->idx.to, tp);
-			if(!fexistcase(fpath) && msg->idx.from)
-				SAFEPRINTF3(fpath,"%sfile/%04u.out/%s"  /* path is path/fname */
-					,cfg.data_dir, msg->idx.from,tp);
-			long length=(long)flength(fpath);
-			if(length<1)
-				bprintf(text[FileDoesNotExist], tp);
-			else if(!(useron.exempt&FLAG('T')) && cur_cps && !SYSOP
-				&& length/(long)cur_cps>(time_t)timeleft)
-				bputs(text[NotEnoughTimeToDl]);
-			else {
-				char 	tmp[512];
-				int		i;
-				SAFEPRINTF2(str, text[DownloadAttachedFileQ]
-					,getfname(fpath),ultoac(length,tmp));
-				if(length>0L && text[DownloadAttachedFileQ][0] && yesno(str)) {
-					{	/* Remote User */
-						xfer_prot_menu(XFER_DOWNLOAD);
-						mnemonics(text[ProtocolOrQuit]);
-						strcpy(str,"Q");
-						for(i=0;i<cfg.total_prots;i++)
-							if(cfg.prot[i]->dlcmd[0]
-								&& chk_ar(cfg.prot[i]->ar,&useron,&client)) {
-								sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
-								SAFECAT(str,tmp);
-							}
-						ch=(char)getkeys(str,0);
-						for(i=0;i<cfg.total_prots;i++)
-							if(cfg.prot[i]->dlcmd[0] && ch==cfg.prot[i]->mnemonic
-								&& chk_ar(cfg.prot[i]->ar,&useron,&client))
-								break;
-						if(i<cfg.total_prots) {
-							int error = protocol(cfg.prot[i], XFER_DOWNLOAD, fpath, nulstr, false);
-							if(checkprotresult(cfg.prot[i],error,&fd)) {
-								if(del)
-									(void)remove(fpath);
-								logon_dlb+=length;	/* Update stats */
-								logon_dls++;
-								useron.dls=(ushort)adjustuserrec(&cfg,useron.number
-									,U_DLS,5,1);
-								useron.dlb=adjustuserrec(&cfg,useron.number
-									,U_DLB,10,length);
-								bprintf(text[FileNBytesSent]
-									,fd.name,ultoac(length,tmp));
-								SAFEPRINTF(str
-									,"downloaded attached file: %s"
-									,fd.name);
-								logline("D-",str);
+			if(strcspn(tp, ILLEGAL_FILENAME_CHARS) == strlen(tp)) {
+				padfname(tp,fd.name);
+				SAFEPRINTF3(fpath,"%sfile/%04u.in/%s"  /* path is path/fname */
+					,cfg.data_dir, msg->idx.to, tp);
+				if(!fexistcase(fpath) && msg->idx.from)
+					SAFEPRINTF3(fpath,"%sfile/%04u.out/%s"  /* path is path/fname */
+						,cfg.data_dir, msg->idx.from,tp);
+				long length=(long)flength(fpath);
+				if(length<1)
+					bprintf(text[FileDoesNotExist], tp);
+				else if(!(useron.exempt&FLAG('T')) && cur_cps && !SYSOP
+					&& length/(long)cur_cps>(time_t)timeleft)
+					bputs(text[NotEnoughTimeToDl]);
+				else {
+					char 	tmp[512];
+					int		i;
+					SAFEPRINTF2(str, text[DownloadAttachedFileQ]
+						,getfname(fpath),ultoac(length,tmp));
+					if(length>0L && text[DownloadAttachedFileQ][0] && yesno(str)) {
+						{	/* Remote User */
+							xfer_prot_menu(XFER_DOWNLOAD);
+							mnemonics(text[ProtocolOrQuit]);
+							strcpy(str,"Q");
+							for(i=0;i<cfg.total_prots;i++)
+								if(cfg.prot[i]->dlcmd[0]
+									&& chk_ar(cfg.prot[i]->ar,&useron,&client)) {
+									sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
+									SAFECAT(str,tmp);
+								}
+							ch=(char)getkeys(str,0);
+							for(i=0;i<cfg.total_prots;i++)
+								if(cfg.prot[i]->dlcmd[0] && ch==cfg.prot[i]->mnemonic
+									&& chk_ar(cfg.prot[i]->ar,&useron,&client))
+									break;
+							if(i<cfg.total_prots) {
+								int error = protocol(cfg.prot[i], XFER_DOWNLOAD, fpath, nulstr, false);
+								if(checkprotresult(cfg.prot[i],error,&fd)) {
+									if(del)
+										(void)remove(fpath);
+									logon_dlb+=length;	/* Update stats */
+									logon_dls++;
+									useron.dls=(ushort)adjustuserrec(&cfg,useron.number
+										,U_DLS,5,1);
+									useron.dlb=adjustuserrec(&cfg,useron.number
+										,U_DLB,10,length);
+									bprintf(text[FileNBytesSent]
+										,fd.name,ultoac(length,tmp));
+									SAFEPRINTF(str
+										,"downloaded attached file: %s"
+										,fd.name);
+									logline("D-",str);
+								}
+								autohangup();
 							}
-							autohangup();
 						}
 					}
 				}
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index 3f269ed0cb640feb1f33998e3c8be411d716a6d8..d0da767fb5f5847b7dd99c5252b3b1941cf6e29c 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -907,8 +907,11 @@ static ulong sockmsgtxt(SOCKET socket, const char* prot, CRYPT_SESSION sess, smb
 					break;
 			} else
 				*tp = '\0';
-			SAFEPRINTF2(filepath, "%s/%s", dirname, getfname(truncsp(p)));
-			strListPush(&file_list, filepath);
+			char* fname = getfname(truncsp(p));
+			if(strcspn(fname, ILLEGAL_FILENAME_CHARS) == strlen(fname)) {
+				SAFEPRINTF2(filepath, "%s/%s", dirname, fname);
+				strListPush(&file_list, filepath);
+			}
 			if(tp == NULL)
 				break;
 			p = tp + 1;
diff --git a/src/sbbs3/writemsg.cpp b/src/sbbs3/writemsg.cpp
index de2341ec5c7c272dc4ee87f958da96786d972ad7..0992f8bbb191a7249281b88b9a5a57c02ff407fd 100644
--- a/src/sbbs3/writemsg.cpp
+++ b/src/sbbs3/writemsg.cpp
@@ -1306,13 +1306,14 @@ bool sbbs_t::editfile(char *fname, bool msg)
 
 /*************************/
 /* Copy file attachments */
+/* TODO: Quoted filename support */
 /*************************/
 bool sbbs_t::copyfattach(uint to, uint from, const char* subj)
 {
-	char str[128],str2[128],str3[128],*tp,*sp,*p;
+	char str[128], dest[MAX_PATH + 1], src[MAX_PATH + 1], *tp, *sp, *p;
 	bool result = false;
 
-	strcpy(str, subj);
+	SAFECOPY(str, subj);
 	tp=str;
 	while(1) {
 		p=strchr(tp,' ');
@@ -1320,12 +1321,13 @@ bool sbbs_t::copyfattach(uint to, uint from, const char* subj)
 		sp=strrchr(tp,'/');              /* sp is slash pointer */
 		if(!sp) sp=strrchr(tp,'\\');
 		if(sp) tp=sp+1;
-		SAFEPRINTF3(str2,"%sfile/%04u.in/%s"  /* str2 is path/fname */
-			,cfg.data_dir,to,tp);
-		SAFEPRINTF3(str3,"%sfile/%04u.in/%s"  /* str2 is path/fname */
-			,cfg.data_dir,from,tp);
-		if(strcmp(str2,str3)) {
-			if(mv(str3, str2, /* copy */true) != 0)
+		if(strcspn(tp, ILLEGAL_FILENAME_CHARS) == strlen(tp)) {
+			if(to == 0)
+				SAFEPRINTF3(dest,"%sfile/%04u.out/%s", cfg.data_dir, from, tp);
+			else
+				SAFEPRINTF3(dest,"%sfile/%04u.in/%s", cfg.data_dir, to, tp);
+			SAFEPRINTF3(src,"%sfile/%04u.in/%s", cfg.data_dir, from, tp);
+			if(mv(src, dest, /* copy */true) != 0)
 				return false;
 			result = true;
 		}