diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index 0246945f3104dc6671f70a55bfae918da71d9419..af68b46aa0ec2d349c9633bf2f1554474b06edc0 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -556,10 +556,10 @@ static ulong sockmimetext(SOCKET socket, smbmsg_t* msg, char* msgtxt, ulong maxl
 			i=sockprintf(socket,"%.*s",MAX_LINE_LEN,p);
 		if(!i)
 			break;
+		lines++;
 		if(tp==NULL)
 			break;
 		p=tp+1;
-		lines++;
 		/* release time-slices every x lines */
 		if(startup->lines_per_yield
 			&& !(lines%startup->lines_per_yield))	
@@ -1124,6 +1124,10 @@ static void pop3_thread(void* arg)
 					continue;
 				}
 
+				if(lines > 0					/* Works around BlackBerry mail server */
+					&& lines >= strlen(msgtxt))	/* which requests the number of bytes (instead of lines) using TOP */
+					lines=-1;					
+
 				sockprintf(socket,"+OK message follows");
 				lprintf(LOG_DEBUG,"%04d POP3 sending message text (%u bytes)"
 					,socket,strlen(msgtxt));
@@ -1518,20 +1522,27 @@ static char* mailcmdstr(char* instr, char* msgpath, char* newpath, char* logpath
 }
 #ifdef JAVASCRIPT
 
+typedef struct {
+	SOCKET		sock;
+	const char*	log_prefix;
+	const char*	proc_name;
+} private_t;
+
 static void
 js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
 {
 	char	line[64];
 	char	file[MAX_PATH+1];
 	char*	warning;
-	SOCKET*		sock;
+	private_t*	p;
 	jsrefcount	rc;
 
-	if((sock=(SOCKET*)JS_GetContextPrivate(cx))==NULL)
+	if((p=(private_t*)JS_GetContextPrivate(cx))==NULL)
 		return;
 
 	if(report==NULL) {
-		lprintf(LOG_ERR,"!JavaScript: %s", message);
+		lprintf(LOG_ERR,"%04d %s %s !JavaScript: %s"
+			, p->sock, p->log_prefix, p->proc_name, message);
 		return;
     }
 
@@ -1554,8 +1565,9 @@ js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
 		warning="";
 
 	rc=JS_SUSPENDREQUEST(cx);
-	lprintf(LOG_ERR,"%04d !JavaScript %s%s%s: %s"
-		,*sock, warning ,file, line, message);
+	lprintf(LOG_ERR,"%04d %s %s !JavaScript %s%s%s: %s"
+		,p->sock, p->log_prefix, p->proc_name
+		,warning ,file, line, message);
 	JS_RESUMEREQUEST(cx, rc);
 }
 
@@ -1565,10 +1577,10 @@ js_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
     uintN		i=0;
 	int32		level=LOG_INFO;
     JSString*	str=NULL;
-	SOCKET*		sock;
+	private_t*	p;
 	jsrefcount	rc;
 
-	if((sock=(SOCKET*)JS_GetContextPrivate(cx))==NULL)
+	if((p=(private_t*)JS_GetContextPrivate(cx))==NULL)
 		return(JS_FALSE);
 
 	if(JSVAL_IS_NUMBER(argv[i]))
@@ -1578,7 +1590,8 @@ js_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 		if((str=JS_ValueToString(cx, argv[i]))==NULL)
 			return(JS_FALSE);
 		rc=JS_SUSPENDREQUEST(cx);
-		lprintf(level,"%04d JavaScript: %s",*sock,JS_GetStringBytes(str));
+		lprintf(level,"%04d %s %s: %s"
+			,p->sock,p->log_prefix,p->proc_name,JS_GetStringBytes(str));
 		JS_RESUMEREQUEST(cx, rc);
 	}
 
@@ -1599,28 +1612,31 @@ static JSFunctionSpec js_global_functions[] = {
 };
 
 static BOOL
