diff --git a/exec/listserver.js b/exec/listserver.js
index 97049c1d47f168afb43156345883a625e37338dd..893ee70627be442345744cf638cab9e2b00b4c28 100644
--- a/exec/listserver.js
+++ b/exec/listserver.js
@@ -10,7 +10,7 @@ log(LOG_INFO,"Synchronet ListServer " + REVISION);
 
 js.auto_terminate=false;
 
-var ini_fname = system.ctrl_dir + "listserv.ini";
+var ini_fname = system.ctrl_dir + "listserver.ini";
 
 ini_file = new File(ini_fname);
 if(!ini_file.open("r")) {
@@ -18,6 +18,7 @@ if(!ini_file.open("r")) {
 		,ini_file.error, ini_fname));
 	exit();
 }
+name_list=ini_file.iniGetValue("config","names",new Array());
 list_array=ini_file.iniGetAllObjects("name","list:");
 ini_file.close();
 if(!list_array.length) {
@@ -25,7 +26,75 @@ if(!list_array.length) {
 	exit();
 }
 
-if(this.message_text_filename!=undefined) {	/* Subscription control */
+if(this.recipient_list_filename!=undefined) {	/* Subscription control */
+
+	var error_file = new File(processing_error_filename);
+	if(!error_file.open("w")) {
+		log(LOG_ERR,format("!ERROR %s opening processing error file: %s"
+			,error_file.error, processing_error_filename));
+		exit();
+	}
+
+	var rcptlst_file = new File(recipient_list_filename);
+	if(!rcptlst_file.open("r")) {
+		error_file.writeln(log(LOG_ERR,format("!ERROR %s opening recipient list: %s"
+			,rcptlst_file.error, recipient_list_filename)));
+		exit();
+	}
+	var rcpt_list=rcptlst_file.iniGetAllObjects("number");
+	rcptlst_file.close();
+
+	var msgtxt_file = new File(message_text_filename);
+	if(!msgtxt_file.open("r")) {
+		error_file.writeln(log(LOG_ERR,format("!ERROR %s opening recipient list: %s"
+			,msgtxt_file.error, message_text_filename)));
+		exit();
+	}
+
+	msgtxt = msgtxt_file.readAll()
+	msgtxt_file.close();
+
+	load("mailproc_util.js");	// import parse_msg_header() and get_msg_body()
+
+	var header = parse_msg_header(msgtxt);
+	var body = get_msg_body(msgtxt);
+
+	/* control message for list server? */
+	for(r=0;r<rcpt_list.length;r++) {
+		for(n=0;n<name_list.length;n++) {
+			if(rcpt_list[r].Recipient.search(new RegExp(name_list[n],"i"))!=-1)
+				break;
+		}
+		if(n<name_list.length)	/* match found */
+			break;
+	}
+	if(r<rcpt_list.length) { 
+
+		log(LOG_INFO,format("ListServer Control message from %s to %s: %s"
+			,header.from, header.to, header.subject));
+
+		process_control_msg(header, body); 
+
+		exit();
+	}
+
+	/* contribution to mailing list? */
+	var contribution=false;
+	for(r=0;r<rcpt_list.length;r++) {
+		for(l=0;l<list_array.length;l++) {
+			if(rcpt_list[r].Recipient.match(/(\S+)@/)[1].toLowerCase()==list_array[l].name
+				&& !list_array[l].disabled
+				&& !list_array[l].readonly)
+				break;
+		}
+		if(l<list_array.length) {	/* match found */
+			log(LOG_INFO,format("ListServer Contribution message from %s to %s: %s"
+				,header.from, rcpt_list[r].Recipient, header.subject));
+
+			if(!process_contribution(header, body, list_array[l]))
+				break;
+		}
+	}
 
 	exit();
 }
@@ -57,7 +126,7 @@ for(l in list_array) {
 	}
 
 	/* Get user (subscriber) list */
-	user_fname = msgbase.file + ".listserv.users";
+	user_fname = msgbase.file + ".list.users";
 	user_file = new File(user_fname);
 	if(!user_file.open("r")) {
 		log(LOG_ERR,format("%s !ERROR %s opening file: %s"
@@ -76,7 +145,7 @@ for(l in list_array) {
 ***/
 
 	/* Get export message pointer */
-	ptr_fname = msgbase.file + ".listserv.ptr";
+	ptr_fname = msgbase.file + ".list.ptr";
 	ptr_file = new File(ptr_fname);
 	if(!ptr_file.open("w+")) {
 		log(LOG_ERR,format("%s !ERROR %s opening/creating file: %s"
@@ -172,4 +241,39 @@ for(l in list_array) {
 }
 
 /* clean-up */
-mailbase.close();
\ No newline at end of file
+mailbase.close();
+
+/* End of Main */
+
+/* Handle Mailing List Control Messages (e.g. subscribe/unsubscribe) here */
+function process_control_msg(header, body)
+{
+}
+
+/* Handle Mailing List Contributions here */
+function process_contribution(header, body, list)
+{
+	// ToDo: apply filtering here?
+
+	var msgbase=new MsgBase(list.sub);
+
+	// ToDo: verify author/sender is a list subscriber here
+
+	if(!msgbase.open()) {
+		error_file.writeln(log(LOG_ERR,format("%s !ERROR %s opening msgbase: %s"
+			,list.name, msgbase.error, list.sub)));
+		return(false);
+	}
+
+	// ToDo: Split header.from into separate name/address fields here
+
+	header.id = header["message-id"]; // Convert to Synchronet-compatible
+
+	if(!msgbase.save_msg(header, body.join('\r\n'))) {
+		log(LOG_ERR,format("%s !ERROR %s saving message to sub: %s"
+			,list.name, msgbase.error, list.sub));
+		return(false);
+	}
+
+	return(true);
+}
\ No newline at end of file