-js_mailproc(SOCKET sock, client_t* client, user_t* user
+js_mailproc(SOCKET sock, client_t* client, user_t* user, struct mailproc* mailproc
 			,char* cmdline
-			,char* eval
 			,char* msgtxt_fname, char* newtxt_fname, char* logtxt_fname
 			,char* rcptlst_fname, char* proc_err_fname
 			,char* sender, char* sender_addr, char* reverse_path, char* hello_name
-			,int* result)
+			,int* result
+			,JSRuntime**	js_runtime
+			,JSContext**	js_cx
+			,JSObject**		js_glob
+			,const char*	log_prefix
+)
 {
 	char*		p;
 	char		fname[MAX_PATH+1];
 	char		path[MAX_PATH+1];
 	char		arg[MAX_PATH+1];
 	BOOL		success=FALSE;
-	JSRuntime*	js_runtime=NULL;
-	JSContext*	js_cx=NULL;
-	JSObject*	js_glob;
+	JSObject*	js_scope=NULL;
 	JSObject*	argv;
 	jsuint		argc;
 	JSScript*	js_script;
 	js_branch_t	js_branch;
 	jsval		val;
 	jsval		rval=JSVAL_VOID;
+	private_t	priv;
 
 	ZERO_VAR(js_branch);
 
@@ -1638,43 +1654,92 @@ js_mailproc(SOCKET sock, client_t* client, user_t* user
 
 	*result = 0;
 	do {
+		if(*js_runtime==NULL) {
+			lprintf(LOG_DEBUG,"%04d %s JavaScript: Creating runtime: %lu bytes\n"
+				,sock, log_prefix, startup->js.max_bytes);
 
-		lprintf(LOG_DEBUG,"%04d JavaScript: Creating runtime: %lu bytes\n"
-			,sock, startup->js.max_bytes);
+			if((*js_runtime = jsrt_GetNew(startup->js.max_bytes, 1000, __FILE__, __LINE__))==NULL)
+				break;
+		}
 
-		if((js_runtime = jsrt_GetNew(startup->js.max_bytes, 1000, __FILE__, __LINE__))==NULL)
-			break;
+		if(*js_cx==NULL) {
+			lprintf(LOG_DEBUG,"%04d %s JavaScript: Initializing context (stack: %lu bytes)\n"
+				,sock, log_prefix, startup->js.cx_stack);
 
-		lprintf(LOG_DEBUG,"%04d JavaScript: Initializing context (stack: %lu bytes)\n"
-			,sock, startup->js.cx_stack);
+			if((*js_cx = JS_NewContext(*js_runtime, startup->js.cx_stack))==NULL)
+				break;
+		}
+		JS_BEGINREQUEST(*js_cx);
+
+		JS_SetErrorReporter(*js_cx, js_ErrorReporter);
+
+		priv.sock=sock;
+		priv.log_prefix=log_prefix;
+		priv.proc_name=mailproc->name;
+		JS_SetContextPrivate(*js_cx, &priv);
+
+		if(*js_glob==NULL) {
+			/* Global Objects (including system, js, client, Socket, MsgBase, File, User, etc. */
+			if((*js_glob=js_CreateCommonObjects(*js_cx, &scfg, &scfg, NULL
+						,uptime, startup->host_name, SOCKLIB_DESC	/* system */
+						,&js_branch									/* js */
+						,client, sock								/* client */
+						,&js_server_props							/* server */
+				))==NULL)
+				break;
 
-		if((js_cx = JS_NewContext(js_runtime, startup->js.cx_stack))==NULL)
-			break;
-		JS_BEGINREQUEST(js_cx);
+			if(!JS_DefineFunctions(*js_cx, *js_glob, js_global_functions))
+				break;
 
-		JS_SetErrorReporter(js_cx, js_ErrorReporter);
+			/* Area and "user" Objects */
+			if(!js_CreateUserObjects(*js_cx, *js_glob, &scfg, user, NULL, NULL)) 
+				break;
 
-		JS_SetContextPrivate(js_cx, &sock);
+			/* Mailproc "API" filenames */
+			JS_DefineProperty(*js_cx, *js_glob, "message_text_filename"
+				,STRING_TO_JSVAL(JS_NewStringCopyZ(*js_cx,msgtxt_fname))
+				,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
 
-		/* Global Objects (including system, js, client, Socket, MsgBase, File, User, etc. */
-		if((js_glob=js_CreateCommonObjects(js_cx, &scfg, &scfg, NULL
-					,uptime, startup->host_name, SOCKLIB_DESC	/* system */
-					,&js_branch									/* js */
-					,client, sock								/* client */
-					,&js_server_props							/* server */
-			))==NULL)
-			break;
+			JS_DefineProperty(*js_cx, *js_glob, "new_message_text_filename"
+				,STRING_TO_JSVAL(JS_NewStringCopyZ(*js_cx,newtxt_fname))
+				,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
 
-		if(!JS_DefineFunctions(js_cx, js_glob, js_global_functions))
-			break;
+			JS_DefineProperty(*js_cx, *js_glob, "log_text_filename"
+				,STRING_TO_JSVAL(JS_NewStringCopyZ(*js_cx,logtxt_fname))
+				,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+
+			JS_DefineProperty(*js_cx, *js_glob, "recipient_list_filename"
+				,STRING_TO_JSVAL(JS_NewStringCopyZ(*js_cx,rcptlst_fname))
+				,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+
+			JS_DefineProperty(*js_cx, *js_glob, "processing_error_filename"
+				,STRING_TO_JSVAL(JS_NewStringCopyZ(*js_cx,proc_err_fname))
+				,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+
+			JS_DefineProperty(*js_cx, *js_glob, "sender_name"
+				,STRING_TO_JSVAL(JS_NewStringCopyZ(*js_cx,sender))
+				,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+
+			JS_DefineProperty(*js_cx, *js_glob, "sender_address"
+				,STRING_TO_JSVAL(JS_NewStringCopyZ(*js_cx,sender_addr))
+				,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
 
-		/* Area and "user" Objects */
-		if(!js_CreateUserObjects(js_cx, js_glob, &scfg, user, NULL, NULL)) 
+			JS_DefineProperty(*js_cx, *js_glob, "reverse_path"
+				,STRING_TO_JSVAL(JS_NewStringCopyZ(*js_cx,reverse_path))
+				,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+
+			JS_DefineProperty(*js_cx, *js_glob, "hello_name"
+				,STRING_TO_JSVAL(JS_NewStringCopyZ(*js_cx,hello_name))
+				,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+
+		}
+
+		if((js_scope=JS_NewObject(*js_cx, NULL, NULL, *js_glob))==NULL)
 			break;
 
 		/* Convert command-line to argv/argc */
-		argv=JS_NewArrayObject(js_cx, 0, NULL);
-		JS_DefineProperty(js_cx, js_glob, "argv", OBJECT_TO_JSVAL(argv)
+		argv=JS_NewArrayObject(*js_cx, 0, NULL);
+		JS_DefineProperty(*js_cx, js_scope, "argv", OBJECT_TO_JSVAL(argv)
 			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
 
 		p=cmdline;
@@ -1683,82 +1748,61 @@ js_mailproc(SOCKET sock, client_t* client, user_t* user
 		for(argc=0;*p;argc++) {
 			SAFECOPY(arg,p);
 			truncstr(arg," \t");
-			val=STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,arg));
-			if(!JS_SetElement(js_cx, argv, argc, &val))
+			val=STRING_TO_JSVAL(JS_NewStringCopyZ(*js_cx,arg));
+			if(!JS_SetElement(*js_cx, argv, argc, &val))
 				break;
 			FIND_WHITESPACE(p);
 			SKIP_WHITESPACE(p);
 		}
-		JS_DefineProperty(js_cx, js_glob, "argc", INT_TO_JSVAL(argc)
+		JS_DefineProperty(*js_cx, js_scope, "argc", INT_TO_JSVAL(argc)
 			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
 
-		/* Mailproc "API" filenames */
-		JS_DefineProperty(js_cx, js_glob, "message_text_filename"
-			,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,msgtxt_fname))
-			,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
-
-		JS_DefineProperty(js_cx, js_glob, "new_message_text_filename"
-			,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,newtxt_fname))
-			,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
-
-		JS_DefineProperty(js_cx, js_glob, "log_text_filename"
-			,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,logtxt_fname))
-			,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
-
-		JS_DefineProperty(js_cx, js_glob, "recipient_list_filename"
-			,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,rcptlst_fname))
-			,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
-
-		JS_DefineProperty(js_cx, js_glob, "processing_error_filename"
-			,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,proc_err_fname))
-			,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
-
-		JS_DefineProperty(js_cx, js_glob, "sender_name"
-			,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,sender))
-			,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
-
-		JS_DefineProperty(js_cx, js_glob, "sender_address"
-			,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,sender_addr))
-			,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+		if(mailproc->eval!=NULL && *mailproc->eval!=0) {
+			lprintf(LOG_DEBUG,"%04d %s JavaScript: Evaluating: %s"
+				,sock, log_prefix, mailproc->eval);
+			js_script=JS_CompileScript(*js_cx, js_scope, mailproc->eval, strlen(mailproc->eval), NULL, 1);
+		} else {
+			lprintf(LOG_DEBUG,"%04d %s JavaScript: Executing: %s"
+				,sock, log_prefix, cmdline);
+			js_script=JS_CompileFile(*js_cx, js_scope, path);
+		}
+		if(js_script==NULL)
+			break;
 
-		JS_DefineProperty(js_cx, js_glob, "reverse_path"
-			,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,reverse_path))
-			,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+		success=JS_ExecuteScript(*js_cx, js_scope, js_script, &rval);
 
-		JS_DefineProperty(js_cx, js_glob, "hello_name"
-			,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,hello_name))
-			,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+		JS_ReportPendingException(*js_cx);
 
-		if(eval!=NULL && *eval!=0)
-			js_script=JS_CompileScript(js_cx, js_glob, eval, strlen(eval), NULL, 1);
-		else
-			js_script=JS_CompileFile(js_cx, js_glob, path);
-		if(js_script==NULL)
-			break;
+		js_EvalOnExit(*js_cx, js_scope, &js_branch);
 
-		success=JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
+		JS_GetProperty(*js_cx, *js_glob, "exit_code", &rval);
 
-		JS_ReportPendingException(js_cx);
+		JS_DestroyScript(*js_cx, js_script);
 
-		js_EvalOnExit(js_cx, js_glob, &js_branch);
+		JS_ClearScope(*js_cx, js_scope);
 
-		JS_GetProperty(js_cx, js_glob, "exit_code", &rval);
+		JS_GC(*js_cx);
 
 	} while(0);
 
-	if(js_cx!=NULL) {
+	if(*js_cx!=NULL) {
 
 		if(rval!=JSVAL_VOID && JSVAL_IS_NUMBER(rval))
-			JS_ValueToInt32(js_cx,rval,result);
+			JS_ValueToInt32(*js_cx,rval,result);
 
-		JS_ENDREQUEST(js_cx);
-		JS_DestroyContext(js_cx);
+		JS_ENDREQUEST(*js_cx);
 	}
-	if(js_runtime!=NULL)
-		jsrt_Release(js_runtime);
 
 	return(success);
 }
+
+js_cleanup(JSRuntime* js_runtime, JSContext* js_cx)
+{
+	if(js_cx!=NULL)
+		JS_DestroyContext(js_cx);
+	if(js_runtime!=NULL)
+		jsrt_Release(js_runtime);
+}
 #endif
 
 
@@ -2052,6 +2096,10 @@ static void smtp_thread(void* arg)
 	SOCKADDR_IN server_addr;
 	IN_ADDR		dnsbl_result;
 	BOOL*		mailproc_to_match;
+	JSRuntime*	js_runtime=NULL;
+	JSContext*	js_cx=NULL;
+	JSObject*	js_glob=NULL;
+
 	enum {
 			 SMTP_STATE_INITIAL
 			,SMTP_STATE_HELO
@@ -2383,10 +2431,12 @@ static void smtp_thread(void* arg)
 							,rcptlst_fname, proc_err_fname
 							,host_name, host_ip, relay_user.number
 							,sender, sender_addr, reverse_path, str);
-						lprintf(LOG_DEBUG,"%04d SMTP Executing external process: %s"
-							,socket, str);
+						lprintf(LOG_INFO,"%04d SMTP Executing external mail processor: %s"
+							,socket, mailproc_list[i].name);
 
 						if(mailproc_list[i].native) {
+							lprintf(LOG_DEBUG,"%04d SMTP Executing external command: %s"
+								,socket, str);
 							if((j=system(str))!=0) {
 								lprintf(LOG_NOTICE,"%04d !SMTP system(%s) returned %d (errno: %d)"
 									,socket, str, j, errno);
@@ -2397,11 +2447,14 @@ static void smtp_thread(void* arg)
 								}
 							}
 						} else {  /* JavaScript */
-							if(!js_mailproc(socket, &client, &relay_user, str /* cmdline */
-								,mailproc_list[i].eval
+							if(!js_mailproc(socket, &client, &relay_user
+								,&mailproc_list[i]
+								,str /* cmdline */
 								,msgtxt_fname, newtxt_fname, logtxt_fname
 								,rcptlst_fname, proc_err_fname
-								,sender, sender_addr, reverse_path, hello_name, &j) || j!=0) {
+								,sender, sender_addr, reverse_path, hello_name, &j
+								,&js_runtime, &js_cx, &js_glob
+								,"SMTP") || j!=0) {
 #if 0 /* calling exit() in a script causes js_mailproc to return FALSE */
 								lprintf(LOG_NOTICE,"%04d !SMTP JavaScript mailproc command (%s) failed (returned: %d)"
 									,socket, str, j);
@@ -2424,7 +2477,7 @@ static void smtp_thread(void* arg)
 							if(!fgets(str,sizeof(str),proc_err))
 								break;
 							truncsp(str);
-							lprintf(LOG_WARNING,"%04d !SMTP external process error: %s", socket, str);
+							lprintf(LOG_WARNING,"%04d !SMTP External mail processor error: %s", socket, str);
 							i=atoi(str);
 							if(i>=100 && i<1000)
 								sockprintf(socket,"%s", str);
@@ -2437,7 +2490,7 @@ static void smtp_thread(void* arg)
 						msg_handled=TRUE;
 					}
 					else if(!fexist(msgtxt_fname) || !fexist(rcptlst_fname)) {
-						lprintf(LOG_WARNING,"%04d SMTP External process removed %s file"
+						lprintf(LOG_NOTICE,"%04d SMTP External mail processor removed %s file"
 							,socket, fexist(msgtxt_fname)==FALSE ? "message text" : "recipient list");
 						sockprintf(socket,ok_rsp);
 						msg_handled=TRUE;
@@ -3549,6 +3602,7 @@ static void smtp_thread(void* arg)
 	remove(rcptlst_fname);
 	if(spy!=NULL)
 		fclose(spy);
+	js_cleanup(js_runtime, js_cx);
 
 	status(STATUS_WFC);
 
@@ -3602,7 +3656,7 @@ BOOL bounce(smb_t* smb, smbmsg_t* msg, char* err, BOOL immediate)
 		return(FALSE);
 	}
 
-	if(msg->from_agent!=AGENT_PERSON	/* don't bounce 'bounce messages' */
+	if(msg->from_agent==AGENT_SMTPSYSMSG	/* don't bounce 'bounce messages' */
 		|| (msg->idx.from==0 && msg->from_net.type==NET_NONE)
 		|| (msg->reverse_path!=NULL && *msg->reverse_path==0)) {
 		lprintf(LOG_WARNING,"0000 !Deleted undeliverable message from %s", msg->from);
@@ -3618,16 +3672,21 @@ BOOL bounce(smb_t* smb, smbmsg_t* msg, char* err, BOOL immediate)
 
 	SAFEPRINTF(str,"Delivery failure: %s",newmsg.subj);
 	smb_hfield_str(&newmsg, SUBJECT, str);
-	smb_hfield_str(&newmsg, RECIPIENT, newmsg.from);
-	if(newmsg.from_ext!=NULL) { /* Back to sender */
-		smb_hfield_str(&newmsg, RECIPIENTEXT, newmsg.from_ext);
-		newmsg.from_ext=NULL;	/* Clear the sender extension */
-	}
+	if(msg->from_agent==AGENT_PERSON) {
+
+		smb_hfield_str(&newmsg, RECIPIENT, newmsg.from);
+		if(newmsg.from_ext!=NULL) { /* Back to sender */
+			smb_hfield_str(&newmsg, RECIPIENTEXT, newmsg.from_ext);
+			newmsg.from_ext=NULL;	/* Clear the sender extension */
+		}
+
+		if((newmsg.from_net.type==NET_QWK || newmsg.from_net.type==NET_INTERNET)
+			&& newmsg.reverse_path!=NULL) {
+			smb_hfield(&newmsg, RECIPIENTNETTYPE, sizeof(newmsg.from_net.type), &newmsg.from_net.type);
+			smb_hfield_str(&newmsg, RECIPIENTNETADDR, newmsg.reverse_path);
+		}
+	} else {
 
-	if((newmsg.from_net.type==NET_QWK || newmsg.from_net.type==NET_INTERNET)
-		&& newmsg.reverse_path!=NULL) {
-		smb_hfield(&newmsg, RECIPIENTNETTYPE, sizeof(newmsg.from_net.type), &newmsg.from_net.type);
-		smb_hfield_str(&newmsg, RECIPIENTNETADDR, newmsg.reverse_path);
 	}
 	strcpy(str,"Mail Delivery Subsystem");
 	smb_hfield_str(&newmsg, SENDER, str);