changeset 47:72765b66e2c3

remove mailing list code
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 18 Jun 2021 17:44:24 -0600
parents 7ac7f55e16cf
children 8c39a2f1dc0c
files conf/Init.luan src/global/web/Index.java src/global/web/Index.jtp src/nabble/model/DailyNumber.java src/nabble/model/ListServer.java src/nabble/model/Lucene.java src/nabble/model/MailSubsystem.java src/nabble/model/MailingList.java src/nabble/model/MailingListImpl.java src/nabble/model/MailingLists.java src/nabble/model/Message.java src/nabble/model/MessageFormatImpls.java src/nabble/model/ModelHome.java src/nabble/model/Node.java src/nabble/model/NodeImpl.java src/nabble/model/NodeSearcher.java src/nabble/model/User.java src/nabble/model/UserImpl.java src/nabble/model/export/AbstractImportImpl.java src/nabble/model/export/Export.java src/nabble/model/export/Import.java src/nabble/model/export/ImportImpl.java src/nabble/model/export/NodeData.java src/nabble/modules/naml/expire_old_threads.naml src/nabble/modules/naml/invite_subscribers.naml src/nabble/modules/naml/mobile.naml src/nabble/modules/naml/ppc.naml src/nabble/view/lib/Jtp.java src/nabble/view/lib/MyJtpServlet.java src/nabble/view/lib/Shared.java src/nabble/view/lib/Shared.jtp src/nabble/view/lib/SubscribeDefaultsMail.java src/nabble/view/lib/SubscribeDefaultsMail.jtp src/nabble/view/lib/help/Help.java src/nabble/view/lib/help/Help.jmp src/nabble/view/naml/app.naml src/nabble/view/naml/compile_all.naml src/nabble/view/naml/create_sub_app.naml src/nabble/view/naml/delete_app.naml src/nabble/view/naml/dropdown.naml src/nabble/view/naml/edit_post.naml src/nabble/view/naml/email.naml src/nabble/view/naml/forgot_password.naml src/nabble/view/naml/mailing_list.naml src/nabble/view/naml/mailing_list_settings.naml src/nabble/view/naml/new_topic.naml src/nabble/view/naml/reply.naml src/nabble/view/naml/subscribe.naml src/nabble/view/naml/topic.naml src/nabble/view/naml/user_nodes.naml src/nabble/view/naml/user_profile.naml src/nabble/view/naml/utilities.naml src/nabble/view/web/app/Addons.java src/nabble/view/web/app/Addons.jtp src/nabble/view/web/help/Index.java src/nabble/view/web/help/Index.jtp src/nabble/view/web/mailing_list/MailingListNamespace.java src/nabble/view/web/mailing_list/MailingListOptions.java src/nabble/view/web/mailing_list/MailingListOptions.jtp src/nabble/view/web/mailing_list/Subscribe.java src/nabble/view/web/mailing_list/Subscribe.jtp src/nabble/view/web/mailing_list/Subscribe2.java src/nabble/view/web/mailing_list/Subscribe2.jtp src/nabble/view/web/mailing_list/SubscribeDefaults.java src/nabble/view/web/mailing_list/SubscribeDefaults.jtp src/nabble/view/web/mailing_list/SubscribeToMailingList.java src/nabble/view/web/mailing_list/SubscribeToMailingList.jtp src/nabble/view/web/mailing_list/Unsubscribe.java src/nabble/view/web/mailing_list/Unsubscribe.jtp src/nabble/view/web/mailing_list/Unsubscribe2.java src/nabble/view/web/mailing_list/Unsubscribe2.jtp src/nabble/view/web/mailing_list/UnsubscribeFromMailingList.java src/nabble/view/web/mailing_list/UnsubscribeFromMailingList.jtp src/nabble/view/web/more/Forum.java src/nabble/view/web/more/Forum.jtp src/nabble/view/web/more/ForumStart.java src/nabble/view/web/more/ForumStart.jtp src/nabble/view/web/more/MailingListRequest.java src/nabble/view/web/more/MailingListRequest.jtp src/nabble/view/web/template/CompileTest.java src/nabble/view/web/template/EmailNamespace.java src/nabble/view/web/template/NabbleNamespace.java src/nabble/view/web/template/NodeNamespace.java src/nabble/view/web/template/UserNamespace.java src/nabble/view/web/tools/SpamSearch.java src/nabble/view/web/tools/SpamSearch.jtp src/nabble/view/web/tools/UploadMbox.java src/nabble/view/web/tools/UploadMbox.jtp src/nabble/view/web/tools/UploadMbox2.java src/nabble/view/web/tools/UploadMbox2.jtp src/nabble/view/web/user/UserPendingNodes.java src/nabble/view/web/user/UserPendingNodes.jtp
diffstat 92 files changed, 107 insertions(+), 7790 deletions(-) [+]
line wrap: on
line diff
--- a/conf/Init.luan	Mon Jun 14 15:35:05 2021 -0600
+++ b/conf/Init.luan	Fri Jun 18 17:44:24 2021 -0600
@@ -37,35 +37,8 @@
 
 Init.defaultHost = "me.nabble.com:8080"
 Init.domain = Init.defaultHost
-Init.mailDomain = Init.defaultHost
 Init.nabbleHost = Init.defaultHost
-Init.mailDomain = "me.nabble.com"
-
-local popMailServer = "pop.fastmail.com"
-
-local function getPop3Server(addr, pwd)
-	local server = MailHome.getPop3Server(popMailServer, addr, pwd)
-	server.useSsl()
-	return server
-end
 
-local pop3 = {
---	lists = 'mailingListArchivePassword'
---	fwd = 'fwdPassword'
---	ml = 'subscriptionsPassword'
---	sb = 'subscriptionBouncesPasword'
-}
-
-local pop3Servers = {
-	lists = 'mailingListArchivePop3Server'
-	fwd = 'fwdPop3Server'
-	ml = 'subscriptionsPop3Server'
-	sb = 'subscriptionBouncesPop3Server'
-}
-
-for name, password in pairs(pop3) do
-	Init[pop3Servers[name]] = getPop3Server( name.."@"..Init.mailDomain, password )
-end
 
 --local HashSet = require "java:java.util.HashSet"
 --Init.sysadmins = HashSet.new {}  -- list of emails
--- a/src/global/web/Index.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/global/web/Index.java	Fri Jun 18 17:44:24 2021 -0600
@@ -6,7 +6,6 @@
 import global.HtmlGlobalUtils;
 import global.Site;
 import nabble.view.web.more.ForumStart;
-import nabble.view.web.more.MailingListRequest;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.TermQuery;
@@ -43,16 +42,13 @@
 
 		out.print( "\r\n<!DOCTYPE html>\r\n<html lang=\"en\">\r\n	<head>\r\n		" );
  HtmlGlobalUtils.head(request, response, "Free Forum &bull; Embeddable Web Apps"); 
-		out.print( "\r\n		<link rel=\"canonical\" href=\"https://www.nabble.com/\">\r\n		<meta name=\"description\" content=\"Create a free forum online in less than one minute. All forums are embeddable and fully customizable with scripting language. Choose a unique style and build a discussion board for your community.\" />\r\n		<meta name=\"keywords\" content=\"free forum, free mailing list, mailing list archive, free photo gallery, free newspaper, free blog, best forum, free message board, message board hosting, bulletin board, customizable, private forum, phpBB, vBulletin, hosted, communities\">\r\n		<meta name=\"google-site-verification\" content=\"SUurO4gVJ46SZyzANkH4pJBGH8q-6Bv5P-ZgRBH8Cck\" />\r\n		<style>\r\n			div[actions] i.fa.fa-chevron-right {\r\n				color: #DDD;\r\n				float: right;\r\n			}\r\n			a[fixed] {\r\n				margin-top: -3em;\r\n				position: absolute;\r\n				right: 1em;\r\n				text-decoration: none;\r\n				background-color: #555;\r\n				border-radius: .5em;\r\n				padding: .5em;\r\n				color: #D0D0D0;\r\n				text-shadow: 0px 1px 1px black;\r\n				border-bottom: 1px dotted #757474;\r\n			}\r\n			@media (max-width: 950px) {\r\n				div[footer] {\r\n					padding-bottom: 5em;\r\n				}\r\n			}\r\n			div[note] {\r\n				margin-top: 1em;\r\n				text-align: right;\r\n			}\r\n		</style>\r\n		<script async=\"true\" src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"></script>\r\n		<script>\r\n			 (adsbygoogle = window.adsbygoogle || []).push({\r\n				  google_ad_client: \"ca-pub-6750305871516672\",\r\n				  enable_page_level_ads: true\r\n			 });\r\n		</script>\r\n	</head>\r\n	<body lato>\r\n		" );
+		out.print( "\r\n		<link rel=\"canonical\" href=\"https://www.nabble.com/\">\r\n		<meta name=\"description\" content=\"Create a free forum online in less than one minute. All forums are embeddable and fully customizable with scripting language. Choose a unique style and build a discussion board for your community.\" />\r\n		<meta name=\"keywords\" content=\"free forum, free photo gallery, free newspaper, free blog, best forum, free message board, message board hosting, bulletin board, customizable, private forum, phpBB, vBulletin, hosted, communities\">\r\n		<meta name=\"google-site-verification\" content=\"SUurO4gVJ46SZyzANkH4pJBGH8q-6Bv5P-ZgRBH8Cck\" />\r\n		<style>\r\n			div[actions] i.fa.fa-chevron-right {\r\n				color: #DDD;\r\n				float: right;\r\n			}\r\n			a[fixed] {\r\n				margin-top: -3em;\r\n				position: absolute;\r\n				right: 1em;\r\n				text-decoration: none;\r\n				background-color: #555;\r\n				border-radius: .5em;\r\n				padding: .5em;\r\n				color: #D0D0D0;\r\n				text-shadow: 0px 1px 1px black;\r\n				border-bottom: 1px dotted #757474;\r\n			}\r\n			@media (max-width: 950px) {\r\n				div[footer] {\r\n					padding-bottom: 5em;\r\n				}\r\n			}\r\n			div[note] {\r\n				margin-top: 1em;\r\n				text-align: right;\r\n			}\r\n		</style>\r\n		<script async=\"true\" src=\"https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js\"></script>\r\n		<script>\r\n			 (adsbygoogle = window.adsbygoogle || []).push({\r\n				  google_ad_client: \"ca-pub-6750305871516672\",\r\n				  enable_page_level_ads: true\r\n			 });\r\n		</script>\r\n	</head>\r\n	<body lato>\r\n		" );
  HtmlGlobalUtils.header(request,response); 
 		out.print( "\r\n		<div full>\r\n			<div content center>\r\n			<span style=\"display:inline-block\">\r\n				<div col1 center>\r\n					<h1 oswald>Free Forum Hosting &amp; Online Web Apps!</h1>\r\n					<h2 lato gray>Clean Look <span light>&bull;</span> Embeddable <span light>&bull;</span> Customizable</h2>\r\n					<img src=\"/assets/images/home.png\" alt=\"Free forum hosting and online embeddable apps\"/>\r\n				</div>\r\n				<div col2 actions>\r\n					<ul>\r\n						<li><a href=\"" );
 		out.print( (HtmlGlobalUtils.nabbleContextUrl) );
 		out.print( (ForumStart.path("forum")) );
 		out.print( "\" title=\"Click to create a free forum\">Create Free Forum</a> <i class=\"fa fa-chevron-right\"></i></li>\r\n						<li><a href=\"" );
 		out.print( (HtmlGlobalUtils.nabbleContextUrl) );
-		out.print( (MailingListRequest.path()) );
-		out.print( "\" title=\"Click to archive a mailing list\">Archive Mailing List</a> <i class=\"fa fa-chevron-right\"></i></li>\r\n						<li><a href=\"" );
-		out.print( (HtmlGlobalUtils.nabbleContextUrl) );
 		out.print( (ForumStart.path("gallery")) );
 		out.print( "\" title=\"Click to create a free photo gallery\">Create Photo Gallery</a> <i class=\"fa fa-chevron-right\"></i></li>\r\n						<li><a href=\"" );
 		out.print( (HtmlGlobalUtils.nabbleContextUrl) );
--- a/src/global/web/Index.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/global/web/Index.jtp	Fri Jun 18 17:44:24 2021 -0600
@@ -6,7 +6,6 @@
 import global.HtmlGlobalUtils;
 import global.Site;
 import nabble.view.web.more.ForumStart;
-import nabble.view.web.more.MailingListRequest;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.TermQuery;
@@ -47,7 +46,7 @@
 		<% HtmlGlobalUtils.head(request, response, "Free Forum &bull; Embeddable Web Apps"); %>
 		<link rel="canonical" href="https://www.nabble.com/">
 		<meta name="description" content="Create a free forum online in less than one minute. All forums are embeddable and fully customizable with scripting language. Choose a unique style and build a discussion board for your community." />
-		<meta name="keywords" content="free forum, free mailing list, mailing list archive, free photo gallery, free newspaper, free blog, best forum, free message board, message board hosting, bulletin board, customizable, private forum, phpBB, vBulletin, hosted, communities">
+		<meta name="keywords" content="free forum, free photo gallery, free newspaper, free blog, best forum, free message board, message board hosting, bulletin board, customizable, private forum, phpBB, vBulletin, hosted, communities">
 		<meta name="google-site-verification" content="SUurO4gVJ46SZyzANkH4pJBGH8q-6Bv5P-ZgRBH8Cck" />
 		<style>
 			div[actions] i.fa.fa-chevron-right {
@@ -97,7 +96,6 @@
 				<div col2 actions>
 					<ul>
 						<li><a href="<%=HtmlGlobalUtils.nabbleContextUrl%><%=ForumStart.path("forum")%>" title="Click to create a free forum">Create Free Forum</a> <i class="fa fa-chevron-right"></i></li>
-						<li><a href="<%=HtmlGlobalUtils.nabbleContextUrl%><%=MailingListRequest.path()%>" title="Click to archive a mailing list">Archive Mailing List</a> <i class="fa fa-chevron-right"></i></li>
 						<li><a href="<%=HtmlGlobalUtils.nabbleContextUrl%><%=ForumStart.path("gallery")%>" title="Click to create a free photo gallery">Create Photo Gallery</a> <i class="fa fa-chevron-right"></i></li>
 						<li><a href="<%=HtmlGlobalUtils.nabbleContextUrl%><%=ForumStart.path("newspaper")%>" title="Click to create a free newspaper">Create News Site</a> <i class="fa fa-chevron-right"></i></li>
 						<li><a href="<%=HtmlGlobalUtils.nabbleContextUrl%><%=ForumStart.path("blog")%>" title="Click to create a free blog">Create Blog</a> <i class="fa fa-chevron-right"></i></li>
--- a/src/nabble/model/DailyNumber.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/DailyNumber.java	Fri Jun 18 17:44:24 2021 -0600
@@ -183,15 +183,10 @@
 						return;
 					}
 					NodeImpl post = node;
-					if( post.isFromMailingList() ) {
-						DailyNumber.externalPosts.inc();
-					} else {
-						DailyNumber.internalPosts.inc();
-						if( post.getAssociatedMailingList() == null )
-							DailyNumber.localForumPosts.inc();
-					}
+					DailyNumber.internalPosts.inc();
+					DailyNumber.localForumPosts.inc();
 					NodeImpl parent = post.getParentImpl();
-					if( parent != null && parent.getKind()==Node.Kind.POST && !parent.isFromMailingList() )
+					if( parent != null && parent.getKind()==Node.Kind.POST )
 						DailyNumber.replies.inc();
 
 					boolean isFirstPost = parent != null && parent.getKind()==Node.Kind.APP && parent.getDescendantCount() == 1;
--- a/src/nabble/model/ListServer.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,698 +0,0 @@
-package nabble.model;
-
-import fschmidt.util.mail.Mail;
-import fschmidt.util.mail.MailAddress;
-import fschmidt.util.mail.MailHome;
-import fschmidt.util.mail.PlainTextContent;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-
-public abstract class ListServer {
-
-	private final static Map<String, ListServer> servers = new HashMap<String, ListServer>();
-
-	public static ListServer getServer(String type) {
-		ListServer listServer = servers.get(type);
-		return listServer==null?unknown:listServer;
-	}
-
-	public static String[] getAllServerTypes() {
-		String[] s = servers.keySet().toArray(new String[servers.keySet().size()]);
-		Arrays.sort(s);
-		return s;
-	}
-
-	private String type;
-
-	private ListServer(String type) {
-		servers.put(type, this);
-		this.type = type;
-	}
-
-	public String getType() {
-		return type;
-	}
-
-	public String getViewName() {
-		return getType();
-	}
-
-	public abstract boolean supportsDeliveryOff();
-	public abstract boolean needsDefaults();
-	
-	abstract Mail defaultsMail(MailAddress emailAddress, String listAddress, String password);
-	abstract Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList);
-	abstract Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password);
-
-	public boolean canSubscribe() {
-		return true;
-	}
-
-	public boolean showInInitialSetup() {
-		return true;
-	}
-
-	String getEnvelopeFrom(Mail mail, MailingList mailingList) {
-		return mailingList.getSubscriberAddress().getAddrSpec();
-	}
-
-	protected Mail adminMail(MailAddress emailAddress, String adminAddress, String command) {
-		Mail mail = MailHome.newMail();
-		mail.setFrom(emailAddress);
-		mail.setTo(new MailAddress(adminAddress));
-		mail.setSentDate(new Date());
-		mail.setContent(new PlainTextContent(command));
-		return mail;
-	}
-
-	protected Mail subjectAdminMail(MailAddress emailAddress, String adminAddress, String subject) {
-		Mail mail = MailHome.newMail();
-		mail.setFrom(emailAddress);
-		mail.setTo(new MailAddress(adminAddress));
-		mail.setSentDate(new Date());
-		mail.setSubject(subject);
-		mail.setContent(new PlainTextContent(""));
-		return mail;
-	}
-
-	protected String listName(String listAddress) {
-		return listAddress.substring(0, listAddress.indexOf('@'));
-	}
-
-	protected String listDomain(String listAddress) {
-		return listAddress.substring(listAddress.indexOf('@')+1);
-	}
-
-	static abstract class Mailman extends ListServer {
-
-		protected Mailman(String type) {
-			super(type);
-		}
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return true;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			return adminMail(emailAddress, getAdminAddress(listAddress), "subscribe "+(password==null?"":password));
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			return adminMail(emailAddress, getAdminAddress(listAddress), "unsubscribe "+(password==null?"":password));
-		}
-
-		protected String getAdminAddress(String listAddress) {
-			return listAddress.replaceFirst("@", "-request@");
-		}
-	}
-
-	public static final ListServer mailman20 = new Mailman("mailman20") {
-
-		public String getViewName() {
-			return "Mailman 2.0.*";
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			StringBuilder buf = new StringBuilder();
-			buf.append("set ack off ");
-			buf.append(password);
-			buf.append("\n");
-			buf.append("set nomail on ");
-			buf.append(password);
-			buf.append("\n");
-			buf.append("set notmetoo on ");
-			buf.append(password);
-			buf.append("\n");
-			buf.append("end\n");
-			return adminMail(emailAddress, getAdminAddress(listAddress), buf.toString());
-		}
-
-	};
-
-	public static final ListServer mailman21 = new Mailman("mailman21") {
-
-		public String getViewName() {
-			return "Mailman 2.1.*";
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			StringBuilder buf = new StringBuilder();
-			buf.append("set authenticate ");
-			buf.append(password);
-			buf.append("\n");
-			buf.append("set delivery off\n");
-			buf.append("set ack off\n");
-			buf.append("set myposts off\n");
-			buf.append("set duplicates off\n");
-			buf.append("set reminders off\n");
-			buf.append("end\n");
-			return adminMail(emailAddress, getAdminAddress(listAddress), buf.toString());
-		}
-
-	};
-
-	public static final ListServer ezmlm = new ListServer("ezmlm") {
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return false;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			String suffix = useMainList?"-subscribe-":"-allow-subscribe-";
-			suffix += emailAddress.getAddrSpec().replace('@','=') + '@';
-			return adminMail(emailAddress, listAddress.replaceFirst("@", suffix), "");
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			String suffix = "-unsubscribe-" + emailAddress.getAddrSpec().replace('@','=') + '@';
-			return adminMail(emailAddress, listAddress.replaceFirst("@", suffix), "");
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			throw new UnsupportedOperationException();
-		}
-
-	};
-
-	public static final ListServer mlmmj = new ListServer("mlmmj") {
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return false;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			String suffix = useMainList?"+subscribe@":"+subscribe-nomail@";
-			return adminMail(emailAddress, listAddress.replaceFirst("@", suffix), "");
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			return adminMail(emailAddress, listAddress.replaceFirst("@", "+unsubscribe@"), "");
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			throw new UnsupportedOperationException();
-		}
-
-	};
-
-	public static final ListServer yahoo = new ListServer("yahoo") {
-
-		public String getViewName() {
-			return "Yahoo! Groups";
-		}
-
-		String getEnvelopeFrom(Mail mail, MailingList mailingList) {
-			//  for yahoogroups it should be the users address
-			return mail.getFrom().getAddrSpec();
-		}
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return true;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			return adminMail(emailAddress, listAddress.replaceFirst("@", "-subscribe@"), "");
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			return adminMail(emailAddress, listAddress.replaceFirst("@", "-unsubscribe@"), "");
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			return adminMail(emailAddress, listAddress.replaceFirst("@", "-nomail@"), "");
-		}
-
-	};
-
-	private abstract static class ListProc extends ListServer {
-
-		protected ListProc(String type) {
-			super(type);
-		}
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return true;
-		}
-
-		public boolean showInInitialSetup() {
-			return false;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			StringBuilder buf = new StringBuilder();
-			buf.append("subscribe ");
-			buf.append(listName(listAddress));
-			buf.append(" ");
-			buf.append(emailAddress.getDisplayName());
-			return adminMail(emailAddress, "listproc@"+listDomain(listAddress), buf.toString());
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			StringBuilder buf = new StringBuilder();
-			buf.append("unsubscribe ");
-			buf.append(listName(listAddress));
-			return adminMail(emailAddress, "listproc@"+listDomain(listAddress), buf.toString());
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			StringBuilder buf = new StringBuilder();
-			buf.append("set ");
-			buf.append(listName(listAddress));
-			buf.append(" mail postpone");
-			return adminMail(emailAddress, "listproc@"+listDomain(listAddress), buf.toString());
-		}
-
-	}
-
-	// cren listproc 
-	public final static ListServer listproc = new ListProc("listproc") {
-	};
-
-	// old listproc broken - uses smtp from only
-	public final static ListServer oldlistproc = new ListProc("oldlistproc") {
-		public boolean canSubscribe() {
-			return false;
-		}
-	};
-
-	// l-soft listserv
-	public static final ListServer listserv = new ListServer("listserv") {
-
-		public String getViewName() {
-			return "LISTSERV";
-		}
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return false;
-		}
-
-		public boolean showInInitialSetup() {
-			return false;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			StringBuilder buf = new StringBuilder();
-			buf.append("subscribe ");
-			buf.append(listName(listAddress));
-			buf.append(" ");
-			buf.append("anonymous");
-			if (!useMainList)
-				buf.append(" with noack nomail norepro");
-			return adminMail(emailAddress, "listserv@"+listDomain(listAddress), buf.toString());
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			StringBuilder buf = new StringBuilder();
-			buf.append("unsubscribe ");
-			buf.append(listName(listAddress));
-			return adminMail(emailAddress, "listserv@"+listDomain(listAddress), buf.toString());
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			throw new UnsupportedOperationException();
-		}
-
-	};
-
-	public static final ListServer lyris = new ListServer("lyris") {
-
-		public String getViewName() {
-			return "Lyris";
-		}
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return true;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			StringBuilder buf = new StringBuilder();
-			buf.append("join ");
-			buf.append(listName(listAddress));
-			buf.append(" ");
-			buf.append(emailAddress.getDisplayName());
-			return adminMail(emailAddress, "lyris@"+listDomain(listAddress), buf.toString());
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			StringBuilder buf = new StringBuilder();
-			buf.append("leave ");
-			buf.append(listName(listAddress));
-			return adminMail(emailAddress, "lyris@"+listDomain(listAddress), buf.toString());
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			StringBuilder buf = new StringBuilder();
-			buf.append("set ");
-			buf.append(listName(listAddress));
-			buf.append(" noack nomail norepro");
-			return adminMail(emailAddress, "lyris@"+listDomain(listAddress), buf.toString());
-		}
-
-	};
-
-	public static final ListServer listserver = new ListServer("listserver") {
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return true;
-		}
-
-		public boolean showInInitialSetup() {
-			return false;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			return adminMail(emailAddress, "listserver@"+listDomain(listAddress),
-					"subscribe "+listName(listAddress)
-					);
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			return adminMail(emailAddress, "listserver@"+listDomain(listAddress),
-					"unsubscribe "+listName(listAddress)
-					);
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			return adminMail(emailAddress, "listserver@"+listDomain(listAddress), "nomail "+listName(listAddress));
-		}
-
-	};
-
-	public static final ListServer communigate = new ListServer("communigate") {
-
-		public String getViewName() {
-			return "CommuniGate";
-		}
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return false;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			String suffix = useMainList?"-subscribe@":"-null@";
-			return adminMail(emailAddress, listAddress.replaceFirst("@", suffix), "");
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			return adminMail(emailAddress, listAddress.replaceFirst("@", "-unsubscribe@"), "");
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			throw new UnsupportedOperationException();
-		}
-
-	};
-
-	public static final ListServer smartlist = new ListServer("smartlist") {
-
-		public String getViewName() {
-			return "SmartList";
-		}
-
-		public boolean supportsDeliveryOff() {
-			return false;
-		}
-
-		public boolean needsDefaults() {
-			return false;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			return subjectAdminMail(emailAddress, listAddress.replaceFirst("@", "-request@"), "subscribe");
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			return subjectAdminMail(emailAddress, listAddress.replaceFirst("@", "-request@"), "unsubscribe");
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			throw new UnsupportedOperationException();
-		}
-
-	};
-
-	public static final ListServer ecartis = new ListServer("ecartis") {
-
-		public String getViewName() {
-			return "Ecartis";
-		}
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return true;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			return subjectAdminMail(emailAddress, "ecartis@"+listDomain(listAddress), "subscribe "+listName(listAddress));
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			return subjectAdminMail(emailAddress, "ecartis@"+listDomain(listAddress), "unsubscribe "+listName(listAddress));
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			return subjectAdminMail(emailAddress, "ecartis@"+listDomain(listAddress), "set "+listName(listAddress)+" vacation");
-		}
-
-	};
-
-	public static final ListServer majordomo = new ListServer("majordomo") {
-
-		public String getViewName() {
-			return "Majordomo";
-		}
-
-		public boolean supportsDeliveryOff() {
-			return false;
-		}
-
-		public boolean needsDefaults() {
-			return false;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			return adminMail(emailAddress, "majordomo@"+listDomain(listAddress), "subscribe "+listName(listAddress));
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			return adminMail(emailAddress, "majordomo@"+listDomain(listAddress), "unsubscribe "+listName(listAddress));
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			throw new UnsupportedOperationException();
-		}
-
-	};
-
-	public static final ListServer majordomo2 = new ListServer("majordomo2") {
-
-		public String getViewName() {
-			return "Majordomo 2";
-		}
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return false;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			return adminMail(emailAddress, "majordomo@"+listDomain(listAddress),
-					"subscribe-set-welcome "+listName(listAddress)+(useMainList?" ":" nomail,")+"noselfcopy,noackpost");
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			return adminMail(emailAddress, "majordomo@"+listDomain(listAddress), "unsubscribe "+listName(listAddress));
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			throw new UnsupportedOperationException();
-		}
-
-	};
-
-	public static final ListServer sympa = new ListServer("sympa") {
-
-		public String getViewName() {
-			return "Sympa";
-		}
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return true;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			StringBuilder buf = new StringBuilder();
-			buf.append("subscribe ");
-			buf.append(listName(listAddress));
-			buf.append(" ");
-			buf.append(emailAddress.getDisplayName());
-			return adminMail(emailAddress, "sympa@"+listDomain(listAddress), buf.toString());
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			StringBuilder buf = new StringBuilder();
-			buf.append("unsubscribe ");
-			buf.append(listName(listAddress));
-			return adminMail(emailAddress, "sympa@"+listDomain(listAddress), buf.toString());
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			String listname = listName(listAddress);
-			StringBuilder buf = new StringBuilder();
-			buf.append("set ");
-			buf.append(listname);
-			buf.append(" nomail\n");
-			buf.append("set ");
-			buf.append(listname);
-			buf.append(" not_me\n");
-			return adminMail(emailAddress, "sympa@"+listDomain(listAddress), buf.toString());
-		}
-
-	};
-
-	public static final ListServer google = new ListServer("google") {
-
-		public String getViewName() {
-			return "Google Groups";
-		}
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean needsDefaults() {
-			return true;
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			return adminMail(emailAddress, listAddress.replaceFirst("@", "+subscribe@"), "");
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			return adminMail(emailAddress, listAddress.replaceFirst("@", "+unsubscribe@"), "");
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			throw new UnsupportedOperationException(); // set nomail only via google website
-		}
-
-		public boolean canSubscribe() {
-			return true;
-		}
-
-	};
-
-	private static abstract class Unsupported extends ListServer {
-
-		protected Unsupported(String type) {
-			super(type);
-		}
-
-		public boolean needsDefaults() {
-			throw new UnsupportedOperationException();
-		}
-
-		Mail subscribeMail(MailAddress emailAddress, String listAddress, String password, boolean useMainList) {
-			throw new UnsupportedOperationException();
-		}
-
-		Mail unsubscribeMail(MailAddress emailAddress, String listAddress, String password) {
-			throw new UnsupportedOperationException();
-		}
-
-		Mail defaultsMail(MailAddress emailAddress, String listAddress, String password) {
-			throw new UnsupportedOperationException();
-		}
-
-		public boolean canSubscribe() {
-			return false;
-		}
-
-	}
-
-	public static final ListServer websitenomail = new Unsupported("websitenomail") {
-
-		public boolean supportsDeliveryOff() {
-			return true;
-		}
-
-		public boolean showInInitialSetup() {
-			return false;
-		}
-	};
-
-	public static final ListServer websitemail = new Unsupported("websitemail") {
-
-		public boolean supportsDeliveryOff() {
-			return false;
-		}
-
-		public boolean showInInitialSetup() {
-			return false;
-		}
-
-	};
-
-	public static final ListServer unknown = new Unsupported("unknown") {
-
-		public String getViewName() {
-			return "Unknown or Other";
-		}
-
-		public boolean supportsDeliveryOff() {
-			return false;
-		}
-
-	};
-
-}
--- a/src/nabble/model/Lucene.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/Lucene.java	Fri Jun 18 17:44:24 2021 -0600
@@ -80,7 +80,6 @@
 	static final String USER_ID_FLD = "userId";
 	static final String AUTHOR_FLD = "author";
 	static final String PRIVATE_NODE_FLD = "privateNode";
-	static final String MAILING_LIST_FLD = "mailingList";
 
 	static final Analyzer analyzer = new SnowballAnalyzer(Version.LUCENE_CURRENT,"English");
 
@@ -223,33 +222,6 @@
 				}
 			}
 		});
-		MailingListImpl.postDeleteListeners.add(new Listener<MailingListImpl>(){
-			public void event(MailingListImpl mailingList) {
-				update(mailingList.getForum());
-			}
-		});
-		MailingListImpl.postInsertListeners.add(new Listener<MailingListImpl>(){
-			public void event(final MailingListImpl mailingList) {
-				mailingList.siteKey.getDb().runAfterCommit(new Runnable(){public void run(){
-					update(mailingList.getForum());
-				}});
-			}
-		});
-		MailingListImpl.preUpdateListeners.add(new Listener<MailingListImpl>(){
-			public void event(MailingListImpl mailingList) {
-				Set fields = mailingList.getDbRecord().fields().keySet();
-				if( CollectionUtils.intersects(fields,mailingListDbFields) ) {
-					final long nodeId = mailingList.getForum().getId();
-					final SiteKey siteKey = mailingList.siteKey;
-					siteKey.getDb().runAfterCommit(new Runnable() {
-						public void run() {
-							NodeImpl node = NodeImpl.getNode(siteKey,nodeId);
-							update(node);
-						}
-					});
-				}
-			}
-		});
 	}
 
 	static void staleNode(NodeImpl node) throws IOException {
@@ -301,11 +273,6 @@
 		String author = owner.getName();
 		doc.add( new Field(AUTHOR_FLD, author, Field.Store.NO, Field.Index.ANALYZED) );
 		doc.add( new Field(PRIVATE_NODE_FLD, formatPrivateNode(node), Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS));
-		MailingList mailingList = node.getMailingList();
-		if (mailingList != null) { // only for forums
-			Field listAddrFld = new Field(MAILING_LIST_FLD, mailingList.getListAddress().toLowerCase(), Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS);
-			doc.add( listAddrFld );
-		}
 		for( DocumentListener documentListener : documentListeners ) {
 			documentListener.event(node,doc);
 		}
@@ -315,8 +282,6 @@
 	private static final String[] nodeDbFields =
 		{"subject", "when_created", "msg_fmt", "parent_id", "is_app", "owner_id", "cookie", "anonymous_name"};
 
-	private static final String[] mailingListDbFields = {"mailing_list"};
-
 
 	public static void updateRecursively(Node node) {
 		update(node);
--- a/src/nabble/model/MailSubsystem.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/MailSubsystem.java	Fri Jun 18 17:44:24 2021 -0600
@@ -20,42 +20,6 @@
 
 	private MailSubsystem() {}  // never
 
-	/**
-	 * Send an error message.
-	 *
-	 * @param mail      a mail caused a message, may be null
-	 * @param mailTo    sent error message to
-	 * @param subject   message subject
-	 * @param errorText error text
-	 */
-	static void sendErrorMail(Mail mail, MailAddress mailTo, String subject, String errorText) {
-		Mail errMail = MailHome.newMail();
-		errMail.setFrom(new MailAddress(ModelHome.noReply));
-		errMail.setTo(mailTo);
-		errMail.setSubject(subject);
-		errMail.setSentDate(new Date());
-		Content content = (mail != null) ?
-				new MixedMultipartContent(new Content[]{
-						new PlainTextContent(errorText),
-						mail,
-				}) :
-				new MixedMultipartContent(new Content[]{
-						new PlainTextContent(errorText)
-				});
-		errMail.setContent(content);
-		ModelHome.send(errMail);
-	}
-
-/*
-	static String stripBrackets(String s) {
-		if (s == null) return null;
-		int start = s.lastIndexOf('<');
-		int end = s.lastIndexOf('>');
-		if (start >= 0 && end > start)
-			s = s.substring(start + 1, end);
-		return s.trim();
-	}
-*/
 	static String stripBrackets(String s) {
 		int start = s.lastIndexOf('<');
 		int end = s.indexOf('>');
@@ -66,68 +30,9 @@
 		return s.substring(start + 1, end);
 	}
 
-	static List<String> stripMultiBrackets(final String s) {
-		List<String> list = new ArrayList<String>();
-		for( int i=0; i<s.length(); ) {
-			int start = s.indexOf('<',i);
-			int end = s.indexOf('>',i);
-			if( start == -1 && end == -1 )
-				break;
-			if( start == -1 || end < start )
-				throw new MailParseException("malformed brackets found in '"+s+"'");
-			list.add( s.substring(start + 1, end) );
-			i = end + 1;
-		}
-		return list;
-	}
-
-
-
-
-	/**
-	 * Prepare message headers for sending
-	 *
-	 * @param mail	   to prepare
-	 * @param node	   node to be sent
-	 */
-	static void setHeaders(Mail mail, NodeImpl node) {
-		mail.setSentDate(new Date());
-		mail.setMessageID("<" + node.getOrGenerateMessageID() + ">");
-		NodeImpl parent = node.getParentImpl();
-		if (parent != null && parent.getKind() != Node.Kind.APP) {
-			mail.setHeader("In-Reply-To", "<" + parent.getOrGenerateMessageID() + ">");
-			mail.setHeader("References", getReferences(parent, 0).trim());
-		}
-	}
-
-	private static final int MAX_REFERENCES = 10;
-
-	private static String getReferences(NodeImpl node, int count) {
-		return (node == null || node.getKind() == Node.Kind.APP || count==MAX_REFERENCES) ?
-				"" :
-				getReferences(node.getParentImpl(), count+1) + " <" + node.getOrGenerateMessageID() + ">";
-	}
-
-
 	static String getReturnPath(Mail mail) {
 		String[] a = mail.getHeader("Return-path");
 		return a==null ? null : MailSubsystem.stripBrackets(a[0]);
 	}
-
-	static void bounce(Mail mail,String msg) {
-		Mail bounce = MailHome.newMail();
-		bounce.setFrom( new MailAddress(ModelHome.noReply,"Nabble") );
-		bounce.setTo( new MailAddress(getReturnPath(mail)) );
-		bounce.setSubject( "Delivery Status Notification (Failure)" );
-		bounce.setHeader( "X-Failed-Recipients", mail.getHeader("Envelope-To") );
-		StringBuilder content = new StringBuilder();
-		content
-			.append( msg )
-			.append( "\n----- Original message -----\n\n" )
-			.append( mail.getRawInput() )
-		;
-		bounce.setContent(new PlainTextContent(content.toString()));
-		ModelHome.send(bounce);
-	}
 }
 
--- a/src/nabble/model/MailingList.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-package nabble.model;
-
-import fschmidt.util.mail.Mail;
-import fschmidt.util.mail.MailAddress;
-
-import java.io.File;
-
-public interface MailingList {
-	public Node getForum();
-	public String getListAddress();
-	public void setListAddress(String listAddress) throws ModelException.EmailFormat;
-	public String getUrl();
-	public long getId();
-	public void delete();
-	public void setUrl(String url) throws ModelException.UrlFormat;
-	public boolean ignoreNoArchive();
-	public void setIgnoreNoArchive(boolean ignoreNoArchive);
-	public boolean plainTextOnly();
-	public void setPlainTextOnly(boolean plainTextOnly);
-	public String getListName();
-	public void setListName(String listName);
-	public ListServer getListServer();
-	public void setListServer(ListServer listServer);
-	public void update();
-	public ImportResult importMbox(File file,String mailErrorsTo,int maxErrors) throws ModelException;
-	public MailAddress getSubscriberAddress();
-	public Node getNodeFromMessageID(String messageID);
-	public void subscribe();
-	public void unsubscribe();
-
-	public Mail subscribeMail();
-	public Mail subscribeMail(User user);
-	public Mail unsubscribeMail();
-	public Mail unsubscribeMail(User user);
-	public Mail defaultsMail(User user, String password);
-
-	// Email of the person who exported this mailing list to another server.
-	public String getExportOwner();
-	public void setExportOwner(String email) throws ModelException.EmailFormat;
-
-	public interface ImportResult {
-		public int getImported();
-		public int getErrors();
-	}
-
-	public String getPassword(User user);
-	public void rethread();
-}
--- a/src/nabble/model/MailingListImpl.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,504 +0,0 @@
-package nabble.model;
-
-import fschmidt.db.DbDatabase;
-import fschmidt.db.DbNull;
-import fschmidt.db.DbObject;
-import fschmidt.db.DbObjectFactory;
-import fschmidt.db.DbRecord;
-import fschmidt.db.DbTable;
-import fschmidt.db.DbUtils;
-import fschmidt.db.ListenerList;
-import fschmidt.db.LongKey;
-import fschmidt.util.java.Computable;
-import fschmidt.util.java.SimpleCache;
-import fschmidt.util.mail.Mail;
-import fschmidt.util.mail.MailAddress;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.sql.Connection;
-import java.sql.Statement;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Random;
-import java.util.WeakHashMap;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-
-public final class MailingListImpl implements MailingList, DbObject<LongKey, MailingListImpl> {
-	private static final Logger logger = LoggerFactory.getLogger(MailingListImpl.class);
-
-	final SiteKey siteKey;
-	private final DbRecord<LongKey, MailingListImpl> record;
-	private String listAddress;
-	private String listName;
-	private String url;
-	private String emailId;
-	private boolean ignoreNoArchive;
-	private boolean plainTextOnly;
-	private ListServer listServer;
-	private String exportOwner;
-
-	private NodeImpl forum;
-
-	private MailingListImpl(SiteKey siteKey,LongKey key, ResultSet rs)
-			throws SQLException
-	{
-		this.siteKey = siteKey;
-		record = table(siteKey).newRecord(this, key);
-		listAddress = rs.getString("list_address");
-		emailId = rs.getString("email_id");
-		listName = rs.getString("list_name");
-		url = rs.getString("list_home_url");
-		ignoreNoArchive = rs.getBoolean("ignore_no_archive");
-		plainTextOnly = rs.getBoolean("plain_text_only");
-		listServer = ListServer.getServer(rs.getString("list_server"));
-		exportOwner = rs.getString("export_owner");
-	}
-
-	MailingListImpl(NodeImpl forum, ListServer listServer, String listAddress, String url)
-		throws ModelException
-	{
-		this.siteKey = forum.siteKey;
-		record = table(siteKey).newRecord(this);
-		long id = forum.getId();
-		record.fields().put("node_id", id);
-		this.forum = forum;
-		setListServer(listServer);
-		setListAddress(listAddress);
-		setUrl(url);
-		record.insert();
-	}
-
-	public DbRecord<LongKey, MailingListImpl> getDbRecord() {
-		return record;
-	}
-
-	private DbTable<LongKey,MailingListImpl> table() {
-		return record.getDbTable();
-	}
-
-	private DbDatabase db() {
-		return table().getDbDatabase();
-	}
-
-	public long getId() {
-		return record.getPrimaryKey().value();
-	}
-
-	NodeImpl getForumImpl() {
-		if (DbUtils.isStale(forum)) {
-			forum = NodeImpl.getNode(siteKey,getId());
-		}
-		return forum;
-	}
-
-	public Node getForum() {
-		return getForumImpl();
-	}
-
-	public String getListAddress() {
-		return listAddress;
-	}
-
-	private static MailingListImpl getMailingList(SiteKey siteKey,long id) {
-		DbTable<LongKey,MailingListImpl> tbl = table(siteKey);
-		return tbl==null ? null : tbl.findByPrimaryKey(new LongKey(id));
-	}
-
-	public void delete() {
-		if (!db().isInTransaction()) {
-			db().beginTransaction();
-			try {
-				MailingListImpl mailingList = DbUtils.getGoodCopy(this);
-				mailingList.delete();
-				db().commitTransaction();
-			} finally {
-				db().endTransaction();
-			}
-			return;
-		}
-		record.delete();
-	}
-
-	static MailingListImpl getMailingListForForum(NodeImpl forum) {
-		MailingListImpl mailingList = table(forum.siteKey).findByPrimaryKey(new LongKey(forum.getId()));
-		if (mailingList != null) {
-			mailingList.forum = forum;
-		}
-		return mailingList;
-	}
-
-	private static class Lazy {
-		static final String emailPrefix;
-		static final String emailSuffix;
-		static final Pattern EMAIL_SUFFIXPATTERN;
-		static final Pattern pattern;
-		static {
-			String addrSpec = MailingLists.pop3Server.getUsername();
-			int ind = addrSpec.indexOf('@');
-			emailPrefix = addrSpec.substring(0, ind) + "+";
-			emailSuffix = addrSpec.substring(ind);
-			EMAIL_SUFFIXPATTERN = Pattern.compile(
-					Pattern.quote(emailPrefix) + "([^@]+)" + Pattern.quote(emailSuffix),
-					Pattern.CASE_INSENSITIVE);
-			pattern = Pattern.compile(
-					Pattern.quote(emailPrefix) + "s(\\d+)n(\\d+)h(\\d+)" + Pattern.quote(emailSuffix),
-					Pattern.CASE_INSENSITIVE);
-		}
-	}
-
-	static MailingListImpl getMailingListByEnvelopeAddress(String address) {
-		Matcher matcher = Lazy.pattern.matcher(address);
-		if( matcher.matches() ) {
-			long siteId = Long.valueOf(matcher.group(1));
-			SiteImpl site = SiteKey.getInstance(siteId).site();
-			if( site == null )
-				return null;
-			long nodeId = Long.valueOf(matcher.group(2));
-			NodeImpl node = site.getNodeImpl(nodeId);
-			if( node == null )
-				return null;
-			MailingListImpl ml = node.getMailingListImpl();
-			if( ml==null )
-				return null;
-			String hash = matcher.group(3);
-			if( !ml.generateHash().equals(hash) )
-				return null;
-			return ml;
-		}
-		matcher = Lazy.EMAIL_SUFFIXPATTERN.matcher(address);
-		if( matcher.matches() ) {
-			String emailId = matcher.group(1);
-			return getMailingListByOldEmailId(emailId);
-		}
-		return null;
-	}
-
-	private static MailingListImpl getMailingListByOldEmailId(String emailId) {
-		try {
-			Connection con = Db.dbGlobal().getConnection();
-			PreparedStatement stmt = con.prepareStatement(
-				"select * from mailing_list_lookup where email_id = ?"
-				, ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE
-			);
-			stmt.setString(1, emailId.trim().toLowerCase());
-			ResultSet rs = stmt.executeQuery();
-			try {
-				if( !rs.next() )
-					return null;
-				long siteId = rs.getLong("site_id");
-				long nodeId = rs.getLong("node_id");
-				SiteKey siteKey = SiteKey.getInstance(siteId);
-				MailingListImpl ml = getMailingList(siteKey,nodeId);
-				if( ml == null ) {
-					logger.error("couldn't find mailing list site="+siteId+" node="+nodeId);
-					rs.deleteRow();
-					return null;
-				}
-				return ml;
-			} finally {
-				rs.close();
-				stmt.close();
-				con.close();
-			}
-		} catch (SQLException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	public static int cleanMailingListLookup() {
-		List<String> emailIds = new ArrayList<String>();
-		try {
-			Connection con = Db.dbGlobal().getConnection();
-			Statement stmt = con.createStatement();
-			ResultSet rs = stmt.executeQuery(
-				"select email_id from mailing_list_lookup"
-			);
-			while( rs.next() ) {
-				String emailId = rs.getString("email_id");
-				emailIds.add(emailId);
-			}
-			rs.close();
-			stmt.close();
-			con.close();
-		} catch (SQLException e) {
-			throw new RuntimeException(e);
-		}
-		int count = 0;
-		for( String emailId : emailIds ) {
-			MailingList ml = getMailingListByOldEmailId(emailId);
-			if (ml == null)
-				count++;
-		}
-		return count;
-	}
-
-	public static List<MailingList> getOldMailingLists() {
-		List<String> emailIds = new ArrayList<String>();
-		try {
-			Connection con = Db.dbGlobal().getConnection();
-			Statement stmt = con.createStatement();
-			ResultSet rs = stmt.executeQuery(
-				"select email_id from mailing_list_lookup"
-			);
-			while( rs.next() ) {
-				String emailId = rs.getString("email_id");
-				emailIds.add(emailId);
-			}
-			rs.close();
-			stmt.close();
-			con.close();
-		} catch (SQLException e) {
-			throw new RuntimeException(e);
-		}
-		List<MailingList> list = new ArrayList<MailingList>();
-		for( String emailId : emailIds ) {
-			MailingList ml = getMailingListByOldEmailId(emailId);
-			if (ml != null)
-				list.add(ml);
-		}
-		return list;
-	}
-
-	private String generateHash() {
-		int h = 31*(int)getId();
-		return Integer.toString(Math.abs(h)%100);
-	}
-
-	public void setListAddress(String listAddress) throws ModelException.EmailFormat {
-		listAddress = listAddress.trim();
-		UserImpl.validateEmail(listAddress);
-		this.listAddress = listAddress;
-		record.fields().put("list_address", listAddress);
-	}
-
-	public String getListName() {
-		return listName;
-	}
-
-	public void setListName(String listName) {
-		if( listName != null ) {
-			listName = listName.trim();
-			if( listName.equals("") )
-				listName = null;
-		}
-		this.listName = listName;
-		record.fields().put("list_name", DbNull.fix(listName));
-	}
-
-	String fixSubject(String subject) {
-		if( listName != null && subject != null ) {
-			if( subject.startsWith(listName) )
-				return subject.substring(listName.length()).trim();
-			String lowerListName = listName.toLowerCase();
-			String lowerSubject = subject.toLowerCase();
-			if( lowerSubject.startsWith( "re: " + lowerListName + " re: " ) )
-				return subject.substring(listName.length()+5);
-			if( lowerSubject.startsWith( "re: " + lowerListName ) )
-				return subject.substring(0,4) + subject.substring(4+listName.length()).trim();
-		}
-		return subject;
-	}
-
-	public String getUrl() {
-		return url;
-	}
-
-	public void setUrl(String url) throws ModelException.UrlFormat {
-		url = url.trim();
-		validateUrl(url);
-		this.url = url;
-		record.fields().put("list_home_url", url);
-	}
-
-	static void validateUrl(String url) throws ModelException.UrlFormat {
-		try {
-			new URL(url);
-		} catch(MalformedURLException e) {
-			throw new ModelException.UrlFormat(url,e);
-		}
-	}
-
-	public boolean ignoreNoArchive() {
-		return ignoreNoArchive;
-	}
-
-	public void setIgnoreNoArchive(boolean ignoreNoArchive) {
-		this.ignoreNoArchive = ignoreNoArchive;
-		record.fields().put("ignore_no_archive", ignoreNoArchive);
-	}
-
-	public boolean plainTextOnly() {
-		return plainTextOnly;
-	}
-
-	public void setPlainTextOnly(boolean plainTextOnly) {
-		this.plainTextOnly = plainTextOnly;
-		record.fields().put("plain_text_only", plainTextOnly);
-	}
-
-	public ListServer getListServer() {
-		return listServer;
-	}
-
-	public void setListServer(ListServer listServer) {
-		this.listServer = listServer;
-		record.fields().put("list_server", listServer.getType());
-	}
-
-	public String getEmailId() {
-		return emailId;
-	}
-
-	public void setEmailId(String emailId) {
-		this.emailId = emailId;
-		record.fields().put("email_id", DbNull.fix(emailId));
-	}
-
-	public void update() {
-		record.update();
-	}
-
-	public boolean equals(Object obj) {
-		return obj instanceof MailingList && ((MailingList) obj).getId() == getId();
-	}
-
-	public int hashCode() {
-		return (int) getId();
-	}
-
-	public String toString() {
-		return "mailing_list-" + getId();
-	}
-
-	public ImportResult importMbox(File file, String mailErrorsTo, int maxErrors)
-		throws ModelException
-	{
-		ModelHome.beginImport();
-		try {
-			return MailingLists.importMbox(file, this, mailErrorsTo, maxErrors);
-		} finally {
-			ModelHome.endImport();
-		}
-	}
-
-	public MailAddress getSubscriberAddress() {
-		return new MailAddress( Lazy.emailPrefix
-			+ (emailId != null ? emailId
-				: "s" + siteKey.getId()
-				+ 'n' + getId()
-				+ 'h' + generateHash()
-			)
-		+ Lazy.emailSuffix );
-	}
-
-	public String getPassword(User user) {
-		Random r = new Random(getId() + user.getId());
-		long p = Math.round(r.nextDouble() * Math.pow(Character.MAX_RADIX, 8));
-		return Long.toString(p, Character.MAX_RADIX);
-	}
-
-	public String getExportOwner() {
-		return exportOwner;
-	}
-
-	public void setExportOwner(String email) throws ModelException.EmailFormat {
-		if( email != null ) {
-			email = email.trim();
-			UserImpl.validateEmail(email);
-		}
-		this.exportOwner = email;
-		record.fields().put("export_owner", DbNull.fix(this.exportOwner));
-	}
-
-	public Node getNodeFromMessageID(String messageID) {
-		return forum.getNodeImplFromMessageID(messageID);
-	}
-
-	public void subscribe() {
-		if (listServer.canSubscribe())
-			ModelHome.send(subscribeMail());
-	}
-
-	public void unsubscribe() {
-		if (listServer.canSubscribe())
-			ModelHome.send(unsubscribeMail());
-	}
-
-	public Mail subscribeMail() {
-		return listServer.subscribeMail(getSubscriberAddress(), getListAddress(), null, true);
-	}
-
-	public Mail subscribeMail(User user) {
-		MailAddress userAddress = new MailAddress(user.getEmail(), user.getName());
-		return listServer.subscribeMail(userAddress, getListAddress(), getPassword(user), false);
-	}
-
-	public Mail unsubscribeMail() {
-		return listServer.unsubscribeMail(getSubscriberAddress(), getListAddress(), null);
-	}
-
-	public Mail unsubscribeMail(User user) {
-		MailAddress userAddress = new MailAddress(user.getEmail(), user.getName());
-		return listServer.unsubscribeMail(userAddress, getListAddress(), null);
-	}
-
-	public Mail defaultsMail(User user, String password) {
-		MailAddress userAddress = new MailAddress(user.getEmail(), user.getName());
-		return listServer.defaultsMail(userAddress, getListAddress(), password);
-	}
-
-
-	static final ListenerList<MailingListImpl> preUpdateListeners = new ListenerList<MailingListImpl>();
-	static final ListenerList<MailingListImpl> postInsertListeners = new ListenerList<MailingListImpl>();
-	static final ListenerList<MailingListImpl> postUpdateListeners = new ListenerList<MailingListImpl>();
-	static final ListenerList<MailingListImpl> postDeleteListeners = new ListenerList<MailingListImpl>();
-
-	private static Computable<SiteKey,DbTable<LongKey,MailingListImpl>> tables = new SimpleCache<SiteKey,DbTable<LongKey,MailingListImpl>>(new WeakHashMap<SiteKey,DbTable<LongKey,MailingListImpl>>(), new Computable<SiteKey,DbTable<LongKey,MailingListImpl>>() {
-		public DbTable<LongKey,MailingListImpl> get(SiteKey siteKey) {
-			DbDatabase db;
-			try {
-				db = siteKey.getDb();
-			} catch(Db.NoSchema e) {
-				return null;
-			}
-			final long siteId = siteKey.getId();
-			DbTable<LongKey,MailingListImpl> table = db.newTable("mailing_list",db.newAssignedLongKeySetter("node_id")
-				, new DbObjectFactory<LongKey,MailingListImpl>() {
-					public MailingListImpl makeDbObject(LongKey key,ResultSet rs,String tableName)
-						throws SQLException
-					{
-						SiteKey siteKey = SiteKey.getInstance(siteId);
-						return new MailingListImpl(siteKey,key,rs);
-					}
-				}
-			);
-			table.getPreUpdateListeners().add(preUpdateListeners);
-			table.getPostInsertListeners().add(postInsertListeners);
-			table.getPostUpdateListeners().add(postUpdateListeners);
-			table.getPostDeleteListeners().add(postDeleteListeners);
-			return table;
-		}
-	});
-
-	private static DbTable<LongKey,MailingListImpl> table(SiteKey siteKey) {
-		return tables.get(siteKey);
-	}
-
-	public void rethread() {
-		try {
-			MailingLists.rethreadForum( getForumImpl(), false );
-		} catch(SQLException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-}
--- a/src/nabble/model/MailingLists.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1170 +0,0 @@
-package nabble.model;
-
-import fschmidt.db.DbDatabase;
-import fschmidt.db.DbNull;
-import fschmidt.util.java.DateUtils;
-import fschmidt.util.java.HtmlUtils;
-import fschmidt.util.mail.Mail;
-import fschmidt.util.mail.MailAddress;
-import fschmidt.util.mail.MailAddressException;
-import fschmidt.util.mail.MailEncodingException;
-import fschmidt.util.mail.MailException;
-import fschmidt.util.mail.MailHome;
-import fschmidt.util.mail.MailIterator;
-import fschmidt.util.mail.MailParseException;
-import fschmidt.util.mail.Pop3Server;
-import fschmidt.util.mail.javamail.MstorInServer;
-import nabble.model.lucene.HitCollector;
-import nabble.model.lucene.LuceneSearcher;
-import org.apache.lucene.document.Document;
-import org.apache.lucene.queryParser.ParseException;
-import org.apache.lucene.queryParser.QueryParser;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.Filter;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.util.Version;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.TimeZone;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.AddressException;
-
-
-final class MailingLists {
-	private static final Logger logger = LoggerFactory.getLogger(MailingLists.class);
-
-	private static final float nameChangeFreq = Init.get("mlNameChangeFreq",0.1f);
-	static final Pop3Server pop3Server = (Pop3Server)Init.get("mailingListArchivePop3Server");
-
-	private MailingLists() {}  // never
-
-	static {
-		if( Init.hasDaemons ) {
-			runMailingLists();
-		}
-	}
-
-	private static void runMailingLists() {
-		if( pop3Server == null ) {
-			logger.warn("no pop3 server defined, mailing lists not running");
-			return;
-		}
-		Executors.scheduleWithFixedDelay(new Runnable() {
-			public void run(){
-				try {
-					processMail();
-					processFwds();
-				} catch(MailException e) {
-					logger.error("mailing list processing",e);
-				}
-			}
-		}, 10, 10, TimeUnit.SECONDS );
-		logger.info("mailing lists enabled");
-	}
-
-	private static void processMail() {
-		MailIterator mails = pop3Server.getMail();
-		int count = 0;
-		try {
-			while( mails.hasNext() ) {
-				Mail mail = mails.next();
-				try {
-					makePost(mail);
-					count++;
-				} catch (MailAddressException e) {
-					logger.warn("mail:\n"+mail.getRawInput(),e);  // screwed-up mail
-				} catch (Exception e) {
-					logger.error("mail:\n"+mail.getRawInput(),e);
-				}
-			}
-		} finally {
-			mails.close();
-			if( count > 0 )
-				logger.error("Processed " + count + " emails.");
-		}
-	}
-
-	static MailingList.ImportResult importMbox(File file,MailingListImpl ml,String mailErrorsToS,int maxErrors)
-		throws ModelException
-	{
-		final DateFormat mailmanDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy");
-		final DateFormat mailDateFormat = new javax.mail.internet.MailDateFormat();
-		mailmanDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
-		mailDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
-		MailAddress mailErrorsTo = new MailAddress(mailErrorsToS);
-		MstorInServer server = new MstorInServer(file);
-		server.setMetaEnabled(false);
-		MailIterator mails = server.getMail();
-		try {
-			int imported = 0;
-			int errors = 0;
-			while( mails.hasNext() ) {
-				Mail mail = mails.next();
-				try {
-					try {
-						mail.getFrom();
-					} catch (MailAddressException e) {
-						String[] from = mail.getHeader("From");
-						if (from == null || from.length == 0)
-							throw new MailAddressException("'From' not found in the header", e);
-						mail.setHeader("From", from[0].replace(" at ", "@"));
-					}
-					Date sentDate = mail.getSentDate();
-					if ((sentDate==null || sentDate.getTime() < 0) && mail.getHeader("Date")!=null) {
-						String dateH = mail.getHeader("Date")[0];
-						if (dateH!=null) {
-							try {
-								sentDate = mailmanDateFormat.parse(dateH);
-							} catch (java.text.ParseException e) {}
-							if (sentDate!=null)
-								mail.setSentDate(sentDate);
-						}
-					}
-					if ((sentDate==null || sentDate.getTime() < 0) && mail.getHeader("Resent-date")!=null) {
-						String dateH = mail.getHeader("Resent-date")[0];
-						if (dateH!=null) {
-							try {
-								sentDate = mailDateFormat.parse(dateH);
-							} catch (java.text.ParseException e) {}
-							if (sentDate!=null)
-								mail.setSentDate(sentDate);
-						}
-					}
-					if ((sentDate==null || sentDate.getTime() < 0)) {
-						String rawInput = mail.getRawInput();
-						try {
-							String dateH = rawInput.substring(rawInput.indexOf(' ',5), rawInput.indexOf('\n')).trim();
-							sentDate = mailmanDateFormat.parse(dateH);
-						} catch (Exception e) {
-							logger.error("",e);  // what kind of exception is ok?
-						}
-						if (sentDate!=null)
-							mail.setSentDate(sentDate);
-					}
-					makeForumPost(mail,ml,true);
-					imported++;
-				} catch (Exception e) {
-					sendErrorMail(mail, e, mailErrorsTo);
-					errors++;
-					if( errors >= maxErrors )
-						throw ModelException.newInstance("import_mbox_errors",""+errors+" errors reached after importing "+imported+" messages");
-				}
-			}
-			final int imported2 = imported;
-			final int errors2 = errors;
-			return new MailingList.ImportResult() {
-				public int getImported() { return imported2; }
-				public int getErrors() { return errors2; }
-			};
-		} finally {
-			mails.close();
-		}
-	}
-
-	private static void makePost(Mail mail)
-		throws ModelException
-	{
-		MailingListImpl ml = getMailingList(mail);
-		if (ml == null) {
-			logger.info("Mailing list not found for: " + Arrays.asList(mail.getTo()));
-			return;
-		}
-		if (checkForward(mail, ml)) {
-			return;
-		}
-		if (checkPending(mail, ml)) {
-			return;
-		}
-		makeForumPost(mail, ml, false);
-	}
-
-	private static void makeForumPost(Mail mail, MailingListImpl ml, boolean isImport)
-		throws ModelException
-	{
-		String messageID = getMessageID(mail, msgFmt);
-		mail.setMessageID(messageID);
-
-		String message = mail.getRawInput();
-		message = message.replace("\000","");  // postgres can't handle 0
-		if( !msgFmt.isOk(message) )
-			return;
-		String text = msgFmt.getMailText(message,null);
-		NodeImpl forum = ml.getForumImpl();
-
-		if( doNotArchive(text) || (doNotArchive(mail) && !ml.ignoreNoArchive()) ) {
-			logger.info("XNoArchive in "+forum.getSubject());
-			return;
-		}
-
-		DbDatabase db;
-		try {
-			db = forum.siteKey.getDb();
-		} catch(UpdatingException e) {
-			return;  // hack for schema migration
-		}
-		db.beginTransaction();
-		try {
-			forum = (NodeImpl)forum.getGoodCopy();
-			MailingListImpl mailingList = forum.getMailingListImpl();
-
-			{
-				NodeImpl post = forum.getNodeImplFromMessageID(messageID);
-				if( post != null) {
-					if(isImport)
-						return;
-					throw new RuntimeException("MessageID "+messageID+" already in db for forum "+forum.getId());
-				}
-			}
-
-			UserImpl user = getUser(mail, mailingList);
-			if (user.isNoArchive())
-				return;
-
-			String subject = mailingList.fixSubject(mail.getSubject());
-			if( subject==null || subject.trim().equals("") )
-				subject = "(no subject)";
-
-			if (!isImport) {
-				ListServer oldListServer = mailingList.getListServer();
-				if (oldListServer==ListServer.unknown || oldListServer instanceof ListServer.Mailman) {
-					ListServer listServer = detectListServer(mail);
-					if (listServer!=null && listServer!=oldListServer && (oldListServer==ListServer.unknown || listServer==ListServer.mailman21)) {
-						mailingList.setListServer(listServer);
-						mailingList.update();
-					}
-				}
-			}
-
-			Date now = new Date();
-			Date date = mail.getSentDate();
-			if( date==null || date.compareTo(now) > 0 || date.getTime() < 0)
-				date = now;
-
-			boolean isGuessedParent = false;
-			String parentID = getParentID(mail, messageID);
-			NodeImpl parent = forum.getNodeImplFromMessageID(parentID);
-			if ( parent!=null && threadBySubject(forum, subject, parent.getSubject()) ) {
-				parent = null;
-			}
-
-			NodeImpl[] orphans = NodeImpl.getFromParentID(messageID,mailingList);
-			if ( parent==null ) {
-				try {
-					parent = guessParent(mail, date, mailingList, subject, orphans);
-					if ( parent != null )
-						isGuessedParent = true;
-				} catch(IOException e) {
-					logger.error("guessParent failed",e);
-				}
-			}
-
-			NodeImpl post = NodeImpl.newChildNode(Node.Kind.POST,user,subject,message,msgFmt,parent==null?forum:parent);
-			if( parent==null && parentID != null ) {
-				logger.debug("Orphan "+messageID+" starting new thread ");
-				isGuessedParent = true;
-			}
-
-			post.setWhenCreated(date);
-			post.setMessageID(messageID);
-			if (isGuessedParent) {
-				post.setGuessedParent(parentID);
-			} else if (parent==null) {
-				//  for root posts which do not have parentID set guess flag to uncertain
-				post.setGuessedParent((Boolean) null);
-			}
-			post.insert(false);
-			if( isGuessedParent && parentID==null )
-				logger.debug("no parentID for "+post);
-
-			for (NodeImpl orphan : orphans) {
-				try {
-					if (!threadBySubject(forum, subject, orphan.getSubject())) {
-						orphan.changeParentImpl(post);
-					}
-				} catch (ModelException.NodeLoop e) {
-					logger.error("", e); // should not happen now...
-					orphan.getDbRecord().fields().put("parent_message_id", DbNull.STRING);
-					orphan.getDbRecord().update();
-				}
-			}
-
-			db.commitTransaction();
-		} finally {
-			db.endTransaction();
-		}
-	}
-
-	private static boolean threadBySubject(Node forum, String subject, String parentSubject) {
-		if (!forumsThreadedBySubject.contains(forum.getId())) return false;
-		return ! normalizeSubject(subject).equals(normalizeSubject(parentSubject));
-	}
-
-	static final Set<Long> forumsThreadedBySubject = new HashSet<Long>(Arrays.asList((Long[])Init.get("forumsThreadedBySubject", new Long[0])));
-
-
-	private static void sendErrorMail(Mail mail, Exception e, MailAddress mailTo) {
-		if( e instanceof UnsupportedEncodingException
-			|| e instanceof MailAddressException
-			|| e instanceof MailEncodingException
-			|| e instanceof MailParseException
-		) {
-			logger.info(e.toString());
-		} else {
-			logger.error("",e);
-		}
-		StringWriter sb = new StringWriter();
-		PrintWriter out = new PrintWriter(sb);
-		e.printStackTrace( out );
-		out.close();
-		String msg = e.getMessage();
-		if (msg!=null && msg.indexOf('\n')>=0) msg = msg.substring(0, msg.indexOf('\n')).trim();
-		String subject = "error: "+msg;
-		MailSubsystem.sendErrorMail(mail, mailTo, subject, sb.toString());
-	}
-
-	private static String getParentID(Mail mail, String messageID) {
-		String[] inReplyTos = mail.getHeader("In-Reply-To");
-		if( inReplyTos == null ) {
-			inReplyTos = mail.getHeader("In-Reply-to");
-			if( inReplyTos != null )
-				logger.error("does this happen - case sensitive");
-		}
-		if( inReplyTos != null ) {
-			for (String inReplyTo : inReplyTos) {
-				for( String s : MailSubsystem.stripMultiBrackets(inReplyTo) ) {
-					if (!s.equals(messageID) && !s.equals("")) return s;
-				}
-			}
-		}
-		try {
-			String[] refs = mail.getHeader("References");
-			if( refs != null ) {
-				for (String ref : refs) {
-					List<String> list = MailSubsystem.stripMultiBrackets(ref);
-					if( list.isEmpty() )
-						continue;
-					String s = list.get(list.size()-1);
-					if (!s.equals(messageID) && !s.equals("")) return s;
-				}
-			}
-		} catch(MailParseException e) {
-			logger.warn("screwed up References for messageID="+messageID,e);
-		}
-		return null;
-	}
-
-	private static NodeImpl guessParent(Mail mail, Date date, MailingListImpl mailingList, String subject, NodeImpl[] orphans) throws IOException {
-		Set<NodeImpl> offspring = new HashSet<NodeImpl>();
-		for (NodeImpl orphan : orphans) {
-			for (NodeImpl n : orphan.getDescendantImpls()) {
-				offspring.add(n);
-			}
-		}
-		return guessParent(mail, date, mailingList, subject, offspring);
-	}
-
-	static NodeImpl guessParent(NodeImpl post, Collection<NodeImpl> ignore) {
-		Mail mail = MailHome.newMail(post.getMessage().getRaw());
-		NodeImpl forum = post.getAppImpl();
-		if (forum == null) {
-			return null;  //  detached post
-		}
-		MailingListImpl mailingList = forum.getAssociatedMailingListImpl();
-		if (mailingList == null) {
-			return null; // forum no longer a mailing list
-		}
-		try {
-			Set<NodeImpl> ignoreSet = new HashSet<NodeImpl>();
-			for( NodeImpl n : post.getDescendantImpls() ) {
-				ignoreSet.add(n);
-			}
-			if (ignore != null) {
-				ignoreSet.addAll(ignore);
-			}
-			return guessParent(mail, post.getWhenCreated(), mailingList, post.getSubject(), ignoreSet);
-		} catch (IOException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	private static NodeImpl guessParent(Mail mail, Date date, MailingListImpl mailingList, String subject, Set<NodeImpl> offspring)
-		throws IOException {
-		// attach to ancestor if any
-		NodeImpl forum = mailingList.getForumImpl();
-		try {
-			String[] refs = mail.getHeader("References");
-			if( refs != null ) {
-				for( String ref : refs ) {
-					final List<String> list = MailSubsystem.stripMultiBrackets(ref);
-					for( int i=list.size()-1; i>=0; i-- ) {
-						String ancestorID = list.get(i);
-						NodeImpl parent = forum.getNodeImplFromMessageID(ancestorID);
-						if (parent!=null && !offspring.contains(parent) && !threadBySubject(forum,subject,parent.getSubject())) {
-							logger.debug("Attaching orphan "+mail.getMessageID()+" to grandparent "+parent);
-							return parent;
-						}
-					}
-				}
-			}
-		} catch(MailParseException e) {
-			logger.warn("screwed up References",e);
-		}
-		// handle lost In-Reply-To headers
-		// heuristics - use Thread-Topic header to find matching subjects in last 3 days
-		String[] threadTopics = mail.getHeader("Thread-Topic");
-		String threadTopic = threadTopics==null?null:mailingList.fixSubject(threadTopics[0]);
-		long forumId = forum.getId();
-		Filter filter = Lucene.getRangeFilter(DateUtils.addDays(date, -7), date);
-		SiteImpl site = forum.getSiteImpl();
-		LuceneSearcher searcher = Lucene.newSearcher(site);
-		try {
-			if( threadTopic != null ) {
-				threadTopic = threadTopic.toLowerCase();
-				if (threadTopic.startsWith("re: "))
-					threadTopic = threadTopic.substring(4);
-				threadTopic = threadTopic.trim();
-				if (!threadTopic.equals("")) {
-					NodeImpl parent = (NodeImpl)getPriorPost(site,searcher, forumId, threadTopic, filter, date, offspring);
-					if( parent!=null && !offspring.contains(parent) && !threadBySubject(forum,subject,parent.getSubject())) return parent;
-				}
-			}
-			// if no thread-topic, but subject starts with Re:, try with subject
-			subject = subject.toLowerCase();
-			if( subject.startsWith("re: ") ) {
-				subject = subject.substring(4).trim();
-				if ( !subject.equals(threadTopic) && !"".equals(subject) ) {
-					NodeImpl parent = (NodeImpl)getPriorPost(site,searcher, forumId, subject, filter, date, offspring);
-					if( parent!=null && !offspring.contains(parent)) return parent;
-				}
-			}
-		} finally {
-			searcher.close();
-		}
-		return null;
-	}
-
-	private static boolean checkPending(Mail mail, MailingListImpl ml) {
-		if (checkPending(getMessageID(mail, msgFmt), ml)) {
-			return true;
-		}
-		String[] xMessageId = mail.getHeader("X-Message-Id");
-		if (xMessageId != null && xMessageId.length > 0 && checkPending(MailSubsystem.stripBrackets(xMessageId[0]), ml)) {
-			return true;
-		}
-		xMessageId = mail.getHeader("X-Original-Message-Id");
-		if (xMessageId != null && xMessageId.length > 0 && checkPending(MailSubsystem.stripBrackets(xMessageId[0]), ml)) {
-			return true;
-		}
-		return false;
-	}
-
-	private static boolean checkPending(String messageID, MailingListImpl ml) {
-		NodeImpl pendingPost = ml.getForumImpl().getNodeImplFromMessageID(messageID);
-		if( pendingPost==null )
-			return false;
-		Node.MailToList mail = pendingPost.getMailToList();
-		if( mail == null ) {
-			logger.warn("MessageID "+messageID+" already in db as "+pendingPost+" for forum "+ml.getId());
-		} else if( !mail.isPending() ) {
-			logger.error("post not pending "+pendingPost);
-		} else {
-			mail.clearPending();
-		}
-		return true;
-	}
-
-	private static boolean doNotArchive(Mail mail) {
-		String[] xNoArchive = mail.getHeader("X-No-Archive");
-		if (xNoArchive != null && xNoArchive.length > 0 && "yes".equalsIgnoreCase(xNoArchive[0])) {
-			return true;
-		}
-		String[] xArchive = mail.getHeader("X-Archive");
-		if (xArchive != null && xArchive.length > 0 && xArchive[0] != null && (xArchive[0].startsWith("expiry") || "no".equalsIgnoreCase(xArchive[0]))) {
-			return true;
-		}
-		String[] archive = mail.getHeader("Archive");
-		if (archive != null && archive.length > 0 && "no".equalsIgnoreCase(archive[0])) {
-			return true;
-		}
-		return false;
-	}
-
-	private static final Pattern xNoArchivePtn = Pattern.compile("(?im)\\AX-No-Archive: yes *$");
-	private static boolean doNotArchive(String text) {
-		return xNoArchivePtn.matcher(text).find();
-	}
-
-	private static MailingListImpl getMailingList(Mail mail) {
-		MailingListImpl ml = null;
-		String[] a = mail.getHeader("Envelope-To");
-		if (a == null)
-			a = mail.getHeader("X-Delivered-to"); // fastmail
-		if (a == null)
-			a = mail.getHeader("X-Original-To"); // postfix
-		if( a.length > 1 )
-			a = new String[] { a[0] };
-		for( String address : a[0].split(",") ) {
-			address = address.trim();
-			MailingListImpl candidate = MailingListImpl.getMailingListByEnvelopeAddress(address);
-			if (candidate == null) {
-				//  escaped list mail, bounce mail
-				String returnPath = MailSubsystem.getReturnPath(mail);
-				if( returnPath.equals(address) )
-					continue;  // ignore spam
-				MailSubsystem.bounce(mail,
-					"Delivery to the following recipient failed permanently:\n\n    "
-					+ address
-					+ "\n\nNo archive exists for this address.\n"
-				);
-				logger.warn( "no mailing list found for "+address+" - bouncing mail to "+returnPath + ":\n" + mail);
-			} else {
-				if( ml != null )
-					logger.error("mailing list already set");
-				ml = candidate;
-			}
-		}
-		return ml;
-	}
-
-	private static String extractDomain(String email) {
-		String domain = email.substring(email.indexOf('@')+1).toLowerCase();
-		// hack to unify google messages
-		return domain.replace("google.com","googlegroups.com");
-	}
-
-	private static boolean checkForward(Mail mail, MailingListImpl ml) {
-		//  check if the archive guessed from subscription address is not presented in the
-		//    common headers that contain list address, forward to the archive owner in this case
-		String envTo[] = mail.getHeader("Envelope-To");
-		if (envTo == null)
-			envTo = mail.getHeader("X-Delivered-to"); // fastmail
-		if (envTo == null)
-			envTo = mail.getHeader("X-Original-To"); // postfix
-		String originalTo = envTo[0];
-		{
-			MailAddress[] to = mail.getTo();
-			if( to==null || to.length!=1 || !to[0].getAddrSpec().equalsIgnoreCase(originalTo) )
-				return false;
-		}
-		//  check for domain of the message's From: or Reply-To:
-		String listAddress = ml.getListAddress();
-		String domain = extractDomain(listAddress);
-		String maintenanceMessageReplyTo = null;
-		{
-			MailAddress[] replyTos = mail.getReplyTo();
-			if (replyTos != null) {
-				for (MailAddress replyTo : replyTos) {
-					String replyDomain = extractDomain(replyTo.getAddrSpec());
-					if (replyDomain.endsWith(domain) || domain.endsWith(replyDomain)) {
-						maintenanceMessageReplyTo = replyTo.getAddrSpec();
-						break;
-					}
-				}
-			}
-		}
-		MailAddress from = mail.getFrom();
-		// first we compare the domains
-		if( maintenanceMessageReplyTo == null && from != null && (extractDomain(from.getAddrSpec()).endsWith(domain) || domain.endsWith(extractDomain(from.getAddrSpec()))))
-			maintenanceMessageReplyTo = from.getAddrSpec();
-		// check if this is a majordomo email
-		if (maintenanceMessageReplyTo == null && from != null && from.getAddrSpec().toLowerCase().startsWith("majordomo@"))
-			maintenanceMessageReplyTo = from.getAddrSpec();
-
-		if( maintenanceMessageReplyTo != null ) {
-			mail.setReplyTo( new MailAddress(fwdEmail(originalTo, maintenanceMessageReplyTo) ));
-			MailAddress ownerAddress = getArchiveOwnerAddress(ml);
-			MailHome.getDefaultSmtpServer().send(mail,ownerAddress);
-			logger.info("Forwarding maintenance message to owner: " + ownerAddress);
-			logger.info(mail.getRawInput());
-			return true;
-		}
-		if( MailSubsystem.getReturnPath(mail).equals("") ) {
-			MailAddress ownerAddress = getArchiveOwnerAddress(ml);
-			MailHome.getDefaultSmtpServer().send(mail,ownerAddress);
-			logger.info("Forwarding maintenance message to owner: " + ownerAddress);
-			logger.info(mail.getRawInput());
-			return true;
-		}
-		logger.info("Bouncing email to: " + MailSubsystem.getReturnPath(mail) + " / envelopeTo = " + originalTo + "\n" + mail.getRawInput());
-		MailSubsystem.bounce(mail,
-			"Delivery to the following recipient failed permanently:\n\n    "
-			+ originalTo
-			+ "\n\nThis email address is only for archiving mailing lists and should not be used directly.\n"
-		);
-		return true;
-	}
-
-	private static MailAddress getArchiveOwnerAddress(MailingListImpl mailingList) {
-		// If this list was exported to another server, we have to send this email
-		// to the person that did the export. Otherwise we send to the current owner.
-		String exportOwner = mailingList.getExportOwner();
-		if (exportOwner == null) {
-			// Send to the current owner...
-			User owner = mailingList.getForumImpl().getOwnerImpl();
-			return new MailAddress(owner.getEmail(), owner.getName());
-		} else {
-			// Send to the person who exported the archive...
-			return new MailAddress(exportOwner);
-		}
-	}
-
-	private static MailAddress toMailAddress(String s) {
-		try {
-			InternetAddress ia = new InternetAddress(s);
-			return new MailAddress(ia.getAddress(),ia.getPersonal());
-		} catch(AddressException e) {
-			return null;
-		}
-	}
-
-	private static UserImpl getUser(Mail mail, MailingListImpl mailingList) {
-		MailAddress addr = null;
-		String a[] = mail.getHeader("X-Original-From");
-		if( a != null )
-			addr = toMailAddress(a[0]);
-		if( addr == null )
-			addr = mail.getFrom();
-		String email = addr.getAddrSpec();
-		if (email == null || "".equals(email.trim()))
-		{
-			throw new MailAddressException("Invalid sender address: "+addr);
-		}
-		SiteImpl site = mailingList.getForumImpl().getSiteImpl();
-		UserImpl user = site.getUserImplFromEmail(email);
-		if( user==null || !user.isRegistered() ) {
-			String username;
-			if( email.equalsIgnoreCase(mailingList.getListAddress()) ) {
-				username = mailingList.getForum().getSubject() + " mailing list";
-			} else {
-				username = addr.getDisplayName();
-				if( username == null || "".equals(username.trim()) ) {
-					username = email.indexOf('@')>0 ? email.substring(0, email.indexOf('@')) : email;
-				}
-			}
-			if( username.endsWith(" (JIRA)") ) {
-				username = "JIRA "+email;
-			}
-			if( user==null ) {
-				user = UserImpl.createGhost(site,email);
-				user.setNameLike(username,false);
-				user.insert();
-			} else {
-				String oldName = user.getName();
-				if( !oldName.toLowerCase().startsWith(username.toLowerCase())
-					&& (Math.random() < nameChangeFreq)
-				) {
-					user.setNameLike(username,false);
-					user.getDbRecord().update();
-					logger.warn("changed name of "+user+" from '"+oldName+"' to '"+user.getName()+"'");
-				}
-			}
-		}
-		return user;
-	}
-
-	static final MailMessageFormat msgFmt = new MailMessageFormat('m', "mail");
-
-	private static Node getPriorPost(final SiteImpl site,final LuceneSearcher searcher, long forumId, final String subject, Filter filter, final Date to, final Set offspring) throws IOException {
-		//String phrase = "\""+QueryParser.escape(subject.replace('\"',' '))+"\"";
-		try {
-			NodeSearcher.Builder query = new NodeSearcher.Builder(site,forumId);
-			query.addNodeKind(Node.Kind.POST);
-			QueryParser parser = new QueryParser(Version.LUCENE_CURRENT,Lucene.SUBJECT_FLD, Lucene.analyzer);
-			parser.setDefaultOperator(QueryParser.AND_OPERATOR);
-			Query subjectQuery = parser.parse(QueryParser.escape(subject.replace('\"',' ').replace("&&"," ")));
-			if (! (subjectQuery instanceof BooleanQuery && ((BooleanQuery)subjectQuery).getClauses().length==0) )
-				query.addQuery(subjectQuery);
-			final Node[] resultHolder = new Node[1];
-			searcher.search( query.build().getQuery(), filter, new HitCollector() {
-				protected void process(Document doc) {
-					NodeImpl post = Lucene.node(site,doc);
-					if (post==null)
-						return;
-					String parentSubject = post.getSubject().toLowerCase();
-					if ( (parentSubject.equals(subject) || (parentSubject.startsWith("re: ") && parentSubject.substring(4).trim().equals(subject)))
-							&& to.after(post.getWhenCreated())
-							&& (resultHolder[0]==null || resultHolder[0].getWhenCreated().before(post.getWhenCreated()))
-							&& !offspring.contains(post)
-					)
-						resultHolder[0] = post;
-				}
-			});
-			Node result = resultHolder[0];
-
-			if (result != null) {
-				//  find the uppermost post with almost-the-same subject
-				String subjectEtalon = normalizeSubject(subject.toLowerCase());
-				Node resultCandidate = result.getTopic();
-				while (result != null) {
-					String resultSubject = normalizeSubject(result.getSubject().toLowerCase());
-					if (!resultSubject.equals(subjectEtalon)) break; //  break when subject really changes
-
-					//  this post has almost-the-same subject
-					if (!offspring.contains(result)) {
-						//  set only if this node is not presented in escape-set
-						resultCandidate = result;
-					}
-					result = result.getParent();
-				}
-				result = resultCandidate;
-			}
-			return result;
-		} catch (ParseException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	private static final Pattern bracketRegex = Pattern.compile("\\[[^\\[]+\\]");
-
-	static Pattern prefixRegex(String prefixes) {
-		return Pattern.compile( "^((" + prefixes + "): *)+" );
-	}
-
-	private static final Pattern defaultPrefixRegex = prefixRegex("re|aw|res|fwd|答复");
-
-	/**
-	 * Remove from subject all possible prefixes which are added while forwarding, replying, etc...
-	 *
-	 * @param subject original subject
-	 * @return normalized subject
-	 */
-	private static String normalizeSubject(String subject) {
-		return normalizeSubject(subject,defaultPrefixRegex);
-	}
-
-	static String normalizeSubject(String subject,Pattern prefixRegex) {
-		if (subject != null) {
-			subject = subject.toLowerCase().trim();
-			subject = bracketRegex.matcher(subject).replaceAll("");
-			subject = prefixRegex.matcher(subject).replaceAll("");
-		}
-		return subject;
-	}
-
-	static void nop() {}
-
-
-	private static ListServer detectListServer(Mail mail) {
-		String[] mailman = mail.getHeader("X-Mailman-Version");
-		if (mailman!=null && mailman.length==1 && mailman[0]!=null) {
-			if (mailman[0].startsWith("2.0")) {
-				return ListServer.mailman20;
-			} else if (mailman[0].startsWith("2.1")) {
-				return ListServer.mailman21;
-			} else if (mailman[0].startsWith("2.")) {
-				logger.error("unknown mailman version: "+mailman[0]+" in message "+mail.getMessageID());
-			}
-			return null;
-		}
-
-		String[] mList = mail.getHeader("Mailing-List");
-		if (mList!=null && mList.length==1 && mList[0]!=null) {
-			if (mList[0].indexOf("run by ezmlm")>=0) {
-				return ListServer.ezmlm;
-			} else if (mList[0].indexOf("@yahoogr")>0 || mList[0].indexOf("@gruposyahoo")>0) {
-				return ListServer.yahoo;
-			} else if (mList[0].indexOf("@googlegroups")>0) {
-				return ListServer.google;
-			}
-		}
-
-		String[] listproc = mail.getHeader("X-Listprocessor-Version");
-		if (listproc!=null && listproc.length==1 && listproc[0]!=null) {
-			if (listproc[0].indexOf("ListProc")>=0) {
-				if (listproc[0].indexOf("CREN")>=0) {
-					return ListServer.listproc;
-				} else {
-					return ListServer.oldlistproc;
-				}
-			} else {
-				logger.error("unknown listproc version: "+listproc[0]+" in message "+mail.getMessageID());
-				return null;
-			}
-		}
-
-		String[] ecartis = mail.getHeader("X-ecartis-version");
-		if (ecartis!=null && ecartis.length==1 && ecartis[0]!=null) {
-			if (ecartis[0].indexOf("Ecartis")>=0) {
-				return ListServer.ecartis;
-			} else {
-				logger.error("unknown ecartis version: "+ecartis[0]+" in message "+mail.getMessageID());
-				return null;
-			}
-		}
-
-		String[] lyris = mail.getHeader("X-LISTMANAGER-Message-Id");
-		if (lyris!=null && lyris.length==1 && lyris[0]!=null) {
-			if (lyris[0].indexOf("LISTMANAGER")>=0) {
-				return ListServer.lyris;
-			} else {
-				logger.error("unexpected x-listmanager-message-id header: "+lyris[0]+" in message "+mail.getMessageID());
-				return null;
-			}
-		}
-
-		String[] xListServer = mail.getHeader("X-ListServer");
-		if (xListServer!=null && xListServer.length==1 && xListServer[0]!=null) {
-			if (xListServer[0].indexOf("CommuniGate")>=0) {
-				return ListServer.communigate;
-			} else {
-				logger.error("unknown x-listserver header: "+xListServer[0]+" in message "+mail.getMessageID());
-				return null;
-			}
-		}
-
-		// may not be reliable
-		String[] listSubscribe = mail.getHeader("List-Subscribe");
-		if (listSubscribe!=null && listSubscribe.length==1 && listSubscribe[0]!=null) {
-			if (listSubscribe[0].indexOf("+subscribe@")>0) {
-				return ListServer.mlmmj;
-			} else if (listSubscribe[0].indexOf("listserver@")>=0) {
-				return ListServer.listserver;
-			} else if (listSubscribe[0].indexOf("sympa@")>=0) {
-				return ListServer.sympa;
-			}
-		}
-
-		// not possible to detect:
-		// listserv
-		// majordomo / majordomo2
-		// smartlist
-
-		return null;
-	}
-/*
-	static void redoGuessedParents() {}
-
-	public static void rethreadPosts(boolean inBatch) throws SQLException{
-		rethreadPosts(1, 0, inBatch);
-	}
-
-	public static void rethreadPosts(long startingPostId, boolean inBatch) throws SQLException{
-		rethreadPosts(startingPostId, 0, inBatch);
-	}
-
-	static void rethreadPosts(long startingPostId, long forumId, boolean inBatch) throws SQLException{
-		Logger batchLog = inBatch ? Batch.logger : logger;
-		if(startingPostId > 1)
-			batchLog.info("Starting rethread from post " + startingPostId);
-		if(forumId > 0)
-			batchLog.info("Rethreading for forum " + forumId);
-
-		//the WHERE condition is post_id > postId !
-		long postId = startingPostId - 1;
-		int processed_post_count = 0;
-		int modified_post_count = 0;
-		int null_parent_count = 0;
-		NodeImpl post = null;
-		boolean more = true;
-		try {
-			outer: while (more) {
-				Connection con = Db.db.getConnection();
-				try {
-					con.setAutoCommit(false);
-					PreparedStatement stmt = con.prepareStatement(
-							(forumId > 0) ?
-									"SELECT * FROM descendants(" + forumId + ") WHERE node_id > ? AND " +
-											"(guessed_parent='t' OR guessed_parent is null) AND " +
-											"msg_fmt='m'" +
-											"ORDER BY node_id LIMIT 1"
-									:
-									"SELECT * FROM node WHERE node_id > ? AND " +
-											"(guessed_parent='t' OR guessed_parent is null) AND " +
-											"msg_fmt='m'" +
-											"ORDER BY node_id LIMIT 1"
-					);
-					stmt.setLong(1, postId);
-					ResultSet rs = stmt.executeQuery();
-					more = false;
-					while (rs.next()) {
-						more = true;
-						post = NodeImpl.getNode(rs);
-						try {
-							postId = post.getId();
-							Mail mail = MailHome.newMail(post.getMessage().getRaw());
-							MailingListImpl mailingList = post.getAppImpl().getAssociatedMailingListImpl();
-							if (mailingList==null) continue; // forum no longer a mailing list
-							List<NodeImpl> descendants = new ArrayList<NodeImpl>();
-							for( NodeImpl n : post.getDescendantImpls() ) {
-								descendants.add(n);
-							}
-							NodeImpl parent = guessParent(mail, post.getWhenCreated(), mailingList, post.getSubject(), descendants.toArray(new NodeImpl[0]));
-
-							if (parent != null && parent.getId() != post.getParentId()) {
-								try {
-									batchLog.debug("setting parent of " + post + " to " + parent);
-									post.setGuessedParent(parent);
-									if(++ modified_post_count % 100 == 0)
-										batchLog.info("Modified " + modified_post_count + " posts");
-								} catch (ModelException.NodeLoop e) {
-									batchLog.error("",e);
-								}
-							} else if(parent == null && post.getParentId() != 0 && post.getParent().getKind()!=Node.Kind.APP){
-								batchLog.info("Null parent at " + post);
-								null_parent_count ++;
-							}
-						} catch(Exception x){
-							batchLog.error("Exception at post " + post, x);
-							break outer;
-						}
-
-						if(++ processed_post_count % 3000 == 0)
-							batchLog.info("Processed " + processed_post_count + " posts, current postId: "+postId);
-
-						if (inBatch) {
-							Batch.checkStopped();
-						}
-					}
-					stmt.close();
-					con.commit();
-				} finally {
-					con.close();
-				}
-			}
-		} finally {
-			batchLog.info("Exited at post " + post);
-			batchLog.info("Processed " + processed_post_count + " posts");
-			batchLog.info("Modified " + modified_post_count + " posts");
-			batchLog.info("Guessed null parent at " + null_parent_count + " posts");
-		}
-	}
-*/
-	private static void getRethreadIds(Connection con,long parentId,Collection<Long> ids)
-		throws SQLException
-	{
-		PreparedStatement stmt = con.prepareStatement(
-			"select node_id, guessed_parent, msg_fmt from node where parent_id = ?"
-		);
-		stmt.setLong(1,parentId);
-		ResultSet rs = stmt.executeQuery();
-		while( rs.next() ) {
-			long id = rs.getLong("node_id");
-			if( "m".equals(rs.getString("msg_fmt"))
-				&& ( rs.getBoolean("guessed_parent") || rs.wasNull() )
-			)
-				ids.add(id);
-			getRethreadIds(con,id,ids);
-		}
-		rs.close();
-		stmt.close();
-	}
-
-	static void rethreadForum(NodeImpl forum, boolean inBatch) throws SQLException{
-		long forumId = forum.getId();
-		long rethreadStart = System.currentTimeMillis();
-		Logger batchLog = inBatch ? Batch.logger : logger;
-		batchLog.info("Rethreading for forum " + forumId);
-		SiteKey siteKey = forum.getSiteImpl().siteKey;
-		DbDatabase db = siteKey.getDb();
-
-		Collection<Long> ids = new ArrayList<Long>();
-		{
-			Connection con = db.getConnection();
-			long queryStart = System.currentTimeMillis();
-			getRethreadIds(con,forumId,ids);
-			batchLog.info("Query took " + (System.currentTimeMillis() - queryStart) + " ms");
-			con.close();
-		}
-
-		batchLog.info(ids.size() + " posts to process...");
-
-		//the WHERE condition is post_id > postId !
-		int processed_post_count = 0;
-		int modified_post_count = 0;
-		int null_parent_count = 0;
-
-		try {
-			while (ids.size() > 0) {
-				Connection con = db.getConnection();
-				try {
-					con.setAutoCommit(false);
-
-					long id = ids.iterator().next();
-					ids.remove(id);
-					NodeImpl post = NodeImpl.getNode(siteKey,id);
-					try {
-						Mail mail = MailHome.newMail(post.getMessage().getRaw());
-						MailingListImpl mailingList = post.getAppImpl().getAssociatedMailingListImpl();
-						if (mailingList==null) continue; // forum no longer a mailing list
-						List<NodeImpl> descendants = new ArrayList<NodeImpl>();
-						for( NodeImpl n : post.getDescendantImpls() ) {
-							descendants.add(n);
-						}
-						NodeImpl parent = guessParent(mail, post.getWhenCreated(), mailingList, post.getSubject(), descendants.toArray(new NodeImpl[0]));
-
-						if (parent != null && parent.getId() != post.getParentId()) {
-							try {
-								batchLog.info("setting parent of " + post + " to " + parent);
-								post.setGuessedParent(parent);
-
-								if(++ modified_post_count % 1000 == 0)
-									batchLog.info("Modified " + modified_post_count + " posts");
-							} catch (ModelException.NodeLoop e) {
-								batchLog.error("",e);
-							}
-						} else if(parent == null && post.getParentId() != 0 && post.getParent().getKind()!=Node.Kind.APP){
-							batchLog.info("Null parent at " + post);
-							null_parent_count ++;
-						}
-					} catch(Exception x){
-						batchLog.error("Exception at " + post + " - message:\n"+post.getMessage().getRaw(), x);
-						break;
-					}
-
-					if(++ processed_post_count % 1000 == 0)
-						batchLog.info("Processed " + processed_post_count + " posts, current postId: "+id);
-
-					if (inBatch) {
-						Batch.checkStopped();
-					}
-					con.commit();
-				} finally {
-					con.close();
-				}
-			}
-		} finally {
-			batchLog.info("Rethread took " + (System.currentTimeMillis() - rethreadStart) + " ms");
-			batchLog.info("Processed " + processed_post_count + " posts");
-			batchLog.info("Modified " + modified_post_count + " posts");
-			batchLog.info("Guessed null parent at " + null_parent_count + " posts");
-		}
-	}
-
-
-	/**
-	 * Get or create message id from an email
-	 *
-	 * @param mail   email message
-	 * @param msgFmt message format to use
-	 * @return message id, never null
-	 */
-	private static String getMessageID(Mail mail, Message.Format msgFmt) {
-		String[] messageIds = mail.getHeader("Message-Id"); // returns both Id and ID
-		if (messageIds == null || messageIds.length == 0 || messageIds[messageIds.length - 1] == null) {
-			return calcMessageID(mail, msgFmt);
-		} else {
-			return MailSubsystem.stripBrackets(messageIds[messageIds.length - 1]);
-		}
-	}
-
-	/**
-	 * Create a new message if for an email message
-	 *
-	 * @param mail   mail message to process
-	 * @param msgFmt message format to use
-	 * @return a new message id, never null
-	 */
-	private static String calcMessageID(Mail mail, Message.Format msgFmt) {
-		StringBuilder msgId = new StringBuilder();
-		msgId.append("MissingID.");
-		String text = msgFmt.getText(mail.getRawInput(),null);
-		msgId.append(Integer.toHexString(text.hashCode()));
-		MailAddress from = mail.getFrom();
-		if (from != null) msgId.append(Integer.toHexString(from.toString().hashCode()));
-		MailAddress[] to = mail.getTo();
-		if (to != null && to.length > 0) msgId.append(Integer.toHexString(to[0].toString().hashCode()));
-		Date date = mail.getSentDate();
-		if (date != null) msgId.append(Integer.toHexString(date.hashCode()));
-		String subject = mail.getSubject();
-		if (subject != null) msgId.append(Integer.toHexString(subject.hashCode()));
-		msgId.append("@nabble.com");
-		return msgId.toString();
-	}
-
-
-
-
-
-	private static final Pop3Server fwdPop3Server = (Pop3Server)Init.get("fwdPop3Server");
-
-	private static class Lazy {
-		static final String emailPrefix;
-		static final String emailSuffix;
-		static final Pattern pattern;
-		static {
-			String addrSpec = fwdPop3Server.getUsername();
-			int ind = addrSpec.indexOf('@');
-			emailPrefix = addrSpec.substring(0, ind) + "+";
-			emailSuffix = addrSpec.substring(ind);
-			pattern = Pattern.compile(
-				Pattern.quote(emailPrefix) + "([^@]+)\\+([^@]+)\\+([^@]+)" + Pattern.quote(emailSuffix)
-				, Pattern.CASE_INSENSITIVE
-			);
-		}
-	}
-
-	private static void processFwds() {
-		if( fwdPop3Server == null ) {
-			logger.error("fwdPop3Server not defined");
-			System.exit(-1);
-		}
-		MailIterator mails = fwdPop3Server.getMail();
-		try {
-			while( mails.hasNext() ) {
-				Mail mail = mails.next();
-				try {
-					fwdMail(mail);
-				} catch (Exception e) {
-					logger.error("mail:\n"+mail.getRawInput(),e);
-				}
-			}
-		} finally {
-			mails.close();
-		}
-	}
-
-	private static void fwdMail(Mail mail) {
-		String[] envTo = mail.getHeader("Envelope-To");
-		if (envTo == null)
-			envTo = mail.getHeader("X-Delivered-to"); // fastmail
-		if (envTo == null)
-			envTo = mail.getHeader("X-Original-To"); // postfix
-		String originalTo = envTo[0];
-		Matcher matcher = Lazy.pattern.matcher(originalTo);
-		if( !matcher.matches() )
-			throw new RuntimeException("invalid email: "+originalTo);
-		String fwdFrom = emailDecode(matcher.group(1));
-		String fwdTo = emailDecode(matcher.group(2));
-		if( (fwdFrom+fwdTo).hashCode() != Integer.parseInt(matcher.group(3)) )
-			throw new RuntimeException("invalid hash: "+originalTo);
-		mail.setFrom(new MailAddress(fwdFrom));
-		mail.setTo(new MailAddress(fwdTo));
-		logger.info("Forwarding email to mailing list: " + fwdTo);
-		MailHome.getDefaultSmtpServer().send(mail);
-	}
-
-	private static String fwdEmail(String from,String to) {
-		return Lazy.emailPrefix + emailEncode(from) + '+' + emailEncode(to) + '+' + (from+to).hashCode() + Lazy.emailSuffix;
-	}
-
-	private static String emailEncode(String s) {
-		return HtmlUtils.urlEncode(s).replace('%','~');
-	}
-
-	private static String emailDecode(String s) {
-		return HtmlUtils.urlDecode(s.replace('~','%'));
-	}
-
-}
--- a/src/nabble/model/Message.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/Message.java	Fri Jun 18 17:44:24 2021 -0600
@@ -146,7 +146,7 @@
 	
 		public static final Format TEXT = MessageFormatImpls.TEXT;
 		public static final Format HTML = MessageFormatImpls.HTML;
-		public static final Format MAILING_LIST = MailingLists.msgFmt;
+		private static final Format MAILING_LIST = new MailMessageFormat('m', "mail");
 		private static final Format SUBSCRIPTION = new MailMessageFormat('s', "subscription");
 
 		public boolean isMail() {
--- a/src/nabble/model/MessageFormatImpls.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/MessageFormatImpls.java	Fri Jun 18 17:44:24 2021 -0600
@@ -277,11 +277,6 @@
 	}
 
 
-	static {
-		MailingLists.nop();
-	}
-
-
 	private static final List<String> ignoredTags = Arrays.asList(
 		"nabble_embed"
 	);
--- a/src/nabble/model/ModelHome.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/ModelHome.java	Fri Jun 18 17:44:24 2021 -0600
@@ -76,15 +76,6 @@
 			return null;
 		return siteKey.siteGlobal().site();
 	}
-/*
-	// unfiltered, Site.getUser() is preferred
-	public static User getUserFromId(long id) {
-		return UserImpl.getUser(id);
-	}
-*/
-	public static void setNodeHeaders(Mail mail, Node node) {
-		MailSubsystem.setHeaders(mail, (NodeImpl) node);
-	}
 
 	public static void setRemoteAddr(Site site, String removeAddr) {
 		((SiteImpl) site).siteGlobal().setRemoteAddr(removeAddr);
@@ -199,30 +190,6 @@
 	public static void endImport() {
 		insideImportProcedure.set(false);
 	}
-/*
-	static {
-		NodeImpl.addPostInsertListener(new Listener<NodeImpl>() {
-			public void event(final NodeImpl post) {
-				if (insideImportProcedure.get())
-					return;
-				Node.MailToList mailToList = post.getMailToList();
-				if( mailToList==null )
-					return;
-				MailingList mailingList = post.getAssociatedMailingListImpl();
-				if( mailingList == null )
-					return;
-				Template template = post.getSite().getTemplate( "mail to list",
-					BasicNamespace.class, NabbleNamespace.class, NodePageNamespace.class
-				);
-				template.run( TemplatePrintWriter.NULL, Collections.<String,Object>emptyMap(),
-					new BasicNamespace(template),
-					new NabbleNamespace(post.getSite()),
-					new NodePageNamespace(post)
-				);
-			}
-		});
-	}
-*/
 
 	public static void preloadMessages(List<Node> nodes) {
 		NodeImpl.preloadMessages(nodes);
--- a/src/nabble/model/Node.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/Node.java	Fri Jun 18 17:44:24 2021 -0600
@@ -23,8 +23,6 @@
 	public NodeIterator<? extends Node> getChildren();
 	public NodeIterator<? extends Node> getChildren(String cnd);
 	public int getChildCount();
-	public MailingList getMailingList();
-	public MailingList getAssociatedMailingList();  // only returns MailingList if not isUIHidden
 	public Kind getKind();
 	public NodeIterator<? extends Node> getAncestors();  // starting with self
 	public NodeIterator<? extends Node> getDescendants();
@@ -42,8 +40,6 @@
 	public int getTopicCount(String cnd,Filter<Node> filter);
 	public Node getLastNode();
 	public Date getLastNodeDate();
-	public MailToList getMailToList();
-	public MailFromList getMailFromList();
 	public String getSubject();
 	public void setSubject(String subject) throws ModelException.RequiredSubject;
 	public String getSubjectHtml();
@@ -86,22 +82,6 @@
 	public boolean hasPinnedTopics();
 	public NodeIterator<? extends Node> getChildApps();
 	public NodeIterator<? extends Node> getChildApps(String cnd);
-	public MailingList newMailingList(ListServer listServer,String listAddress,String url) throws ModelException;
-	public void deleteMailingList();
-
-	public interface MailToList {
-		public Node getNode();
-		public boolean isPending();
-		public void clearPending();
-		public Date getWhenSent();
-		public String getOrGenerateMessageID();
-	}
-
-	public interface MailFromList {
-		public boolean hasGuessedParent();
-		public String getMessageID();
-		public MailFromList getParentMailFromList();
-	}
 
 	public enum Kind { APP, POST }
 
--- a/src/nabble/model/NodeImpl.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/NodeImpl.java	Fri Jun 18 17:44:24 2021 -0600
@@ -49,7 +49,7 @@
 import java.util.concurrent.TimeUnit;
 
 
-final class NodeImpl implements Node, Node.MailFromList {
+final class NodeImpl implements Node {
 	private static final Logger logger = LoggerFactory.getLogger(NodeImpl.class);
 
 	private static final Message DELETED_MESSAGE = new Message("- deleted -", Message.Format.TEXT) {
@@ -66,10 +66,7 @@
 	private UserImpl owner;
 	private long parentId = 0L;
 	private NodeImpl parent;
-	private String messageID;
 	private Date whenUpdated;
-	private Boolean isGuessedParent = false;
-	private Date whenSent;
 	private long lastNodeId;
 	private Date lastNodeDate;
 	private int nodeCount;
@@ -95,11 +92,7 @@
 		whenCreated = rs.getTimestamp("when_created");
 		ownerId = rs.getLong("owner_id");
 		parentId = rs.getLong("parent_id");
-		messageID = rs.getString("message_id");
 		whenUpdated = rs.getTimestamp("when_updated");
-		isGuessedParent = rs.getBoolean("guessed_parent");
-		if (rs.wasNull()) isGuessedParent = null;
-		whenSent = rs.getTimestamp("when_sent");
 		lastNodeId = rs.getLong("last_node_id");
 		lastNodeDate = rs.getTimestamp("last_node_date");
 		nodeCount = rs.getInt("node_count");
@@ -272,7 +265,7 @@
 
 	private void setWhenUpdated() {
 		long timeDiff = new Date().getTime() - getWhenCreated().getTime();
-		boolean acceptChanges = timeDiff > TEN_MINUTES || !getChildren().isEmpty() || isMailToList();
+		boolean acceptChanges = timeDiff > TEN_MINUTES || !getChildren().isEmpty();
 		if (acceptChanges) {
 			setWhenUpdated( new Date() );
 		}
@@ -370,15 +363,10 @@
 			}
 			return;
 		}
-		MailingListImpl mailingList = getMailingListImpl();
-		if (mailingList != null) {
-			mailingList.unsubscribe();
-		}
 		if( getChildCount() == 0 ) {
 			deleteRecursively();
 		} else {
 			setMessage(DELETED_MESSAGE.getRaw(),DELETED_MESSAGE.getFormat());
-			clearPending();
 			update();
 		}
 	}
@@ -472,8 +460,6 @@
 			if (owner != null)
 				owner.updateNewPostLimit();
 		}
-		if( isMailToList() && isDoneByPoster )
-			throw new RuntimeException("no more pending");
 		String message = (String)record.fields().remove("message");
 		record.insert();
 		insertMessage(message);
@@ -1163,14 +1149,6 @@
 
 	static void addPostUpdateListener(final Listener<? super NodeImpl> listener) {
 		postUpdateListeners.add(listener);
-		Listener<MailingListImpl> mlListener = new Listener<MailingListImpl>() {
-			public void event(MailingListImpl ml) {
-				listener.event(ml.getForumImpl());
-			}
-		};
-		MailingListImpl.postInsertListeners.add(mlListener);
-		MailingListImpl.postUpdateListeners.add(mlListener);
-		MailingListImpl.postDeleteListeners.add(mlListener);
 	}
 
 	static void addPostDeleteListener(final Listener<? super NodeImpl> listener) {
@@ -1775,258 +1753,6 @@
 	}
 
 
-
-	// mailing list related
-
-	static final String messageIDEnding;
-	static {
-		try {
-			messageIDEnding = ".post@" + Init.get("mailDomain",InetAddress.getLocalHost().getHostName());
-		} catch(UnknownHostException e) {
-			logger.error("",e);
-			System.exit(-1);
-			throw new RuntimeException();  // for compiler
-		}
-	}
-
-	public String getMessageID() {
-		return messageID;
-	}
-
-	public MailFromList getParentMailFromList() {
-		Node node = getParent();
-		return (node == null) ? null : node.getMailFromList();
-	}
-
-	public String getOrGenerateMessageID() {
-		if (messageID == null) {
-			String id = "" + System.currentTimeMillis() + "-" + getId() + messageIDEnding;
-			setMessageID(id);
-			if( isInDb() )
-				this.record.update();
-		}
-		return messageID;
-	}
-
-	void setMessageID(String messageID) {
-		this.messageID = messageID;
-		record.fields().put("message_id",messageID);
-	}
-
-	void setGuessedParent(NodeImpl newParent)
-		throws ModelException
-	{
-		setGuessedParent(true);
-		changeParentImpl(newParent);
-	}
-
-	boolean isGuessedParent() {
-		return (isGuessedParent != null) && isGuessedParent;
-	}
-
-	boolean isNotGuessedParent() {
-		return (isGuessedParent != null) && !isGuessedParent;
-	}
-
-	public boolean hasGuessedParent() {
-		return isGuessedParent();
-	}
-
-	Boolean rawGuessedParent() {
-		return isGuessedParent;
-	}
-
-	/**
-	 * Set 'guessed_parent' flag of the post.
-	 *
-	 * @param guessed flag value
-	 */
-	void setGuessedParent(Boolean guessed) {
-		this.isGuessedParent = guessed;
-		record.fields().put("guessed_parent", DbNull.fix(this.isGuessedParent) );
-	}
-
-	void setGuessedParent(String parentID) {
-		setGuessedParent(Boolean.TRUE);
-		setRawParentMessageId(parentID);
-	}
-
-	// only returns MailingList if not isUIHidden
-	public MailingList getAssociatedMailingList() {
-		return getAssociatedMailingListImpl();
-	}
-
-	MailingListImpl getAssociatedMailingListImpl() {
-		for( NodeImpl node=this; node!=null; node=node.getParentImpl() ) {
-			if( node.getKind()==Kind.APP ) {
-				MailingListImpl ml = node.getMailingListImpl();
-				if( ml != null )
-					return ml;
-			}
-		}
-		return null;
-	}
-
-	boolean isFromMailingList() {
-		return message.getFormat() == Message.Format.MAILING_LIST;
-	}
-
-	void clearPending() {
-		whenSent = null;
-		record.fields().put("when_sent", DbNull.TIMESTAMP);
-		if( !db().isInTransaction() ) {
-			record.update();
-			DbUtils.uncache(getOwnerImpl());
-		}
-	}
-
-	private boolean isMailToList() {
-		return getKind() == Kind.POST && getAssociatedMailingListImpl() != null && !isFromMailingList();
-	}
-
-	public MailToList getMailToList() {
-		if( !isMailToList() )
-			return null;
-		return new MailToList() {
-
-			public Node getNode() {
-				return NodeImpl.this;
-			}
-
-			public boolean isPending() {
-				return whenSent != null;
-			}
-
-			public void clearPending() {
-				NodeImpl.this.clearPending();
-			}
-
-			public Date getWhenSent() {
-				return whenSent;
-			}
-
-			public String getOrGenerateMessageID() {
-				return NodeImpl.this.getOrGenerateMessageID();
-			}
-
-		};
-	}
-
-
-	public MailFromList getMailFromList() {
-		//  MailFromList is used to work with all messages from mailing lists, both local and external
-		return (getKind() == Kind.POST && getAssociatedMailingListImpl() != null) ? this : null;
-	}
-
-	public MailingList newMailingList(ListServer listServer,String listAddress,String url) throws ModelException {
-		if( getKind() != Kind.APP )
-			throw new UnsupportedOperationException();
-		if( !ModelHome.insideImportProcedure.get() )
-			DailyNumber.forumsStarted.dec();
-        setMailingList(new MailingListImpl(this, listServer, listAddress, url));
-        DbUtils.uncache(this);
-        return mailingList;
-	}
-
-	private void setRawParentMessageId(String parentMessageId) {
-		record.fields().put("parent_message_id", DbNull.fix(parentMessageId));
-	}
-
-	static NodeImpl[] getFromParentID(String parentID, MailingListImpl mailingList) {
-		try {
-			SiteKey siteKey = mailingList.siteKey;
-			Connection con = siteKey.getDb().getConnection();
-			PreparedStatement stmt = con.prepareStatement(
-					"select *"
-					+" from node"
-					+" where lower(parent_message_id)=?"
-			);
-			stmt.setString(1,parentID.toLowerCase());
-			ResultSet rs = stmt.executeQuery();
-			try {
-				List<NodeImpl> list = new ArrayList<NodeImpl>();
-				while( rs.next() ) {
-					NodeImpl post = getNode(siteKey,rs);
-					if (mailingList.equals(post.getAssociatedMailingListImpl()))
-						list.add( post );
-				}
-				return list.toArray(new NodeImpl[0]);
-			} finally {
-				rs.close();
-				stmt.close();
-				con.close();
-			}
-		} catch(SQLException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	NodeImpl getNodeImplFromMessageID(String messageID) {
-		if( messageID == null )
-			return null;
-		try {
-			Connection con = db().getConnection();
-			PreparedStatement stmt = con.prepareStatement(
-					"select * from node"
-					+" where lower(message_id)=? and message_id is not null"
-			);
-			stmt.setString(1,messageID.toLowerCase());
-			ResultSet rs = stmt.executeQuery();
-			try {
-				while (rs.next()) {
-					NodeImpl post = getNode(rs);
-					if( post.getAncestors().contains(this) )
-						return post;
-				}
-				return null;
-			} finally {
-				rs.close();
-				stmt.close();
-				con.close();
-			}
-		} catch(SQLException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-
-
-
-
-	private MailingListImpl mailingList;
-    private boolean mailingListSet = false;
-
-    private void setMailingList(MailingListImpl mailingList) {
-        this.mailingList = mailingList;
-        mailingListSet = true;
-    }
-
-	MailingListImpl getMailingListImpl() {
-		if( getKind() != Kind.APP )
-			return null;
-        if (!mailingListSet || (mailingList != null && DbUtils.isStale(mailingList))) {
-            setMailingList(MailingListImpl.getMailingListForForum(this));
-        }
-        return mailingList;
-    }
-
-	public MailingList getMailingList() {
-		return getMailingListImpl();
-	}
-
-	public void deleteMailingList() {
-		MailingList mailingList = getMailingList();
-		if (mailingList != null) {
-			mailingList.delete();
-			this.mailingList = null;
-			this.mailingListSet = false;
-			DbUtils.uncache(this);
-		}
-	}
-
-
-
-
 	// export/import
 
 	NodeImpl(SiteImpl site,NodeData data)
@@ -2051,21 +1777,8 @@
 		setType( data.type );
 		if( data.pin != null )
 			record.fields().put( "pin", data.pin );
-		if( data.messageID != null )
-			setMessageID( data.messageID );
-		setGuessedParent( data.isGuessedParent );
 		insert(false);
 
-		if( data.mlAddress != null ) {
-			ListServer listServer = ListServer.getServer( data.mlServer );
-			MailingList mailingList = newMailingList( listServer, data.mlAddress, data.mlUrl );
-			mailingList.setPlainTextOnly( data.mlPlainTextOnly );
-			mailingList.setIgnoreNoArchive( data.mlIgnoreNoArchive );
-			mailingList.setListName( data.mlListName );
-			mailingList.update();
-			update();
-		}
-
 		for( URL url : data.fileUrls ) {
 			try {
 				FileUpload.uploadFile( new FileUpload.UrlFileItem(url), this );
@@ -2104,20 +1817,6 @@
 		data.whenCreated = whenCreated;
 		data.whenUpdated = whenUpdated;
 		data.type = type;
-		data.messageID = messageID;
-		data.isGuessedParent = isGuessedParent;
-
-		MailingListImpl mailingList = getMailingListImpl();
-		if( mailingList != null ) {
-			data.mlAddress = mailingList.getListAddress();
-			data.mlUrl = mailingList.getUrl();
-			if( data.mlUrl==null )
-				data.mlUrl = "http://localhost";
-			data.mlPlainTextOnly = mailingList.plainTextOnly();
-			data.mlIgnoreNoArchive = mailingList.ignoreNoArchive();
-			data.mlServer = mailingList.getListServer().getType();
-			data.mlListName = mailingList.getListName();
-		}
 
 		List<URL> urls = new ArrayList<URL>();
 		Message.Format fmt = message.getFormat();
--- a/src/nabble/model/NodeSearcher.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/NodeSearcher.java	Fri Jun 18 17:44:24 2021 -0600
@@ -54,7 +54,7 @@
 
 	public static class Builder {
 		private static final String[] nodeSearchFields = new String[]{
-			Lucene.SUBJECT_FLD, Lucene.MESSAGE_FLD, Lucene.AUTHOR_FLD, Lucene.MAILING_LIST_FLD
+			Lucene.SUBJECT_FLD, Lucene.MESSAGE_FLD, Lucene.AUTHOR_FLD
 		};
 
 		private final SiteImpl site;
--- a/src/nabble/model/User.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/User.java	Fri Jun 18 17:44:24 2021 -0600
@@ -32,8 +32,6 @@
 
 	public int getExternalHash(String url); // not used anywhere
 
-	public NodeIterator<? extends Node> getPendingPosts();
-
 	public User setSignature( String signature, Message.Format signatureFormat ) throws ModelException;
 
 	public boolean isSubscribed(Node node);
@@ -79,6 +77,4 @@
 	public boolean checkPasscookie(String passcookie);
 	public String getResetcode();
 	public boolean checkResetcode(String resetcode);
-
-	public void setNoArchive(boolean noArchive);
 }
--- a/src/nabble/model/UserImpl.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/UserImpl.java	Fri Jun 18 17:44:24 2021 -0600
@@ -56,7 +56,6 @@
 	private String passwordDigest;
 	private String name;
 	private Date registered;
-	private boolean noArchive;
 	private Message signature = null;
 	private int bounces;
 
@@ -69,7 +68,6 @@
 		passwordDigest = rs.getString("password_digest");
 		name = rs.getString("name");
 		registered = DbUtils.getDate(rs,"registered");
-		noArchive = rs.getBoolean("no_archive");
 		String signatureRaw = rs.getString("signature");
 		String signatureFormatS = rs.getString("signature_format");
 		if( signatureRaw!=null && signatureFormatS!=null ) {
@@ -115,31 +113,7 @@
 	}
 
 	public boolean isDeactivated() {
-		return !isRegistered() && isNoArchive();
-	}
-
-	boolean isNoArchive() {
-		return noArchive;
-	}
-
-	public void setNoArchive(boolean noArchive) {
-		if( this.noArchive == noArchive )
-			return;
-
-		if( !db().isInTransaction() ) {
-			db().beginTransaction();
-			try {
-				UserImpl user = DbUtils.getGoodCopy(this);
-				user.setNoArchive(noArchive);
-				user.getDbRecord().update();
-				db().commitTransaction();
-				return;
-			} finally {
-				db().endTransaction();
-			}
-		}
-		this.noArchive = noArchive;
-		record.fields().put("no_archive",DbNull.fix(noArchive));
+		return !isRegistered();
 	}
 
 	public String getEmail() {
@@ -344,8 +318,6 @@
 			throw new RuntimeException();
 		setRegistered( registerDate );
 		if( record.isInDb() ) {
-			if( isNoArchive() )
-				setNoArchive(false);
 			record.update();
 		} else {
 			insert();
@@ -784,7 +756,6 @@
 		db().beginTransaction();
 		try {
 			UserImpl user = DbUtils.getGoodCopy(this);
-			user.setNoArchive(true);
 			user.setRegistered(null);
 			user.setPasswordDigest(null);
 			user.record.update();
@@ -803,17 +774,6 @@
 		};
 	}
 
-	public NodeIterator<? extends Node> getPendingPosts() {
-		return new CursorNodeIterator( siteKey,
-				"select *"
-				+" from node"
-				+" where owner_id = ?"
-				+" and when_sent is not null"
-				+" order by when_sent"
-			, simpleParamSetter()
-		);
-	}
-
 	public Message getSignature() {
 		return signature;
 	}
--- a/src/nabble/model/export/AbstractImportImpl.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/export/AbstractImportImpl.java	Fri Jun 18 17:44:24 2021 -0600
@@ -2,7 +2,6 @@
 
 import fschmidt.db.SQLRuntimeException;
 import fschmidt.util.java.ProxyIntoThread;
-import nabble.model.MailingList;
 import nabble.model.ModelException;
 import nabble.model.Node;
 import nabble.model.Site;
@@ -21,7 +20,6 @@
 
 	final Site site;
 	private ProxyIntoThread pit = null;
-	private MailingList currentMailingList = null;
 	private boolean isStarted = false;
 	private boolean isClosed = false;
 
@@ -73,14 +71,7 @@
 			isStarted = true;
 		}
 		try {
-			Node node = null;
-			if( currentMailingList != null )
-				node = currentMailingList.getNodeFromMessageID(data.messageID);
-
-			if (node != null)
-				return Jtp.url(node);
-			else
-				return createNode(data);
+			return createNode(data);
 		} catch(ModelException e) {
 			logger.error("node "+data.exportId + " / data.exportId=" + data.exportId, e);
 			throw new RuntimeException(e.toString());
@@ -94,33 +85,6 @@
 		return site.getNode(nodeId);
 	}
 
-	public void setMailingList(Long nodeId) {
-		if( nodeId==null ) {
-			currentMailingList = null;
-		} else {
-			if( currentMailingList != null )
-				throw new RuntimeException("Already have mailing list "+currentMailingList);
-			currentMailingList = getNode(nodeId).getMailingList();
-			if( currentMailingList == null )
-				throw new RuntimeException("No mailing list for node "+nodeId);
-		}
-	}
-
-	public void subscribe(long nodeId) {
-		getNode(nodeId).getMailingList().subscribe();
-	}
-
-	public void setExportOwner(long nodeId,String exportOwner) {
-		try {
-			MailingList ml = getNode(nodeId).getMailingList();
-			ml.setExportOwner(exportOwner);
-			ml.update();
-		} catch(ModelException e) {
-			logger.error(exportOwner,e);
-			throw new RuntimeException(e.toString());
-		}
-	}
-
 	public void close() {
 		isClosed = true;
 		if (pit != null) {
--- a/src/nabble/model/export/Export.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/export/Export.java	Fri Jun 18 17:44:24 2021 -0600
@@ -6,7 +6,6 @@
 import fschmidt.util.mail.MailAddress;
 import fschmidt.util.mail.MailHome;
 import fschmidt.util.mail.PlainTextContent;
-import nabble.model.MailingList;
 import nabble.model.ModelException;
 import nabble.model.ModelHome;
 import nabble.model.Executors;
@@ -50,7 +49,6 @@
 	private final Import imp;
 	private final ExportMessages messages;
 	private final String permalink;
-	private boolean handledMailingList = false;
 	private Set<Long> movedUserIds = new TreeSet<Long>();
 
 	protected Export(Node rootNode,String permalink,String email, ImportServer is, ExportMessages messages)
@@ -126,12 +124,6 @@
 			Node rootNode = this.rootNode.getGoodCopy();
 			long parentId = imp.getNodeId(permalink);
 			export(rootNode.getGoodCopy(),parentId,null);
-			if( handledMailingList ) {
-				handledMailingList = false;
-				export(rootNode.getGoodCopy(),parentId,null);
-				if( handledMailingList )
-					throw new RuntimeException();
-			}
 			// The last step is to delete the old nodes, so there is no reason
 			// to keep this connection open. Let's close it.
 			imp.close();
@@ -178,75 +170,50 @@
 		if( Executors.isShuttingDown() )
 			throw new ShutdownException();
 		long id = node.getExportedNodeId();
-		try {
-			final MailingList ml = node.getMailingList();
-			Integer pinOrder = pin == null || !node.isPinned()? null : ++pin[0];
-			if( id==0L ) {
-				NodeData data = node.getData();
-				data.parentId = parentId;
-				data.pin = pinOrder;
-				String redirectUrl = imp.importNode(data);
-				try {
-					id = imp.getNodeId(redirectUrl);
-				} catch(Import.BadLink e) {
-					logger.error(""+node+" url = "+redirectUrl,e);
-					throw new RuntimeException("redirect url not found: "+redirectUrl);
-				}
-				setExportedNodeId(node, id);
-				if (ml != null) {
-					imp.setExportOwner(id,email);
-					imp.subscribe(id);
-					ml.setExportOwner(email);
-					ml.update();
-					ml.unsubscribe();
-					handledMailingList = true;
-				}
-			} else {
-				if (ml!=null) {
-					imp.setExportOwner(id,null);
-					ml.setExportOwner(null);
-					ml.update();
-				}
+		Integer pinOrder = pin == null || !node.isPinned()? null : ++pin[0];
+		if( id==0L ) {
+			NodeData data = node.getData();
+			data.parentId = parentId;
+			data.pin = pinOrder;
+			String redirectUrl = imp.importNode(data);
+			try {
+				id = imp.getNodeId(redirectUrl);
+			} catch(Import.BadLink e) {
+				logger.error(""+node+" url = "+redirectUrl,e);
+				throw new RuntimeException("redirect url not found: "+redirectUrl);
 			}
-
-			if (ml != null)
-				imp.setMailingList(id);
+			setExportedNodeId(node, id);
+		}
 
-			// Move author
-			Person author = node.getOwner();
-			if (author instanceof User) {
-				User user = (User) author;
-				if (user.isRegistered() && !movedUserIds.contains(user.getId())) {
-					String smallAvatarUrl = null;
-					String bigAvatarUrl = null;
-					if (user.hasAvatar()) {
-						String base = node.getSite().getBaseUrl() + "/file/a" + user.getId() + '/';
-						smallAvatarUrl = base + ModelHome.AVATAR_SMALL;
-						bigAvatarUrl = base + ModelHome.AVATAR_BIG;
-					}
-					imp.addUser(user.getName(), user.getEmail(), user.getPasswordDigest(), user.getRegistered(), smallAvatarUrl, bigAvatarUrl);
-					movedUserIds.add(user.getId());
+		// Move author
+		Person author = node.getOwner();
+		if (author instanceof User) {
+			User user = (User) author;
+			if (user.isRegistered() && !movedUserIds.contains(user.getId())) {
+				String smallAvatarUrl = null;
+				String bigAvatarUrl = null;
+				if (user.hasAvatar()) {
+					String base = node.getSite().getBaseUrl() + "/file/a" + user.getId() + '/';
+					smallAvatarUrl = base + ModelHome.AVATAR_SMALL;
+					bigAvatarUrl = base + ModelHome.AVATAR_BIG;
 				}
+				imp.addUser(user.getName(), user.getEmail(), user.getPasswordDigest(), user.getRegistered(), smallAvatarUrl, bigAvatarUrl);
+				movedUserIds.add(user.getId());
 			}
+		}
 
-			pin = new int[1];
+		pin = new int[1];
 
-			// Here we use an iterator because something may go wrong with the
-			// migration (e.g., the other server may go down or the network may fail)
-			// So we should make sure all DB connections are properly closed.
-			NodeIterator<? extends Node> iterator = node.getChildren();
-			try {
-				while (iterator.hasNext()) {
-					export(iterator.next(), id, pin );
-				}
-			} finally {
-				iterator.close();
+		// Here we use an iterator because something may go wrong with the
+		// migration (e.g., the other server may go down or the network may fail)
+		// So we should make sure all DB connections are properly closed.
+		NodeIterator<? extends Node> iterator = node.getChildren();
+		try {
+			while (iterator.hasNext()) {
+				export(iterator.next(), id, pin );
 			}
-			if (ml != null)
-				imp.setMailingList(null);
-		} catch(ModelException e) {
-			logger.error(""+node,e);
-			throw new RuntimeException(e.toString());
+		} finally {
+			iterator.close();
 		}
 	}
 
--- a/src/nabble/model/export/Import.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/export/Import.java	Fri Jun 18 17:44:24 2021 -0600
@@ -9,12 +9,6 @@
 	public static final class BadLink extends Exception {}
 	public long getNodeId(String permalink) throws RemoteException, BadLink;
 	public String importNode(NodeData nodeData) throws RemoteException;
-	public void setMailingList(Long nodeId) throws RemoteException;
-	public void subscribe(long nodeId) throws RemoteException;
-	public void setExportOwner(long nodeId,String exportOwner) throws RemoteException;
 	public void addUser(String name, String email, String password, Date registrationDate, String smallAvatarUrl, String bigAvatarUrl) throws RemoteException;
 	public void close() throws RemoteException;
-
-	/** FOR OLD NABBLE ONLY -- TO BE REMOVED SOON */
-	public void addUser0(String name, String email, String password, long registrationDate) throws RemoteException;
 }
--- a/src/nabble/model/export/ImportImpl.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/export/ImportImpl.java	Fri Jun 18 17:44:24 2021 -0600
@@ -67,23 +67,4 @@
 			db.endTransaction();
 		}
 	}
-
-	/** FOR OLD NABBLE ONLY -- TO BE REMOVED SOON */
-	public void addUser0(String name, String email, String password, long registrationDate) {
-		final DbDatabase db = site.getDb();
-		db.beginTransaction();
-		try {
-			User user = site.getOrCreateUser(email, name);
-			if (!user.isRegistered()) {
-				user.setPassword(password);
-				user.register(new Date(registrationDate));
-				user.update();
-			}
-			db.commitTransaction();
-		} catch (ModelException e) {
-			// do nothing -- skip this user
-		} finally {
-			db.endTransaction();
-		}
-	}
 }
--- a/src/nabble/model/export/NodeData.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/model/export/NodeData.java	Fri Jun 18 17:44:24 2021 -0600
@@ -22,16 +22,6 @@
 	public String type;
 	public String customStyle;
 	public Integer pin;
-	public String messageID;
-	public Boolean isGuessedParent;
-	// didn't bother with parent_message_id and when_sent
-
-	public String mlAddress;
-	public String mlUrl;
-	public boolean mlPlainTextOnly;
-	public boolean mlIgnoreNoArchive;
-	public String mlServer;
-	public String mlListName;
 
 	public URL[] fileUrls;
 	public transient Map<String, byte[]> files;
--- a/src/nabble/modules/naml/expire_old_threads.naml	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-<override_macro name="reply" requires="servlet">
-	<n.node_page.>
-		<n.if.page_node.when_created.is_older_than days="[n.thread_expiration_days/]">
-			<then.redirect_to.expired_thread_page_path/>
-			<else.overridden/>
-		</n.if.page_node.when_created.is_older_than>
-	</n.node_page.>
-</override_macro>
-
-<macro name="thread_expiration_days">
-	365
-</macro>
-
-<macro name="expired_thread_page_path" requires="node_page">
-	/template/NamlServlet.jtp?macro=expired_thread_page&node=<n.page_node.id/>
-</macro>
-
-<macro name="expired_thread_page" requires="servlet">
-	<n.node_page.>
-		<n.html>
-			<head>
-				<title><t>This thread is read-only</t></title>
-			</head>
-			<body>
-				<h1><t>This thread is read-only</t></h1>
-
-				<p>
-					<t>This topic was created a long time ago and a new reply here would be confusing to a lot of people.</t><br/>
-					<t>If you have questions about this subject, please <a href="[n.page_node.get_app_node.new_topic_path/]">create a new topic</a> and link to this thread if needed.</t>
-				</p>
-				<p>
-					&laquo; <a href="[n.page_node.path/]">Go back</a>
-				</p>
-			</body>
-		</n.html>
-	</n.node_page.>
-</macro>
\ No newline at end of file
--- a/src/nabble/modules/naml/invite_subscribers.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/modules/naml/invite_subscribers.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -109,9 +109,7 @@
 				<t><t.owner_name.page_node.owner.name/> is inviting you to subscribe to <t.location.page_node.subject/>:</t>
 				<n.page_node.url/>
 
-				<t>With your subscription, updates will be sent directly to your email address
-				and you can reply to them to participate in the discussion. Your subscription works the same
-				as a mailing list.</t>
+				<t>With your subscription, updates will be sent directly to your email address.</t>
 
 				<t>To confirm your subscription, click on the link below:</t>
 				<n.local_subscription.send_subscription_invite_subscribe_by_code_url/>
@@ -128,9 +126,7 @@
 				<t><t.owner_name.page_node.owner.name/> is inviting you to subscribe to <t.location.bold.page_node.subject/>:</t><br/>
 				<a href="[n.page_node.url/]"><n.page_node.url/></a><br/>
 				<br/>
-				<t>With your subscription, updates will be sent directly to your email address
-				and you can reply to them to participate in the discussion. Your subscription works the same
-				as a mailing list.</t><br/>
+				<t>With your subscription, updates will be sent directly to your email address.</t><br/>
 				<br/>
 				<t>To confirm your subscription, click on the link below:</t>
 				<div style="background-color:#FFFADB;border:#EDDD79 solid 1px;margin:1.2em 0;padding:.5em">
--- a/src/nabble/modules/naml/mobile.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/modules/naml/mobile.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -125,7 +125,7 @@
     </n.encode_url.>
 </macro>
 
-<macro name="new_post5" parameters="page_name,mailing_list_etiquette,bottom,focus" requires="servlet">
+<macro name="new_post5" parameters="page_name,bottom,focus" requires="servlet">
     <n.mobile.>
         <n.node_page.>
             <n.handle_new_node_permission_error/>
@@ -200,7 +200,6 @@
 
                     <n.form. onsubmit="return singleSubmit(this)">
                         <n.type_field.hidden/>
-                        <n.mailing_list_notice.mailing_list_etiquette/>
 
                         <n.reply_form />
 
@@ -227,10 +226,6 @@
         <focus>
             <n.message_field.focus/>
         </focus>
-        <mailing_list_etiquette>
-            <li><t>Quote what you reply to and trim it to only the relevant parts. This provides context for those who will read your message by email.</t></li>
-            <li><t>Avoid small talk such as "Thank you", "Great"... You can <n.page_node.reply_to_author_link.>send a private email</n.page_node.reply_to_author_link.> if you want.</t></li>
-        </mailing_list_etiquette>
         <bottom>
             <n.in_reply_to/>
         </bottom>
@@ -327,9 +322,5 @@
         <focus>
             <n.subject_field.focus/>
         </focus>
-        <mailing_list_etiquette>
-            <li><t>If you are posting a question, please try search first. Your question may have already been answered.</t></li>
-            <li><t>Don't post repeatedly. Wait for a few days. People will read your post by email.</t></li>
-        </mailing_list_etiquette>
     </n.new_post5>
 </macro>
\ No newline at end of file
--- a/src/nabble/modules/naml/ppc.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/modules/naml/ppc.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -115,8 +115,7 @@
 				<n.page_node.owner.name/> subscribed you to <n.page_node.subject/>:
 				<n.page_node.url/>
 
-				With your subscription, posts and replies will be sent directly to your email
-				and you can reply to them to participate. Your subscription works as a mailing list.
+				With your subscription, posts and replies will be sent directly to your email.
 
 				If you don't want to be a subscriber, please click on the link below:
 				<n.local_subscription.unsubscribe_by_code_url/>
@@ -133,8 +132,7 @@
 				<n.page_node.owner.name/> subscribed you to <n.page_node.subject/>:<br/>
 				<n.page_node.url/><br/>
 				<br/>
-				With your subscription, posts and replies will be sent directly to your email
-				and you can reply to them to participate. Your subscription works as a mailing list.<br/>
+				With your subscription, posts and replies will be sent directly to your email.<br/>
 				<br/>
 				If you don't want to be a subscriber, please click on the link below:<br/>
 				<div style="background-color:#FFFADB;border:#EDDD79 solid 1px;margin:1.2em 0;padding:.5em">
--- a/src/nabble/view/lib/Jtp.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/lib/Jtp.java	Fri Jun 18 17:44:24 2021 -0600
@@ -346,8 +346,6 @@
 				words.add("board");
 				words.add("community");
 			}
-			if (node.getAssociatedMailingList() != null)
-				words.add("mailing list archive");
 		}
 		return metaKeywords(words);
 	}
@@ -361,8 +359,6 @@
 			if (! (name.toLowerCase().indexOf(viewName) >= 0)) {
 				buf.append(' ').append(viewName);
 			}
-			if (node.getAssociatedMailingList()!=null)
-				buf.append(" and mailing list archive");
 			buf.append(".");
 		}
 		appendSnippet(node.getMessage().getText(), buf);
--- a/src/nabble/view/lib/MyJtpServlet.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/lib/MyJtpServlet.java	Fri Jun 18 17:44:24 2021 -0600
@@ -48,7 +48,6 @@
 			nabble.view.web.forum.AttachmentDownload.class,
 			nabble.view.web.template.NamlDownload.class,
 			nabble.view.web.more.Forum.class,
-			nabble.view.web.more.MailingListRequest.class,
 			nabble.view.web.more.ForumStart.class,
 			nabble.view.web.seo.WidgetRedir.class,
 			nabble.view.web.util.GradientImage.class,
--- a/src/nabble/view/lib/Shared.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/lib/Shared.java	Fri Jun 18 17:44:24 2021 -0600
@@ -310,21 +310,6 @@
 
 	}
 
-	public static void showPending(PrintWriter out, Node post) {
-		Node.MailToList mail = post.getMailToList();
-		if (mail == null || !(post.getOwner() instanceof User))
-			return;
-		showPending(out, mail.isPending());
-	}
-
-    public static void showPending(PrintWriter out, boolean isPending) {
-		if (isPending) {
-			
-		out.print( "\r\n<img src=\"/images/icon_pending.png\" class=\"image16\" title=\"Pending - this message has not been accepted by the mailing list yet\"/>\r\n" );
-
-		}
-	}
-
 	public static void errorMessage(HttpServletRequest request,HttpServletResponse response,String errorMsg,String prompt)
 		throws ServletException, IOException
 	{
--- a/src/nabble/view/lib/Shared.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/lib/Shared.jtp	Fri Jun 18 17:44:24 2021 -0600
@@ -322,21 +322,6 @@
 		<%
 	}
 
-	public static void showPending(PrintWriter out, Node post) {
-		Node.MailToList mail = post.getMailToList();
-		if (mail == null || !(post.getOwner() instanceof User))
-			return;
-		showPending(out, mail.isPending());
-	}
-
-    public static void showPending(PrintWriter out, boolean isPending) {
-		if (isPending) {
-			%>
-			<img src="/images/icon_pending.png" class="image16" title="Pending - this message has not been accepted by the mailing list yet"/>
-			<%
-		}
-	}
-
 	public static void errorMessage(HttpServletRequest request,HttpServletResponse response,String errorMsg,String prompt)
 		throws ServletException, IOException
 	{
--- a/src/nabble/view/lib/SubscribeDefaultsMail.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-
-package nabble.view.lib;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.Date;
-import fschmidt.util.mail.Mail;
-import fschmidt.util.mail.MailException;
-import fschmidt.util.mail.MailHome;
-import fschmidt.util.mail.MailAddress;
-import fschmidt.util.mail.PlainTextContent;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-
-
-public final class SubscribeDefaultsMail {
-
-	public static Mail newMail(String email, MailingList mailingList, String url) {
-		StringWriter content = new StringWriter();
-		PrintWriter out = new PrintWriter(content);
-		
-		out.print( "\nDear Nabble user:\n\nAfter your subscription request to " );
-		out.print( (mailingList.getListAddress()) );
-		out.print( " has been accepted,\nplease follow the link below to turn off list mail delivery to your email address:\n\n" );
-		out.print( (url) );
-		out.print( "\n\nRegards,\nThe Nabble Team\n" );
-
-		out.close();
-		try {
-			Mail mail = MailHome.newMail();
-			mail.setFrom( new MailAddress(ModelHome.noReply) );
-			mail.setTo( new MailAddress(email) );
-			mail.setSubject( "Mailing list subscription settings" );
-			mail.setContent( new PlainTextContent(content.toString()) );
-			mail.setSentDate( new Date() );
-			return mail;
-		} catch(MailException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-}
-
--- a/src/nabble/view/lib/SubscribeDefaultsMail.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<%
-package nabble.view.lib;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.Date;
-import fschmidt.util.mail.Mail;
-import fschmidt.util.mail.MailException;
-import fschmidt.util.mail.MailHome;
-import fschmidt.util.mail.MailAddress;
-import fschmidt.util.mail.PlainTextContent;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-
-
-public final class SubscribeDefaultsMail {
-
-	public static Mail newMail(String email, MailingList mailingList, String url) {
-		StringWriter content = new StringWriter();
-		PrintWriter out = new PrintWriter(content);
-		%>
-		Dear Nabble user:
-		
-		After your subscription request to <%=mailingList.getListAddress()%> has been accepted,
-		please follow the link below to turn off list mail delivery to your email address:
-		
-		<%=url%>
-		
-		Regards,
-		The Nabble Team
-		<%
-		out.close();
-		try {
-			Mail mail = MailHome.newMail();
-			mail.setFrom( new MailAddress(ModelHome.noReply) );
-			mail.setTo( new MailAddress(email) );
-			mail.setSubject( "Mailing list subscription settings" );
-			mail.setContent( new PlainTextContent(content.toString()) );
-			mail.setSentDate( new Date() );
-			return mail;
-		} catch(MailException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-}
-%>
--- a/src/nabble/view/lib/help/Help.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/lib/help/Help.java	Fri Jun 18 17:44:24 2021 -0600
@@ -76,67 +76,25 @@
 		1, 
 		"What is Nabble?"
 ){public String answer(){return 
-		"\r\n		<p>\r\n		Nabble wants to improve public discussions on the web and provide useful embeddable applications to end users.\r\n		This includes forums, user groups, message boards, mailing lists, photo galleries, newspapers, blogs, etc.  There are many vibrant discussions in these places, so are problems such as cluttered UI, broken search, moderation, and cataloging. Nabble wants to be a place where your discussion can grow and be free of these problems.\r\n		</p>\r\n	"
+		"\r\n		<p>\r\n		Nabble wants to improve public discussions on the web and provide useful embeddable applications to end users.\r\n		This includes forums, user groups, message boards, photo galleries, newspapers, blogs, etc.  There are many vibrant discussions in these places, so are problems such as cluttered UI, broken search, moderation, and cataloging. Nabble wants to be a place where your discussion can grow and be free of these problems.\r\n		</p>\r\n	"
 ;}};
 	public static final Help free = new Help(
 		2, 
 		"Is Nabble really free?"
 ){public String answer(){return 
-		"\r\n		<p>\r\n		Yes. Nabble is absolutely free and will remain free to the users. This includes the end users,\r\n		mailing list owners, and webmasters. If your website uses Nabble as a hosted forum or a list archive,\r\n		be assured that there is no limit on traffic or disk space, no hosting fees, no pay-for versions or label schemes.\r\n		Nabble is just free.\r\n		</p>\r\n	"
-;}};
-	public static final Help add = new Help(
-		4, 
-		"How do I add my mailing list to Nabble archive?"
-){public String answer(){return 
-		"\r\n		<p>\r\n		Go the <a href=\"/\">Nabble home page</a>, and click on the <a href=\"/more/MailingListRequest.jtp\">Archive Mailing list</a> link.\r\n		Fill out the form and follow the instructions there.\r\n		</p>\r\n	"
-;}};
-	public static final Help find = new Help(
-		5, 
-		"How do I find my mailing list on Nabble?"
-){public String answer(){return 
-		"\r\n		<p>\r\n		Search your mailing list address from <a href=\"/\">Nabble home page</a>. If there is a match, you will find a forum link in the upper part of the result page.\r\n		</p>\r\n	"
-;}};
-	public static final Help owner = new Help(
-		6, 
-		"Do I have to be the list owner to archive a list at Nabble?"
-){public String answer(){return 
-		"\r\n		<p>\r\n			No. Anybody can add a list to Nabble archive.\r\n			If you subscribe to a list, and find yourself receiving too many emails, or having a hard time searching through the messages, you can consider getting a Nabble archive for the list.\r\n			This way you can view, search, post, entirely from the web without cluttering your inbox.\r\n		</p>\r\n	"
-;}};
-	public static final Help why = new Help(
-		7, 
-		"Why is my mailing list archived without my knowledge?"
-){public String answer(){return 
-		"\r\n		<p>\r\n		Mailing list archive is not something new. Besides Nabble, a public mailing list is very likely archived somewhere else.\r\n		For example, try searching on <a href=\"http://gmane.org/find.php\" target=\"_top\" rel=\"nofollow\">Gmane</a>, <a href=\"http://www.mail-archive.com/\" target=\"_top\" rel=\"nofollow\">Mail-archive</a>, <a href=\"http://marc.theaimsgroup.com/\" target=\"_top\" rel=\"nofollow\">MARC</a>, and <a href=\"http://opensubscriber.com/\" target=\"_top\" rel=\"nofollow\">OpenSubscriber</a>.\r\n		They have all existed long before Nabble. Nabble may have found your public mailing list from these places.\r\n		Or, your list's members may have added your list to Nabble's archive.\r\n		</p>\r\n		<p>\r\n		If you feel upset because nobody asked you for permission, take it easy.\r\n		An archive works like Google. Google will use a crawler to crawl your site to collect the web pages and index them,\r\n		much the same way as an archive using an email address to subscribe to your list to receive the messages and index them.\r\n		Were Google to ask permission from every webmaster, it would take too long, and there\r\n		would be no Google or search engines. But, if you don't like it, we will delete it.\r\n		</p>\r\n	"
+		"\r\n		<p>\r\n		Yes. Nabble is absolutely free and will remain free to the users. This includes the end users\r\n		and webmasters. If your website uses Nabble as a hosted forum,\r\n		be assured that there is no limit on traffic or disk space, no hosting fees, no pay-for versions or label schemes.\r\n		Nabble is just free.\r\n		</p>\r\n	"
 ;}};
 	public static final Help sell = new Help(
 		10, 
-		"Can Nabble sell the data (archive)?"
+		"Can Nabble sell the data?"
 ){public String answer(){return 
 		"\r\n		<p>\r\n		It's like asking can Google sell the web pages in its index?\r\n		Absolutely not. A message belongs to its author. Besides, an email address is sacred.\r\n		</p>\r\n	"
 ;}};
-	public static final Help post = new Help(
-		11, 
-		"Did Nabble break my subscription policy?"
-){public String answer(){return 
-		"\r\n		<p>\r\n		Nabble supports many mailing list software such as mailman, ezmlm, and listserv. For all supported list software, Nabble conforms to the mailing list subscription policy. A non-subscriber will be prompted to subscribe to the mailing list before he/she can post to the mailing list. Without subscription, the post will be rejected as a non-subscriber post. Note that only registered users can post from Nabble. The Nabble registration process is the same as the mailing list subscription process. This means extra protection and validation.\r\n		</p>\r\n		<p>\r\n		You can think of Nabble as a web interface to your list. Without it, a user will have to view and post from an email box that tends to clutter. With Nabble, users who prefer the web view can post from the web, and interact with the same email users seamlessly.\r\n		</p>\r\n		<p>\r\n		The feature of bridging a forum and a list is not new. It is called mail-to-news gateway - Gmane.org probably has already archived your list this way. If you still have concerns, please contact us.\r\n		</p>\r\n	"
-;}};
-	public static final Help userid = new Help(
-		12, 
-		"Why do I see a user account with my name when I haven't registered?"
-){public String answer(){return 
-		"\r\n		<p>\r\n		Nabble archives public mailing lists and will create user accounts for users on these lists.  If you have posted to the  mailing lists before, Nabble may have created an unregistered account for you.  Since this account is unregistered, you cannot use it until you register with Nabble.  When you register with Nabble using the same email address as you used on the mailing list, you will be able to take ownership of this account and will be able to post messages.\r\n		</p>\r\n		<p>\r\n		It is important that you use the same email address (that you used for the mailing list) to register because Nabble identifies users by their email addresses.  If you use an email address different from the one that you used for the mailing list, you are just creating a new account.  Nabble currently does not support merging of multiple user accounts.\r\n		</p>\r\n	"
-;}};
 	public static final Help delpost = new Help(
 		13, 
 		"How do I delete my posts?"
 ){public String answer(){return 
-		"\r\n		<p>\r\n		Log in to (or register with) Nabble and then you can find and delete your posts on Nabble.\r\n		</p>\r\n		<p>\r\n		Please note that Nabble archives public mailing lists. If you post to a public mailing list, then your message will become public records and anybody can archive it. There are several public mailing list archives like Nabble, for example, Gmane and mail-archive.com; in addition, a mailing list usually has its own native archive. Once you make a public post, it's hard to remove it from the web.\r\n		</p>\r\n		<p>\r\n		Most archives do not allow you to delete your message. With Nabble, you can. But you will need to register with Nabble using the same email address that you used for your post. Please note that we have no particular interest in knowing your email address because your email address is already available to public through the mailing list archives. We require you to register only because we need to verify that you are the owner of the post. After you register, log in, go to your post, and you will find a \"delete\" link to delete your post.\r\n		</p>\r\n	"
-;}};
-	public static final Help pending = new Help(
-		15, 
-		"Why is my post \"pending\"? How to fix it?"
-){public String answer(){return 
-		"\r\n		<p>\r\n		Your post is pending because you posted it to a special Nabble forum which is both a forum and a web\r\n		gateway to a mailing list. Your message is already posted on Nabble, but it has not been accepted by\r\n		the mailing list yet.\r\n		</p>\r\n		<p>\r\n		A mailing list is a subscriber-only email forwarding service. A subscriber sends email to the\r\n		mailing list, and the mailing list fowards his email to all subscribers. This allows subscribers to discuss\r\n		topics by reading and replying via email. Nabble works as a bridge to forward your post to the mailing list.\r\n		If you are a subscriber, the mailing list will take your post and forward it to all subscribers.\r\n		But if you are not, then your post will be rejected and thus it will be in a \"pending\" status.\r\n		</p>\r\n		<p>\r\n		<strong>Are you a registered user of Nabble?</strong> Please note that being registered with Nabble does not mean that you are a subscriber to mailing lists. In fact, each mailing list requires a separate subscription.\r\n		</p>\r\n		<p>\r\n		Have you confirmed your subscription yet? You may have just clicked a \"Subscribe\" button, but may not have followed\r\n		through with the two additional steps:\r\n		</p>\r\n		<ol>\r\n			<li>Check your email for a confirmation email from the mailing list.\r\n			<li>Follow the instruction in the email to confirm subscription.\r\n		</ol>\r\n		<p>\r\n		Sounds complicated? You bet. But the good part of this mechanism is that it helps to filter out careless posters.\r\n		Because most users on a mailing list are dedicated and careful users, you are likely to get quality responses\r\n		once your post goes through.\r\n		</p>\r\n		<h3>How to fix pending messages?</h3>\r\n		<p>\r\n			Nabble doesn't allow you to resend your message to the mailing list.\r\n			The right way of doing this is to compose a new message, which will be sent as a new email.\r\n			You might want to delete your old pending messages in order to keep the forum clean and organized.\r\n			To find your pending messages, go to <b>Your Account > Account Settings > Pending Posts</b>.\r\n		</p>\r\n		<p>\r\n		The most important thing is to make sure you are a subscriber.\r\n		If you haven't subscribed yet, do it and wait for confirmation.\r\n		Then follow the instruction to confirm.\r\n		If you don't remember whether you have subscribed before, subscribe again.\r\n		After you have confirmed a subscription, go back to your pending message and repost the message.\r\n		</p>\r\n\r\n		<h3>I am sure I have subscribed, but why is my message still pending?</h3>\r\n		<p>\r\n		A post to a mailing list will appear as pending right after being posted.\r\n		This is normal because it takes a few minutes for your post to get forwarded and processed by a mailing list server.\r\n		Usually, if you are a subscriber, after a few minutes, your pending message will get posted and the pending messages page will remove that post from the list.\r\n		</p>\r\n		<p>\r\n		When you are a subscriber and you see a post pending for several hours after your have posted, it could be that the mailing list server is slow or unavailable.\r\n		Your post may be pending simply because the mailing list server has not processed it yet.\r\n		Try going to the mailing list website to see if it is slow. Don't post repeatedly. Try reposting in a day or two.\r\n		</p>\r\n		<p>\r\n		Sometimes mailing lists may reject your message for format or editorial reasons. For example, some mailing lists\r\n		do not accept HTML formats, and some forbids certain language or content. Usually, the mailing list will reject\r\n		your post and email you a notice with an explanation. In such cases, go to the pending post to \"Edit\" it so that\r\n		it conforms with the mailing list requirement, then post again. Or, you can simply delete your post.\r\n		</p>\r\n	"
+		"\r\n		<p>\r\n		Log in to (or register with) Nabble and then you can find and delete your posts on Nabble.\r\n		</p>\r\n	"
 ;}};
 	public static final Help moderation = new Help(
 		16, 
@@ -144,18 +102,6 @@
 ){public String answer(){return 
 		"\r\n		<p>\r\n			SPAM and bad posts are common problems for forums.\r\n			With Nabble, forum owners can easily remove unwanted messages and ban bad users.\r\n			Both actions are available in the dropdown menu close to the message.\r\n		</p>\r\n		<p>\r\n			We should remember that anonymous users can't be banned.\r\n			However, you can disable anonymous posts for your forum by accessing the <b>Options > Users > Control anonymous users</b> action in the forum options menu.\r\n		</p>\r\n	"
 ;}};
-	public static final Help mailingListIntro = new Help(
-		17, 
-		"What is a \"mailing list\"?"
-){public String answer(){return 
-		"\r\n		<p>\r\n		A mailing list is an email forwarding service for subscribers. People set up a mailing list to distribute information about a certain topic. If you are interested in the topic, you can subscribe and then start receiving messages via email. You can also email your questions or relevant information to the mailing list which will then forward them to all other subscribers. Some people call \"mailing list\" the email discussion group.\r\n		</p>\r\n		<h2>Nabble provides a web archive/gateway to mailing lists.</h2>\r\n		<p>\r\n		Nabble works as a web archive to mailing lists to allow search and browsing. Also it allows web users to post messages through Nabble which then forwards it as an email to the mailing list. This means web users can join an email discussion through the web and all users are in sync.\r\n		</p>\r\n		<p>\r\n		Nabble supports many mailing list software. For all the supported listserv software, Nabble conforms with the mailing list's subscription policy. This means that a user will need to become a subscriber to a mailing list before he can post through the Nabble web archive.\r\n		</p>\r\n		<p>\r\n		<b>Please note:</b> being a registered Nabble user does not mean you are a subscriber to a mailing list. Each mailing list requires separate subscription.\r\n		</p>\r\n	"
-;}};
-	public static final Help stopEmails = new Help(
-		18, 
-		"Why do I receive emails after I made a post on Nabble? How to stop it?"
-){public String answer(){return 
-		"\r\n		<p>\r\n		If you find yourself receiving many emails (not spam, just regular emails) after making a post on Nabble, don't worry, it can be easily fixed.\r\n		</p>\r\n		<p>\r\n		What happened is that your were probably posting through Nabble to a \"mailing list\", also known as the email discussion group,\r\n		and it requires that you become a subscriber before you can post. You probably remember seeing the prompt to subscribe.\r\n		You have to do that in order for your post to go out, but as a result, you subscribed and that is why you are receiving\r\n		the emails. You should also have received an automatic email from Nabble with a link that you can click to stop\r\n		receiving emails. If you missed that email or don't remember, continue reading.\r\n		</p>\r\n		<h3>How to stop it?</h3>\r\n		<ol>\r\n		<li>Go to the forum where you posted a message.\r\n		<br/>If you remember where you posted, go there directly. If you don't, try to find your post first, then go up one level\r\n		to the forum level. Or, you can search Nabble by the email address of the mailing list. You can find the email address by\r\n		looking for the \"to:\" field in those unwanted emails that you received from the mailing list.\r\n		<br/><br/>\r\n		<li>Click the \"mailing list options\" link.\r\n		<br/>In the subsequent page you will find options to turn off email delievery or simply unsubscribe. Follow through\r\n		the instructions there.\r\n		</ol>\r\n	"
-;}};
 	public static final Help stopAlert = new Help(
 		19, 
 		"How do I stop an email alert?"
@@ -168,17 +114,6 @@
 ){public String answer(){return 
 		"\r\n		<p>\r\n			Under the \"Options\" menu, under \"Users\", is the option \"Who can view & post\".\r\n			This page controls who can view and post in this forum.  But if this forum has a parent forum\r\n			and if the parent forum has restrictions, then those restriction will also apply.\r\n			This means that restrictions are only added as you go down your forum hierarchy.\r\n			This makes sense because when you set restrictions, you assume that they will apply to\r\n			all sub-forums as well.\r\n		</p>\r\n		<p>\r\n			Let's look at a few examples.  Suppose you have a forum hierarchy and want to ban anonymous users\r\n			throughout. You would go to the top forum and select that only registered users can create new topics and replies:\r\n		</p>\r\n		<p><img src=\"/images/help/registered_only.png\" width=505 height=108 style=\"padding-left:2em\"/></p>\r\n		<p>\r\n			Now suppose that under the top forum, you have an \"Official Business\" forum where only members of\r\n			a group should be allowed to post.  You would select that only members can create new topics and replies:\r\n		</p>\r\n		<p><img src=\"/images/help/members_only.png\" width=505 height=108 style=\"padding-left:2em\"/></p>\r\n		<p>\r\n			You would then authorize the right members for that \"Official Business\" forum only.\r\n		</p>\r\n		<p>\r\n			Now suppose that under that forum, you have an \"Announcements\" forum where only the organizer should\r\n			post.  The organizer should create that forum and select again that only members can post and reply in that forum,\r\n			but this time not authorize anyone else.  Now only the owner of the \"Announcements\" forum is authorized\r\n			to post there.  But suppose you want to allow members to comment on announcements but not to\r\n			make announcements.  Then instead of members can create new topics, but let everyone reply.\r\n			Note that \"Everyone\" means everyone who would otherwise be allowed to post.  So now within the \"Announcements\" forum,\r\n			only the owner can create threads, but all members can reply to those threads.\r\n		</p>\r\n	"
 ;}};
-
-	public static final Help copy = new Help(
-		9, 
-		"Isn't Nabble trying to copy and replace me?"
-){public String answer(){return 
-		"\r\n		<p>\r\n		Nabble wants to be useful and transparent.  If you feel shocked on seeing the Nabble mirror of your content,\r\n		please relax and be assured that the content is still yours, and you can delete it anytime. Then, before cursing\r\n		Nabble, try asking yourself:\r\n		</p>\r\n\r\n		<ul>\r\n		<li><p>Is Nabble useful?\r\n		<br>You probably will find the archive search useful. Nabble search is fast, and you can cross search all your\r\n		lists instead of searching each list or relying on Google's \"site:archive url\" search (which is a hack because\r\n		Google does not index all your posts, especially the new ones). What's more, some of your users may want a web\r\n		interface to read and post instead of using a cluttered email box. With Nabble, these users can talk from the\r\n		web and interact with the traditional email users seamlessly.\r\n		</p>\r\n		<li><p>Is Nabble taking users away from my site?\r\n		<br>We understand this concern. You put in effort to grow your users, and we have no right to get in between.\r\n		What we offer is an <a href=\""
-		+(Help.embed_what_how.url())
-		+"\" target=\"_top\" rel=\"nofollow\">\"embeddable\" forum</a>.\r\n		It means that you can customize the Nabble mirror to \"embed\" it into your website. The Nabble mirror will still be hosted at\r\n		Nabble, but you can control the look and feel so that it looks like a part of\r\n		your site, complete with your logo, style sheet, javascript, and even your ads.\r\n		</p>\r\n		<li><p>Is Nabble bypassing me?\r\n		<br>No. <a href=\""
-		+(Help.post.url())
-		+"\" target=\"_top\" rel=\"nofollow\">Nabble conforms with your subscription policy</a>.\r\n		This means if users want to post to your list via Nabble, they will have to join your list to become subscribers.\r\n		</p>\r\n		<li><p>What's in it for Nabble?\r\n		<br>Nabble wants to become the best place for online discussions. That's it for now. We don't know\r\n		yet how to make money.\r\n		</p>\r\n		</ul>\r\n		<p>\r\n		Keep in mind that by mirroring your discussion on Nabble, you could also expand your subscribers through\r\n		Nabble users. They may join your discussions and thus expand your membership.\r\n		They could also go from the discussion page to visit your website.\r\n		</p>\r\n	"
-;}};
 	public static final Help listSpam = new Help(
 		22, 
 		"My list received spam from Nabble. What do I do to prevent it from happening again?"
@@ -209,40 +144,20 @@
 ){public String answer(){return 
 		"\r\n		<p>\r\n		Yes. Nabble's content pages are designed with SEO (Search Engine Optimization) in mind.\r\n		Our SEO effort goes further beyond the usual tags and headers to advanced techniques such as URL encoding and PageRank distribution.\r\n		</p>\r\n	"
 ;}};
-	public static final Help mirror = new Help(
-		30, 
-		"Can I mirror my groups on Nabble?"
-){public String answer(){return 
-		"\r\n		<p>\r\n		If you own a discussion group such as Yahoo or Google group, you can mirror it on Nabble by using Nabble's mailing list archive feature. Nabble complements your existing group by providing a nice threaded view and a <a href=\""
-		+(Help.search.url())
-		+"\">powerful search</a>. What's more, if you have a quality group you may expand it by getting new users from Nabble.\r\n		</p>\r\n		<p>\r\n		Most importantly, Nabble adds an extra layer of redundancy. With Nabble, you can download all your content for backup or moving purposes anytime you want. This means you will never get stuck with any forum provider including Nabble.\r\n		</p>\r\n	"
-;}};
 	public static final Help search = new Help(
 		31, 
 		"What search features does Nabble provide?"
 ){public String answer(){return 
 		"\r\n		<p>\r\n		Nabble allows many flavors of specific search.\r\n		</p>\r\n		<ul>\r\n		<li>You can search entire Nabble (with the help of Google Search).\r\n		<li>You can search within an application (e.g., forum, photo gallery, newspaper, blog) to include all subcategories below.\r\n		<li>You can narrow your search result by date.\r\n		<li>You can search messages by user. Click a user name link to go to the user's profile page, search from there. Then you can narrow your search result by date, by category, or by both.\r\n		<li>Nabble search supports keyword stemming, i.e. search, searching, searched, searches...\r\n		</ul>\r\n\r\n		<h2>Examples</h2>\r\n\r\n		<p>\r\n		<table class=\"search-tips-table\" style=\"\r\n			width: 100%;\r\n			border-collapse: collapse;\r\n		\">\r\n		<style type=\"text/css\">\r\n		.nabble .search-tips-table th {\r\n			text-align: left;\r\n			font-weight: bold;\r\n			padding: .5em;\r\n			vertical-align: top;\r\n		}\r\n		.nabble .search-tips-table td {\r\n			padding: .3em;\r\n			border-bottom-width: 1px;\r\n			border-bottom-style: solid;\r\n			vertical-align: top;\r\n		}\r\n		</style>\r\n		<tr>\r\n			<th>Your search</th>\r\n			<th>What will search results show</th>\r\n		</tr>\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">hello world</code></td>\r\n\r\n			<td class=\"info-message\">Messages with both <code class=\"important\">hello</code> and <code class=\"important\">world</code></td>\r\n		</tr>\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">\"hello world\"</code></td>\r\n			<td class=\"info-message\">Messages with the phrase <code class=\"important\">hello world</code></td>\r\n\r\n		</tr>\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">hello OR world</code></td>\r\n			<td class=\"info-message\">Messages with either <code class=\"important\">hello</code> or <code class=\"important\">world</code></td>\r\n		</tr>\r\n		<tr>\r\n\r\n			<td class=\"info-message\"><code class=\"important\">hello AND world</code></td>\r\n			<td class=\"info-message\">Messages with <code class=\"important\">hello</code> and <code class=\"important\">world</code>; same as entering <code class=\"important\">hello world</code></td>\r\n		</tr>\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">\"hello world\" lucene</code></td>\r\n\r\n			<td class=\"info-message\">Messages with both the phrase <code class=\"important\">hello world</code> and <code class=\"important\">lucene</code></td>\r\n		</tr>\r\n\r\n\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">hello NOT world</code></td>\r\n			<td class=\"info-message\">Messages that have <code class=\"important\">hello</code>, but do not have <code class=\"important\">world</code></td>\r\n\r\n		</tr>\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">(\"hello world\" lucene) OR apache</code></td>\r\n			<td class=\"info-message\">Messages with either both <code class=\"important\">hello world</code> and <code class=\"important\">lucene</code>, or <code class=\"important\">apache</code></td>\r\n		</tr>\r\n\r\n\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">lucene NOT \"hello world\"</code></td>\r\n			<td class=\"info-message\">Messages with <code class=\"important\">lucene</code>, but not the phrase <code class=\"important\">hello world</code></td>\r\n		</tr>\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">hello*</code></td>\r\n\r\n			<td class=\"info-message\">Messages that have words that begin with <code class=\"important\">hello</code>. For example, <code class=\"important\">hello</code>, <code class=\"important\">helloworld</code>, and <code class=\"important\">hellooooooo</code>. * is a wildcard and matches 0 or more characters.</td>\r\n		</tr>\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">par?</code></td>\r\n\r\n			<td class=\"info-message\">Messages that have words such as <code class=\"important\">park</code>, <code class=\"important\">part</code>, <code class=\"important\">para</code>, and so forth. ? is a 1-character wildcard and matches 1 and only 1 character.</td>\r\n		</tr>\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">subject:\"hello world\"</code></td>\r\n			<td class=\"info-message\">Messages with the phrase <code class=\"important\">hello world</code> in its <code class=\"important\">subject</code> only.</td>\r\n\r\n		</tr>\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">subject:(hello world)</code></td>\r\n			<td class=\"info-message\">Messages with <code class=\"important\">hello</code> and <code class=\"important\">world</code> in its <code class=\"important\">subject</code> only. Note the use of () to groups words together, rather than \"\" which denote a phrase.</td>\r\n	    </tr>\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">message:\"hello world\"</code></td>\r\n			<td class=\"info-message\">Messages with the phrase <code class=\"important\">hello world</code> in its <code class=\"important\">message body</code> only.</td>\r\n		</tr>\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">author:\"Erik Hatcher\"</code></td>\r\n			<td class=\"info-message\">Messages of <code class=\"important\">Erik Hatcher</code> only.</td>\r\n		</tr>\r\n		<tr>\r\n			<td class=\"info-message\"><code class=\"important\">roam~</code></td>\r\n			<td class=\"info-message\">Messages with <code class=\"important\">foam</code>, <code class=\"important\">roam</code>, and so forth. In essence, messages that match or sound like <code class=\"important\">roam</code>.</td>\r\n		</tr>\r\n		</table>\r\n		</p>\r\n\r\n		<a name=\"search1\"><h2>Search Using Words or Phrases </h2></a>\r\n		<p>You may search Nabble using a single-word (e.g., \"test\" or \"hello\") or use a group of words or a phrase surrounded by double quotes (e.g., \"hello dolly\"). When searching by a group of words or a phrase, Nabble will return only those items that have both the words present. </p>\r\n\r\n		<a name=\"search2\"><h2>Boolean Searches</h2></a>\r\n		<p>Boolean operators allow combining of search terms using logical operators such as AND, OR, and NOT. Please note that the Boolean operators must be all caps as in the examples below:</p>\r\n\r\n		<ul>\r\n			<li>To search for documents that contain \"debian linux\" and \"java\" use: \"debian linux\" AND java </li>\r\n			<li>To search for documents that contain either \"jetty\" or \"resin\" use: jetty OR resin </li>\r\n			<li>To search for documents that contain \"linux\" but not \"kernel\" use: linux NOT kernel </li>\r\n			<li>To search for documents that contain \"lucene\" or \"nutch\" but not \"apache\" use: (lucene OR nutch) NOT apache </li>\r\n		</ul>\r\n\r\n		<a name=\"search3\"><h2>Search Messages, Subjects, Authors</h2></a>\r\n		<p>You can limit your search to either the message text, the subject of the message, the author name, the name of the forum, and/or the topic of the discussion by using the syntax shown in examples below: </p>\r\n\r\n		<ul>\r\n			<li>subject:\"lord of the rings\" message:film </li>\r\n			<li>author:\"doug cutting\" message:lucene </li>\r\n		</ul>\r\n\r\n		<p>If you don't specify the type of search, it will search all -- message, subject, author. </p>\r\n\r\n		<a name=\"search4\"><h2>Wildcard Searches </h2></a>\r\n		<p>Nabble allows you to do both single and multiple character wildcard searches. </p>\r\n\r\n		<ul>\r\n			<li>To perform a single character wildcard search use the \"?\" symbol. The single character wildcard search looks for terms that match that with the single character replaced. For example, to search for \"text\" or \"test\" you can use: te?t </li>\r\n			<li>To perform a multiple character wildcard search use the \"*\" symbol. Multiple character wildcard searches looks for 0 or more characters. For example, to search for photo, photography, photographer, you can use: photo* </li>\r\n			<li>You can also use the wildcard searches in the middle of a term.</li>\r\n		</ul>\r\n\r\n		<p><strong>Note:</strong> You cannot use a * or ? symbol as the first character of a search. Also if your wildcard search will result in too many matches, it cannot be processed.</p>\r\n\r\n		<a name=\"search5\"><h2>Fuzzy Searches</h2> </a>\r\n		<p>To do a fuzzy search use the tilde, \"~\", symbol at the end of a single word search. For example to search for a term similar in spelling to \"roam\" use the fuzzy search: roam~ </p>\r\n\r\n		<p>This search will find terms like foam and roams. </p>\r\n\r\n		<a name=\"search6\"><h2>Proximity Searches </h2></a>\r\n		<p>Nabble supports proximity search -- that is, finding words that are a within a specific distance away from each other. To do a proximity search use the tilde, \"~\", symbol at the end of a Phrase. For example to search for a \"apache\" and \"jakarta\" within 10 words of each other in a document use: \"jakarta apache\"~10 </p>\r\n\r\n	"
 ;}};
-    public static final Help orphan = new Help(
-		34, 
-		"What does \"parent message unknown\" mean?"
-){public String answer(){return 
-		"\r\n		<p>\r\n		Some messages that we receive from mailing lists don't have enough information for us to determine which message the message we received was in reply to.  In other words, we don't know the parent of that message.  So we mark the message with the image <img alt=\"Parent Message unknown\" title=\"Parent Message unknown\" width=\"13\" height=\"14\" src=\"/images/icon_orphan.png\" style=\"vertical-align:middle; vertical-align: absmiddle;\" border=\"0\" /> and usually assign the first post in the thread as the parent.  This only matters in the \"Threaded\" view where you can see the structure of messages and their replies.\r\n		</p>\r\n	"
-;}};
-	public static final Help security = new Help(
-		35, 
-		"Does Nabble have a security policy for mailing lists?"
-){public String answer(){return 
-		"\r\n		<p>\r\n		Yes.\r\n		</p>\r\n		<p>\r\n		Javascript code is not allowed in Nabble's archive.\r\n		Thus, any code that may arrive with an email is blocked for your security.\r\n		Only the safe part of the message is displayed in the archive, and\r\n		we also show a warning that the JavaScript was blocked.\r\n		</p>\r\n		<p>Nabble also removes <b>&lt;style&gt;</b> tags because they might prevent messages from being displayed properly.</p>\r\n	"
-;}};
 	public static final Help embed_what_how = new Help(
 		36, 
-		"Embeddable Forum, Photo Gallery, News, Blog, Mailing List & Other Apps!"
+		"Embeddable Forum, Photo Gallery, News, Blog & Other Apps!"
 ){
 		public String getMetaDescription() { return "Nabble has different embeddable applications, including free forum, photo gallery, news, blog and much more! All applications have no installation, no HTML hassle, just copy and paste of a small javascript code."; }
-		public String getMetaKeywords() { return "free, embeddable, forum, photo gallery, newspaper, blog, mailing list archive, easy, embedding, embedded, embed my forum, hosted, website, site, HTML"; }
+		public String getMetaKeywords() { return "free, embeddable, forum, photo gallery, newspaper, blog, easy, embedding, embedded, embed my forum, hosted, website, site, HTML"; }
 		public String answer(){return 
-		"\r\n\r\n		<h2>All Nabble apps are naturally embeddable!</h2>\r\n\r\n		<p>Yes, with Nabble, you get an embeddable forum, embeddable photo gallery, embeddable news, embeddable blog, embeddable mailing list & archive... and there are more to come!</p>\r\n		<p>All these embeddable apps are fully featured web applications. They all have full text search, user profile and access control, email subscription and integration, XML feed, moderation, CSS customization, unlimited uploading of pictures and files, threading, cataloging ... What's more, embedding a Nabble app is as easy as embedding a YouTube video - you just copy and paste a line of javascript code into your HTML page.</p>\r\n		<p>You may have seen some embeddable widgets, but Nabble's \"embeddability\" is far more advanced. A widget runs in a fixed frame, making the content either underflows or overflows (frame scrolling is your only option). In contrast, a Nabble embeddable app adjusts its height automatically and always fit seamlessly into your site.</p>\r\n\r\n		<p>All you have to do is go to your application, click on \"Options > Embedding options\" and you will see a text area with a code snippet.</p>\r\n		<p>Copy and paste that snippet into your HTML web page. Now open the page and you will see that your forum loads up seamlessly. No installation, no HTML hassle, just copy and paste.</p>\r\n		<p><b>Embedding may have issues with third-party cookies.</b>  This can be a problem if the user has disabled third-party cookies or if they are using Safari.  To avoid problems, we suggest that you use a <a href=\""
+		"\r\n\r\n		<h2>All Nabble apps are naturally embeddable!</h2>\r\n\r\n		<p>Yes, with Nabble, you get an embeddable forum, embeddable photo gallery, embeddable news & embeddable blog... and there are more to come!</p>\r\n		<p>All these embeddable apps are fully featured web applications. They all have full text search, user profile and access control, email subscription and integration, XML feed, moderation, CSS customization, unlimited uploading of pictures and files, threading, cataloging ... What's more, embedding a Nabble app is as easy as embedding a YouTube video - you just copy and paste a line of javascript code into your HTML page.</p>\r\n		<p>You may have seen some embeddable widgets, but Nabble's \"embeddability\" is far more advanced. A widget runs in a fixed frame, making the content either underflows or overflows (frame scrolling is your only option). In contrast, a Nabble embeddable app adjusts its height automatically and always fit seamlessly into your site.</p>\r\n\r\n		<p>All you have to do is go to your application, click on \"Options > Embedding options\" and you will see a text area with a code snippet.</p>\r\n		<p>Copy and paste that snippet into your HTML web page. Now open the page and you will see that your forum loads up seamlessly. No installation, no HTML hassle, just copy and paste.</p>\r\n		<p><b>Embedding may have issues with third-party cookies.</b>  This can be a problem if the user has disabled third-party cookies or if they are using Safari.  To avoid problems, we suggest that you use a <a href=\""
 		+(Help.domain_names.url())
 		+"\">custom domain</a> for Nabble that matches your domain.  For example, if your website is www.your-domain.com, you could use forum.your-domain.com for Nabble.  This ensures that Nabble's cookies aren't considered third-party by the browser.</p>\r\n		<p>Users will browse, search, post, and navigate without ever leaving your page. Your embedded application works as if it were custom built, installed, and visually integrated with your website.</p>\r\n		<p>Try this feature by creating a new application (e.g., forum, photo gallery, newspaper, blog, etc.) or using any Nabble forum that allows embedding. It is dead easy and seamless.</p>\r\n		"
 ;}};
@@ -259,8 +174,8 @@
 		39, 
 		"How can I customize the appearance of my embeddable application?"
 ){
-		public String getMetaDescription() { return "All Nabble applications are fully customizable. You can easily change the CSS stylesheet of your embeddable forum, photo gallery, newspaper, blog and mailing list archives."; }
-		public String getMetaKeywords() { return "customizable, embeddable, forum, photo gallery, newspaper, blog, mailing list archive, css, skins, examples, simple, easy"; }
+		public String getMetaDescription() { return "All Nabble applications are fully customizable. You can easily change the CSS stylesheet of your embeddable forum, photo gallery, newspaper, or blog."; }
+		public String getMetaKeywords() { return "customizable, embeddable, forum, photo gallery, newspaper, blog, css, skins, examples, simple, easy"; }
 		public String answer(){return 
 		"\r\n		<p>\r\n			Go to \"Options > Editor > Change appearance\" link in your application.\r\n			This screen has easy options to customize the basic look of your application:\r\n		</p>\r\n		<p><img src=\"/images/help/help_style_easy.png\" style=\"padding-left:2em\" alt=\"Here you can customize details about your application\"/></p>\r\n		<p>\r\n			If you want a more detailed customization, you can go to the \"Look and Feel\" section in order to provide a custom CSS (Cascading Style Sheets) text for your application.\r\n		</p>\r\n		<p><img src=\"/images/help/help_style_tab.png\" style=\"padding-left:2em\"/></p>\r\n		<p>As you can see in the image above, Nabble has some predefined styles ready for you. You can simply click on them to get their CSS into the text area.\r\n			After that, you can modify the text the way you want. This is a valuable source of examples that you can also use to learn more about Nabble's style.</p>\r\n		<h2>How to write your custom CSS</h2>\r\n		<p>\r\n			If you want to change the appearance of your application, you have to override <a href=\""
 		+(Shared.getCssPath())
@@ -337,13 +252,6 @@
 		"\r\n		<p>\r\n			In traditional forums, a bulleting board only shows subcategories where users are allowed to post messages.\r\n			With Nabble, any forum can be displayed as a bulletin board and this might create a strange board with threads and forums mixed in the same list.\r\n			This situation is not easy to create since Nabble doesn't allow users to post new topics under a board,\r\n			but you could face this problem if you change a regular forum into a bulletin board format or move threads directly to the board.\r\n		</p>\r\n		<p>\r\n			A mixed board generally isn't a good idea and should be fixed in order to avoid confusion.\r\n			Note that Nabble doesn't hide threads in that view because this would increase the confusion among users.\r\n			It is the forum owner's responsibility to keep the forum clean and organized.\r\n		</p>\r\n		<h3>How to fix it?</h3>\r\n		<p>\r\n			If your forum has a mixed bulletin board, do the following:\r\n		</p>\r\n		<ol>\r\n			<li style=\"padding-bottom:.3em\">If you have just a few threads under the board, you can move them one by one to the appropriate sub-forum.</li>\r\n			<li>\r\n				If the number of threads is high and moving one by one is inefficient, you should create a new board and move the current forum as a sub-forum of it.\r\n				You might have to move other sub-forums around in order to rebuild the bulletin board.\r\n			</li>\r\n		</ol>\r\n	"
 ;}};
 
-	public static final Help subscriptions = new Help(
-		45, 
-		"Is it possible to post messages through email?"
-){public String answer(){return 
-		"\r\n		<p>\r\n			Yes. Nabble has email subscriptions that allow you to receive emails for each message\r\n			posted under a forum. If you reply to those emails, your response will be appended to\r\n			the discussion in the forum archive.\r\n		</p>\r\n		<p>\r\n			To subscribe to a forum, open the forum page and click on <i>Options > Subscribe via email</i>.\r\n			You can choose if you want to receive an email for each message posted or just new topics.\r\n		</p>\r\n\r\n		<h2>Detailed Explanation</h2>\r\n\r\n		<p>\r\n		All forums at Nabble have a built-in mailing list that people can use to communicate.\r\n		In other words, users can compose, read and reply to messages via email independently of the forum web interface.\r\n		</p>\r\n\r\n		<p>If you want to subscribe to a mailing list, open the forum interface and click on \"Options > Subscribe via email\" as seen below:</p>\r\n\r\n		<p><img src=\"/images/help/subscribe.png\" alt=\"Subscribe via email\"></p>\r\n\r\n		<p>Here you can see the options when you click on that link:</p>\r\n\r\n		<p><img src=\"/images/help/subscribe2.png\" alt=\"Subscription options\"></p>\r\n\r\n		<p><b>(1) Individual emails</b> - You receive one email for each new post under the forum. If you reply to such emails, your message will be archived as a new reply on the forum.</p>\r\n\r\n		<p><b>(2) Digest</b> - You receive one email with a summary of all posts created in the last 24 hours. You can't reply to this type of email.</p>\r\n\r\n		<p>To manage your subscriptions, click on your profile (top right corner), then click on \"Personal Settings > Email Subscriptions\". From that screen you can change and remove subscriptions.</p>\r\n\r\n		<h2>Posting via Email</h2>\r\n\r\n		<p>To know the email of a given forum, go to the forum and click on \"Options > Post by email...\". To prevent spam, forum addresses are unique for each user. So you can't get a forum address and send it to your friends (they must click on that link).</p>\r\n	"
-;}};
-
 	public static final Help embed_js_options = new Help(
 		48, 
 		"Can I change other behaviors of an embedded forum?"
@@ -357,8 +265,8 @@
 		49, 
 		"Is it possible to show which users are online?"
 ){
-		public String getMetaDescription() { return "Nabble applications display who is online when you browse forums, photo galleries, newspapers, blogs and mailing list archives."; }
-		public String getMetaKeywords() { return "online users, forum, photo gallery, newspaper, blog, mailing list archive, free forum, free blog, free photo gallery"; }
+		public String getMetaDescription() { return "Nabble applications display who is online when you browse forums, photo galleries, newspapers and blogs."; }
+		public String getMetaKeywords() { return "online users, forum, photo gallery, newspaper, blog, free forum, free blog, free photo gallery"; }
 		public String answer(){return 
 		"\r\n		<p>\r\n			Yes, all Nabble applications (e.g., forum, photo gallery, newspaper, blog, etc.) have this feature.\r\n			Online users have a green circle at the bottom right corner of their avatars.\r\n		</p>\r\n	"
 ;}};
@@ -388,7 +296,7 @@
 		public String answer(){return 
 		"\r\n		<p>Yes, Nabble can export your forum data, subcategories and messages to the standard XML format.\r\n			You can download these files by clicking on \"Options > Download archives\". You will realize that Nabble\r\n			doesn't have these files ready for you, so first you will have to build them. This process may take some\r\n			minutes or even hours depending on the size of your application. You will receive an email when this process\r\n			has finished.</p>\r\n		<p>To make downloading easier, Nabble groups XML files into zip archives. Each zip archive contains thousands\r\n			of XML files, where each file represents a node in the forum structure (<a href=\""
 		+(Jtp.homeContextUrl())
-		+"/back-end.html\">learn more</a>).\r\n			Below you can find the description of each field in the XML file, which may help you in creating a parser for this information.</p>\r\n\r\n			<table class=\"editor-table\" cellpadding=\"5\" style=\"font-size:90%;\">\r\n			<tr class=\"shaded-bg-color\">\r\n			<th align=\"left\">Field</th>\r\n			<th align=\"left\">Description</th>\r\n			</tr>\r\n			<tr>\r\n			<td>exportId</td>\r\n			<td>ID of the node represented by the XML file. This ID may be referenced by other XML files as a way to express relationship.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>kind</td>\r\n			<td>Kind of the node (\"APP\" for applications or \"POST\" for messages).</td>\r\n			</tr>\r\n			<tr>\r\n			<td>ownerEmail</td>\r\n			<td>Email of the user who created the node represented by the XML file.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>ownerName</td>\r\n			<td>Name of the user who created the node represented by the XML file.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>ownerAnonymousId</td>\r\n			<td>If the node was created by an anonymous user, this ID will identify this user (anonymous users are not registered and thus have no email information).</td>\r\n			</tr>\r\n			<tr>\r\n			<td>subject</td>\r\n			<td>Title/subject of this node.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>message</td>\r\n			<td>Message contents of this node.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>msgFmt</td>\r\n			<td>Format of the message (m=mail, h=html or t=text).</td>\r\n			</tr>\r\n			<tr>\r\n			<td>parentId</td>\r\n			<td>ID of the parent node.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>whenCreated</td>\r\n			<td>Date/Time when the node was created (number of milliseconds since January 1, 1970, 00:00:00 GMT)</td>\r\n			</tr>\r\n			<tr>\r\n			<td>hasReplyAlert</td>\r\n			<td>true/false if user wants to receive new replies by email.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>whenUpdated</td>\r\n			<td>Date/Time when the node was updated (number of milliseconds since January 1, 1970, 00:00:00 GMT)</td>\r\n			</tr>\r\n			<tr>\r\n			<td>restriction</td>\r\n			<td>Type of restriction for this node (i.e., indicates who can view and post messages under this node): NONE, REGISTERED, PROTECTED_CHILDREN, REGISTERED_PROTECTED_CHILDREN, PROTECTED, PRIVATE, PROTECTED_READ_ONLY, PRIVATE_READ_ONLY.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>type</td>\r\n			<td>Node/Application type (FORUM, BOARD, CATEGORY, NEWS, GALLERY, BLOG, COMMENT)</td>\r\n			</tr>\r\n			<tr>\r\n			<td>customStyle</td>\r\n			<td>Custom CSS stylesheet created for this node.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>pin</td>\r\n			<td>Order of this node in the pinned list of the parent node.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>files</td>\r\n			<td>Files attached to this node. Creates one entry for each file. Contents are byte arrays encrypted using Base64 encoding.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>messageID</td>\r\n			<td>\"Message ID\" header of the email sent for this node (only for mailing list archives).</td>\r\n			</tr>\r\n			<tr>\r\n			<td>isGuessedParent</td>\r\n			<td>true/false if Nabble had to guess the parent of this node (only for mailing list archives).</td>\r\n			</tr>\r\n			<tr>\r\n			<td>mlAddress</td>\r\n			<td>Email address of the mailing list archived by this node (only for mailing list archives).</td>\r\n			</tr>\r\n			<tr>\r\n			<td>mlUrl</td>\r\n			<td>Website URL of the mailing list archived by this node.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>mlPlainTextOnly</td>\r\n			<td>true/false if this mailing list accepts only plain-text emails.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>mlIgnoreNoArchive</td>\r\n			<td>true/false if Nabble should ignore the X-No-Archive header in emails sent to this mailing list archive.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>mlServer</td>\r\n			<td>Mailing list server type (e.g., google groups, yahoo groups, mailman, etc.)</td>\r\n			</tr>\r\n			</table>\r\n	"
+		+"/back-end.html\">learn more</a>).\r\n			Below you can find the description of each field in the XML file, which may help you in creating a parser for this information.</p>\r\n\r\n			<table class=\"editor-table\" cellpadding=\"5\" style=\"font-size:90%;\">\r\n			<tr class=\"shaded-bg-color\">\r\n			<th align=\"left\">Field</th>\r\n			<th align=\"left\">Description</th>\r\n			</tr>\r\n			<tr>\r\n			<td>exportId</td>\r\n			<td>ID of the node represented by the XML file. This ID may be referenced by other XML files as a way to express relationship.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>kind</td>\r\n			<td>Kind of the node (\"APP\" for applications or \"POST\" for messages).</td>\r\n			</tr>\r\n			<tr>\r\n			<td>ownerEmail</td>\r\n			<td>Email of the user who created the node represented by the XML file.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>ownerName</td>\r\n			<td>Name of the user who created the node represented by the XML file.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>ownerAnonymousId</td>\r\n			<td>If the node was created by an anonymous user, this ID will identify this user (anonymous users are not registered and thus have no email information).</td>\r\n			</tr>\r\n			<tr>\r\n			<td>subject</td>\r\n			<td>Title/subject of this node.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>message</td>\r\n			<td>Message contents of this node.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>msgFmt</td>\r\n			<td>Format of the message (m=mail, h=html or t=text).</td>\r\n			</tr>\r\n			<tr>\r\n			<td>parentId</td>\r\n			<td>ID of the parent node.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>whenCreated</td>\r\n			<td>Date/Time when the node was created (number of milliseconds since January 1, 1970, 00:00:00 GMT)</td>\r\n			</tr>\r\n			<tr>\r\n			<td>hasReplyAlert</td>\r\n			<td>true/false if user wants to receive new replies by email.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>whenUpdated</td>\r\n			<td>Date/Time when the node was updated (number of milliseconds since January 1, 1970, 00:00:00 GMT)</td>\r\n			</tr>\r\n			<tr>\r\n			<td>restriction</td>\r\n			<td>Type of restriction for this node (i.e., indicates who can view and post messages under this node): NONE, REGISTERED, PROTECTED_CHILDREN, REGISTERED_PROTECTED_CHILDREN, PROTECTED, PRIVATE, PROTECTED_READ_ONLY, PRIVATE_READ_ONLY.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>type</td>\r\n			<td>Node/Application type (FORUM, BOARD, CATEGORY, NEWS, GALLERY, BLOG, COMMENT)</td>\r\n			</tr>\r\n			<tr>\r\n			<td>customStyle</td>\r\n			<td>Custom CSS stylesheet created for this node.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>pin</td>\r\n			<td>Order of this node in the pinned list of the parent node.</td>\r\n			</tr>\r\n			<tr>\r\n			<td>files</td>\r\n			<td>Files attached to this node. Creates one entry for each file. Contents are byte arrays encrypted using Base64 encoding.</td>\r\n			</tr>\r\n			</table>\r\n	"
 ;}};
 
 	public static final Help pinned_subapps = new Help(
--- a/src/nabble/view/lib/help/Help.jmp	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/lib/help/Help.jmp	Fri Jun 18 17:44:24 2021 -0600
@@ -70,157 +70,30 @@
 		1, %>What is Nabble?<%){public String answer(){return %>
 		<p>
 		Nabble wants to improve public discussions on the web and provide useful embeddable applications to end users.
-		This includes forums, user groups, message boards, mailing lists, photo galleries, newspapers, blogs, etc.  There are many vibrant discussions in these places, so are problems such as cluttered UI, broken search, moderation, and cataloging. Nabble wants to be a place where your discussion can grow and be free of these problems.
+		This includes forums, user groups, message boards, photo galleries, newspapers, blogs, etc.  There are many vibrant discussions in these places, so are problems such as cluttered UI, broken search, moderation, and cataloging. Nabble wants to be a place where your discussion can grow and be free of these problems.
 		</p>
 	<%;}};
 	public static final Help free = new Help(
 		2, %>Is Nabble really free?<%){public String answer(){return %>
 		<p>
-		Yes. Nabble is absolutely free and will remain free to the users. This includes the end users,
-		mailing list owners, and webmasters. If your website uses Nabble as a hosted forum or a list archive,
+		Yes. Nabble is absolutely free and will remain free to the users. This includes the end users
+		and webmasters. If your website uses Nabble as a hosted forum,
 		be assured that there is no limit on traffic or disk space, no hosting fees, no pay-for versions or label schemes.
 		Nabble is just free.
 		</p>
 	<%;}};
-	public static final Help add = new Help(
-		4, %>How do I add my mailing list to Nabble archive?<%){public String answer(){return %>
-		<p>
-		Go the <a href="/">Nabble home page</a>, and click on the <a href="/more/MailingListRequest.jtp">Archive Mailing list</a> link.
-		Fill out the form and follow the instructions there.
-		</p>
-	<%;}};
-	public static final Help find = new Help(
-		5, %>How do I find my mailing list on Nabble?<%){public String answer(){return %>
-		<p>
-		Search your mailing list address from <a href="/">Nabble home page</a>. If there is a match, you will find a forum link in the upper part of the result page.
-		</p>
-	<%;}};
-	public static final Help owner = new Help(
-		6, %>Do I have to be the list owner to archive a list at Nabble?<%){public String answer(){return %>
-		<p>
-			No. Anybody can add a list to Nabble archive.
-			If you subscribe to a list, and find yourself receiving too many emails, or having a hard time searching through the messages, you can consider getting a Nabble archive for the list.
-			This way you can view, search, post, entirely from the web without cluttering your inbox.
-		</p>
-	<%;}};
-	public static final Help why = new Help(
-		7, %>Why is my mailing list archived without my knowledge?<%){public String answer(){return %>
-		<p>
-		Mailing list archive is not something new. Besides Nabble, a public mailing list is very likely archived somewhere else.
-		For example, try searching on <a href="http://gmane.org/find.php" target="_top" rel="nofollow">Gmane</a>, <a href="http://www.mail-archive.com/" target="_top" rel="nofollow">Mail-archive</a>, <a href="http://marc.theaimsgroup.com/" target="_top" rel="nofollow">MARC</a>, and <a href="http://opensubscriber.com/" target="_top" rel="nofollow">OpenSubscriber</a>.
-		They have all existed long before Nabble. Nabble may have found your public mailing list from these places.
-		Or, your list's members may have added your list to Nabble's archive.
-		</p>
-		<p>
-		If you feel upset because nobody asked you for permission, take it easy.
-		An archive works like Google. Google will use a crawler to crawl your site to collect the web pages and index them,
-		much the same way as an archive using an email address to subscribe to your list to receive the messages and index them.
-		Were Google to ask permission from every webmaster, it would take too long, and there
-		would be no Google or search engines. But, if you don't like it, we will delete it.
-		</p>
-	<%;}};
 	public static final Help sell = new Help(
-		10, %>Can Nabble sell the data (archive)?<%){public String answer(){return %>
+		10, %>Can Nabble sell the data?<%){public String answer(){return %>
 		<p>
 		It's like asking can Google sell the web pages in its index?
 		Absolutely not. A message belongs to its author. Besides, an email address is sacred.
 		</p>
 	<%;}};
-	public static final Help post = new Help(
-		11, %>Did Nabble break my subscription policy?<%){public String answer(){return %>
-		<p>
-		Nabble supports many mailing list software such as mailman, ezmlm, and listserv. For all supported list software, Nabble conforms to the mailing list subscription policy. A non-subscriber will be prompted to subscribe to the mailing list before he/she can post to the mailing list. Without subscription, the post will be rejected as a non-subscriber post. Note that only registered users can post from Nabble. The Nabble registration process is the same as the mailing list subscription process. This means extra protection and validation.
-		</p>
-		<p>
-		You can think of Nabble as a web interface to your list. Without it, a user will have to view and post from an email box that tends to clutter. With Nabble, users who prefer the web view can post from the web, and interact with the same email users seamlessly.
-		</p>
-		<p>
-		The feature of bridging a forum and a list is not new. It is called mail-to-news gateway - Gmane.org probably has already archived your list this way. If you still have concerns, please contact us.
-		</p>
-	<%;}};
-	public static final Help userid = new Help(
-		12, %>Why do I see a user account with my name when I haven't registered?<%){public String answer(){return %>
-		<p>
-		Nabble archives public mailing lists and will create user accounts for users on these lists.  If you have posted to the  mailing lists before, Nabble may have created an unregistered account for you.  Since this account is unregistered, you cannot use it until you register with Nabble.  When you register with Nabble using the same email address as you used on the mailing list, you will be able to take ownership of this account and will be able to post messages.
-		</p>
-		<p>
-		It is important that you use the same email address (that you used for the mailing list) to register because Nabble identifies users by their email addresses.  If you use an email address different from the one that you used for the mailing list, you are just creating a new account.  Nabble currently does not support merging of multiple user accounts.
-		</p>
-	<%;}};
 	public static final Help delpost = new Help(
 		13, %>How do I delete my posts?<%){public String answer(){return %>
 		<p>
 		Log in to (or register with) Nabble and then you can find and delete your posts on Nabble.
 		</p>
-		<p>
-		Please note that Nabble archives public mailing lists. If you post to a public mailing list, then your message will become public records and anybody can archive it. There are several public mailing list archives like Nabble, for example, Gmane and mail-archive.com; in addition, a mailing list usually has its own native archive. Once you make a public post, it's hard to remove it from the web.
-		</p>
-		<p>
-		Most archives do not allow you to delete your message. With Nabble, you can. But you will need to register with Nabble using the same email address that you used for your post. Please note that we have no particular interest in knowing your email address because your email address is already available to public through the mailing list archives. We require you to register only because we need to verify that you are the owner of the post. After you register, log in, go to your post, and you will find a "delete" link to delete your post.
-		</p>
-	<%;}};
-	public static final Help pending = new Help(
-		15, %>Why is my post "pending"? How to fix it?<%){public String answer(){return %>
-		<p>
-		Your post is pending because you posted it to a special Nabble forum which is both a forum and a web
-		gateway to a mailing list. Your message is already posted on Nabble, but it has not been accepted by
-		the mailing list yet.
-		</p>
-		<p>
-		A mailing list is a subscriber-only email forwarding service. A subscriber sends email to the
-		mailing list, and the mailing list fowards his email to all subscribers. This allows subscribers to discuss
-		topics by reading and replying via email. Nabble works as a bridge to forward your post to the mailing list.
-		If you are a subscriber, the mailing list will take your post and forward it to all subscribers.
-		But if you are not, then your post will be rejected and thus it will be in a "pending" status.
-		</p>
-		<p>
-		<strong>Are you a registered user of Nabble?</strong> Please note that being registered with Nabble does not mean that you are a subscriber to mailing lists. In fact, each mailing list requires a separate subscription.
-		</p>
-		<p>
-		Have you confirmed your subscription yet? You may have just clicked a "Subscribe" button, but may not have followed
-		through with the two additional steps:
-		</p>
-		<ol>
-			<li>Check your email for a confirmation email from the mailing list.
-			<li>Follow the instruction in the email to confirm subscription.
-		</ol>
-		<p>
-		Sounds complicated? You bet. But the good part of this mechanism is that it helps to filter out careless posters.
-		Because most users on a mailing list are dedicated and careful users, you are likely to get quality responses
-		once your post goes through.
-		</p>
-		<h3>How to fix pending messages?</h3>
-		<p>
-			Nabble doesn't allow you to resend your message to the mailing list.
-			The right way of doing this is to compose a new message, which will be sent as a new email.
-			You might want to delete your old pending messages in order to keep the forum clean and organized.
-			To find your pending messages, go to <b>Your Account > Account Settings > Pending Posts</b>.
-		</p>
-		<p>
-		The most important thing is to make sure you are a subscriber.
-		If you haven't subscribed yet, do it and wait for confirmation.
-		Then follow the instruction to confirm.
-		If you don't remember whether you have subscribed before, subscribe again.
-		After you have confirmed a subscription, go back to your pending message and repost the message.
-		</p>
-
-		<h3>I am sure I have subscribed, but why is my message still pending?</h3>
-		<p>
-		A post to a mailing list will appear as pending right after being posted.
-		This is normal because it takes a few minutes for your post to get forwarded and processed by a mailing list server.
-		Usually, if you are a subscriber, after a few minutes, your pending message will get posted and the pending messages page will remove that post from the list.
-		</p>
-		<p>
-		When you are a subscriber and you see a post pending for several hours after your have posted, it could be that the mailing list server is slow or unavailable.
-		Your post may be pending simply because the mailing list server has not processed it yet.
-		Try going to the mailing list website to see if it is slow. Don't post repeatedly. Try reposting in a day or two.
-		</p>
-		<p>
-		Sometimes mailing lists may reject your message for format or editorial reasons. For example, some mailing lists
-		do not accept HTML formats, and some forbids certain language or content. Usually, the mailing list will reject
-		your post and email you a notice with an explanation. In such cases, go to the pending post to "Edit" it so that
-		it conforms with the mailing list requirement, then post again. Or, you can simply delete your post.
-		</p>
 	<%;}};
 	public static final Help moderation = new Help(
 		16, %>How do I remove SPAM or bad users from my forum?<%){public String answer(){return %>
@@ -234,46 +107,6 @@
 			However, you can disable anonymous posts for your forum by accessing the <b>Options > Users > Control anonymous users</b> action in the forum options menu.
 		</p>
 	<%;}};
-	public static final Help mailingListIntro = new Help(
-		17, %>What is a "mailing list"?<%){public String answer(){return %>
-		<p>
-		A mailing list is an email forwarding service for subscribers. People set up a mailing list to distribute information about a certain topic. If you are interested in the topic, you can subscribe and then start receiving messages via email. You can also email your questions or relevant information to the mailing list which will then forward them to all other subscribers. Some people call "mailing list" the email discussion group.
-		</p>
-		<h2>Nabble provides a web archive/gateway to mailing lists.</h2>
-		<p>
-		Nabble works as a web archive to mailing lists to allow search and browsing. Also it allows web users to post messages through Nabble which then forwards it as an email to the mailing list. This means web users can join an email discussion through the web and all users are in sync.
-		</p>
-		<p>
-		Nabble supports many mailing list software. For all the supported listserv software, Nabble conforms with the mailing list's subscription policy. This means that a user will need to become a subscriber to a mailing list before he can post through the Nabble web archive.
-		</p>
-		<p>
-		<b>Please note:</b> being a registered Nabble user does not mean you are a subscriber to a mailing list. Each mailing list requires separate subscription.
-		</p>
-	<%;}};
-	public static final Help stopEmails = new Help(
-		18, %>Why do I receive emails after I made a post on Nabble? How to stop it?<%){public String answer(){return %>
-		<p>
-		If you find yourself receiving many emails (not spam, just regular emails) after making a post on Nabble, don't worry, it can be easily fixed.
-		</p>
-		<p>
-		What happened is that your were probably posting through Nabble to a "mailing list", also known as the email discussion group,
-		and it requires that you become a subscriber before you can post. You probably remember seeing the prompt to subscribe.
-		You have to do that in order for your post to go out, but as a result, you subscribed and that is why you are receiving
-		the emails. You should also have received an automatic email from Nabble with a link that you can click to stop
-		receiving emails. If you missed that email or don't remember, continue reading.
-		</p>
-		<h3>How to stop it?</h3>
-		<ol>
-		<li>Go to the forum where you posted a message.
-		<br/>If you remember where you posted, go there directly. If you don't, try to find your post first, then go up one level
-		to the forum level. Or, you can search Nabble by the email address of the mailing list. You can find the email address by
-		looking for the "to:" field in those unwanted emails that you received from the mailing list.
-		<br/><br/>
-		<li>Click the "mailing list options" link.
-		<br/>In the subsequent page you will find options to turn off email delievery or simply unsubscribe. Follow through
-		the instructions there.
-		</ol>
-	<%;}};
 	public static final Help stopAlert = new Help(
 		19, %>How do I stop an email alert?<%){public String answer(){return %>
 		<p>
@@ -312,45 +145,6 @@
 			only the owner can create threads, but all members can reply to those threads.
 		</p>
 	<%;}};
-
-	public static final Help copy = new Help(
-		9, %>Isn't Nabble trying to copy and replace me?<%){public String answer(){return %>
-		<p>
-		Nabble wants to be useful and transparent.  If you feel shocked on seeing the Nabble mirror of your content,
-		please relax and be assured that the content is still yours, and you can delete it anytime. Then, before cursing
-		Nabble, try asking yourself:
-		</p>
-
-		<ul>
-		<li><p>Is Nabble useful?
-		<br>You probably will find the archive search useful. Nabble search is fast, and you can cross search all your
-		lists instead of searching each list or relying on Google's "site:archive url" search (which is a hack because
-		Google does not index all your posts, especially the new ones). What's more, some of your users may want a web
-		interface to read and post instead of using a cluttered email box. With Nabble, these users can talk from the
-		web and interact with the traditional email users seamlessly.
-		</p>
-		<li><p>Is Nabble taking users away from my site?
-		<br>We understand this concern. You put in effort to grow your users, and we have no right to get in between.
-		What we offer is an <a href="<%=Help.embed_what_how.url()%>" target="_top" rel="nofollow">"embeddable" forum</a>.
-		It means that you can customize the Nabble mirror to "embed" it into your website. The Nabble mirror will still be hosted at
-		Nabble, but you can control the look and feel so that it looks like a part of
-		your site, complete with your logo, style sheet, javascript, and even your ads.
-		</p>
-		<li><p>Is Nabble bypassing me?
-		<br>No. <a href="<%=Help.post.url()%>" target="_top" rel="nofollow">Nabble conforms with your subscription policy</a>.
-		This means if users want to post to your list via Nabble, they will have to join your list to become subscribers.
-		</p>
-		<li><p>What's in it for Nabble?
-		<br>Nabble wants to become the best place for online discussions. That's it for now. We don't know
-		yet how to make money.
-		</p>
-		</ul>
-		<p>
-		Keep in mind that by mirroring your discussion on Nabble, you could also expand your subscribers through
-		Nabble users. They may join your discussions and thus expand your membership.
-		They could also go from the discussion page to visit your website.
-		</p>
-	<%;}};
 	public static final Help listSpam = new Help(
 		22, %>My list received spam from Nabble. What do I do to prevent it from happening again?<%){public String answer(){return %>
 		<p>
@@ -400,15 +194,6 @@
 		Our SEO effort goes further beyond the usual tags and headers to advanced techniques such as URL encoding and PageRank distribution.
 		</p>
 	<%;}};
-	public static final Help mirror = new Help(
-		30, %>Can I mirror my groups on Nabble?<%){public String answer(){return %>
-		<p>
-		If you own a discussion group such as Yahoo or Google group, you can mirror it on Nabble by using Nabble's mailing list archive feature. Nabble complements your existing group by providing a nice threaded view and a <a href="<%=Help.search.url()%>">powerful search</a>. What's more, if you have a quality group you may expand it by getting new users from Nabble.
-		</p>
-		<p>
-		Most importantly, Nabble adds an extra layer of redundancy. With Nabble, you can download all your content for backup or moving purposes anytime you want. This means you will never get stuck with any forum provider including Nabble.
-		</p>
-	<%;}};
 	public static final Help search = new Help(
 		31, %>What search features does Nabble provide?<%){public String answer(){return %>
 		<p>
@@ -565,34 +350,15 @@
 		<p>Nabble supports proximity search -- that is, finding words that are a within a specific distance away from each other. To do a proximity search use the tilde, "~", symbol at the end of a Phrase. For example to search for a "apache" and "jakarta" within 10 words of each other in a document use: "jakarta apache"~10 </p>
 
 	<%;}};
-    public static final Help orphan = new Help(
-		34, %>What does "parent message unknown" mean?<%){public String answer(){return %>
-		<p>
-		Some messages that we receive from mailing lists don't have enough information for us to determine which message the message we received was in reply to.  In other words, we don't know the parent of that message.  So we mark the message with the image <img alt="Parent Message unknown" title="Parent Message unknown" width="13" height="14" src="/images/icon_orphan.png" style="vertical-align:middle; vertical-align: absmiddle;" border="0" /> and usually assign the first post in the thread as the parent.  This only matters in the "Threaded" view where you can see the structure of messages and their replies.
-		</p>
-	<%;}};
-	public static final Help security = new Help(
-		35, %>Does Nabble have a security policy for mailing lists?<%){public String answer(){return %>
-		<p>
-		Yes.
-		</p>
-		<p>
-		Javascript code is not allowed in Nabble's archive.
-		Thus, any code that may arrive with an email is blocked for your security.
-		Only the safe part of the message is displayed in the archive, and
-		we also show a warning that the JavaScript was blocked.
-		</p>
-		<p>Nabble also removes <b>&lt;style&gt;</b> tags because they might prevent messages from being displayed properly.</p>
-	<%;}};
 	public static final Help embed_what_how = new Help(
-		36, %>Embeddable Forum, Photo Gallery, News, Blog, Mailing List & Other Apps!<%){
+		36, %>Embeddable Forum, Photo Gallery, News, Blog & Other Apps!<%){
 		public String getMetaDescription() { return "Nabble has different embeddable applications, including free forum, photo gallery, news, blog and much more! All applications have no installation, no HTML hassle, just copy and paste of a small javascript code."; }
-		public String getMetaKeywords() { return "free, embeddable, forum, photo gallery, newspaper, blog, mailing list archive, easy, embedding, embedded, embed my forum, hosted, website, site, HTML"; }
+		public String getMetaKeywords() { return "free, embeddable, forum, photo gallery, newspaper, blog, easy, embedding, embedded, embed my forum, hosted, website, site, HTML"; }
 		public String answer(){return %>
 
 		<h2>All Nabble apps are naturally embeddable!</h2>
 
-		<p>Yes, with Nabble, you get an embeddable forum, embeddable photo gallery, embeddable news, embeddable blog, embeddable mailing list & archive... and there are more to come!</p>
+		<p>Yes, with Nabble, you get an embeddable forum, embeddable photo gallery, embeddable news & embeddable blog... and there are more to come!</p>
 		<p>All these embeddable apps are fully featured web applications. They all have full text search, user profile and access control, email subscription and integration, XML feed, moderation, CSS customization, unlimited uploading of pictures and files, threading, cataloging ... What's more, embedding a Nabble app is as easy as embedding a YouTube video - you just copy and paste a line of javascript code into your HTML page.</p>
 		<p>You may have seen some embeddable widgets, but Nabble's "embeddability" is far more advanced. A widget runs in a fixed frame, making the content either underflows or overflows (frame scrolling is your only option). In contrast, a Nabble embeddable app adjusts its height automatically and always fit seamlessly into your site.</p>
 
@@ -618,8 +384,8 @@
 	<%;}};
 	public static final Help embed_skin = new Help(
 		39, %>How can I customize the appearance of my embeddable application?<%){
-		public String getMetaDescription() { return "All Nabble applications are fully customizable. You can easily change the CSS stylesheet of your embeddable forum, photo gallery, newspaper, blog and mailing list archives."; }
-		public String getMetaKeywords() { return "customizable, embeddable, forum, photo gallery, newspaper, blog, mailing list archive, css, skins, examples, simple, easy"; }
+		public String getMetaDescription() { return "All Nabble applications are fully customizable. You can easily change the CSS stylesheet of your embeddable forum, photo gallery, newspaper, or blog."; }
+		public String getMetaKeywords() { return "customizable, embeddable, forum, photo gallery, newspaper, blog, css, skins, examples, simple, easy"; }
 		public String answer(){return %>
 		<p>
 			Go to "Options > Editor > Change appearance" link in your application.
@@ -1054,44 +820,6 @@
 		</ol>
 	<%;}};
 
-	public static final Help subscriptions = new Help(
-		45, %>Is it possible to post messages through email?<%){public String answer(){return %>
-		<p>
-			Yes. Nabble has email subscriptions that allow you to receive emails for each message
-			posted under a forum. If you reply to those emails, your response will be appended to
-			the discussion in the forum archive.
-		</p>
-		<p>
-			To subscribe to a forum, open the forum page and click on <i>Options > Subscribe via email</i>.
-			You can choose if you want to receive an email for each message posted or just new topics.
-		</p>
-
-		<h2>Detailed Explanation</h2>
-
-		<p>
-		All forums at Nabble have a built-in mailing list that people can use to communicate.
-		In other words, users can compose, read and reply to messages via email independently of the forum web interface.
-		</p>
-
-		<p>If you want to subscribe to a mailing list, open the forum interface and click on "Options > Subscribe via email" as seen below:</p>
-
-		<p><img src="/images/help/subscribe.png" alt="Subscribe via email"></p>
-
-		<p>Here you can see the options when you click on that link:</p>
-
-		<p><img src="/images/help/subscribe2.png" alt="Subscription options"></p>
-
-		<p><b>(1) Individual emails</b> - You receive one email for each new post under the forum. If you reply to such emails, your message will be archived as a new reply on the forum.</p>
-
-		<p><b>(2) Digest</b> - You receive one email with a summary of all posts created in the last 24 hours. You can't reply to this type of email.</p>
-
-		<p>To manage your subscriptions, click on your profile (top right corner), then click on "Personal Settings > Email Subscriptions". From that screen you can change and remove subscriptions.</p>
-
-		<h2>Posting via Email</h2>
-
-		<p>To know the email of a given forum, go to the forum and click on "Options > Post by email...". To prevent spam, forum addresses are unique for each user. So you can't get a forum address and send it to your friends (they must click on that link).</p>
-	<%;}};
-
 	public static final Help embed_js_options = new Help(
 		48, %>Can I change other behaviors of an embedded forum?<%){public String answer(){return %>
 		<p>
@@ -1159,8 +887,8 @@
 
 	public static final Help online = new Help(
 		49, %>Is it possible to show which users are online?<%){
-		public String getMetaDescription() { return "Nabble applications display who is online when you browse forums, photo galleries, newspapers, blogs and mailing list archives."; }
-		public String getMetaKeywords() { return "online users, forum, photo gallery, newspaper, blog, mailing list archive, free forum, free blog, free photo gallery"; }
+		public String getMetaDescription() { return "Nabble applications display who is online when you browse forums, photo galleries, newspapers and blogs."; }
+		public String getMetaKeywords() { return "online users, forum, photo gallery, newspaper, blog, free forum, free blog, free photo gallery"; }
 		public String answer(){return %>
 		<p>
 			Yes, all Nabble applications (e.g., forum, photo gallery, newspaper, blog, etc.) have this feature.
@@ -1312,34 +1040,6 @@
 			<td>files</td>
 			<td>Files attached to this node. Creates one entry for each file. Contents are byte arrays encrypted using Base64 encoding.</td>
 			</tr>
-			<tr>
-			<td>messageID</td>
-			<td>"Message ID" header of the email sent for this node (only for mailing list archives).</td>
-			</tr>
-			<tr>
-			<td>isGuessedParent</td>
-			<td>true/false if Nabble had to guess the parent of this node (only for mailing list archives).</td>
-			</tr>
-			<tr>
-			<td>mlAddress</td>
-			<td>Email address of the mailing list archived by this node (only for mailing list archives).</td>
-			</tr>
-			<tr>
-			<td>mlUrl</td>
-			<td>Website URL of the mailing list archived by this node.</td>
-			</tr>
-			<tr>
-			<td>mlPlainTextOnly</td>
-			<td>true/false if this mailing list accepts only plain-text emails.</td>
-			</tr>
-			<tr>
-			<td>mlIgnoreNoArchive</td>
-			<td>true/false if Nabble should ignore the X-No-Archive header in emails sent to this mailing list archive.</td>
-			</tr>
-			<tr>
-			<td>mlServer</td>
-			<td>Mailing list server type (e.g., google groups, yahoo groups, mailman, etc.)</td>
-			</tr>
 			</table>
 	<%;}};
 
--- a/src/nabble/view/naml/app.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/app.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -218,9 +218,6 @@
 </macro>
 
 <macro name="app_title_ending" requires="node">
-	<n.if.is_associated_with_mailing_list_archive>
-		<then>| <t>Mailing List Archive</t></then>
-	</n.if.is_associated_with_mailing_list_archive>
 	<n.if.not.equal value1="[n.app_template/]" value2="[n.app_default_template/]">
 		<then>| <n.capitalize.substring text="[n.app_template/]" begin="5" /></then>
 	</n.if.not.equal>
@@ -234,7 +231,6 @@
 		<div id="forum-header">
 			<h1 id="forum-title" class="app-title-[n.id/] adbayes-content"><n.subject/></h1>
 			<div id="description-box" class="adbayes-content">
-				<n.mailing_list_information/>
 				<n.node_message_as_html/>
 			</div>
 			<div id="search-box" class="search-box">
--- a/src/nabble/view/naml/compile_all.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/compile_all.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -131,7 +131,6 @@
 	<n.compile macro="new_topic" namespaces="[n.standard_classes/]" />
 	<n.compile macro="change_post_date" namespaces="[n.standard_classes/]" />
 	<n.compile macro="create_sub_app" namespaces="[n.standard_classes/]" />
-	<n.compile macro="mailing_list_archive_settings" namespaces="[n.standard_classes/]" />
 	<n.compile macro="app_people" namespaces="[n.standard_classes/]" />
 	<n.compile macro="subscribe" namespaces="[n.standard_classes/]" />
 	<n.compile macro="subscribe_by_code" namespaces="[n.standard_classes/]" />
--- a/src/nabble/view/naml/create_sub_app.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/create_sub_app.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -25,10 +25,6 @@
 					<n.if.visitor.can_edit.page_node>
 						<then.new_node.pin/>
 					</n.if.visitor.can_edit.page_node>
-					<n.if.equal value1="[n.is_mailing_list_field.value/]" value2="[n.true/]">
-						<then><n.redirect_to.new_node.mailing_list_archive_settings_path/></then>
-						<else><n.redirect_to.new_node.path/></else>
-					</n.if.equal>
 				</n.catch_exception.>
 			</else>
 		</n.if.not.is_submitted_form>
@@ -90,16 +86,6 @@
 								</div>
 							</div>
 						</then>
-						<else>
-							<n.if.not.page_node.is_associated_with_mailing_list_archive>
-								<then>
-									<div style="margin:.5em 0 1em">
-										<n.is_mailing_list_field.checkbox />
-										<label for="[n.is_mailing_list_field.name/]"><t>This is a mailing list archive</t></label>
-									</div>
-								</then>
-							</n.if.not.page_node.is_associated_with_mailing_list_archive>
-						</else>
 					</n.if.not.visitor.is_registered>
 
 					<input type="submit" class="toolbar action-button" value="[t]Create [t.element.page_node.child_name/][/t]"/>
@@ -115,10 +101,6 @@
 	</n.node_page.>
 </macro>
 
-<macro name="is_mailing_list_field" dot_parameter="do">
-	<n.field. name="is_mailing_list"><n.do/></n.field.>
-</macro>
-
 <macro name="sub_app_type" requires="node">
 	<n.if.regex_matches text="[n.type/]" pattern="forum|category|mixed">
 		<then>forum</then>
--- a/src/nabble/view/naml/delete_app.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/delete_app.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -19,10 +19,6 @@
 				<n.edit_header first_text="[t]Delete Application[/t]" second_text="[n.page_node.subject/]"/>
 
 				<n.form.>
-					<n.if.page_node.is_a_mailing_list_archive>
-						<then><n.mailing_list_unsubscription_notice/></then>
-					</n.if.page_node.is_a_mailing_list_archive>
-
 					<div class="second-font field-title" style="margin-bottom:.6em">
 						<t>Do you really want to permanently <n.important.>delete</n.important.> <t.location><i><n.page_node.subject/></i></t.location>?</t>
 					</div>
@@ -43,26 +39,3 @@
 		</n.html>
 	</n.node_page.>
 </macro>
-
-<macro name="mailing_list_unsubscription_notice" requires="node_page">
-	<table style="margin:1em 0 .3em">
-		<tr>
-			<td><img src="/images/icon_alert_sm.png" align="absmiddle" height="16" width="16" alt="Important note"/></td>
-			<td class="second-font" style="font-weight:bold;font-size:110%;"><t>Before deleting this archive...</t></td>
-		</tr>
-	</table>
-	<div class="weak-color" style="margin-bottom:1em">
-		<t>Since this application is a mailing list archive, please unsubscribe the email address below before clicking on the delete button.</t>
-		<div style="padding:1em">
-			<span class="info-message rounded bold" style="padding:.4em .3em">
-				<n.page_node.get_this_mailing_list_archive.subscriber_address/>
-			</span>
-		</div>
-		<t>We have prepared a page with <n.unsubscription_instructions_link.>some instructions on how to unsubscribe this archive</n.unsubscription_instructions_link.>.</t><br/>
-		<t>If you have already removed the subscription, then you can proceed with the deletion.</t>
-	</div>
-</macro>
-
-<macro name="unsubscription_instructions_link" dot_parameter="text" requires="node_page">
-	<a href="[n.page_node.unsubscription_instructions_path/]"><n.text/></a>
-</macro>
\ No newline at end of file
--- a/src/nabble/view/naml/dropdown.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/dropdown.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -14,7 +14,6 @@
 			<n.menu_change_type/>
 			<n.menu_change_appearance/>
 			<n.menu_change_domain_name/>
-			<n.menu_mailing_list_archive_settings/>
 			<n.menu_change_language/>
 			<n.menu_change_title_and_meta_tags/>
 			<n.menu_extras_and_addons/>
@@ -56,7 +55,6 @@
 		<n.menu_change_type/>
 		<n.menu_change_appearance/>
 		<n.menu_change_domain_name/>
-		<n.menu_mailing_list_archive_settings/>
 		<n.menu_change_language/>
 		<n.menu_change_title_and_meta_tags/>
 		<n.menu_extras_and_addons/>
@@ -497,35 +495,6 @@
 	</n.if.is_in_command>
 </macro>
 
-<macro name="menu_mailing_list_archive_settings" requires="node">
-	<n.if.is_in_command name="dropdown">
-		<then>
-			dropdown.add('mailingListSettings', '<n.javascript_string_encode.mailing_list_archive_settings_link/>', 'display:none');
-		</then>
-		<else>
-			<n.set_local_node.this_node/>
-			<n.if>
-				<condition>
-					<n.both>
-						<condition1>
-							<n.visitor.can_edit.local_node/>
-						</condition1>
-						<condition2>
-							<n.either>
-								<condition1><n.local_node.is_a_mailing_list_archive/></condition1>
-								<condition2><n.not.local_node.has_sub_archive/></condition2>
-							</n.either>
-						</condition2>
-					</n.both>
-				</condition>
-				<then>
-					NabbleDropdown.show('mailingListSettings');
-				</then>
-			</n.if>
-		</else>
-	</n.if.is_in_command>
-</macro>
-
 <macro name="menu_embedding_options" requires="node">
 	<n.if.is_in_command name="dropdown">
 		<then>
@@ -800,23 +769,12 @@
 	<n.if.is_in_command name="dropdown">
 		<then>
 			dropdown.add('openShell', null, 'display:none');
-			<n.if.is_a_mailing_list_archive>
-				<then>
-					dropdown.add('uploadMbox', null, 'display:none');
-					dropdown.add('deleteRecursively', null, 'display:none');
-				</then>
-			</n.if.is_a_mailing_list_archive>
 		</then>
 		<else>
 			<n.set_local_node.this_node/>
 			<n.if.visitor.is_sysadmin>
 				<then>
 					NabbleDropdown.addContents('openShell','<n.javascript_string_encode.local_node.shell_link/>');
-					<n.if.local_node.is_a_mailing_list_archive>
-						<then>
-							NabbleDropdown.addContents('uploadMbox','<n.javascript_string_encode.local_node.upload_mbox_link/>');
-						</then>
-					</n.if.local_node.is_a_mailing_list_archive>
 				</then>
 			</n.if.visitor.is_sysadmin>
 		</else>
--- a/src/nabble/view/naml/edit_post.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/edit_post.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -79,18 +79,6 @@
 </macro>
 
 <macro name="edit_post_form">
-	<n.if.page_node.is_mail_to_list>
-		<then>
-			<div class="title-row info-message" style="font-weight:normal;padding:.3em .5em">
-				<div class="important" style="font-weight:bold">
-					<t>Your changes will not be sent to the mailing list.</t>
-				</div>
-				<t>If you want others in the mailing list to know of your changes,
-					please compose a new message or reply to your original message.</t>
-			</div>
-		</then>
-	</n.if.page_node.is_mail_to_list>
-
 	<n.if.page_node.message.is_imported_mail>
 		<then>
 			<div class="info-message" style="font-weight:bold;padding:.3em .5em">                
--- a/src/nabble/view/naml/email.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/email.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -35,7 +35,6 @@
 				<subject.local_node.subject/>
 				<text_part.text_part/>
 				<html_part.html_part/>
-				<set_headers_for.local_node/>
 			</n.send>
 		</n.new_email.>
 	</n.block.>
@@ -51,7 +50,6 @@
 				<subject.page_node.subject/>
 				<text_part.assign_text/>
 				<html_part.assign_html/>
-				<set_headers_for.page_node/>
 			</n.send>
 		</then.new_email.>
 	</n.if.topic_assignee.can_view.page_node>
--- a/src/nabble/view/naml/forgot_password.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/forgot_password.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -111,9 +111,6 @@
 				<t>If this email address is yours, you should <n.register_link.>register</n.register_link.> using this same address.
 				After registration, you will own this user account.</t>
 			</p>
-			<p>
-				<t>For more info, see: <t.info.help.userid.link/></t>
-			</p>
 		</body>
 	</n.html>
 </macro>
--- a/src/nabble/view/naml/mailing_list.naml	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-<macro name="send_mail_to_list" unindent="true">
-	<n.new_node.get_associated_mailing_list_archive.>
-		<n.new_email.>
-			<n.send>
-				<from><n.new_node.owner.user_email/></from>
-				<from_name><n.new_node.owner.name/></from_name>
-				<to><n.mailing_list_address/></to>
-				<subject><n.new_node.subject/></subject>
-				<text_part>
-					<n.new_node.text_email_message_with_signature />
-					--
-					Sent from: <n.mailing_list_node.url/>
-				</text_part>
-				<html_part>
-					<n.if.either condition1="[n.plain_text_only/]" condition2="[n.new_node.message.is_text_format/]">
-						<then.null/>
-						<else>
-							<n.new_node.html_email_message_with_signature />
-							<br/><hr align="left" width="300" />
-							Sent from the <a href="[n.mailing_list_node.url/]"><n.mailing_list_node.subject/> mailing list archive</a> at Nabble.com.<br/>
-						</else>
-					</n.if.either>
-				</html_part>
-				<set_headers_for.new_node/>
-			</n.send>
-		</n.new_email.>
-	</n.new_node.get_associated_mailing_list_archive.>
-</macro>
--- a/src/nabble/view/naml/mailing_list_settings.naml	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-<macro name="mailing_list_archive_settings" requires="servlet">
-	<n.node_page.>
-		<n.if.not.visitor.can_edit.page_node>
-			<then>
-				<n.login.><t>Only authorized users can proceed in this area.</t></n.login.>
-			</then>
-		</n.if.not.visitor.can_edit.page_node>
-
-		<n.page_node.get_this_mailing_list_archive.>
-			<n.if.not.is_submitted_form>
-				<then.fill_in_mailing_list_archive_fields/>
-				<else>
-					<n.if.is_remove_mailing_list_archive_settings>
-						<then.remove_mailing_list_archive_settings_and_redirect/>
-						<else.save_mailing_list_archive_settings_and_redirect/>
-					</n.if.is_remove_mailing_list_archive_settings>
-				</else>
-			</n.if.not.is_submitted_form>
-
-			<n.html>
-				<head>
-					<META NAME="robots" CONTENT="noindex,nofollow"/>
-					<n.title.><t>Mailing List Archive Settings</t></n.title.>
-					<n.mailing_list_address_field.focus/>
-					<style type="text/css">
-						div.field-title { margin-top: 0; }
-						div.tip { font-size:80%; margin-top:.4em; }
-					</style>
-					<script type="text/javascript">
-						$(document).ready(function() {
-							$('form').submit(function() {
-								var action = $('#action').val();
-								if (action == 'remove')
-									return confirm('<t>Do you really want to remove the mailing list archive settings?</t>');
-								return true;
-							});
-						});
-					</script>
-				</head>
-				<body>
-					<n.edit_header first_text="[n.page_node.get_app_node.subject/]" second_text="[t]Mailing List Archive Settings[/t]" />
-
-					<n.if.is_submitted_form>
-						<then.show_mailing_list_error/>
-					</n.if.is_submitted_form>
-
-					<n.form.>
-						<input id="action" type="hidden" name="action" value="save"/>
-						<n.mailing_list_address_group/>
-						<n.mailing_list_website_group/>
-						<n.mailing_list_server_group/>
-						<n.mailing_list_subject_prefix_group/>
-						<n.mailing_list_other_settings_group/>
-
-						<input type="submit" class="toolbar action-button" value="[t]Save Settings[/t]" onclick="$('#action').val('save')"/>
-						<input type="submit" class="toolbar action-button" value="[t]Remove Settings[/t]" onclick="$('#action').val('remove')"/>
-						<t>or</t> <a href="[n.page_node.url /]"><t>Cancel</t></a>
-					</n.form.>
-				</body>
-			</n.html>
-		</n.page_node.get_this_mailing_list_archive.>
-	</n.node_page.>
-</macro>
-
-<macro name="fill_in_mailing_list_archive_fields" requires="mailing_list">
-	<n.if.page_node.is_a_mailing_list_archive>
-		<then>
-			<n.mailing_list_address_field.set_value value="[n.mailing_list_address/]" />
-			<n.mailing_list_url_field.set_value value="[n.mailing_list_url/]" />
-			<n.mailing_list_server_field.set_value value="[n.mailing_list_server/]" />
-			<n.mailing_list_prefix_field.set_value value="[n.mailing_list_prefix/]" />
-			<n.plain_text_only_field.set_value value="[n.plain_text_only/]" />
-			<n.ignore_xnoarchive_field.set_value value="[n.ignore_xnoarchive/]" />
-		</then>
-		<else>
-			<n.mailing_list_server_field.set_value value="unknown" />
-		</else>
-	</n.if.page_node.is_a_mailing_list_archive>
-</macro>
-
-<macro name="remove_mailing_list_archive_settings_and_redirect" requires="mailing_list, node_page">
-	<n.catch_exception. id="save-block">
-		<n.remove/>
-		<n.redirect_to.page_node.url/>
-	</n.catch_exception.>
-</macro>
-
-<macro name="save_mailing_list_archive_settings_and_redirect" requires="mailing_list, node_page">
-	<n.catch_exception. id="save-block">
-		<n.set_var. name="is-new">
-			<n.if.page_node.is_a_mailing_list_archive>
-				<then>no</then>
-				<else>yes</else>
-			</n.if.page_node.is_a_mailing_list_archive>
-		</n.set_var.>
-		<n.save>
-			<address><n.mailing_list_address_field.value/></address>
-			<url><n.mailing_list_url_field.value/></url>
-			<server><n.mailing_list_server_field.value/></server>
-			<prefix><n.mailing_list_prefix_field.value/></prefix>
-			<plain_text_only><n.plain_text_only_field.value/></plain_text_only>
-			<ignore_xnoarchive><n.ignore_xnoarchive_field.value/></ignore_xnoarchive>
-			<do>
-			</do>
-		</n.save>
-		<n.if.equal value1="[n.var name='is-new'/]" value2="yes">
-			<then.redirect_to.page_node.subscription_instructions_path/>
-			<else.redirect_to.page_node.url/>
-		</n.if.equal>
-	</n.catch_exception.>
-</macro>
-
-<macro name="mailing_list_address_group" requires="mailing_list">
-	<div class="field-box light-border-color">
-		<div class="second-font field-title"><t>Mailing List Address</t> <span class="important">*</span></div>
-		<div class="weak-color">
-			<n.mailing_list_address_field.input size="40" />
-		</div>
-		<div class="weak-color tip">
-			<t>Example: listname@listdomain.com</t>
-		</div>
-
-		<n.if.page_node.is_a_mailing_list_archive>
-			<then>
-				<div class="shaded-bg-color rounded" style="padding: .6em .5em;margin:.4em 0 0">
-					<div style="float:left;height:2em;margin-right:.5em">
-						<img src="/images/tool_big.png" width="27" height="27"/>
-					</div>
-					<div style="margin-left:.5em">
-						<t><b>IMPORTANT</b>: You must subscribe this archive to the mailing list in order to make it work.</t><br/>
-						<div style="margin-top:.3em">
-							<t>Please follow the <n.subscribe_instructions_link.>subscription instructions</n.subscribe_instructions_link.> for this archive.</t>
-						</div>
-					</div>
-				</div>
-			</then>
-		</n.if.page_node.is_a_mailing_list_archive>
-	</div>
-</macro>
-
-<macro name="mailing_list_website_group" requires="mailing_list">
-	<div class="field-box light-border-color">
-		<div class="second-font field-title"><t>Mailing List Website</t> <span class="important">*</span></div>
-		<div class="weak-color">
-			<t>Enter the homepage of this mailing list, where users can find more information.</t><br/>
-			<n.mailing_list_url_field.input size="72" />
-		</div>
-	</div>
-</macro>
-
-<macro name="mailing_list_server_group" requires="mailing_list">
-	<div class="field-box light-border-color">
-		<div class="second-font field-title"><t>List Server</t></div>
-		<div class="weak-color">
-			<t>If you know, please select the mailing list server application and its version.</t><br/>
-			<n.mailing_list_server_field.select.>
-				<n.available_servers.loop.>
-					<n.set_var. name='server_name'>
-						<n.if.equal value1="[n.current_server_name/]" value2="Unknown or Other">
-							<then><t>Unknown or Other</t></then>
-							<else><n.current_server_name/></else>
-						</n.if.equal>
-					</n.set_var.>
-					<n.select_option value="[n.current_server/]" selectedValue="[n.mailing_list_server_field.value/]" text="[n.var name='server_name'/]"/>
-				</n.available_servers.loop.>
-			</n.mailing_list_server_field.select.>
-		</div>
-	</div>
-</macro>
-
-<macro name="mailing_list_subject_prefix_group" requires="mailing_list">
-	<div class="field-box light-border-color">
-		<div class="second-font field-title"><t>Subject Prefix</t></div>
-		<div class="weak-color">
-			<t>Enter the prefix that this mailing list uses before the subject.
-			The prefix will be automatically removed from the imported emails.</t>
-			<br/>
-			<n.mailing_list_prefix_field.input size="25" />
-			<div class="weak-color tip">
-				<t>Examples: '[the-list]', 'Abc:', etc.</t>
-			</div>
-		</div>
-	</div>
-</macro>
-
-<macro name="mailing_list_other_settings_group" requires="mailing_list">
-	<div class="field-box light-border-color">
-		<div class="second-font field-title"><t>Other Settings</t></div>
-		<table>
-			<tr>
-				<td><n.plain_text_only_field.checkbox /></td>
-				<td><label for="[n.plain_text_only_field.name/]"><t>This list accepts only plain-text emails</t></label></td>
-			</tr>
-			<tr style="vertical-align:top">
-				<td><n.ignore_xnoarchive_field.checkbox /></td>
-				<td style="padding-top:.2em">
-					<label for="[n.ignore_xnoarchive_field.name/]"><t>Ignore X-No-Archive header</t></label>
-					<div class="weak-color tip"><t>TIP: If your archive is subscribed to the mailing list and it is still not working, you may try ignoring the X-No-Archive header.</t></div>
-				</td>
-			</tr>
-		</table>
-	</div>
-</macro>
-
-<macro name="subscribe_instructions_link" dot_parameter="text" requires="node_page">
-	<a href="[n.page_node.subscription_instructions_path/]"><n.text/></a>
-</macro>
-
-<macro name="mailing_list_address_field" dot_parameter="do">
-	<n.field. name="mailing_list_address"><n.do/></n.field.>
-</macro>
-
-<macro name="mailing_list_url_field" dot_parameter="do">
-	<n.field. name="mailing_list_url"><n.do/></n.field.>
-</macro>
-
-<macro name="mailing_list_server_field" dot_parameter="do">
-	<n.field. name="mailing_list_server"><n.do/></n.field.>
-</macro>
-
-<macro name="mailing_list_prefix_field" dot_parameter="do">
-	<n.field. name="mailing_list_prefix"><n.do/></n.field.>
-</macro>
-
-<macro name="plain_text_only_field" dot_parameter="do">
-	<n.field. name="plain_text_only"><n.do/></n.field.>
-</macro>
-
-<macro name="ignore_xnoarchive_field" dot_parameter="do">
-	<n.field. name="ignore_xnoarchive"><n.do/></n.field.>
-</macro>
-
-<macro name="show_mailing_list_error">
-	<n.format_error.handle_exception. for="save-block">
-		<n.exception. name="invalid_list_address">
-			<t>You must enter a valid email address for this mailing list.</t>
-		</n.exception.>
-		<n.exception. name="invalid_list_url">
-			<t>You must enter a valid website URL for this mailing list.</t>
-		</n.exception.>
-	</n.format_error.handle_exception.>
-</macro>
-
-<macro name="is_remove_mailing_list_archive_settings">
-	<n.equal value1="[n.get_parameter name='action'/]" value2="remove"/>
-</macro>
--- a/src/nabble/view/naml/new_topic.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/new_topic.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -6,9 +6,5 @@
 		<focus>
 			<n.subject_field.focus/>
 		</focus>
-		<mailing_list_etiquette>
-			<li><t>If you are posting a question, please try search first. Your question may have already been answered.</t></li>
-			<li><t>Don't post repeatedly. Wait for a few days. People will read your post by email.</t></li>
-		</mailing_list_etiquette>
 	</n.new_post>
 </macro>
--- a/src/nabble/view/naml/reply.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/reply.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -6,17 +6,13 @@
 		<focus>
 			<n.message_field.focus/>
 		</focus>
-		<mailing_list_etiquette>
-			<li><t>Quote what you reply to and trim it to only the relevant parts. This provides context for those who will read your message by email.</t></li>
-			<li><t>Avoid small talk such as "Thank you", "Great"... You can <n.page_node.reply_to_author_link.>send a private email</n.page_node.reply_to_author_link.> if you want.</t></li>
-		</mailing_list_etiquette>
 		<bottom>
 			<n.in_reply_to/>
 		</bottom>
 	</n.new_post>
 </macro>
 
-<macro name="new_post" parameters="page_name,mailing_list_etiquette,bottom,focus" requires="servlet">
+<macro name="new_post" parameters="page_name,bottom,focus" requires="servlet">
 	<n.node_page.>
 		<n.handle_new_node_permission_error/>
 		<n.if.not.is_submitted_form>
@@ -39,28 +35,17 @@
 							<n.remember_new_node/>
 							<n.if.not.is_preview>
 								<then>
-									<n.if.new_node.is_associated_with_mailing_list_archive>
-										<then>
-											<n.send_mail_to_list/>
-										</then>
-										<else>
-											<n.save_post/>
-											<n.save_new_post_custom_fields/>
-											<n.new_node.send_node_as_email/>
-										</else>
-									</n.if.new_node.is_associated_with_mailing_list_archive>
+									<n.save_post/>
+									<n.save_new_post_custom_fields/>
+									<n.new_node.send_node_as_email/>
 								</then>
 							</n.if.not.is_preview>
 						</do>
 					</n.create_child_of_page_node>
 					<n.if.not.is_preview>
 						<then>
-							<n.if.not.new_node.is_associated_with_mailing_list_archive>
-								<then>
-									<n.new_node.save_alert_field/>
-									<n.redirect_to.new_node.path/>
-								</then>
-							</n.if.not.new_node.is_associated_with_mailing_list_archive>
+							<n.new_node.save_alert_field/>
+							<n.redirect_to.new_node.path/>
 						</then>
 					</n.if.not.is_preview>
 				</n.catch_exception.>
@@ -91,13 +76,6 @@
 							<else>
 								<n.if.is_preview>
 									<then.new_node.preview/>
-									<else.if.new_node.is_associated_with_mailing_list_archive>
-										<then>
-											<n.new_node.preview/>
-											<n.after_send/>
-											<n.global_set_var name="sent" value="true" />
-										</then>
-									</else.if.new_node.is_associated_with_mailing_list_archive>
 								</n.if.is_preview>
 							</else>
 						</n.if.has_exception>
@@ -106,11 +84,8 @@
 
 				<n.if.not.global_is_var_set name="sent">
 					<then>
-						<n.subscription_reminder/>
-		
 						<n.form. onsubmit="return singleSubmit(this)">
 							<n.type_field.hidden/>
-							<n.mailing_list_notice.mailing_list_etiquette/>
 		
 							<n.reply_form />
 		
@@ -209,23 +184,19 @@
 
 <macro name="new_post_extra_fields" requires="node_page">
 	<n.extra_fields.>
-		<n.if.not.page_node.is_associated_with_mailing_list_archive>
+		<n.if.visitor.is_registered>
 			<then>
-				<n.if.visitor.is_registered>
-					<then>
-						<div class="extra-fields">
-							<n.alert_field.checkbox style="margin-top:.1em"/>
-							<label for="[n.alert_field.name/]"><t>Alert me by email when someone posts to this thread</t></label>
-						</div>
-		
-						<div class="extra-fields">
-							<img src="/images/mail.png" width="18" height="13" style="margin-top:.2em"/>
-							<n.send_node_as_email_input />
-						</div>
-					</then>
-				</n.if.visitor.is_registered>
+				<div class="extra-fields">
+					<n.alert_field.checkbox style="margin-top:.1em"/>
+					<label for="[n.alert_field.name/]"><t>Alert me by email when someone posts to this thread</t></label>
+				</div>
+
+				<div class="extra-fields">
+					<img src="/images/mail.png" width="18" height="13" style="margin-top:.2em"/>
+					<n.send_node_as_email_input />
+				</div>
 			</then>
-		</n.if.not.page_node.is_associated_with_mailing_list_archive>
+		</n.if.visitor.is_registered>
 	</n.extra_fields.>
 </macro>
 
@@ -409,89 +380,6 @@
 	<n.exit/>
 </macro>
 
-<macro name="subscription_reminder" requires="node_page">
-	<n.if.page_node.is_associated_with_mailing_list_archive>
-		<then>
-			<n.page_node.get_associated_mailing_list_archive.>
-				<div id="window" class="window-content no-bg-color medium-border-color">
-					<n.put_in_head.>
-						<style type="text/css">
-							div.subscription-reminder {
-								font-weight:bold;
-								font-size:110%;
-								margin-bottom:1em;
-								text-align:center;
-								padding:.5em;
-							}
-						</style>
-					</n.put_in_head.>
-					<div class="second-font shaded-bg-color subscription-reminder">
-						<t>Mailing List Subscription Reminder</t>
-					</div>
-					<t>This forum is an archive/gateway which will forward your post to the <b><n.mailing_list_address/></b> mailing list.</t>
-					<br/><br/>
-					<t>The mailing list may require your subscription before accepting your post. Please note that being registered with Nabble does NOT automatically subscribe you to this mailing list. If you haven't subscribed yet, please do it now. If you aren't sure or don't remember, just subscribe again because there is no harm.</t>
-					<br/><br/>
-
-					<div class="nowrap">
-						<n.if.can_subscribe>
-							<then><n.subscribe_button.><t>Subscribe</t></n.subscribe_button.></then>
-							<else><a href="[n.mailing_list_url/]"><t>View mailing list website</t></a></else>
-						</n.if.can_subscribe>
-						<t>or</t>
-						<n.mailing_list_options_link.><t>Learn more</t></n.mailing_list_options_link.>
-					</div>
-
-					<br/>
-					<table style="margin-bottom:1em">
-						<tr>
-							<td><input type="checkbox" id="do-not-show" name="subscribe" onclick="Nabble.toggleMsg('ml-reminder', this.checked)"/></td>
-							<td><label for="do-not-show"><t>Don't show this message again</t></label></td>
-						</tr>
-					</table>
-					<div style="text-align:center;">
-						<input type="button" onclick="$('#window,#black-overlay').fadeOut();" value="[t]I'm a subscriber, let me post now[/t]"></input>
-					</div>
-				</div>
-				<div id="black-overlay" class="black-overlay"></div>
-				<script type="text/javascript">
-					if (Nabble.openMsg('ml-reminder'))
-						$('#window,#black-overlay').fadeIn();
-				</script>
-			</n.page_node.get_associated_mailing_list_archive.>
-		</then>
-	</n.if.page_node.is_associated_with_mailing_list_archive>
-</macro>
-
-<macro name="subscribe_button" requires="mailing_list" dot_parameter="text">
-	<form action="/mailing_list/Subscribe.jtp" style="display:inline">
-		<input type="hidden" name="forum" value="[n.mailing_list_node.id/]" />
-		<input type="submit" value="[n.text/]" />
-	</form>
-</macro>
-
-<macro name="mailing_list_notice" requires="node_page" dot_parameter="etiquette">
-	<n.if.page_node.is_associated_with_mailing_list_archive>
-		<then>
-			<n.page_node.get_associated_mailing_list_archive.>
-				<div class="title-row info-message" style="font-weight:normal">
-					<t>This message will be sent from <b><t.from.visitor.user_email/></b> to the <b><t.to.mailing_list_address/></b> mailing list.</t>
-					<br/>
-					<t>You may need to <n.mailing_list_options_link.>subscribe to this mailing list</n.mailing_list_options_link.> for your message to be accepted.</t>
-					<div class="important" style="font-size:90%; margin-top: 6px;">
-						<img src="/images/icon_alert_sm.png" width="16"  height="16" alt="" border="0" style="float:left; margin-right: 6px;" />
-						<t>Please respect mailing list etiquette</t>:
-						<ul>
-							<n.etiquette/>
-						</ul>
-					</div>
-					<n.help.mailing_list_intro.link/>
-				</div>
-			</n.page_node.get_associated_mailing_list_archive.>
-		</then>
-	</n.if.page_node.is_associated_with_mailing_list_archive>
-</macro>
-
 <macro name="in_reply_to">
 	<div class="title-row light-border-color shaded-bg-color" style="margin-top:2.5em"><t>In Reply To</t></div>
 	<div style="margin-left:1.2em;padding-top:1em">
@@ -660,13 +548,3 @@
 <macro name="has_spambot_security">
 	true
 </macro>
-
-<macro name="after_send" requires="node_page" dot_parameter="etiquette">
-	<n.page_node.get_associated_mailing_list_archive.>
-		<div class="title-row info-message" style="font-weight:normal">
-			<t>This message was sent from <b><t.from.visitor.user_email/></b> to the <b><t.to.mailing_list_address/></b> mailing list.</t>
-			<br/>
-			<t>This message will not appear in this archive until it has been accepted by the mailing list.  You may want to save a copy of this message in case it is not accepted.</t>
-		</div>
-	</n.page_node.get_associated_mailing_list_archive.>
-</macro>
--- a/src/nabble/view/naml/subscribe.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/subscribe.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -86,8 +86,6 @@
 			<else.post_subscription_controls/>
 		</n.if.page_node.is_app>
 
-		<n.show_mailing_list_alert/>
-
 		<br/>
 		<input type="submit" class="toolbar action-button" value="[t]Save Subscription[/t]"/>
 
@@ -160,32 +158,6 @@
 	/template/NamlServlet.jtp?macro=unsubscribe&node=<n.id/>
 </macro>
 
-<macro name="show_mailing_list_alert" requires="node_page">
-	<n.if>
-		<condition>
-			<n.either>
-				<condition1.page_node.is_associated_with_mailing_list_archive/>
-				<condition2.page_node.has_sub_archive/>
-			</n.either>
-		</condition>
-		<then>
-			<div class="info-message rounded" style="padding:.5em;margin-top:1em">
-				<t><b>IMPORTANT:</b> This subscription is independent of the real mailing list subscription.
-				Basically, you will subscribe to the forum archive, not to the mailing list itself.
-				The archive subscription won't guarantee that your messages will be accepted by mailing list.</t>
-				<n.if.page_node.is_a_mailing_list_archive>
-					<then>
-						<n.page_node.get_associated_mailing_list_archive.>
-						<t>If you want to subscribe to the mailing list instead,
-						<n.mailing_list_options_link.>visit this page</n.mailing_list_options_link.>.</t>
-						</n.page_node.get_associated_mailing_list_archive.>
-					</then>
-				</n.if.page_node.is_a_mailing_list_archive>
-			</div>
-		</then>
-	</n.if>
-</macro>
-
 <macro name="subscription_to_field" dot_parameter="do">
 	<n.field. name="subscription_to"><n.do/></n.field.>
 </macro>
@@ -290,9 +262,7 @@
 				<t>You have been invited to subscribe to <t.location.page_node.subject/>, which is available at:</t>
 				<n.page_node.url/>
 
-				<t>With your subscription, updates will be sent directly to your email address
-				and you can reply to them to participate in the discussion. Your subscription works the same
-				as a mailing list.</t>
+				<t>With your subscription, updates will be sent directly to your email address.</t>
 
 				<t>To confirm your subscription, click on the link below:</t>
 				<n.local_subscription.subscription_confirmation_subscribe_by_code_url/>
@@ -309,9 +279,7 @@
 				<t>You have been invited to subscribe to <t.location.bold.page_node.subject/>, which is available at:</t><br/>
 				<a href="[n.page_node.url/]"><n.page_node.url/></a><br/>
 				<br/>
-				<t>With your subscription, updates will be sent directly to your email address
-				and you can reply to them to participate in the discussion. Your subscription works the same
-				as a mailing list.</t><br/>
+				<t>With your subscription, updates will be sent directly to your email address.</t><br/>
 				<br/>
 				<t>To confirm your subscription, click on the link below:</t>
 				<div style="background-color:#FFFADB;border:#EDDD79 solid 1px;margin:1.2em 0;padding:.5em">
--- a/src/nabble/view/naml/topic.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/topic.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -588,7 +588,6 @@
 </macro>
 
 <macro name="classic_message_cell" requires="node">
-	<n.pending_notice/>
 	<n.updated_notice/>
 	<n.reply_notice/>
 	<n.message_text/>
@@ -620,16 +619,6 @@
 	</n.if.was_updated>
 </macro>
 
-<macro name="pending_notice" requires="node">
-	<n.if.is_pending>
-		<then>
-			<div class="info-message rounded" style="padding:.5em;margin:-.8em -.8em .8em -.8em;font-size:90%">
-				<t>This post has NOT been accepted by the mailing list yet.</t>
-			</div>
-		</then>
-	</n.if.is_pending>
-</macro>
-
 <macro name="reply_notice" requires="node">
 	<n.if.both condition1="[n.has_previous_node/]" condition2="[n.not.parent_node.equals.previous_node/]">
 		<then>
@@ -1096,7 +1085,6 @@
 						<n.owner.user_link/>
 						<n.post_subject/>
 					</div>
-					<n.pending_notice/>
 					<n.updated_notice/>
 					<n.message_text/>
 				</div>
--- a/src/nabble/view/naml/user_nodes.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/user_nodes.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -210,9 +210,6 @@
 				<n.if.current_node.is_private>
 					<then><span class="weak-color"><t>(private)</t></span></then>
 				</n.if.current_node.is_private>
-				<n.if.current_node.is_pending>
-					<then><img src="/images/icon_pending.png" class="image16" title="[t]This post has NOT been accepted by the mailing list yet.[/t]"/></then>
-				</n.if.current_node.is_pending>
 			</td>
 		</body>
 	</n.table_column>
--- a/src/nabble/view/naml/user_profile.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/user_profile.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -163,15 +163,6 @@
 		</then>
 	</n.if.not.equal>
 
-	<n.if.root_node.has_sub_archive>
-		<then>
-			<div style="margin-top:.5em">
-				<img src="/images/icon_pending.png" class="image16" style="margin:0 1px" />
-				<a href="[n.pending_posts_path/]"><t>My Pending Posts</t></a>
-			</div>
-		</then>
-	</n.if.root_node.has_sub_archive>
-
 	<div style="margin-top:.5em">
 		<img src="/images/forum_sm.png" class="image16" style="margin:0 1px"/>
 		<a href="[n.nabble_global_apps_url/]" target="_top"><t>My Nabble Applications</t></a>
--- a/src/nabble/view/naml/utilities.naml	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/naml/utilities.naml	Fri Jun 18 17:44:24 2021 -0600
@@ -276,20 +276,6 @@
 	</n.param_loop.>
 </macro>
 
-<macro name="mailing_list_information">
-	<n.if.is_associated_with_mailing_list_archive>
-		<then>
-			<n.get_associated_mailing_list_archive.>
-				<div style="margin:.5em 0">
-					<t>This forum is an archive for the mailing list</t>
-					<strong><n.mailing_list_address/></strong> (<n.mailing_list_options_link.><t>more options</t></n.mailing_list_options_link.>)
-					<t>Messages posted here will be sent to this mailing list.</t>
-				</div>
-			</n.get_associated_mailing_list_archive.>
-		</then>
-	</n.if.is_associated_with_mailing_list_archive>
-</macro>
-
 
 EDIT NODE
 
@@ -542,10 +528,6 @@
 	<a href="[n.send_email_path/]" class="[n.class/]" rel="nofollow" title="[n.title/]"><n.text/></a>
 </macro>
 
-<macro name="mailing_list_options_link" requires="mailing_list" dot_parameter="text" parameters="title, class">
-	<a href="[n.mailing_list_options_path/]" class="[n.class/]" rel="nofollow" title="[n.title/]"><n.text/></a>
-</macro>
-
 <macro name="change_type_path" requires="node">
 	<n.encode_url.>
 		/template/NamlServlet.jtp?macro=change_app_type&node=<n.id/>
@@ -606,16 +588,6 @@
 	</n.encode_url.>
 </macro>
 
-<macro name="mailing_list_archive_settings_link" requires="node" dot_parameter="text" parameters="title, class">
-	<a href="[n.mailing_list_archive_settings_path/]" class="[n.class/]" rel="nofollow" title="[n.title/]"><n.default. to="[t]Mailing list archive settings[/t]"><n.text/></n.default.></a>
-</macro>
-
-<macro name="mailing_list_archive_settings_path" requires="node">
-	<n.encode_url.>
-		/template/NamlServlet.jtp?macro=mailing_list_archive_settings&node=<n.id/>
-	</n.encode_url.>
-</macro>
-
 <macro name="embedding_options_link" requires="node" dot_parameter="text" parameters="title, class">
 	<a href="[n.embedding_options_path/]" class="[n.class/]" rel="nofollow" title="[n.title/]"><n.default. to="[t]Embedding options[/t]"><n.text/></n.default.></a>
 </macro>
--- a/src/nabble/view/web/app/Addons.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/app/Addons.java	Fri Jun 18 17:44:24 2021 -0600
@@ -72,8 +72,6 @@
 
 		addModule("Email & Notifications",  "email_registration_notification", "Notify me when someone registers", "When a user completes the registration process, an email is sent to all administrators with the details of the user (e.g., username, email, link to profile page).");
 
-		addModule("Mailing List Archives",  "expire_old_threads", "Lock old threads", "This add-on prevents new replies to old threads, which could be confusing to the mailing list users. Users that try to reply to an old thread will see a message that suggests them to create a new topic instead. By default, a thread is locked if it was created more than 365 days ago. You can change this number by tweaking the \"thread_expiration_days\" macro. ");
-
 		addModule("Privacy & Law",  "cookie_policy", "Cookie Law Compliance Solution", "Add-on for obtaining a user's explicit consent for the use of cookies on their browsers. This is required by some countries (mainly UK and EU) and visitors must explicitly agree with the E-Privacy Directive before having cookies read from/written to their browsers. The consent is requested just once. By default, the consent is requested to UK visitors only, but you can change the list of countries with NAML (i.e., override the <i>cookie_countries</i> macro).");
 
 		addModule("Responsiveness",  "responsive", "Responsive layout", "Add-on that improves the responsiveness of Nabble apps and make pages more readable on small screens.");
--- a/src/nabble/view/web/app/Addons.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/app/Addons.jtp	Fri Jun 18 17:44:24 2021 -0600
@@ -72,8 +72,6 @@
 
 		addModule("Email & Notifications",  "email_registration_notification", "Notify me when someone registers", "When a user completes the registration process, an email is sent to all administrators with the details of the user (e.g., username, email, link to profile page).");
 
-		addModule("Mailing List Archives",  "expire_old_threads", "Lock old threads", "This add-on prevents new replies to old threads, which could be confusing to the mailing list users. Users that try to reply to an old thread will see a message that suggests them to create a new topic instead. By default, a thread is locked if it was created more than 365 days ago. You can change this number by tweaking the \"thread_expiration_days\" macro. ");
-
 		addModule("Privacy & Law",  "cookie_policy", "Cookie Law Compliance Solution", "Add-on for obtaining a user's explicit consent for the use of cookies on their browsers. This is required by some countries (mainly UK and EU) and visitors must explicitly agree with the E-Privacy Directive before having cookies read from/written to their browsers. The consent is requested just once. By default, the consent is requested to UK visitors only, but you can change the list of countries with NAML (i.e., override the <i>cookie_countries</i> macro).");
 
 		addModule("Responsiveness",  "responsive", "Responsive layout", "Add-on that improves the responsiveness of Nabble apps and make pages more readable on small screens.");
--- a/src/nabble/view/web/help/Index.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/help/Index.java	Fri Jun 18 17:44:24 2021 -0600
@@ -45,8 +45,6 @@
 		out.print( "</li>\r\n			<li>" );
 		out.print( (Help.online.link(request)) );
 		out.print( "</li>\r\n			<li>" );
-		out.print( (Help.subscriptions.link(request)) );
-		out.print( "</li>					\r\n			<li>" );
 		out.print( (Help.search.link(request)) );
 		out.print( "</li>\r\n			<li>" );
 		out.print( (Help.seo.link(request)) );
@@ -69,45 +67,21 @@
 		out.print( "</li>\r\n			<li>" );
 		out.print( (Help.anonymous.link(request)) );
 		out.print( "</li>\r\n			<li>" );
-		out.print( (Help.userid.link(request)) );
-		out.print( "</li>\r\n			<li>" );
 		out.print( (Help.delpost.link(request)) );
 		out.print( "</li>\r\n		</ul>\r\n		<h2>Forum Users</h2>\r\n		<ul>\r\n			<li>" );
-		out.print( (Help.mailingListIntro.link(request)) );
-		out.print( "</li>\r\n			<li>" );
-		out.print( (Help.pending.link(request)) );
-		out.print( "</li>\r\n			<li>" );
 		out.print( (Help.moderation.link(request)) );
 		out.print( "</li>\r\n			<li>" );
-		out.print( (Help.stopEmails.link(request)) );
-		out.print( "</li>\r\n			<li>" );
 		out.print( (Help.restrictions.link(request)) );
 		out.print( "</li>\r\n			<li>" );
-		out.print( (Help.owner.link(request)) );
-		out.print( "</li>\r\n			<li>" );
 		out.print( (Help.cataloging.link(request)) );
 		out.print( "</li>\r\n			<li>" );
 		out.print( (Help.inactivity_deletion.link(request)) );
-		out.print( "</li>\r\n		</ul>\r\n		<h2>Mailing List Owners</h2>\r\n		<ul>\r\n			<li>" );
-		out.print( (Help.add.link(request)) );
-		out.print( "</li>\r\n			<li>" );
-		out.print( (Help.find.link(request)) );
-		out.print( "</li>\r\n			<li>" );
-		out.print( (Help.why.link(request)) );
-		out.print( "</li>\r\n			<li>" );
-		out.print( (Help.copy.link(request)) );
+		out.print( "</li>\r\n		</ul>\r\n		<h2>Forum Starters</h2>\r\n		<ul>\r\n			<li>" );
+		out.print( (Help.mixed.link(request)) );
 		out.print( "</li>\r\n			<li>" );
 		out.print( (Help.sell.link(request)) );
 		out.print( "</li>\r\n			<li>" );
-		out.print( (Help.post.link(request)) );
-		out.print( "</li>\r\n			<li>" );
 		out.print( (Help.listSpam.link(request)) );
-		out.print( "</li>\r\n			<li>" );
-		out.print( (Help.security.link(request)) );
-		out.print( "</li>\r\n		</ul>\r\n		<h2>Forum Starters</h2>\r\n		<ul>\r\n			<li>" );
-		out.print( (Help.mirror.link(request)) );
-		out.print( "</li>\r\n			<li>" );
-		out.print( (Help.mixed.link(request)) );
 		out.print( "</li>\r\n		</ul>\r\n		<p><br />If you still have questions, visit the " );
 		out.print( (Jtp.supportLink()) );
 		out.print( " forum.</p>\r\n		</div>\r\n\r\n		" );
--- a/src/nabble/view/web/help/Index.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/help/Index.jtp	Fri Jun 18 17:44:24 2021 -0600
@@ -52,7 +52,6 @@
 					<li><%=Help.embed_what_how.link(request)%></li>
 					<li><%=Help.embed_skin.link(request)%></li>
 					<li><%=Help.online.link(request)%></li>
-					<li><%=Help.subscriptions.link(request)%></li>					
 					<li><%=Help.search.link(request)%></li>
 					<li><%=Help.seo.link(request)%></li>
 					<li><%=Help.embed_permalinks.link(request)%></li>
@@ -67,35 +66,20 @@
 					<li><%=Help.formatting.link(request)%></li>
 					<li><%=Help.password.link(request)%></li>
 					<li><%=Help.anonymous.link(request)%></li>
-					<li><%=Help.userid.link(request)%></li>
 					<li><%=Help.delpost.link(request)%></li>
 				</ul>
 				<h2>Forum Users</h2>
 				<ul>
-					<li><%=Help.mailingListIntro.link(request)%></li>
-					<li><%=Help.pending.link(request)%></li>
 					<li><%=Help.moderation.link(request)%></li>
-					<li><%=Help.stopEmails.link(request)%></li>
 					<li><%=Help.restrictions.link(request)%></li>
-					<li><%=Help.owner.link(request)%></li>
 					<li><%=Help.cataloging.link(request)%></li>
 					<li><%=Help.inactivity_deletion.link(request)%></li>
 				</ul>
-				<h2>Mailing List Owners</h2>
-				<ul>
-					<li><%=Help.add.link(request)%></li>
-					<li><%=Help.find.link(request)%></li>
-					<li><%=Help.why.link(request)%></li>
-					<li><%=Help.copy.link(request)%></li>
-					<li><%=Help.sell.link(request)%></li>
-					<li><%=Help.post.link(request)%></li>
-					<li><%=Help.listSpam.link(request)%></li>
-					<li><%=Help.security.link(request)%></li>
-				</ul>
 				<h2>Forum Starters</h2>
 				<ul>
-					<li><%=Help.mirror.link(request)%></li>
 					<li><%=Help.mixed.link(request)%></li>
+					<li><%=Help.sell.link(request)%></li>
+					<li><%=Help.listSpam.link(request)%></li>
 				</ul>
 				<p><br />If you still have questions, visit the <%=Jtp.supportLink()%> forum.</p>
 				</div>
--- a/src/nabble/view/web/mailing_list/MailingListNamespace.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-package nabble.view.web.mailing_list;
-
-import fschmidt.db.DbDatabase;
-import fschmidt.util.mail.MailAddress;
-import nabble.model.Db;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelException;
-import nabble.model.Node;
-import nabble.naml.compiler.Command;
-import nabble.naml.compiler.CommandSpec;
-import nabble.naml.compiler.IPrintWriter;
-import nabble.naml.compiler.Interpreter;
-import nabble.naml.compiler.Namespace;
-import nabble.naml.compiler.ScopedInterpreter;
-import nabble.naml.namespaces.ListSequence;
-import nabble.naml.namespaces.TemplateException;
-import nabble.view.web.template.NodeNamespace;
-import nabble.view.web.template.ServletNamespace;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.List;
-
-
-@Namespace (
-	name = "mailing_list",
-	global = true
-)
-public class MailingListNamespace {
-	private Node node;
-	private MailingList mailingList;
-
-	public MailingListNamespace(Node node) {
-		this.node = node;
-		this.mailingList = node.getMailingList();
-	}
-
-	public MailingListNamespace(MailingList mailingList) {
-		this.node = mailingList.getForum();
-		this.mailingList = mailingList;
-	}
-
-	private DbDatabase db() {
-		return node.getSite().getDb();
-	}
-
-	public static final CommandSpec mailing_list_node = CommandSpec.DO;
-
-	@Command public void mailing_list_node(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
-		NodeNamespace ns = new NodeNamespace(node);
-		out.print( interp.getArg(ns,"do") );
-	}
-
-	@Command public void mailing_list_address(IPrintWriter out,Interpreter interp) {
-		out.print( mailingList.getListAddress() );
-	}
-
-	@Command public void mailing_list_url(IPrintWriter out,Interpreter interp) {
-		out.print( interp.encode( mailingList.getUrl() ) );
-	}
-
-	@Command public void mailing_list_server(IPrintWriter out,Interpreter interp) {
-		out.print( mailingList.getListServer().getType() );
-	}
-
-	@Command public void mailing_list_prefix(IPrintWriter out,Interpreter interp) {
-		out.print( mailingList.getListName() );
-	}
-
-	@Command public void plain_text_only(IPrintWriter out,Interpreter interp) {
-		out.print( mailingList.plainTextOnly() );
-	}
-
-	@Command public void ignore_xnoarchive(IPrintWriter out,Interpreter interp) {
-		out.print( mailingList.ignoreNoArchive() );
-	}
-
-	@Command public void mailing_list_options_path(IPrintWriter out,Interpreter interp) {
-		out.print( interp.encode( "/mailing_list/MailingListOptions.jtp?forum=" + node.getId() ) );
-	}
-
-	@Command public void can_subscribe(IPrintWriter out,Interpreter interp) {
-		out.print( mailingList.getListServer().canSubscribe() );
-	}
-
-	@Command public void subscriber_address(IPrintWriter out,Interpreter interp) {
-		out.print( mailingList.getSubscriberAddress().getAddrSpec() );
-	}
-
-	public static final CommandSpec available_servers = CommandSpec.DO;
-
-	@Command public void available_servers(IPrintWriter out,ScopedInterpreter<Servers> interp)
-		throws IOException, ServletException
-	{
-		String[] serverTypes = ListServer.getAllServerTypes();
-		Object block = interp.getArg(new Servers(Arrays.asList(serverTypes)),"do");
-		out.print(block);
-	}
-
-	@Namespace (
-		name = "server_list",
-		global = false
-	)
-	public static final class Servers extends ListSequence<String> {
-
-		Servers(List<String> serverTypes) {
-			super(serverTypes);
-		}
-
-		@Command public void current_server(IPrintWriter out,Interpreter interp) {
-			out.print(ListServer.getServer(get()).getType());
-		}
-
-		@Command public void current_server_name(IPrintWriter out,Interpreter interp) {
-			out.print(ListServer.getServer(get()).getViewName());
-		}
-	}
-
-	public static final CommandSpec save = new CommandSpec.Builder()
-		.dotParameter("do")
-		.parameters("address","url","server","plain_text_only","ignore_xnoarchive")
-		.optionalParameters("prefix")
-		.requiredInStack(ServletNamespace.class)
-		.build()
-	;
-
-	@Command public void save(IPrintWriter out,Interpreter interp)
-		throws TemplateException
-	{
-		ServletNamespace servletNs = interp.getFromStack(ServletNamespace.class);
-		HttpServletRequest request = servletNs.request;
-		if( !"POST".equals(request.getMethod()) )
-			return;
-
-		String address = interp.getArgString("address");
-		if (address == null)
-			throw ModelException.newInstance("invalid_list_address");
-		address = address.trim().toLowerCase();
-		if (!new MailAddress(address).isValid())
-			throw ModelException.newInstance("invalid_list_address");
-
-		String url = interp.getArgString("url");
-		if (url == null)
-			throw ModelException.newInstance("invalid_list_url");
-		try {
-			new URL(url);
-		} catch (MalformedURLException e) {
-			throw ModelException.newInstance("invalid_list_url");
-		}
-
-		String server = interp.getArgString("server");
-		ListServer listServerType = ListServer.getServer(server);
-
-		String prefix = interp.getArgString("prefix");
-		if (prefix != null && prefix.trim().length() == 0)
-			prefix = null;
-
-		boolean isPlainTextOnly = interp.getArgAsBoolean("plain_text_only",false);
-		boolean isIgnoreXNoArchive = interp.getArgAsBoolean("ignore_xnoarchive",false);
-
-		db().beginTransaction();
-		try {
-			node = node.getGoodCopy(); // In case the node needs to be updated in the "do" block.
-			mailingList = node.getMailingList();
-			if (mailingList != null) {
-				mailingList.setListAddress(address);
-				mailingList.setUrl(url);
-				mailingList.setListServer(listServerType);
-			} else {
-				mailingList = node.newMailingList(listServerType, address, url);
-			}
-			mailingList.setListName(prefix);
-			mailingList.setPlainTextOnly(isPlainTextOnly);
-			mailingList.setIgnoreNoArchive(isIgnoreXNoArchive);
-
-			interp.getArgString("do");
-			mailingList.update();
-			db().commitTransaction();
-		} finally {
-			db().endTransaction();
-		}
-	}
-
-	@Command public void remove(IPrintWriter out,Interpreter interp)
-		throws TemplateException
-	{
-		db().beginTransaction();
-		try {
-			node.getGoodCopy().deleteMailingList();
-			db().commitTransaction();
-		} finally {
-			db().endTransaction();
-		}
-	}
-}
--- a/src/nabble/view/web/mailing_list/MailingListOptions.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-
-package nabble.view.web.mailing_list;
-
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-import nabble.view.lib.help.Help;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-
-public final class MailingListOptions extends HttpServlet {
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		Node forum = Jtp.getSiteNotNull(request).getNode(Jtp.getLong(request,"forum"));
-		if (forum == null) {
-			response.sendError(HttpServletResponse.SC_GONE, "This app has been deleted.");
-			return;
-		}
-
-		MailingList mailingList = forum.getAssociatedMailingList();
-		ListServer listServer = mailingList.getListServer();
-		
-		out.print( "\r\n<html>\r\n	<head>\r\n		" );
- Shared.title(request,response,"Mailing List Options"); 
-		out.print( "\r\n	</head>\r\n	<body>\r\n	" );
- Shared.minHeader(request, response, forum);
-		out.print( "\r\n	" );
- Shared.editHeader(forum.getSubjectHtml(), "Mailing List Options", out); 
-		out.print( "\r\n	\r\n	" );
-
-			if( listServer.canSubscribe() ) {
-				
-		out.print( "\r\n<p>\r\nNabble provides a web archive and gateway to the mailing list: <strong>" );
-		out.print( (mailingList.getListAddress()) );
-		out.print( "</strong> (<a href=\"" );
-		out.print( (Help.mailingListIntro.url(request)) );
-		out.print( "\">What is a mailing list?</a>).\r\n</p>\r\n<p>Below are a set of mailing list actions you can take through Nabble. (You may also visit the <a href=\"" );
-		out.print( (mailingList.getUrl()) );
-		out.print( "\" target=\"_top\">" );
-		out.print( (mailingList.getListAddress()) );
-		out.print( " website</a> for additional information and options.)\r\n</p>\r\n\r\n<h3>Subscribe to " );
-		out.print( (mailingList.getListAddress()) );
-		out.print( "</h3>\r\n<p>\r\n	Most mailing lists require subscription before you can post messages. Click <strong>Subscribe</strong> below to send a subscription request to the mailing list: " );
-		out.print( (mailingList.getListAddress()) );
-		out.print( ".\r\n</p>\r\n\r\n<p>\r\n	<strong>REMEMBER</strong>: Clicking \"Subscribe\" only sends the request to the mailing list. You have the following additional step to complete the subscription process.</p>\r\n\r\n<p>\r\n	After clicking Subscribe, wait for a confirmation email which will provide instructions on how to confirm your subscription. Follow the instructions in the confirmation email to confirm your subscription. This usually requires replying to an email or clicking the confirmation link.\r\n	(<strong>NOTE: </strong>Most mailing lists send the confirmation email almost instantaneously. However, some may require that you wait for a few hours.)\r\n</p>\r\n\r\n<p>\r\n<form action=\"Subscribe.jtp\">\r\n<input type=\"hidden\" name=\"forum\" value=\"" );
-		out.print( (forum.getId()) );
-		out.print( "\" />\r\n<input type=\"submit\" value=\"Subscribe\" />\r\n</form>\r\n</p>\r\n" );
-
-				if( !listServer.supportsDeliveryOff() ) {
-					
-		out.print( "\r\n<p>\r\n	Becoming a subscriber allows you to post to a mailing list, but at the same time, you will also receive all the emails posted to the mailing list. If you prefer not to receive the emails, you can unsubscribe after posting to the list.\r\n</p>\r\n\r\n<h3>Unsubscribe</h3>\r\n<p>\r\n	This mailing list does not support the option to turn off email delivery, so you may want to consider unsubscribing; it's acceptable to subscribe to a mailing list to post a message, but then unsubscribe after the message is sent.\r\n</p>\r\n" );
-
-				} else if( listServer.needsDefaults() ) {
-					
-		out.print( "\r\n<p>\r\n	Becoming a subscriber allows you to post messages to a mailing list. However, you also have to receive all the emails posted to the mailing list. If you prefer not to receive the emails, you have the option to turn off mail delivery.\r\n</p>\r\n\r\n<h3>Turn off mail delivery</h3>\r\n<p>This mailing list may allow you to turn off email delivery but remain a subscriber. This means you can post messages without having to receive the emails. This option works only after you have become a subscriber.</p>\r\n" );
-
-					if ( listServer == ListServer.google ) {
-						
-		out.print( "\r\n<p>To turn off email delivery, please visit <a href=\"" );
-		out.print( (mailingList.getUrl()) );
-		out.print( "\">" );
-		out.print( (mailingList.getListAddress()) );
-		out.print( "'s website</a>.</p>\r\n" );
-
-					} else {
-						
-		out.print( "\r\n<p><b>Please Note</b>: This option may not work for some early versions of Mailman. In that case, use the Unsubscribe option below.</p>\r\n<p>\r\n<form action=\"SubscribeDefaults.jtp\">\r\n<input type=\"hidden\" name=\"Action\" value=\"set\" />\r\n<input type=\"hidden\" name=\"forum\" value=\"" );
-		out.print( (forum.getId()) );
-		out.print( "\" />\r\n<input type=\"submit\" value=\"Turn off mail delivery\" />\r\n</form>\r\n</p>\r\n" );
-
-					}
-					
-		out.print( "\r\n<h3>Unsubscribe</h3>\r\n<p>You may unsubscribe from this mailing list.</p>\r\n" );
-
-				} else {
-					
-		out.print( "\r\n<p>Your subscription will be with email delivery turned off, so you can post messages without having to receive all list emails.</p>\r\n<h3>Unsubscribe</h3>\r\n<p>You may unsubscribe from this mailing list.</p>\r\n" );
-
-				}
-				
-		out.print( "\r\n<form action=\"Unsubscribe.jtp\">\r\n<input type=\"hidden\" name=\"forum\" value=\"" );
-		out.print( (forum.getId()) );
-		out.print( "\" />\r\n<input type=\"submit\" value=\"Unsubscribe\" />\r\n</form>\r\n" );
-
-			} else {
-				
-		out.print( "\r\n<p>\r\n	Nabble provides a web archive and gateway to the mailing list: <strong>" );
-		out.print( (mailingList.getListAddress()) );
-		out.print( "</strong> (<a href=\"" );
-		out.print( (Help.mailingListIntro.url(request)) );
-		out.print( "\">?</a>).\r\n</p>\r\n<p>\r\n	To subscribe or unsubscribe, please visit <a href=\"" );
-		out.print( (mailingList.getUrl()) );
-		out.print( "\">" );
-		out.print( (mailingList.getListAddress()) );
-		out.print( "'s website</a>.\r\n</p>\r\n<p>\r\n	<strong>NOTE:</strong> Please complete the subscription process before posting any messages to this mailing list to ensure that your messages are accepted by the mailing list.\r\n</p>\r\n" );
-
-			}
-			
-		out.print( "\r\n" );
- Shared.footer(request,response); 
-		out.print( "\r\n" );
- Shared.analytics(request,response); 
-		out.print( "\r\n</body>\r\n</html>\r\n" );
-
-	}
-}
-
--- a/src/nabble/view/web/mailing_list/MailingListOptions.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-<%
-package nabble.view.web.mailing_list;
-
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-import nabble.view.lib.help.Help;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-
-public final class MailingListOptions extends HttpServlet {
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		Node forum = Jtp.getSiteNotNull(request).getNode(Jtp.getLong(request,"forum"));
-		if (forum == null) {
-			response.sendError(HttpServletResponse.SC_GONE, "This app has been deleted.");
-			return;
-		}
-
-		MailingList mailingList = forum.getAssociatedMailingList();
-		ListServer listServer = mailingList.getListServer();
-		%>
-		<html>
-			<head>
-				<% Shared.title(request,response,"Mailing List Options"); %>
-			</head>
-			<body>
-			<% Shared.minHeader(request, response, forum);%>
-			<% Shared.editHeader(forum.getSubjectHtml(), "Mailing List Options", out); %>
-			
-			<%
-			if( listServer.canSubscribe() ) {
-				%>
-				<p>
-				Nabble provides a web archive and gateway to the mailing list: <strong><%=mailingList.getListAddress()%></strong> (<a href="<%=Help.mailingListIntro.url(request)%>">What is a mailing list?</a>).
-				</p>
-				<p>Below are a set of mailing list actions you can take through Nabble. (You may also visit the <a href="<%=mailingList.getUrl()%>" target="_top"><%=mailingList.getListAddress()%> website</a> for additional information and options.)
-				</p>
-
-				<h3>Subscribe to <%=mailingList.getListAddress()%></h3>
-				<p>
-					Most mailing lists require subscription before you can post messages. Click <strong>Subscribe</strong> below to send a subscription request to the mailing list: <%=mailingList.getListAddress()%>.
-				</p>
-
-				<p>
-					<strong>REMEMBER</strong>: Clicking "Subscribe" only sends the request to the mailing list. You have the following additional step to complete the subscription process.</p>
-
-				<p>
-					After clicking Subscribe, wait for a confirmation email which will provide instructions on how to confirm your subscription. Follow the instructions in the confirmation email to confirm your subscription. This usually requires replying to an email or clicking the confirmation link.
-					(<strong>NOTE: </strong>Most mailing lists send the confirmation email almost instantaneously. However, some may require that you wait for a few hours.)
-				</p>
-
-				<p>
-				<form action="Subscribe.jtp">
-				<input type="hidden" name="forum" value="<%=forum.getId()%>" />
-				<input type="submit" value="Subscribe" />
-				</form>
-				</p>
-				<%
-				if( !listServer.supportsDeliveryOff() ) {
-					%>
-					<p>
-						Becoming a subscriber allows you to post to a mailing list, but at the same time, you will also receive all the emails posted to the mailing list. If you prefer not to receive the emails, you can unsubscribe after posting to the list.
-					</p>
-
-					<h3>Unsubscribe</h3>
-					<p>
-						This mailing list does not support the option to turn off email delivery, so you may want to consider unsubscribing; it's acceptable to subscribe to a mailing list to post a message, but then unsubscribe after the message is sent.
-					</p>
-					<%
-				} else if( listServer.needsDefaults() ) {
-					%>
-					<p>
-						Becoming a subscriber allows you to post messages to a mailing list. However, you also have to receive all the emails posted to the mailing list. If you prefer not to receive the emails, you have the option to turn off mail delivery.
-					</p>
-
-					<h3>Turn off mail delivery</h3>
-					<p>This mailing list may allow you to turn off email delivery but remain a subscriber. This means you can post messages without having to receive the emails. This option works only after you have become a subscriber.</p>
-					<%
-					if ( listServer == ListServer.google ) {
-						%>
-						<p>To turn off email delivery, please visit <a href="<%=mailingList.getUrl()%>"><%=mailingList.getListAddress()%>'s website</a>.</p>
-						<%
-					} else {
-						%>
-					<p><b>Please Note</b>: This option may not work for some early versions of Mailman. In that case, use the Unsubscribe option below.</p>
-					<p>
-					<form action="SubscribeDefaults.jtp">
-					<input type="hidden" name="Action" value="set" />
-					<input type="hidden" name="forum" value="<%=forum.getId()%>" />
-					<input type="submit" value="Turn off mail delivery" />
-					</form>
-					</p>
-						<%
-					}
-					%>
-					<h3>Unsubscribe</h3>
-					<p>You may unsubscribe from this mailing list.</p>
-					<%
-				} else {
-					%>
-					<p>Your subscription will be with email delivery turned off, so you can post messages without having to receive all list emails.</p>
-					<h3>Unsubscribe</h3>
-					<p>You may unsubscribe from this mailing list.</p>
-					<%
-				}
-				%>
-				<form action="Unsubscribe.jtp">
-				<input type="hidden" name="forum" value="<%=forum.getId()%>" />
-				<input type="submit" value="Unsubscribe" />
-				</form>
-				<%
-			} else {
-				%>
-				<p>
-					Nabble provides a web archive and gateway to the mailing list: <strong><%=mailingList.getListAddress()%></strong> (<a href="<%=Help.mailingListIntro.url(request)%>">?</a>).
-				</p>
-				<p>
-					To subscribe or unsubscribe, please visit <a href="<%=mailingList.getUrl()%>"><%=mailingList.getListAddress()%>'s website</a>.
-				</p>
-				<p>
-					<strong>NOTE:</strong> Please complete the subscription process before posting any messages to this mailing list to ensure that your messages are accepted by the mailing list.
-				</p>
-				<%
-			}
-			%>
-			<% Shared.footer(request,response); %>
-			<% Shared.analytics(request,response); %>
-			</body>
-		</html>
-		<%
-	}
-}
-%>
--- a/src/nabble/view/web/mailing_list/Subscribe.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-
-package nabble.view.web.mailing_list;
-
-import fschmidt.util.mail.Mail;
-import fschmidt.util.servlet.ServletUtils;
-import nabble.model.Init;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Executors;
-import nabble.model.Node;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.SubscribeDefaultsMail;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.concurrent.TimeUnit;
-
-
-public final class Subscribe extends HttpServlet {
-
-	private static final Logger logger = LoggerFactory.getLogger(Subscribe.class);
-
-	private final static long secondsUntilDeliveryOffMail = Init.get("secondsUntilDeliveryOffMail",20*60);  // why so long?
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		User user = Jtp.getUser(request);
-		if (user == null) {
-			Jtp.login("You must login to be able to subscribe to a list.",request,response);
-			return;
-		}
-		Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(request.getParameter("forum")));
-		MailingList mailingList = forum.getAssociatedMailingList();
-		Mail userSubscribeMail = mailingList.subscribeMail(user);
-		ModelHome.send(userSubscribeMail);
-		logger.info("subscription request from "+user.getEmail()+" to "+mailingList.getListAddress());
-
-		if (mailingList.getListServer().needsDefaults() && mailingList.getListServer() != ListServer.google) {
-			String url = ServletUtils.getContextURL(request) + "/mailing_list/SubscribeDefaults.jtp?forum="+forum.getId()+"&k="+mailingList.getPassword(user);
-			final Mail mail = SubscribeDefaultsMail.newMail(user.getEmail(), mailingList, url);
-			Executors.schedule(
-				new Runnable(){public void run(){
-					ModelHome.send(mail);
-				}}, secondsUntilDeliveryOffMail, TimeUnit.SECONDS
-			);
-		}
-		response.sendRedirect("Subscribe2.jtp?forum="+forum.getId());
-	}
-}
-
--- a/src/nabble/view/web/mailing_list/Subscribe.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-<%
-package nabble.view.web.mailing_list;
-
-import fschmidt.util.mail.Mail;
-import fschmidt.util.servlet.ServletUtils;
-import nabble.model.Init;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Executors;
-import nabble.model.Node;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.SubscribeDefaultsMail;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.concurrent.TimeUnit;
-
-
-public final class Subscribe extends HttpServlet {
-
-	private static final Logger logger = LoggerFactory.getLogger(Subscribe.class);
-
-	private final static long secondsUntilDeliveryOffMail = Init.get("secondsUntilDeliveryOffMail",20*60);  // why so long?
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		User user = Jtp.getUser(request);
-		if (user == null) {
-			Jtp.login("You must login to be able to subscribe to a list.",request,response);
-			return;
-		}
-		Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(request.getParameter("forum")));
-		MailingList mailingList = forum.getAssociatedMailingList();
-		Mail userSubscribeMail = mailingList.subscribeMail(user);
-		ModelHome.send(userSubscribeMail);
-		logger.info("subscription request from "+user.getEmail()+" to "+mailingList.getListAddress());
-
-		if (mailingList.getListServer().needsDefaults() && mailingList.getListServer() != ListServer.google) {
-			String url = ServletUtils.getContextURL(request) + "/mailing_list/SubscribeDefaults.jtp?forum="+forum.getId()+"&k="+mailingList.getPassword(user);
-			final Mail mail = SubscribeDefaultsMail.newMail(user.getEmail(), mailingList, url);
-			Executors.schedule(
-				new Runnable(){public void run(){
-					ModelHome.send(mail);
-				}}, secondsUntilDeliveryOffMail, TimeUnit.SECONDS
-			);
-		}
-		response.sendRedirect("Subscribe2.jtp?forum="+forum.getId());
-	}
-}
-%>
--- a/src/nabble/view/web/mailing_list/Subscribe2.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-
-package nabble.view.web.mailing_list;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import fschmidt.util.mail.MailAddress;
-import nabble.model.Node;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-
-
-public final class Subscribe2 extends HttpServlet {
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		String context = request.getContextPath();
-		User user = Jtp.getUser(request);
-		if( user==null ) {
-			Jtp.login("You must login to be able to subscribe to a list.",request,response);
-			return;
-		}
-		Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(request.getParameter("forum")));
-		MailingList mailingList = forum.getAssociatedMailingList();
-		ListServer listServer = mailingList.getListServer();
-		MailAddress emailAddress = new MailAddress(user.getEmail(), user.getName());
-		
-		out.print( "\n<html>\n<head>\n" );
-
-		Shared.title(request,response,"Subscribe to mailing list");
-		
-		out.print( "\n</head>\n<body>\n" );
- Shared.minHeader(request, response, forum); 
-		out.print( "\n<h1>Subscription Request Was Sent</h1>\n<p>\nA subscription request was sent on your behalf to the mailing list: <strong>" );
-		out.print( (mailingList.getListAddress()) );
-		out.print( "</strong>.\nYou will soon receive a confirmation request by email at <strong>" );
-		out.print( (user.getEmail()) );
-		out.print( "</strong>. Please follow the\ninstructions in the email to complete your subscription.\n</p>\n\n<p>\nTo ensure that your posts are accepted by the mailing list, complete the subscription process before posting any messages to this forum.  If you have already posted messages that have not been accepted by the mailing list, you will need to resend them after you have finished subscribing.\n</p>\n\n<p><strong>Remember:</strong> You are not subscribed to the <strong>" );
-		out.print( (mailingList.getListAddress()) );
-		out.print( "</strong> list until you have followed the instructions in the email.</p>\n\n" );
-
-		if( listServer.needsDefaults() && listServer!=ListServer.google ) {
-			
-		out.print( "\n<p>\nAlso, we have sent you an email to help you turn off list mail delivery to your email address (" );
-		out.print( (user.getEmail()) );
-		out.print( "). After your subscription has been approved, please click the corresponding link in the email to turn off list mail delivery.\n</p>\n" );
-
-		}
-		
-		out.print( "\n<br /><br />\n<p>\n&#171; <a href=\"" );
-		out.print( (Jtp.path(forum)) );
-		out.print( "\">Return to forum</a><br /><br />\n</p>\n" );
-
-		Shared.footer(request,response);
-		
-		out.print( "\n" );
- Shared.analytics(request,response); 
-		out.print( "\n</body>\n</html>\n" );
-
-	}
-
-}
-
--- a/src/nabble/view/web/mailing_list/Subscribe2.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-<%
-package nabble.view.web.mailing_list;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import fschmidt.util.mail.MailAddress;
-import nabble.model.Node;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-
-
-public final class Subscribe2 extends HttpServlet {
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		String context = request.getContextPath();
-		User user = Jtp.getUser(request);
-		if( user==null ) {
-			Jtp.login("You must login to be able to subscribe to a list.",request,response);
-			return;
-		}
-		Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(request.getParameter("forum")));
-		MailingList mailingList = forum.getAssociatedMailingList();
-		ListServer listServer = mailingList.getListServer();
-		MailAddress emailAddress = new MailAddress(user.getEmail(), user.getName());
-		%>
-		<html>
-		<head>
-		<%
-		Shared.title(request,response,"Subscribe to mailing list");
-		%>
-		</head>
-		<body>
-		<% Shared.minHeader(request, response, forum); %>
-		<h1>Subscription Request Was Sent</h1>
-		<p>
-		A subscription request was sent on your behalf to the mailing list: <strong><%=mailingList.getListAddress()%></strong>.
-		You will soon receive a confirmation request by email at <strong><%=user.getEmail()%></strong>. Please follow the
-		instructions in the email to complete your subscription.
-		</p>
-		
-		<p>
-		To ensure that your posts are accepted by the mailing list, complete the subscription process before posting any messages to this forum.  If you have already posted messages that have not been accepted by the mailing list, you will need to resend them after you have finished subscribing.
-		</p>
-		
-		<p><strong>Remember:</strong> You are not subscribed to the <strong><%=mailingList.getListAddress()%></strong> list until you have followed the instructions in the email.</p>
-
-		<%
-		if( listServer.needsDefaults() && listServer!=ListServer.google ) {
-			%>
-			<p>
-			Also, we have sent you an email to help you turn off list mail delivery to your email address (<%=user.getEmail()%>). After your subscription has been approved, please click the corresponding link in the email to turn off list mail delivery.
-			</p>
-			<%
-		}
-		%>
-		<br /><br />
-		<p>
-		&#171; <a href="<%=Jtp.path(forum)%>">Return to forum</a><br /><br />
-		</p>
-		<%
-		Shared.footer(request,response);
-		%>
-		<% Shared.analytics(request,response); %>
-		</body>
-		</html>
-		<%
-	}
-
-}
-%>
--- a/src/nabble/view/web/mailing_list/SubscribeDefaults.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-
-package nabble.view.web.mailing_list;
-
-import fschmidt.util.mail.Mail;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-
-public final class SubscribeDefaults extends HttpServlet {
-
-	private static final Logger logger = LoggerFactory.getLogger(SubscribeDefaults.class);
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		User user = Jtp.getUser(request);
-		if( user==null ) {
-			Jtp.login("You must login to be able to subscribe to a list.",request,response);
-			return;
-		}
-		Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(request.getParameter("forum")));
-		MailingList mailingList = forum.getAssociatedMailingList();
-		ListServer listServer = mailingList.getListServer();
-		if( "set".equals( request.getParameter("Action") ) ) {
-			Mail defaultsMail = mailingList.defaultsMail(user, request.getParameter("k"));
-			ModelHome.send(defaultsMail);
-			logger.info("set nomail request from "+user.getEmail()
-					+" to "+mailingList.getListAddress());
-			response.sendRedirect("SubscribeDefaults.jtp?forum="+forum.getId()+"&done=y");
-			return;
-		}
-		boolean done = "y".equals(request.getParameter("done"));
-		
-		out.print( "\n<html>\n<head>\n	" );
- Shared.title(request,response,"Subscribe to mailing list"); 
-		out.print( "\n</head>\n<body>\n	" );
- Shared.minHeader(request, response, forum); 
-		out.print( "\n	<h1>Mailing list subscription</h1>\n	" );
-
-			if (done) {
-				
-		out.print( "\n<p>\n	The request to turn off list mail delivery from <strong>" );
-		out.print( (mailingList.getListAddress()) );
-		out.print( "</strong> to your email address (" );
-		out.print( (user.getEmail()) );
-		out.print( ") has been submitted. You should not receive any more messages from this mailing list at this email address.\n</p>\n<br /><br />\n<p>\n	&#171; <a href=\"" );
-		out.print( (Jtp.path(forum)) );
-		out.print( "\">Return to forum</a>\n</p>\n" );
-
-			} else if(listServer.supportsDeliveryOff()){
-				
-		out.print( "\n<form method=post action=\"" );
-		out.print( (response.encodeURL("SubscribeDefaults.jtp")) );
-		out.print( "\">\n<input type=hidden name=\"Action\" value=\"set\">\n<input type=hidden name=\"forum\" value=\"" );
-		out.print( (forum.getId()) );
-		out.print( "\">\n<input type=hidden name=\"k\" value=\"" );
-		out.print( (Jtp.hideNull(request.getParameter("k"))) );
-		out.print( "\">\n<p>\n	This will submit a request to turn off mail delivery from the mailing list <strong>" );
-		out.print( (mailingList.getListAddress()) );
-		out.print( "</strong>.\n</p>\n\n<p>\n	<strong>NOTE: </strong> Submitting this request will only work after your subscription to the mailing list\nhas been approved. If your subscription is not yet approved, you will receive an error message via email. In this case, please submit the request again after your subscription is approved.\n</p>\n<br /><br />\n<input type=submit value=\"Turn Off Email Delivery\">\n</form>\n" );
-
-			} else {
-				
-		out.print( "\n	<strong>We're sorry!</strong> Turning off email delivery is not supported by <strong>" );
-		out.print( (mailingList.getListAddress()) );
-		out.print( "</strong>. However, you can use the Unsubscribe option offered by the mailing list to stop receiving emails from them.\n" );
-
-			}
-			
-		out.print( "\n" );
- Shared.footer(request,response); 
-		out.print( "\n" );
- Shared.analytics(request,response); 
-		out.print( "\n</body>\n</html>\n" );
-
-	}
-}
-
--- a/src/nabble/view/web/mailing_list/SubscribeDefaults.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-<%
-package nabble.view.web.mailing_list;
-
-import fschmidt.util.mail.Mail;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-
-public final class SubscribeDefaults extends HttpServlet {
-
-	private static final Logger logger = LoggerFactory.getLogger(SubscribeDefaults.class);
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		User user = Jtp.getUser(request);
-		if( user==null ) {
-			Jtp.login("You must login to be able to subscribe to a list.",request,response);
-			return;
-		}
-		Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(request.getParameter("forum")));
-		MailingList mailingList = forum.getAssociatedMailingList();
-		ListServer listServer = mailingList.getListServer();
-		if( "set".equals( request.getParameter("Action") ) ) {
-			Mail defaultsMail = mailingList.defaultsMail(user, request.getParameter("k"));
-			ModelHome.send(defaultsMail);
-			logger.info("set nomail request from "+user.getEmail()
-					+" to "+mailingList.getListAddress());
-			response.sendRedirect("SubscribeDefaults.jtp?forum="+forum.getId()+"&done=y");
-			return;
-		}
-		boolean done = "y".equals(request.getParameter("done"));
-		%>
-		<html>
-		<head>
-			<% Shared.title(request,response,"Subscribe to mailing list"); %>
-		</head>
-		<body>
-			<% Shared.minHeader(request, response, forum); %>
-			<h1>Mailing list subscription</h1>
-			<%
-			if (done) {
-				%>
-				<p>
-					The request to turn off list mail delivery from <strong><%=mailingList.getListAddress()%></strong> to your email address (<%=user.getEmail()%>) has been submitted. You should not receive any more messages from this mailing list at this email address.
-				</p>
-				<br /><br />
-				<p>
-					&#171; <a href="<%=Jtp.path(forum)%>">Return to forum</a>
-				</p>
-				<%
-			} else if(listServer.supportsDeliveryOff()){
-				%>
-				<form method=post action="<%=response.encodeURL("SubscribeDefaults.jtp")%>">
-				<input type=hidden name="Action" value="set">
-				<input type=hidden name="forum" value="<%=forum.getId()%>">
-				<input type=hidden name="k" value="<%=Jtp.hideNull(request.getParameter("k"))%>">
-				<p>
-					This will submit a request to turn off mail delivery from the mailing list <strong><%=mailingList.getListAddress()%></strong>.
-				</p>
-
-				<p>
-					<strong>NOTE: </strong> Submitting this request will only work after your subscription to the mailing list
-				has been approved. If your subscription is not yet approved, you will receive an error message via email. In this case, please submit the request again after your subscription is approved.
-				</p>
-				<br /><br />
-				<input type=submit value="Turn Off Email Delivery">
-				</form>
-				<%
-			} else {
-				%>
-					<strong>We're sorry!</strong> Turning off email delivery is not supported by <strong><%=mailingList.getListAddress()%></strong>. However, you can use the Unsubscribe option offered by the mailing list to stop receiving emails from them.
-				<%
-			}
-			%>
-			<% Shared.footer(request,response); %>
-			<% Shared.analytics(request,response); %>
-		</body>
-		</html>
-		<%
-	}
-}
-%>
--- a/src/nabble/view/web/mailing_list/SubscribeToMailingList.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-
-package nabble.view.web.mailing_list;
-
-import fschmidt.util.mail.Mail;
-import fschmidt.util.mail.MailAddress;
-import fschmidt.util.mail.MailException;
-import fschmidt.util.mail.MailHome;
-import fschmidt.util.mail.PlainTextContent;
-import fschmidt.util.mail.TextContent;
-import fschmidt.util.servlet.AuthorizingServlet;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-
-public final class SubscribeToMailingList extends HttpServlet implements AuthorizingServlet {
-
-	private static final Logger logger = LoggerFactory.getLogger(SubscribeToMailingList.class);
-
-	public String getAuthorizationKey(HttpServletRequest request) throws ServletException {
-		return Jtp.getReadAuthorizationKey( Jtp.getSiteNotNull(request).getNode(Jtp.getLong(request,"node")) );
-	}
-
-	public boolean authorize(String key,HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
-		return Jtp.authorizeForRead(key,request,response); 
-	}
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		User user = Jtp.getUser(request);
-
-		if (user == null) {
-			Jtp.login("You must login to subscribe to mailing list.", request, response);
-			return;
-		}
-
-		Node node = Jtp.getSiteNotNull(request).getNode(Jtp.getLong(request, "node"));
-		boolean allowed = Jtp.canBeEditedBy(node,user);
-		if (!allowed) {
-			Jtp.login("Only administrators can proceed in this area.", request, response);
-			return;
-		}
-
-		PrintWriter out = response.getWriter();
-		boolean isSendEmail = "SendEmail".equals(request.getParameter("action"));
-
-		MailingList mailingList = node.getMailingList();
-		String subscriptionAddress = mailingList.getSubscriberAddress().getAddrSpec();
-		char c = 'A';
-		
-		out.print( "\n<html>\n	<head>\n		<META NAME=\"robots\" CONTENT=\"noindex,nofollow\">\n		" );
- Shared.title(request,response,"Subscription Instructions"); 
-		out.print( "\n		<style type=\"text/css\">\n			div.field-title {\n				margin-top: 0;\n			}\n			td.number {\n				width: 3em;\n				padding-bottom: .2em;\n			}\n			span.number {\n				font-size: 200%;\n				padding: 0 .3em .03em;\n				border-width:1px;\n				border-style:solid;\n			}\n		</style>\n	</head>\n	<body>\n		" );
- Shared.minHeader(request, response, node);
-		out.print( "\n		" );
- Shared.editHeader(node.getSubjectHtml(), "Subscription Instructions", out); 
-		out.print( "\n		" );
-
-				if (isSendEmail && "POST".equals(request.getMethod())) {
-					String errorMsg = sendRequest(node, request, out);
-					Shared.errorMessage(request, response, errorMsg, "Failed to send the request." );
-				}
-				
-		out.print( "\n<div class=\"field-box light-border-color\">\n	<div class=\"second-font field-title\">General Instructions</div>\n	<div style=\"margin-left:1.5em\">\n		Your mailing list archive will <b>ONLY</b> work properly if you have the following email address subscribed to the mailing list:\n		<div class=\"info-message\" style=\"margin:.2em;padding:.2em;font-weight:bold\">" );
-		out.print( (subscriptionAddress) );
-		out.print( "</div>\n		This can be done in several ways. Below you can find the most common ones.\n	</div>\n</div>\n\n<div class=\"second-font field-title\" style=\"margin-top:1em\">Subscription Options</div>\n<div class=\"weak-color\">Choose the best option for this mailing list.</div>\n\n<div class=\"field-box light-border-color\">\n	<table style=\"margin-left:1.3em\">\n		<tr valign=\"top\">\n			<td class=\"number\"><span class=\"number shaded-bg-color medium-border-color\">" );
-		out.print( (c++) );
-		out.print( "</span></td>\n			<td>\n				<div class=\"second-font field-title\">Add to subscriber's list</div>\n				Mailing list administrators usually can add email addresses to the subscribers' list directly.\n				If you can do this, add <b>" );
-		out.print( (subscriptionAddress) );
-		out.print( "</b> to that list.\n			</td>\n		</tr>\n	</table>\n</div>\n\n" );
- if (mailingList.getListServer() == ListServer.google) { 
-		out.print( "\n<div class=\"field-box light-border-color\">\n	<table style=\"margin-left:1.3em\">\n		<tr valign=\"top\">\n			<td class=\"number\"><span class=\"number shaded-bg-color medium-border-color\">" );
-		out.print( (c++) );
-		out.print( "</span></td>\n			<td>\n				<div class=\"second-font field-title\">Use the \"Invite\" feature of GoogleGroups </div>\n				You can go to the <a href=\"http://groups.google.com/\" rel=\"nofollow\">Google Groups website</a> and\n				invite the following address to be a member:\n				<b>" );
-		out.print( (subscriptionAddress) );
-		out.print( "</b>.<br>\n				The confirmation email will be forwarded to you so that you can complete this step.\n			</td>\n		</tr>\n	</table>\n</div>\n<div class=\"field-box light-border-color\">\n	<table style=\"margin-left:1.3em\">\n		<tr valign=\"top\">\n			<td class=\"number\"><span class=\"number shaded-bg-color medium-border-color\">" );
-		out.print( (c++) );
-		out.print( "</span></td>\n			<td>\n				<div class=\"second-font field-title\">Create an account in GoogleGroups for the subscription email</div>\n				You can go to the <a href=\"http://groups.google.com/\" rel=\"nofollow\">Google Groups website</a> and\n				create an account for this email:\n				<b>" );
-		out.print( (subscriptionAddress) );
-		out.print( "</b>.<br>\n				(Google will probably send a confirmation number to your cell phone so that you can finish the registration)<br>\n				When you have finished the account set up, you can go to the mailing list page and click on \"Join this group\".\n			</td>\n		</tr>\n	</table>\n</div>\n" );
- } else { 
-		out.print( "\n	<div class=\"field-box light-border-color\">\n		<table style=\"margin-left:1.3em\">\n			<tr valign=\"top\">\n				<td class=\"number\"><span class=\"number shaded-bg-color medium-border-color\">" );
-		out.print( (c++) );
-		out.print( "</span></td>\n				<td>\n					<div class=\"second-font field-title\">Go to mailing list website</div>\n					You can go to the mailing list homepage (<a href=\"" );
-		out.print( (mailingList.getUrl()) );
-		out.print( "\">" );
-		out.print( (mailingList.getUrl()) );
-		out.print( "</a>)\n					and subscribe <b>" );
-		out.print( (subscriptionAddress) );
-		out.print( "</b> to the list.\n					The confirmation email will be forwarded to your email address as soon as it is received by Nabble.com.\n					You will have to follow the instructions in that email to confirm this request.\n				</td>\n			</tr>\n		</table>\n	</div>\n" );
- } 
-		out.print( "\n" );
- emailForm(node, true, "Subscribe by email", "Send Subscription Request", c, request, out); 
-		out.print( "\n\n" );
- Shared.footer(request,response); 
-		out.print( "\n" );
- Shared.analytics(request,response); 
-		out.print( "\n</body>\n</html>\n" );
-
-	}
-
-	static String sendRequest(Node node, HttpServletRequest request, PrintWriter out)
-		throws ServletException, IOException
-	{
-		String emailFrom = request.getParameter("emailFrom");
-		String emailToUser = request.getParameter("emailToUser");
-		String emailToDomain = request.getParameter("emailToDomain");
-		String emailSubject = request.getParameter("emailSubject");
-		String emailBody = request.getParameter("emailBody");
-
-		if (emailFrom == null || emailToUser == null || emailToDomain == null) {
-			return "Invalid message parameters";
-		} else {
-			MailAddress toAddress = new MailAddress(emailToUser + emailToDomain);
-			try {
-				Mail mail = MailHome.newMail();
-				mail.setFrom(new MailAddress(emailFrom, "Nabble Forums"));
-				mail.setTo(toAddress);
-				mail.setSubject(emailSubject);
-				mail.setContent(new PlainTextContent(emailBody));
-				ModelHome.send(mail);
-			} catch(MailException e) {
-				logger.warn("",e);
-				return e.getMessage();
-			}
-			
-		out.print( "\n<div class=\"info-message\" style=\"padding:1em\">\n	<b>Email Sent</b><br/>\n	The request has been successfully sent. The confirmation email will be forwarded to your email\n	address as soon as it is received by Nabble. You will have to follow the instructions in\n	that email to finish the process.<br/>\n	<a href=\"" );
-		out.print( (Jtp.path(node)) );
-		out.print( "\">Return to forum</a>\n</div>\n" );
-
-		}
-		return null;
-	}	
-
-	static void emailForm(Node node, boolean isSubscription, String title, String button, char c, HttpServletRequest request, PrintWriter out) {
-		MailingList mailingList = node.getMailingList();
-		if (!mailingList.getListServer().canSubscribe())
-			return;
-		
-		out.print( "\n<div class=\"field-box light-border-color\">\n	<table style=\"margin-left:1.3em\">\n		<tr valign=\"top\">\n			<td class=\"number\"><span class=\"number shaded-bg-color medium-border-color\">" );
-		out.print( (c) );
-		out.print( "</span></td>\n			<td>\n				<div class=\"second-font field-title\">" );
-		out.print( (title) );
-		out.print( "</div>\n				You can send the request by email. Default content of the email is\n				provided according to the mailing list server type (<b>" );
-		out.print( (mailingList.getListServer().getViewName()) );
-		out.print( "</b>)\n				that you have specified during the mailing list setup. You can modify it if necessary.\n			</td>\n		</tr>\n	</table>\n</div>\n" );
-
-		String emailFrom = request.getParameter("emailFrom");
-		String emailToUser = request.getParameter("emailToUser");
-		String emailToDomain = request.getParameter("emailToDomain");
-		String emailSubject = request.getParameter("emailSubject");
-		String emailBody = request.getParameter("emailBody");
-		Mail mail = isSubscription? mailingList.subscribeMail(): mailingList.unsubscribeMail();
-
-		if (emailFrom == null) {
-			emailFrom = mail.getFrom().getAddrSpec();
-		}
-
-		if (emailToUser == null || emailToDomain == null) {
-			String emailTo = mail.getTo()[0].getAddrSpec();
-			int index = emailTo.indexOf("@");
-			if(index < 0) {
-				throw new RuntimeException("Invalid emailTo: " + emailTo);
-			}
-			emailToUser = emailTo.substring(0, index);
-			emailToDomain = emailTo.substring(index);
-		}
-
-		if (emailSubject == null) {
-			emailSubject = Jtp.hideNull(mail.getSubject());
-		}
-
-		if (emailBody == null) {
-			emailBody = ((TextContent) mail.getContent()).getText();
-		}
-		
-		out.print( "\n<form method=\"post\" action=\"/mailing_list/" );
-		out.print( (isSubscription? "SubscribeToMailingList.jtp":"UnsubscribeFromMailingList.jtp") );
-		out.print( "\" accept-charset=\"UTF-8\">\n	<input type=\"hidden\" name=\"node\" value=\"" );
-		out.print( (node.getId()) );
-		out.print( "\">\n	<input type=\"hidden\" name=\"action\" value=\"SendEmail\">\n	<input type=\"hidden\" name=\"emailToDomain\" value=\"" );
-		out.print( (emailToDomain) );
-		out.print( "\">\n	<input type=\"hidden\" name=\"emailToUser\" value=\"" );
-		out.print( (emailToUser) );
-		out.print( "\">\n	<input type=\"hidden\" name=\"emailSubject\" value=\"" );
-		out.print( (emailSubject) );
-		out.print( "\">\n	<input type=\"hidden\" name=\"emailBody\" value=\"" );
-		out.print( (emailBody) );
-		out.print( "\">\n	<input type=\"hidden\" name=\"emailFrom\" value=\"" );
-		out.print( (emailFrom) );
-		out.print( "\"/>\n	<table style=\"margin-left:2em\">\n		<tr>\n			<td align=right>From:&nbsp;</td>\n			<td><input type=\"text\" name=\"emailFrom2\" value=\"" );
-		out.print( (emailFrom) );
-		out.print( "\" size=\"50\" disabled/></td>\n		</tr>\n		<tr>\n			<td align=right>To:&nbsp;</td>\n			<td valign=\"middle\"><input type=\"text\" name=\"emailToUser2\" value=\"" );
-		out.print( (emailToUser) );
-		out.print( "\" size=\"50\" disabled/>" );
-		out.print( (emailToDomain) );
-		out.print( "</td>\n		</tr>\n		<tr>\n			<td align=right>Subject:&nbsp;</td>\n			<td><input type=\"text\" name=\"emailSubject2\" value=\"" );
-		out.print( (emailSubject) );
-		out.print( "\" size=\"50\" disabled/></td>\n		</tr>\n		<tr>\n			<td align=right valign=top>Message:&nbsp;</td>\n			<td><textarea cols=\"50\" rows=\"5\" name=\"emailBody2\" wrap=\"SOFT\" disabled>" );
-		out.print( (emailBody) );
-		out.print( "</textarea></td>\n		</tr>\n		<tr>\n			<td><br></td>\n			<td>\n				<input type=\"submit\" value=\"" );
-		out.print( (button) );
-		out.print( "\" />\n			</td>\n		</tr>\n	</table>\n</form>\n" );
-
-	}
-
-}
-
--- a/src/nabble/view/web/mailing_list/SubscribeToMailingList.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,296 +0,0 @@
-<%
-package nabble.view.web.mailing_list;
-
-import fschmidt.util.mail.Mail;
-import fschmidt.util.mail.MailAddress;
-import fschmidt.util.mail.MailException;
-import fschmidt.util.mail.MailHome;
-import fschmidt.util.mail.PlainTextContent;
-import fschmidt.util.mail.TextContent;
-import fschmidt.util.servlet.AuthorizingServlet;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-
-public final class SubscribeToMailingList extends HttpServlet implements AuthorizingServlet {
-
-	private static final Logger logger = LoggerFactory.getLogger(SubscribeToMailingList.class);
-
-	public String getAuthorizationKey(HttpServletRequest request) throws ServletException {
-		return Jtp.getReadAuthorizationKey( Jtp.getSiteNotNull(request).getNode(Jtp.getLong(request,"node")) );
-	}
-
-	public boolean authorize(String key,HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
-		return Jtp.authorizeForRead(key,request,response); 
-	}
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		User user = Jtp.getUser(request);
-
-		if (user == null) {
-			Jtp.login("You must login to subscribe to mailing list.", request, response);
-			return;
-		}
-
-		Node node = Jtp.getSiteNotNull(request).getNode(Jtp.getLong(request, "node"));
-		boolean allowed = Jtp.canBeEditedBy(node,user);
-		if (!allowed) {
-			Jtp.login("Only administrators can proceed in this area.", request, response);
-			return;
-		}
-
-		PrintWriter out = response.getWriter();
-		boolean isSendEmail = "SendEmail".equals(request.getParameter("action"));
-
-		MailingList mailingList = node.getMailingList();
-		String subscriptionAddress = mailingList.getSubscriberAddress().getAddrSpec();
-		char c = 'A';
-		%>
-		<html>
-			<head>
-				<META NAME="robots" CONTENT="noindex,nofollow">
-				<% Shared.title(request,response,"Subscription Instructions"); %>
-				<style type="text/css">
-					div.field-title {
-						margin-top: 0;
-					}
-					td.number {
-						width: 3em;
-						padding-bottom: .2em;
-					}
-					span.number {
-						font-size: 200%;
-						padding: 0 .3em .03em;
-						border-width:1px;
-						border-style:solid;
-					}
-				</style>
-			</head>
-			<body>
-				<% Shared.minHeader(request, response, node);%>
-				<% Shared.editHeader(node.getSubjectHtml(), "Subscription Instructions", out); %>
-				<%
-				if (isSendEmail && "POST".equals(request.getMethod())) {
-					String errorMsg = sendRequest(node, request, out);
-					Shared.errorMessage(request, response, errorMsg, "Failed to send the request." );
-				}
-				%>
-				<div class="field-box light-border-color">
-					<div class="second-font field-title">General Instructions</div>
-					<div style="margin-left:1.5em">
-						Your mailing list archive will <b>ONLY</b> work properly if you have the following email address subscribed to the mailing list:
-						<div class="info-message" style="margin:.2em;padding:.2em;font-weight:bold"><%=subscriptionAddress%></div>
-						This can be done in several ways. Below you can find the most common ones.
-					</div>
-				</div>
-
-				<div class="second-font field-title" style="margin-top:1em">Subscription Options</div>
-				<div class="weak-color">Choose the best option for this mailing list.</div>
-
-				<div class="field-box light-border-color">
-					<table style="margin-left:1.3em">
-						<tr valign="top">
-							<td class="number"><span class="number shaded-bg-color medium-border-color"><%=c++%></span></td>
-							<td>
-								<div class="second-font field-title">Add to subscriber's list</div>
-								Mailing list administrators usually can add email addresses to the subscribers' list directly.
-								If you can do this, add <b><%=subscriptionAddress%></b> to that list.
-							</td>
-						</tr>
-					</table>
-				</div>
-
-				<% if (mailingList.getListServer() == ListServer.google) { %>
-				<div class="field-box light-border-color">
-					<table style="margin-left:1.3em">
-						<tr valign="top">
-							<td class="number"><span class="number shaded-bg-color medium-border-color"><%=c++%></span></td>
-							<td>
-								<div class="second-font field-title">Use the "Invite" feature of GoogleGroups </div>
-								You can go to the <a href="http://groups.google.com/" rel="nofollow">Google Groups website</a> and
-								invite the following address to be a member:
-								<b><%=subscriptionAddress%></b>.<br>
-								The confirmation email will be forwarded to you so that you can complete this step.
-							</td>
-						</tr>
-					</table>
-				</div>
-				<div class="field-box light-border-color">
-					<table style="margin-left:1.3em">
-						<tr valign="top">
-							<td class="number"><span class="number shaded-bg-color medium-border-color"><%=c++%></span></td>
-							<td>
-								<div class="second-font field-title">Create an account in GoogleGroups for the subscription email</div>
-								You can go to the <a href="http://groups.google.com/" rel="nofollow">Google Groups website</a> and
-								create an account for this email:
-								<b><%=subscriptionAddress%></b>.<br>
-								(Google will probably send a confirmation number to your cell phone so that you can finish the registration)<br>
-								When you have finished the account set up, you can go to the mailing list page and click on "Join this group".
-							</td>
-						</tr>
-					</table>
-				</div>
-				<% } else { %>
-					<div class="field-box light-border-color">
-						<table style="margin-left:1.3em">
-							<tr valign="top">
-								<td class="number"><span class="number shaded-bg-color medium-border-color"><%=c++%></span></td>
-								<td>
-									<div class="second-font field-title">Go to mailing list website</div>
-									You can go to the mailing list homepage (<a href="<%=mailingList.getUrl()%>"><%=mailingList.getUrl()%></a>)
-									and subscribe <b><%=subscriptionAddress%></b> to the list.
-									The confirmation email will be forwarded to your email address as soon as it is received by Nabble.com.
-									You will have to follow the instructions in that email to confirm this request.
-								</td>
-							</tr>
-						</table>
-					</div>
-				<% } %>
-				<% emailForm(node, true, "Subscribe by email", "Send Subscription Request", c, request, out); %>
-
-				<% Shared.footer(request,response); %>
-				<% Shared.analytics(request,response); %>
-			</body>
-		</html>
-		<%
-	}
-
-	static String sendRequest(Node node, HttpServletRequest request, PrintWriter out)
-		throws ServletException, IOException
-	{
-		String emailFrom = request.getParameter("emailFrom");
-		String emailToUser = request.getParameter("emailToUser");
-		String emailToDomain = request.getParameter("emailToDomain");
-		String emailSubject = request.getParameter("emailSubject");
-		String emailBody = request.getParameter("emailBody");
-
-		if (emailFrom == null || emailToUser == null || emailToDomain == null) {
-			return "Invalid message parameters";
-		} else {
-			MailAddress toAddress = new MailAddress(emailToUser + emailToDomain);
-			try {
-				Mail mail = MailHome.newMail();
-				mail.setFrom(new MailAddress(emailFrom, "Nabble Forums"));
-				mail.setTo(toAddress);
-				mail.setSubject(emailSubject);
-				mail.setContent(new PlainTextContent(emailBody));
-				ModelHome.send(mail);
-			} catch(MailException e) {
-				logger.warn("",e);
-				return e.getMessage();
-			}
-			%>
-			<div class="info-message" style="padding:1em">
-				<b>Email Sent</b><br/>
-				The request has been successfully sent. The confirmation email will be forwarded to your email
-				address as soon as it is received by Nabble. You will have to follow the instructions in
-				that email to finish the process.<br/>
-				<a href="<%=Jtp.path(node)%>">Return to forum</a>
-			</div>
-			<%
-		}
-		return null;
-	}	
-
-	static void emailForm(Node node, boolean isSubscription, String title, String button, char c, HttpServletRequest request, PrintWriter out) {
-		MailingList mailingList = node.getMailingList();
-		if (!mailingList.getListServer().canSubscribe())
-			return;
-		%>
-		<div class="field-box light-border-color">
-			<table style="margin-left:1.3em">
-				<tr valign="top">
-					<td class="number"><span class="number shaded-bg-color medium-border-color"><%=c%></span></td>
-					<td>
-						<div class="second-font field-title"><%=title%></div>
-						You can send the request by email. Default content of the email is
-						provided according to the mailing list server type (<b><%=mailingList.getListServer().getViewName()%></b>)
-						that you have specified during the mailing list setup. You can modify it if necessary.
-					</td>
-				</tr>
-			</table>
-		</div>
-		<%
-		String emailFrom = request.getParameter("emailFrom");
-		String emailToUser = request.getParameter("emailToUser");
-		String emailToDomain = request.getParameter("emailToDomain");
-		String emailSubject = request.getParameter("emailSubject");
-		String emailBody = request.getParameter("emailBody");
-		Mail mail = isSubscription? mailingList.subscribeMail(): mailingList.unsubscribeMail();
-
-		if (emailFrom == null) {
-			emailFrom = mail.getFrom().getAddrSpec();
-		}
-
-		if (emailToUser == null || emailToDomain == null) {
-			String emailTo = mail.getTo()[0].getAddrSpec();
-			int index = emailTo.indexOf("@");
-			if(index < 0) {
-				throw new RuntimeException("Invalid emailTo: " + emailTo);
-			}
-			emailToUser = emailTo.substring(0, index);
-			emailToDomain = emailTo.substring(index);
-		}
-
-		if (emailSubject == null) {
-			emailSubject = Jtp.hideNull(mail.getSubject());
-		}
-
-		if (emailBody == null) {
-			emailBody = ((TextContent) mail.getContent()).getText();
-		}
-		%>
-		<form method="post" action="/mailing_list/<%=isSubscription? "SubscribeToMailingList.jtp":"UnsubscribeFromMailingList.jtp"%>" accept-charset="UTF-8">
-			<input type="hidden" name="node" value="<%=node.getId()%>">
-			<input type="hidden" name="action" value="SendEmail">
-			<input type="hidden" name="emailToDomain" value="<%=emailToDomain%>">
-			<input type="hidden" name="emailToUser" value="<%=emailToUser%>">
-			<input type="hidden" name="emailSubject" value="<%=emailSubject%>">
-			<input type="hidden" name="emailBody" value="<%=emailBody%>">
-			<input type="hidden" name="emailFrom" value="<%=emailFrom%>"/>
-			<table style="margin-left:2em">
-				<tr>
-					<td align=right>From:&nbsp;</td>
-					<td><input type="text" name="emailFrom2" value="<%=emailFrom%>" size="50" disabled/></td>
-				</tr>
-				<tr>
-					<td align=right>To:&nbsp;</td>
-					<td valign="middle"><input type="text" name="emailToUser2" value="<%=emailToUser%>" size="50" disabled/><%=emailToDomain%></td>
-				</tr>
-				<tr>
-					<td align=right>Subject:&nbsp;</td>
-					<td><input type="text" name="emailSubject2" value="<%=emailSubject%>" size="50" disabled/></td>
-				</tr>
-				<tr>
-					<td align=right valign=top>Message:&nbsp;</td>
-					<td><textarea cols="50" rows="5" name="emailBody2" wrap="SOFT" disabled><%=emailBody%></textarea></td>
-				</tr>
-				<tr>
-					<td><br></td>
-					<td>
-						<input type="submit" value="<%=button%>" />
-					</td>
-				</tr>
-			</table>
-		</form>
-		<%
-	}
-
-}
-%>
--- a/src/nabble/view/web/mailing_list/Unsubscribe.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-
-package nabble.view.web.mailing_list;
-
-import fschmidt.util.mail.Mail;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
-
-public final class Unsubscribe extends HttpServlet {
-
-	private static final Logger logger = LoggerFactory.getLogger(Unsubscribe.class);
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		User user = Jtp.getUser(request);
-		if( user==null ) {
-			Jtp.login("You must login to be able to unsubscribe from a list.",request,response);
-			return;
-		}
-		Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(request.getParameter("forum")));
-		MailingList mailingList = forum.getAssociatedMailingList();
-		Mail unsubscribeMail = mailingList.unsubscribeMail(user);
-		ModelHome.send(unsubscribeMail);
-		logger.info("unsubscription request from "+user.getEmail()+" to "+mailingList.getListAddress());
-		response.sendRedirect("Unsubscribe2.jtp?forum="+forum.getId());
-	}
-}
-
--- a/src/nabble/view/web/mailing_list/Unsubscribe.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-<%
-package nabble.view.web.mailing_list;
-
-import fschmidt.util.mail.Mail;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
-
-public final class Unsubscribe extends HttpServlet {
-
-	private static final Logger logger = LoggerFactory.getLogger(Unsubscribe.class);
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		User user = Jtp.getUser(request);
-		if( user==null ) {
-			Jtp.login("You must login to be able to unsubscribe from a list.",request,response);
-			return;
-		}
-		Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(request.getParameter("forum")));
-		MailingList mailingList = forum.getAssociatedMailingList();
-		Mail unsubscribeMail = mailingList.unsubscribeMail(user);
-		ModelHome.send(unsubscribeMail);
-		logger.info("unsubscription request from "+user.getEmail()+" to "+mailingList.getListAddress());
-		response.sendRedirect("Unsubscribe2.jtp?forum="+forum.getId());
-	}
-}
-%>
--- a/src/nabble/view/web/mailing_list/Unsubscribe2.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-
-package nabble.view.web.mailing_list;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import nabble.model.Node;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-import fschmidt.util.mail.MailAddress;
-
-
-public final class Unsubscribe2 extends HttpServlet {
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		String context = request.getContextPath();
-		User user = Jtp.getUser(request);
-		if( user==null ) {
-			Jtp.login("You must login to be able to subscribe to a list.",request,response);
-			return;
-		}
-		Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(request.getParameter("forum")));
-		MailingList mailingList = forum.getAssociatedMailingList();
-		ListServer listServer = mailingList.getListServer();
-		MailAddress emailAddress = new MailAddress(user.getEmail(), user.getName());
-		
-		out.print( "\r\n<html>\r\n<head>\r\n" );
-
-		Shared.title(request,response,"Subscribe to mailing list");
-		
-		out.print( "\r\n</head>\r\n<body>\r\n" );
- Shared.minHeader(request, response, forum); 
-		out.print( "\r\n<h1>Unsubscription Request Was Sent</h1>\r\n<p>\r\n	An unsubscription request was sent on your behalf to the mailing list: <strong>" );
-		out.print( (mailingList.getListAddress()) );
-		out.print( "</strong>.\r\n</p>\r\n<p>\r\n	You will soon receive a confirmation request by email at <strong>" );
-		out.print( (user.getEmail()) );
-		out.print( "</strong>. Please follow the\r\ninstructions in this request to unsubscribe from the mailing list.\r\n</p>\r\n<p>\r\n	<strong>Remember:</strong> You are not unsubscribed from the <strong>" );
-		out.print( (mailingList.getListAddress()) );
-		out.print( "</strong> list until you have followed the instructions in the email.\r\n</p>\r\n\r\n<br /><br />\r\n<p>&#171; <a href=\"" );
-		out.print( (Jtp.path(forum)) );
-		out.print( "\">Return to forum</a></p>\r\n" );
-
-		Shared.footer(request,response);
-		Shared.analytics(request,response);
-		
-		out.print( "\r\n</body>\r\n</html>\r\n" );
-
-	}
-}
-
--- a/src/nabble/view/web/mailing_list/Unsubscribe2.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-<%
-package nabble.view.web.mailing_list;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import nabble.model.Node;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-import fschmidt.util.mail.MailAddress;
-
-
-public final class Unsubscribe2 extends HttpServlet {
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		String context = request.getContextPath();
-		User user = Jtp.getUser(request);
-		if( user==null ) {
-			Jtp.login("You must login to be able to subscribe to a list.",request,response);
-			return;
-		}
-		Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(request.getParameter("forum")));
-		MailingList mailingList = forum.getAssociatedMailingList();
-		ListServer listServer = mailingList.getListServer();
-		MailAddress emailAddress = new MailAddress(user.getEmail(), user.getName());
-		%>
-		<html>
-		<head>
-		<%
-		Shared.title(request,response,"Subscribe to mailing list");
-		%>
-		</head>
-		<body>
-		<% Shared.minHeader(request, response, forum); %>
-		<h1>Unsubscription Request Was Sent</h1>
-		<p>
-			An unsubscription request was sent on your behalf to the mailing list: <strong><%=mailingList.getListAddress()%></strong>.
-		</p>
-		<p>
-			You will soon receive a confirmation request by email at <strong><%=user.getEmail()%></strong>. Please follow the
-		instructions in this request to unsubscribe from the mailing list.
-		</p>
-		<p>
-			<strong>Remember:</strong> You are not unsubscribed from the <strong><%=mailingList.getListAddress()%></strong> list until you have followed the instructions in the email.
-		</p>
-		
-		<br /><br />
-		<p>&#171; <a href="<%=Jtp.path(forum)%>">Return to forum</a></p>
-		<%
-		Shared.footer(request,response);
-		Shared.analytics(request,response);
-		%>
-		</body>
-		</html>
-		<%
-	}
-}
-%>
--- a/src/nabble/view/web/mailing_list/UnsubscribeFromMailingList.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-
-package nabble.view.web.mailing_list;
-
-import fschmidt.util.servlet.AuthorizingServlet;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-
-public final class UnsubscribeFromMailingList extends HttpServlet implements AuthorizingServlet {
-
-	public String getAuthorizationKey(HttpServletRequest request) throws ServletException {
-		return Jtp.getReadAuthorizationKey( Jtp.getSiteNotNull(request).getNode(Jtp.getLong(request,"node")) );
-	}
-
-	public boolean authorize(String key,HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
-		return Jtp.authorizeForRead(key,request,response);
-	}
-
-    protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		User user = Jtp.getUser(request);
-
-		if (user == null) {
-			Jtp.login("You must login to unsubscribe from a mailing list.", request, response);
-			return;
-		}
-
-		Node forum = Jtp.getSiteNotNull(request).getNode(Jtp.getLong(request, "node"));
-		boolean allowed = Jtp.canBeEditedBy(forum,user);
-		if (!allowed) {
-			Jtp.login("Only administrators can proceed in this area.", request, response);
-			return;
-		}
-
-		String errorMsg = null;
-		boolean isSendEmail = "SendEmail".equals(request.getParameter("action"));
-
-		MailingList mailingList = forum.getMailingList();
-		String subscriptionAddress = mailingList.getSubscriberAddress().getAddrSpec();
-		PrintWriter out = response.getWriter();
-		char c = 'A';
-		
-		out.print( "\r\n<html>\r\n	<head>\r\n		<META NAME=\"robots\" CONTENT=\"noindex,nofollow\">\r\n		" );
- Shared.title(request,response,"How to Unsubscribe this Forum"); 
-		out.print( "\r\n		<style type=\"text/css\">\r\n			div.field-title {\r\n				margin-top: 0;\r\n			}\r\n			td.number {\r\n				width: 3em;\r\n				padding-bottom: .2em;\r\n			}\r\n			span.number {\r\n				font-size: 200%;\r\n				padding: 0 .3em .03em;\r\n				border-width:1px;\r\n				border-style:solid;\r\n			}\r\n		</style>\r\n	</head>\r\n	<body>\r\n		" );
- Shared.minHeader(request, response, forum);
-		out.print( "\r\n		" );
- Shared.editHeader(forum.getSubjectHtml(), "How to Unsubscribe this Forum", out); 
-		out.print( "\r\n		" );
- Shared.errorMessage(request,response,errorMsg, "Please fix the error and try again." ); 
-		out.print( "\r\n		" );
-
-				if (isSendEmail && "POST".equals(request.getMethod())) {
-					errorMsg = SubscribeToMailingList.sendRequest(forum, request, out);
-					Shared.errorMessage(request, response, errorMsg, "Failed to send the request." );
-				}
-				
-		out.print( "\r\n\r\n<div class=\"field-box light-border-color\">\r\n	<div class=\"second-font field-title\">General Instructions</div>\r\n	<div style=\"margin-left:1.5em\">\r\n		If you want to unsubscribe this forum from a mailing list, you have to remove the following email address from the mailing list subscriber's list:\r\n		<div class=\"info-message\" style=\"margin:.2em;padding:.2em;font-weight:bold\">" );
-		out.print( (subscriptionAddress) );
-		out.print( "</div>\r\n		This can be done in several ways. Below you can find the most common ones.\r\n	</div>\r\n</div>\r\n\r\n<div class=\"second-font field-title\" style=\"margin-top:1em\">Unsubscription Options</div>\r\n<div class=\"weak-color\">Choose the best option for this mailing list.</div>\r\n\r\n<div class=\"field-box light-border-color\">\r\n	<table style=\"margin-left:1.3em\">\r\n		<tr valign=\"top\">\r\n			<td class=\"number\"><span class=\"number shaded-bg-color medium-border-color\">" );
-		out.print( (c++) );
-		out.print( "</span></td>\r\n			<td>\r\n				<div class=\"second-font field-title\">Remove from subscriber's list</div>\r\n				Mailing list administrators usually can remove email addresses from the subscribers' list directly.\r\n				If you can do this, remove <b>" );
-		out.print( (subscriptionAddress) );
-		out.print( "</b> from that list.\r\n			</td>\r\n		</tr>\r\n	</table>\r\n</div>\r\n\r\n<div class=\"field-box light-border-color\">\r\n	<table style=\"margin-left:1.3em\">\r\n		<tr valign=\"top\">\r\n			<td class=\"number\"><span class=\"number shaded-bg-color medium-border-color\">" );
-		out.print( (c++) );
-		out.print( "</span></td>\r\n			<td>\r\n				<div class=\"second-font field-title\">Go to mailing list website</div>\r\n				You can go to the mailing list homepage (<a href=\"" );
-		out.print( (mailingList.getUrl()) );
-		out.print( "\">" );
-		out.print( (mailingList.getUrl()) );
-		out.print( "</a>)\r\n				and unsubscribe <b>" );
-		out.print( (subscriptionAddress) );
-		out.print( "</b> from the list.\r\n				The confirmation email will be forwarded to your email address as soon as it is received by Nabble.com.\r\n				You will have to follow the instructions in that email to confirm this request.\r\n			</td>\r\n		</tr>\r\n	</table>\r\n</div>\r\n" );
- SubscribeToMailingList.emailForm(forum, false, "Unsubscribe by email", "Send Unsubscription Request", c, request, out); 
-		out.print( "\r\n" );
- Shared.footer(request,response); 
-		out.print( "\r\n" );
- Shared.analytics(request,response); 
-		out.print( "\r\n</body>\r\n</html>\r\n" );
-
-	}
-
-}
-
--- a/src/nabble/view/web/mailing_list/UnsubscribeFromMailingList.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-<%
-package nabble.view.web.mailing_list;
-
-import fschmidt.util.servlet.AuthorizingServlet;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-
-public final class UnsubscribeFromMailingList extends HttpServlet implements AuthorizingServlet {
-
-	public String getAuthorizationKey(HttpServletRequest request) throws ServletException {
-		return Jtp.getReadAuthorizationKey( Jtp.getSiteNotNull(request).getNode(Jtp.getLong(request,"node")) );
-	}
-
-	public boolean authorize(String key,HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
-		return Jtp.authorizeForRead(key,request,response);
-	}
-
-    protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		User user = Jtp.getUser(request);
-
-		if (user == null) {
-			Jtp.login("You must login to unsubscribe from a mailing list.", request, response);
-			return;
-		}
-
-		Node forum = Jtp.getSiteNotNull(request).getNode(Jtp.getLong(request, "node"));
-		boolean allowed = Jtp.canBeEditedBy(forum,user);
-		if (!allowed) {
-			Jtp.login("Only administrators can proceed in this area.", request, response);
-			return;
-		}
-
-		String errorMsg = null;
-		boolean isSendEmail = "SendEmail".equals(request.getParameter("action"));
-
-		MailingList mailingList = forum.getMailingList();
-		String subscriptionAddress = mailingList.getSubscriberAddress().getAddrSpec();
-		PrintWriter out = response.getWriter();
-		char c = 'A';
-		%>
-		<html>
-			<head>
-				<META NAME="robots" CONTENT="noindex,nofollow">
-				<% Shared.title(request,response,"How to Unsubscribe this Forum"); %>
-				<style type="text/css">
-					div.field-title {
-						margin-top: 0;
-					}
-					td.number {
-						width: 3em;
-						padding-bottom: .2em;
-					}
-					span.number {
-						font-size: 200%;
-						padding: 0 .3em .03em;
-						border-width:1px;
-						border-style:solid;
-					}
-				</style>
-			</head>
-			<body>
-				<% Shared.minHeader(request, response, forum);%>
-				<% Shared.editHeader(forum.getSubjectHtml(), "How to Unsubscribe this Forum", out); %>
-				<% Shared.errorMessage(request,response,errorMsg, "Please fix the error and try again." ); %>
-				<%
-				if (isSendEmail && "POST".equals(request.getMethod())) {
-					errorMsg = SubscribeToMailingList.sendRequest(forum, request, out);
-					Shared.errorMessage(request, response, errorMsg, "Failed to send the request." );
-				}
-				%>
-
-				<div class="field-box light-border-color">
-					<div class="second-font field-title">General Instructions</div>
-					<div style="margin-left:1.5em">
-						If you want to unsubscribe this forum from a mailing list, you have to remove the following email address from the mailing list subscriber's list:
-						<div class="info-message" style="margin:.2em;padding:.2em;font-weight:bold"><%=subscriptionAddress%></div>
-						This can be done in several ways. Below you can find the most common ones.
-					</div>
-				</div>
-
-				<div class="second-font field-title" style="margin-top:1em">Unsubscription Options</div>
-				<div class="weak-color">Choose the best option for this mailing list.</div>
-
-				<div class="field-box light-border-color">
-					<table style="margin-left:1.3em">
-						<tr valign="top">
-							<td class="number"><span class="number shaded-bg-color medium-border-color"><%=c++%></span></td>
-							<td>
-								<div class="second-font field-title">Remove from subscriber's list</div>
-								Mailing list administrators usually can remove email addresses from the subscribers' list directly.
-								If you can do this, remove <b><%=subscriptionAddress%></b> from that list.
-							</td>
-						</tr>
-					</table>
-				</div>
-
-				<div class="field-box light-border-color">
-					<table style="margin-left:1.3em">
-						<tr valign="top">
-							<td class="number"><span class="number shaded-bg-color medium-border-color"><%=c++%></span></td>
-							<td>
-								<div class="second-font field-title">Go to mailing list website</div>
-								You can go to the mailing list homepage (<a href="<%=mailingList.getUrl()%>"><%=mailingList.getUrl()%></a>)
-								and unsubscribe <b><%=subscriptionAddress%></b> from the list.
-								The confirmation email will be forwarded to your email address as soon as it is received by Nabble.com.
-								You will have to follow the instructions in that email to confirm this request.
-							</td>
-						</tr>
-					</table>
-				</div>
-				<% SubscribeToMailingList.emailForm(forum, false, "Unsubscribe by email", "Send Unsubscription Request", c, request, out); %>
-				<% Shared.footer(request,response); %>
-				<% Shared.analytics(request,response); %>
-			</body>
-		</html>
-		<%
-	}
-
-}
-%>
--- a/src/nabble/view/web/more/Forum.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/more/Forum.java	Fri Jun 18 17:44:24 2021 -0600
@@ -54,9 +54,7 @@
 		out.print( (Help.search.url(request)) );
 		out.print( "\">more</a>).<br>\r\n			Fast loading of pages.<br>\r\n			Fast support.<br>\r\n		</td>\r\n	</tr>\r\n</table>\r\n\r\n<table class=\"category\">\r\n	<tr valign=\"top\">\r\n		<td class=\"number\">\r\n			<span class=\"number shaded-bg-color medium-border-color\">5</span>\r\n		</td>\r\n		<td>\r\n			<span class=\"title medium-border-color\">Advanced</span>\r\n			SEO (<a class=\"more\" href=\"" );
 		out.print( (Help.seo.url(request)) );
-		out.print( "\">more</a>).<br>\r\n			Mirror your group (<a class=\"more\" href=\"" );
-		out.print( (Help.mirror.url(request)) );
-		out.print( "\">more</a>).\r\n		</td>\r\n	</tr>\r\n</table>\r\n<br/>\r\n<a class=\"forum-link\" href=\"" );
+		out.print( "\">more</a>).).\r\n		</td>\r\n	</tr>\r\n</table>\r\n<br/>\r\n<a class=\"forum-link\" href=\"" );
 		out.print( (ForumStart.path("forum")) );
 		out.print( "\">Start a free forum now</a> &raquo;\r\n\r\n" );
 
--- a/src/nabble/view/web/more/Forum.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/more/Forum.jtp	Fri Jun 18 17:44:24 2021 -0600
@@ -147,8 +147,7 @@
 				</td>
 				<td>
 					<span class="title medium-border-color">Advanced</span>
-					SEO (<a class="more" href="<%=Help.seo.url(request)%>">more</a>).<br>
-					Mirror your group (<a class="more" href="<%=Help.mirror.url(request)%>">more</a>).
+					SEO (<a class="more" href="<%=Help.seo.url(request)%>">more</a>).).
 				</td>
 			</tr>
 		</table>
--- a/src/nabble/view/web/more/ForumStart.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/more/ForumStart.java	Fri Jun 18 17:44:24 2021 -0600
@@ -42,7 +42,7 @@
 public final class ForumStart extends HttpServlet implements UrlMappable, CanonicalUrl {
 	private static final Logger logger = LoggerFactory.getLogger(ForumStart.class);
 
-	private static final Pattern URL_PATTERN = Pattern.compile("/free-(forum|gallery|newspaper|blog|mailing-list)\\.html$");
+	private static final Pattern URL_PATTERN = Pattern.compile("/free-(forum|gallery|newspaper|blog)\\.html$");
 
 	public static String url(String what) {
 		return Jtp.defaultContextUrl() + path(what);
@@ -83,14 +83,10 @@
 		String what = request.getParameter("what");
 		if (what == null)
 			what = "Forum";
-		else if ("mailing-list".equals(what))
-			what = "Mailing List";
 		else
 			what = Jtp.capitalize(what);
 
 		String imgName = what.toLowerCase();
-		if ("Mailing List".equals(what))
-			imgName = "mailing-list";
 
 		
 		out.print( "\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html>\r\n	<head>\r\n		" );
@@ -220,18 +216,6 @@
 			String type = get("type", request);
 			type = "newspaper".equals(type)? "news" : type;
 
-			String extraMessage = "";
-			if ("mailinglist".equals(type)) {
-				type = "forum";
-				StringBuilder m = new StringBuilder();
-				m.append("\n\nMailing List Options\n");
-				m.append("Click \"Options > Subscribe via email\" to subscribe to this mailing list;\n");
-				m.append("Click \"Options > Post by email...\" to get the email address of this mailing list;\n");
-				m.append("You can post messages via email or through the forum interface below;\n");
-				m.append("All web posts and emails are archived here.");
-				extraMessage = m.toString();
-			}
-
 			if (errors.isEmpty()) {
 				if( newSitePassword!=null && !newSitePassword.equals(password) ) {
 					logger.info("ignoring "+email);
@@ -242,7 +226,7 @@
 				db.beginTransaction();
 				try {
 					Recaptcha.check(request);
-					Site site = ModelHome.newSite(type,subject, message + extraMessage, Message.Format.TEXT, email, username);
+					Site site = ModelHome.newSite(type,subject, message, Message.Format.TEXT, email, username);
 					Permissions.addToGroup( (User)site.getRootNode().getOwner(), Permissions.ADMINISTRATORS_GROUP );
 					String key = site.newRegistration(email,password,username,"/");
 					db.commitTransaction();
--- a/src/nabble/view/web/more/ForumStart.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/more/ForumStart.jtp	Fri Jun 18 17:44:24 2021 -0600
@@ -42,7 +42,7 @@
 public final class ForumStart extends HttpServlet implements UrlMappable, CanonicalUrl {
 	private static final Logger logger = LoggerFactory.getLogger(ForumStart.class);
 
-	private static final Pattern URL_PATTERN = Pattern.compile("/free-(forum|gallery|newspaper|blog|mailing-list)\\.html$");
+	private static final Pattern URL_PATTERN = Pattern.compile("/free-(forum|gallery|newspaper|blog)\\.html$");
 
 	public static String url(String what) {
 		return Jtp.defaultContextUrl() + path(what);
@@ -83,14 +83,10 @@
 		String what = request.getParameter("what");
 		if (what == null)
 			what = "Forum";
-		else if ("mailing-list".equals(what))
-			what = "Mailing List";
 		else
 			what = Jtp.capitalize(what);
 
 		String imgName = what.toLowerCase();
-		if ("Mailing List".equals(what))
-			imgName = "mailing-list";
 
 		%>
 		<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
@@ -285,18 +281,6 @@
 			String type = get("type", request);
 			type = "newspaper".equals(type)? "news" : type;
 
-			String extraMessage = "";
-			if ("mailinglist".equals(type)) {
-				type = "forum";
-				StringBuilder m = new StringBuilder();
-				m.append("\n\nMailing List Options\n");
-				m.append("Click \"Options > Subscribe via email\" to subscribe to this mailing list;\n");
-				m.append("Click \"Options > Post by email...\" to get the email address of this mailing list;\n");
-				m.append("You can post messages via email or through the forum interface below;\n");
-				m.append("All web posts and emails are archived here.");
-				extraMessage = m.toString();
-			}
-
 			if (errors.isEmpty()) {
 				if( newSitePassword!=null && !newSitePassword.equals(password) ) {
 					logger.info("ignoring "+email);
@@ -307,7 +291,7 @@
 				db.beginTransaction();
 				try {
 					Recaptcha.check(request);
-					Site site = ModelHome.newSite(type,subject, message + extraMessage, Message.Format.TEXT, email, username);
+					Site site = ModelHome.newSite(type,subject, message, Message.Format.TEXT, email, username);
 					Permissions.addToGroup( (User)site.getRootNode().getOwner(), Permissions.ADMINISTRATORS_GROUP );
 					String key = site.newRegistration(email,password,username,"/");
 					db.commitTransaction();
--- a/src/nabble/view/web/more/MailingListRequest.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,281 +0,0 @@
-
-package nabble.view.web.more;
-
-import fschmidt.db.DbDatabase;
-import fschmidt.util.mail.MailAddress;
-import fschmidt.util.servlet.CanonicalUrl;
-import nabble.model.Db;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.Message;
-import nabble.model.ModelException;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.model.Site;
-import nabble.model.User;
-import nabble.model.Init;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.NewSiteMail;
-import nabble.view.lib.Permissions;
-import nabble.view.lib.Shared;
-import nabble.view.lib.UrlMappable;
-import nabble.view.lib.Recaptcha;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-public final class MailingListRequest extends HttpServlet implements UrlMappable, CanonicalUrl {
-	private static final Logger logger = LoggerFactory.getLogger(MailingListRequest.class);
-
-	private static final Pattern URL_PATTERN = Pattern.compile("/archive-your-mailing-list\\.html$");
-
-	public static String url() {
-		return Jtp.defaultContextUrl() + path();
-	}
-
-	public static String path() {
-		return "/archive-your-mailing-list.html";
-	}
-
-	public String getCanonicalUrl(HttpServletRequest request) {
-		return url();
-	}
-
-	public Map<String,String[]> getParameterMapFromUrl(HttpServletRequest request,String mappedUrl) {
-		Matcher m = URL_PATTERN.matcher(mappedUrl);
-		if( !m.find() )
-			throw new RuntimeException();
-		return new HashMap<String,String[]>();
-	}
-
-	public Pattern getUrlPattern() {
-		return URL_PATTERN;
-	}
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		build(request, response, Collections.<String,String>emptyMap(), Collections.<String,String>emptyMap());
-	}
-
-	private static void build(HttpServletRequest request,HttpServletResponse response, Map<String,String> values, Map<String,String> errors)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		
-		out.print( "\r\n<html>\r\n	<head>\r\n		" );
- Shared.title(request,response,"Archive Your Mailing List"); 
-		out.print( "\r\n		<META NAME=\"description\" CONTENT=\"Archiving a mailing list at Nabble is quick and easy. Fill in one simple form and you're done.\">\r\n		<META NAME=\"keywords\" CONTENT=\"free, mailing list archive, forum interface, gateway, customizable, easy, quick setup\">\r\n		<style type=\"text/css\">\r\n			div.field-title {\r\n				margin-top: 0;\r\n			}\r\n			td.column1 {\r\n				text-align:right;\r\n				width:7em;\r\n				white-space:nowrap;\r\n			}\r\n			div.field-box {\r\n				border:none;\r\n				margin:0;\r\n			}\r\n			input[type=text],input[type=password],select {\r\n                        padding:.3em 0;\r\n                    }\r\n			.important { font-weight:bold }\r\n		</style>\r\n		<script type=\"text/javascript\">\r\n			$(document).ready(function() {\r\n				$('#username').focus();\r\n			});\r\n		</script>\r\n		" );
-		out.print( ( Recaptcha.JS ) );
-		out.print( "\r\n	</head>\r\n	<body>\r\n		" );
- Shared.minHeaderGlobal(request,response); 
-		out.print( "\r\n\r\n		<h1>Archive Your Mailing List</h1>\r\n		<p>\r\n			<img src=\"/images/homepage/archive.png\" style=\"float:left;margin: 0 1em 1em 1em\"/>\r\n			You can archive your mailing list to a fully functional forum at Nabble by filling out\r\n			the form below.  This makes it easy for users to browse and search archived emails.\r\n			Users can even post to the Nabble forum and we will forward these posts to your mailing list.\r\n		</p>\r\n\r\n		" );
- if (errors.size() > 0) { 
-		out.print( "\r\n			<div class=\"error-message important\" style=\"margin:1em;padding:.5em 0 .5em 12em\">\r\n				" );
- String generic = errors.get("generic"); 
-		out.print( "\r\n				" );
-		out.print( (generic != null? generic : errors.size() > 0? "Please check the errors below" : "") );
-		out.print( "\r\n			</div>\r\n		" );
- } 
-		out.print( "\r\n\r\n		<form method=\"post\" action=\"/more/MailingListRequest$Save.jtp\" accept-charset=\"UTF-8\">\r\n			<input type=\"hidden\" name=\"Action\" value=\"save\">\r\n\r\n			<div style=\"border-bottom:2px solid #eeeeee;padding:1em;width:50em\">\r\n				<div class=\"weak-color\" style=\"width:11.5em;text-align:center;float:left\">\r\n					<div style=\"font-weight:bold\">Account</div>\r\n					<img src=\"/images/account.png\"/>\r\n					<div style=\"margin-top:1em;font-size:80%\">\r\n						You will receive an email with a link to activate your account\r\n					</div>\r\n				</div>\r\n				<table>\r\n					<tr>\r\n						<td><div class=\"second-font field-title\">User Name</div></td>\r\n						<td><input type=\"text\" id=\"username\" size=\"35\" maxlength=\"30\" name=\"username\" value=\"" );
-		out.print( (Jtp.hideNull(values.get("username"))) );
-		out.print( "\" /></td>\r\n						<td class=\"important\">" );
-		out.print( (errors.containsKey("username")? errors.get("username"):"") );
-		out.print( "</td>\r\n					</tr>\r\n					<tr>\r\n						<td><div class=\"second-font field-title\">Email</div></td>\r\n						<td><input type=\"text\" size=\"35\" maxlength=\"60\" name=\"email\" value=\"" );
-		out.print( (Jtp.hideNull(values.get("email"))) );
-		out.print( "\"/></td>\r\n						<td class=\"important\">" );
-		out.print( (errors.containsKey("email")? errors.get("email"):"") );
-		out.print( "</td>\r\n					</tr>\r\n					<tr>\r\n						<td><div class=\"second-font field-title\">Password</div></td>\r\n						<td><input type=\"password\" size=\"35\" maxlength=\"15\" name=\"password\" value=\"" );
-		out.print( (Jtp.hideNull(values.get("password"))) );
-		out.print( "\"/></td>\r\n						<td class=\"important\">" );
-		out.print( (errors.containsKey("password")? errors.get("password"):"") );
-		out.print( "</td>\r\n					</tr>\r\n					<tr>\r\n						<td class=\"column1\"><input type=\"checkbox\" id=\"terms\" name=\"terms\" value=\"y\" " );
-		out.print( ("y".equals(values.get("terms"))?"checked":"") );
-		out.print( " /></td>\r\n						<td colspan=2><label for=\"terms\">I have read and I agree to Nabble's <a href=\"" );
-		out.print( (Jtp.termsUrl(true)) );
-		out.print( "\">Terms of Use</a>.</label></td>\r\n					</tr>\r\n				</table>\r\n			</div>\r\n\r\n			<div style=\"padding:.5em;width:50em\">\r\n				<div class=\"weak-color\" style=\"width:12em;text-align:center;float:left;height:50em;padding-top:1em\">\r\n					<div style=\"font-weight:bold\">Mailing List</div>\r\n					<img src=\"/images/homepage/mailing-list.png\" alt=\"Free Mailing List Archive\">\r\n				</div>\r\n\r\n				<div class=\"field-box\">\r\n					<div class=\"second-font field-title\">Mailing List Address</div>\r\n					<div class=\"weak-color\">\r\n						<input id=\"mailingList\" type=\"text\" name=\"ml-address\" value=\"" );
-		out.print( (Jtp.hideNull(values.get("ml-address"))) );
-		out.print( "\" size=\"46\" />\r\n						<span class=\"important\">" );
-		out.print( (errors.containsKey("ml-address")? errors.get("ml-address"):"") );
-		out.print( "</span>\r\n						<div class=\"weak-color\">e.g., mygroup@yahoogroups.com</div>\r\n					</div>\r\n				</div>\r\n\r\n				<div class=\"field-box light-border-color\">\r\n					<div class=\"second-font field-title\">Mailing List URL</div>\r\n					<div class=\"weak-color\">\r\n						Enter the homepage of this mailing list, where other users can find more information.<br/>\r\n						<input type=\"text\" name=\"ml-url\" size=\"55\" value=\"" );
-		out.print( (Jtp.hideNull(values.get("ml-url"))) );
-		out.print( "\" />\r\n						<span class=\"important\">" );
-		out.print( (errors.containsKey("ml-url")? errors.get("ml-url"):"") );
-		out.print( "</span>\r\n						<div class=\"weak-color\">e.g., http://www.mailinglist.com/list</div>\r\n					</div>\r\n				</div>\r\n\r\n				<div class=\"field-box light-border-color\">\r\n					<div class=\"second-font field-title\">Forum Name</div>\r\n					<div class=\"weak-color\">\r\n						Enter the name of the forum for this mailing list.<br/>\r\n						<input type=\"text\" name=\"subject\" size=\"46\" value=\"" );
-		out.print( (Jtp.hideNull(values.get("subject"))) );
-		out.print( "\" />\r\n						<span class=\"important\">" );
-		out.print( (errors.containsKey("subject")? errors.get("subject"):"") );
-		out.print( "</span>\r\n					</div>\r\n				</div>\r\n\r\n				<div class=\"field-box light-border-color\">\r\n					<div class=\"second-font field-title\">Forum Description</div>\r\n					<div class=\"weak-color\">\r\n						<textarea cols=46 rows=5 name=\"message\" id=\"nabble.desc\" wrap=\"SOFT\">" );
-		out.print( (Jtp.hideNull(values.get("message"))) );
-		out.print( "</textarea>\r\n					</div>\r\n				</div>\r\n\r\n				<div class=\"field-box light-border-color\">\r\n					<div class=\"second-font field-title\">List Server and Version</div>\r\n					<div class=\"weak-color\">\r\n						If you know, please select the mailing list server application.<br/>\r\n						<select name=\"server-type\">\r\n							" );
-
-									String[] serverTypes = ListServer.getAllServerTypes();
-									ListServer selectedServer = ListServer.getServer(values.get("server-type"));
-									for (String s : serverTypes) {
-										ListServer currentServer = ListServer.getServer(s);
-										if(currentServer.showInInitialSetup()) {
-											
-		out.print( "<option value=\"" );
-		out.print( (currentServer.getType()) );
-		out.print( "\" " );
-		out.print( (currentServer == selectedServer?"selected":"") );
-		out.print( ">" );
-		out.print( (currentServer.getViewName()) );
-		out.print( "</option>" );
-
-										}
-									}
-									
-		out.print( "\r\n</select>\r\n<div class=\"weak-color\">If you are not absolutely sure about the version of the list server, it is better if you leave it as Unknown</div>\r\n</div>\r\n</div>\r\n\r\n<div class=\"field-box light-border-color\">\r\n<div class=\"second-font field-title\">Other Settings</div>\r\n<table>\r\n<tr>\r\n<td><input id=\"plain-text\" name=\"plain-text\" type=\"checkbox\" value=\"y\" " );
-		out.print( ("y".equals(values.get("plain-text"))?"checked":"") );
-		out.print( " /></td>\r\n<td><label for=\"plain-text\">This list accepts only plain-text emails</label>.</td>\r\n</tr>\r\n<tr>\r\n<td><input id=\"ignore-x-noarchive\" name=\"ignore-x-noarchive\" type=\"checkbox\" value=\"y\" " );
-		out.print( ("y".equals(values.get("ignore-x-noarchive"))?"checked":"") );
-		out.print( " /></td>\r\n<td><label for=\"ignore-x-noarchive\">Ignore X-No-Archive Header</label>.</td>\r\n</tr>\r\n<tr>\r\n<td colspan=2 style=\"padding-top:1em\">\r\n	" );
-		out.print( ( Recaptcha.DIV ) );
-		out.print( "\r\n</td>\r\n</tr>\r\n</table>\r\n</div>\r\n\r\n<input type=\"submit\" value=\"Create Mailing List Archive\" style=\"padding:.5em .8em;font-size:110%;font-weight:bold\"/>\r\n</div>\r\n</form>\r\n\r\n" );
- Shared.footer(request,response); 
-		out.print( "\r\n" );
- Shared.analytics(request,response); 
-		out.print( "\r\n</body>\r\n</html>\r\n" );
-
-	}
-
-	private static final String newSitePassword = (String)Init.get("new_site_password");
-
-	public static class Save extends HttpServlet {
-
-		private static String get(String name, HttpServletRequest request) {
-			String s = request.getParameter(name);
-			return s == null? null : s.trim();
-		}
-
-		protected void service(HttpServletRequest request, HttpServletResponse response)
-				throws ServletException, IOException
-		{
-			String username = get("username", request);
-			String email = get("email", request);
-			String password = get("password", request);
-			boolean agreed = "y".equals(get("terms", request));
-
-			String mlAddress = get("ml-address", request);
-			String mlUrl = get("ml-url", request);
-			String subject = get("subject", request);
-			String message = get("message", request);
-			String serverType = get("server-type", request);
-			boolean isPlainText = "y".equals(get("plain-text", request));
-			boolean isIgnoreXNoArchive = "y".equals(get("ignore-x-noarchive", request));
-
-			Map<String,String> errors = new HashMap<String,String>();
-			if (username == null || username.trim().length() == 0)
-				errors.put("username", "required");
-			if (email == null || email.length() == 0)
-				errors.put("email", "required");
-			else if (!new MailAddress(email).isValid())
-				errors.put("email", "invalid email");
-			if (password == null || password.length() < 4)
-				errors.put("password", "too short");
-			if (!agreed)
-				errors.put("generic", "You must agree to the Terms and Conditions");
-			if (subject == null || subject.length() == 0)
-				errors.put("subject", "required");
-			if (mlAddress == null || mlAddress.length() == 0)
-				errors.put("ml-address", "required");
-			else if (!new MailAddress(mlAddress).isValid())
-				errors.put("ml-address", "invalid email");
-			if (mlUrl == null || mlUrl.length() == 0)
-				errors.put("ml-url", "required");
-			else {
-				try {
-					new URL(mlUrl);
-				} catch (MalformedURLException e) {
-					errors.put("ml-url", "invalid URL");
-				}
-			}
-
-			if (errors.isEmpty()) {
-				if( newSitePassword!=null && !newSitePassword.equals(password) ) {
-					logger.info("ignoring "+email);
-					return;
-				}
-
-				DbDatabase db = Db.dbGlobal();
-				db.beginTransaction();
-				try {
-					Recaptcha.check(request);
-					Site site = ModelHome.newSite(Node.Type.FORUM,subject, message, Message.Format.TEXT, email, username);
-					Permissions.addToGroup( (User)site.getRootNode().getOwner(), Permissions.ADMINISTRATORS_GROUP );
-					String key = site.newRegistration(email,password,username,"/mailing_list/SubscribeToMailingList.jtp?node="+site.getRootNode().getId());
-
-					MailingList ml = site.getRootNode().newMailingList(ListServer.getServer(serverType), mlAddress, mlUrl);
-					ml.setPlainTextOnly(isPlainText);
-					ml.setIgnoreNoArchive(isIgnoreXNoArchive);
-					ml.update();
-
-					db.commitTransaction();
-
-					site = site.getGoodCopy();
-					ForumStart.sendRegisterMail(site, email, key);
-					NewSiteMail.send(site, request, response);
-					response.sendRedirect(site.getBaseUrl()+"/more/MailingListRequest$FinalSteps.jtp");
-					return;
-				} catch(ModelException e) {
-					errors.put("generic", e.getMessage());
-				} finally {
-					db.endTransaction();
-				}
-			}
-
-			Map<String,String> values = new HashMap<String,String>();
-			values.put("username", username);
-			values.put("email", email);
-			values.put("password", password);
-			values.put("terms", agreed?"y":"");
-
-			values.put("ml-address", mlAddress);
-			values.put("ml-url", mlUrl);
-			values.put("subject", subject);
-			values.put("message", message);
-			values.put("server-type", serverType);
-			values.put("plain-text", isPlainText?"y":"");
-			values.put("ignore-x-noarchive", isIgnoreXNoArchive?"y":"");
-			build(request, response, values, errors);
-		}
-	}
-
-	public static class FinalSteps extends HttpServlet {
-
-		protected void service(HttpServletRequest request, HttpServletResponse response)
-				throws ServletException, IOException
-		{
-			PrintWriter out = response.getWriter();
-			
-		out.print( "\r\n<html>\r\n	<head>\r\n		" );
- Shared.title(request,response,"Archive Created, But Subscription is Needed"); 
-		out.print( "\r\n	</head>\r\n	<body>\r\n		" );
- Shared.minHeaderGlobal(request,response); 
-		out.print( "\r\n		<h1>Success</h1>\r\n		<p>Your mailing list archive has been successfully created.</p>\r\n		<h2>What should I do now?</h2>\r\n		<p>\r\n			You should now check your email and click on the activation link sent to you.\r\n			That link will complete your account registration and take you to the page where you can subscribe the Nabble archive to the mailing list.\r\n			<b>If you don't subscribe the archive to the mailing list, it will NOT work properly!</b>\r\n		</p>\r\n		<p>You can contact <a href=\"" );
-		out.print( (Jtp.supportUrl()) );
-		out.print( "\">Nabble Support</a> if you have questions.</p>\r\n		" );
- Shared.footer(request,response); 
-		out.print( "\r\n		" );
- Shared.analytics(request,response); 
-		out.print( "\r\n	</body>\r\n</html>\r\n" );
-
-		}
-	}
-}
-
--- a/src/nabble/view/web/more/MailingListRequest.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,385 +0,0 @@
-<%
-package nabble.view.web.more;
-
-import fschmidt.db.DbDatabase;
-import fschmidt.util.mail.MailAddress;
-import fschmidt.util.servlet.CanonicalUrl;
-import nabble.model.Db;
-import nabble.model.ListServer;
-import nabble.model.MailingList;
-import nabble.model.Message;
-import nabble.model.ModelException;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.model.Site;
-import nabble.model.User;
-import nabble.model.Init;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.NewSiteMail;
-import nabble.view.lib.Permissions;
-import nabble.view.lib.Shared;
-import nabble.view.lib.UrlMappable;
-import nabble.view.lib.Recaptcha;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-public final class MailingListRequest extends HttpServlet implements UrlMappable, CanonicalUrl {
-	private static final Logger logger = LoggerFactory.getLogger(MailingListRequest.class);
-
-	private static final Pattern URL_PATTERN = Pattern.compile("/archive-your-mailing-list\\.html$");
-
-	public static String url() {
-		return Jtp.defaultContextUrl() + path();
-	}
-
-	public static String path() {
-		return "/archive-your-mailing-list.html";
-	}
-
-	public String getCanonicalUrl(HttpServletRequest request) {
-		return url();
-	}
-
-	public Map<String,String[]> getParameterMapFromUrl(HttpServletRequest request,String mappedUrl) {
-		Matcher m = URL_PATTERN.matcher(mappedUrl);
-		if( !m.find() )
-			throw new RuntimeException();
-		return new HashMap<String,String[]>();
-	}
-
-	public Pattern getUrlPattern() {
-		return URL_PATTERN;
-	}
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		build(request, response, Collections.<String,String>emptyMap(), Collections.<String,String>emptyMap());
-	}
-
-	private static void build(HttpServletRequest request,HttpServletResponse response, Map<String,String> values, Map<String,String> errors)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		%>
-		<html>
-			<head>
-				<% Shared.title(request,response,"Archive Your Mailing List"); %>
-				<META NAME="description" CONTENT="Archiving a mailing list at Nabble is quick and easy. Fill in one simple form and you're done.">
-				<META NAME="keywords" CONTENT="free, mailing list archive, forum interface, gateway, customizable, easy, quick setup">
-				<style type="text/css">
-					div.field-title {
-						margin-top: 0;
-					}
-					td.column1 {
-						text-align:right;
-						width:7em;
-						white-space:nowrap;
-					}
-					div.field-box {
-						border:none;
-						margin:0;
-					}
-					input[type=text],input[type=password],select {
-                        padding:.3em 0;
-                    }
-					.important { font-weight:bold }
-				</style>
-				<script type="text/javascript">
-					$(document).ready(function() {
-						$('#username').focus();
-					});
-				</script>
-				<%= Recaptcha.JS %>
-			</head>
-			<body>
-				<% Shared.minHeaderGlobal(request,response); %>
-
-				<h1>Archive Your Mailing List</h1>
-				<p>
-					<img src="/images/homepage/archive.png" style="float:left;margin: 0 1em 1em 1em"/>
-					You can archive your mailing list to a fully functional forum at Nabble by filling out
-					the form below.  This makes it easy for users to browse and search archived emails.
-					Users can even post to the Nabble forum and we will forward these posts to your mailing list.
-				</p>
-
-				<% if (errors.size() > 0) { %>
-					<div class="error-message important" style="margin:1em;padding:.5em 0 .5em 12em">
-						<% String generic = errors.get("generic"); %>
-						<%=generic != null? generic : errors.size() > 0? "Please check the errors below" : ""%>
-					</div>
-				<% } %>
-
-				<form method="post" action="/more/MailingListRequest$Save.jtp" accept-charset="UTF-8">
-					<input type="hidden" name="Action" value="save">
-
-					<div style="border-bottom:2px solid #eeeeee;padding:1em;width:50em">
-						<div class="weak-color" style="width:11.5em;text-align:center;float:left">
-							<div style="font-weight:bold">Account</div>
-							<img src="/images/account.png"/>
-							<div style="margin-top:1em;font-size:80%">
-								You will receive an email with a link to activate your account
-							</div>
-						</div>
-						<table>
-							<tr>
-								<td><div class="second-font field-title">User Name</div></td>
-								<td><input type="text" id="username" size="35" maxlength="30" name="username" value="<%=Jtp.hideNull(values.get("username"))%>" /></td>
-								<td class="important"><%=errors.containsKey("username")? errors.get("username"):""%></td>
-							</tr>
-							<tr>
-								<td><div class="second-font field-title">Email</div></td>
-								<td><input type="text" size="35" maxlength="60" name="email" value="<%=Jtp.hideNull(values.get("email"))%>"/></td>
-								<td class="important"><%=errors.containsKey("email")? errors.get("email"):""%></td>
-							</tr>
-							<tr>
-								<td><div class="second-font field-title">Password</div></td>
-								<td><input type="password" size="35" maxlength="15" name="password" value="<%=Jtp.hideNull(values.get("password"))%>"/></td>
-								<td class="important"><%=errors.containsKey("password")? errors.get("password"):""%></td>
-							</tr>
-							<tr>
-								<td class="column1"><input type="checkbox" id="terms" name="terms" value="y" <%="y".equals(values.get("terms"))?"checked":""%> /></td>
-								<td colspan=2><label for="terms">I have read and I agree to Nabble's <a href="<%=Jtp.termsUrl(true)%>">Terms of Use</a>.</label></td>
-							</tr>
-						</table>
-					</div>
-
-					<div style="padding:.5em;width:50em">
-						<div class="weak-color" style="width:12em;text-align:center;float:left;height:50em;padding-top:1em">
-							<div style="font-weight:bold">Mailing List</div>
-							<img src="/images/homepage/mailing-list.png" alt="Free Mailing List Archive">
-						</div>
-
-						<div class="field-box">
-							<div class="second-font field-title">Mailing List Address</div>
-							<div class="weak-color">
-								<input id="mailingList" type="text" name="ml-address" value="<%=Jtp.hideNull(values.get("ml-address"))%>" size="46" />
-								<span class="important"><%=errors.containsKey("ml-address")? errors.get("ml-address"):""%></span>
-								<div class="weak-color">e.g., mygroup@yahoogroups.com</div>
-							</div>
-						</div>
-
-						<div class="field-box light-border-color">
-							<div class="second-font field-title">Mailing List URL</div>
-							<div class="weak-color">
-								Enter the homepage of this mailing list, where other users can find more information.<br/>
-								<input type="text" name="ml-url" size="55" value="<%=Jtp.hideNull(values.get("ml-url"))%>" />
-								<span class="important"><%=errors.containsKey("ml-url")? errors.get("ml-url"):""%></span>
-								<div class="weak-color">e.g., http://www.mailinglist.com/list</div>
-							</div>
-						</div>
-
-						<div class="field-box light-border-color">
-							<div class="second-font field-title">Forum Name</div>
-							<div class="weak-color">
-								Enter the name of the forum for this mailing list.<br/>
-								<input type="text" name="subject" size="46" value="<%=Jtp.hideNull(values.get("subject"))%>" />
-								<span class="important"><%=errors.containsKey("subject")? errors.get("subject"):""%></span>
-							</div>
-						</div>
-
-						<div class="field-box light-border-color">
-							<div class="second-font field-title">Forum Description</div>
-							<div class="weak-color">
-								<textarea cols=46 rows=5 name="message" id="nabble.desc" wrap="SOFT"><%=Jtp.hideNull(values.get("message"))%></textarea>
-							</div>
-						</div>
-
-						<div class="field-box light-border-color">
-							<div class="second-font field-title">List Server and Version</div>
-							<div class="weak-color">
-								If you know, please select the mailing list server application.<br/>
-								<select name="server-type">
-									<%
-									String[] serverTypes = ListServer.getAllServerTypes();
-									ListServer selectedServer = ListServer.getServer(values.get("server-type"));
-									for (String s : serverTypes) {
-										ListServer currentServer = ListServer.getServer(s);
-										if(currentServer.showInInitialSetup()) {
-											%><option value="<%=currentServer.getType()%>" <%=currentServer == selectedServer?"selected":""%>><%=currentServer.getViewName()%></option><%
-										}
-									}
-									%>
-								</select>
-								<div class="weak-color">If you are not absolutely sure about the version of the list server, it is better if you leave it as Unknown</div>
-							</div>
-						</div>
-
-						<div class="field-box light-border-color">
-							<div class="second-font field-title">Other Settings</div>
-							<table>
-								<tr>
-									<td><input id="plain-text" name="plain-text" type="checkbox" value="y" <%="y".equals(values.get("plain-text"))?"checked":""%> /></td>
-									<td><label for="plain-text">This list accepts only plain-text emails</label>.</td>
-								</tr>
-								<tr>
-									<td><input id="ignore-x-noarchive" name="ignore-x-noarchive" type="checkbox" value="y" <%="y".equals(values.get("ignore-x-noarchive"))?"checked":""%> /></td>
-									<td><label for="ignore-x-noarchive">Ignore X-No-Archive Header</label>.</td>
-								</tr>
-								<tr>
-									<td colspan=2 style="padding-top:1em">
-										<%= Recaptcha.DIV %>
-									</td>
-								</tr>
-							</table>
-						</div>
-
-						<input type="submit" value="Create Mailing List Archive" style="padding:.5em .8em;font-size:110%;font-weight:bold"/>
-					</div>
-				</form>
-
-				<% Shared.footer(request,response); %>
-				<% Shared.analytics(request,response); %>
-			</body>
-		</html>
-		<%
-	}
-
-	private static final String newSitePassword = (String)Init.get("new_site_password");
-
-	public static class Save extends HttpServlet {
-
-		private static String get(String name, HttpServletRequest request) {
-			String s = request.getParameter(name);
-			return s == null? null : s.trim();
-		}
-
-		protected void service(HttpServletRequest request, HttpServletResponse response)
-				throws ServletException, IOException
-		{
-			String username = get("username", request);
-			String email = get("email", request);
-			String password = get("password", request);
-			boolean agreed = "y".equals(get("terms", request));
-
-			String mlAddress = get("ml-address", request);
-			String mlUrl = get("ml-url", request);
-			String subject = get("subject", request);
-			String message = get("message", request);
-			String serverType = get("server-type", request);
-			boolean isPlainText = "y".equals(get("plain-text", request));
-			boolean isIgnoreXNoArchive = "y".equals(get("ignore-x-noarchive", request));
-
-			Map<String,String> errors = new HashMap<String,String>();
-			if (username == null || username.trim().length() == 0)
-				errors.put("username", "required");
-			if (email == null || email.length() == 0)
-				errors.put("email", "required");
-			else if (!new MailAddress(email).isValid())
-				errors.put("email", "invalid email");
-			if (password == null || password.length() < 4)
-				errors.put("password", "too short");
-			if (!agreed)
-				errors.put("generic", "You must agree to the Terms and Conditions");
-			if (subject == null || subject.length() == 0)
-				errors.put("subject", "required");
-			if (mlAddress == null || mlAddress.length() == 0)
-				errors.put("ml-address", "required");
-			else if (!new MailAddress(mlAddress).isValid())
-				errors.put("ml-address", "invalid email");
-			if (mlUrl == null || mlUrl.length() == 0)
-				errors.put("ml-url", "required");
-			else {
-				try {
-					new URL(mlUrl);
-				} catch (MalformedURLException e) {
-					errors.put("ml-url", "invalid URL");
-				}
-			}
-
-			if (errors.isEmpty()) {
-				if( newSitePassword!=null && !newSitePassword.equals(password) ) {
-					logger.info("ignoring "+email);
-					return;
-				}
-
-				DbDatabase db = Db.dbGlobal();
-				db.beginTransaction();
-				try {
-					Recaptcha.check(request);
-					Site site = ModelHome.newSite(Node.Type.FORUM,subject, message, Message.Format.TEXT, email, username);
-					Permissions.addToGroup( (User)site.getRootNode().getOwner(), Permissions.ADMINISTRATORS_GROUP );
-					String key = site.newRegistration(email,password,username,"/mailing_list/SubscribeToMailingList.jtp?node="+site.getRootNode().getId());
-
-					MailingList ml = site.getRootNode().newMailingList(ListServer.getServer(serverType), mlAddress, mlUrl);
-					ml.setPlainTextOnly(isPlainText);
-					ml.setIgnoreNoArchive(isIgnoreXNoArchive);
-					ml.update();
-
-					db.commitTransaction();
-
-					site = site.getGoodCopy();
-					ForumStart.sendRegisterMail(site, email, key);
-					NewSiteMail.send(site, request, response);
-					response.sendRedirect(site.getBaseUrl()+"/more/MailingListRequest$FinalSteps.jtp");
-					return;
-				} catch(ModelException e) {
-					errors.put("generic", e.getMessage());
-				} finally {
-					db.endTransaction();
-				}
-			}
-
-			Map<String,String> values = new HashMap<String,String>();
-			values.put("username", username);
-			values.put("email", email);
-			values.put("password", password);
-			values.put("terms", agreed?"y":"");
-
-			values.put("ml-address", mlAddress);
-			values.put("ml-url", mlUrl);
-			values.put("subject", subject);
-			values.put("message", message);
-			values.put("server-type", serverType);
-			values.put("plain-text", isPlainText?"y":"");
-			values.put("ignore-x-noarchive", isIgnoreXNoArchive?"y":"");
-			build(request, response, values, errors);
-		}
-	}
-
-	public static class FinalSteps extends HttpServlet {
-
-		protected void service(HttpServletRequest request, HttpServletResponse response)
-				throws ServletException, IOException
-		{
-			PrintWriter out = response.getWriter();
-			%>
-			<html>
-				<head>
-					<% Shared.title(request,response,"Archive Created, But Subscription is Needed"); %>
-				</head>
-				<body>
-					<% Shared.minHeaderGlobal(request,response); %>
-					<h1>Success</h1>
-					<p>Your mailing list archive has been successfully created.</p>
-					<h2>What should I do now?</h2>
-					<p>
-						You should now check your email and click on the activation link sent to you.
-						That link will complete your account registration and take you to the page where you can subscribe the Nabble archive to the mailing list.
-						<b>If you don't subscribe the archive to the mailing list, it will NOT work properly!</b>
-					</p>
-					<p>You can contact <a href="<%=Jtp.supportUrl()%>">Nabble Support</a> if you have questions.</p>
-					<% Shared.footer(request,response); %>
-					<% Shared.analytics(request,response); %>
-				</body>
-			</html>
-			<%
-		}
-	}
-}
-%>
--- a/src/nabble/view/web/template/CompileTest.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/template/CompileTest.java	Fri Jun 18 17:44:24 2021 -0600
@@ -103,6 +103,7 @@
 
 		logger.info("----- Workgroup -----");
 		testModule("workgroup", new String[] { "view_app", "topic", "new_topic", "reply" });
+		testEmails("workgroup");
 /*
 		logger.info("----- Poll -----");
 		testModule("poll", new String[] { "new_topic", "reply", "edit_post", "topic", "change_permissions" });
--- a/src/nabble/view/web/template/EmailNamespace.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/template/EmailNamespace.java	Fri Jun 18 17:44:24 2021 -0600
@@ -90,7 +90,7 @@
 
 	public static final CommandSpec send = new CommandSpec.Builder()
 		.parameters("to", "subject", "text_part")
-		.optionalParameters("cc", "bcc", "to_name", "from", "from_name", "html_part", "aol_part", "set_headers_for", "bounce_to", "attachments")
+		.optionalParameters("cc", "bcc", "to_name", "from", "from_name", "html_part", "aol_part", "bounce_to", "attachments")
 		.build();
 
 	@Command public void send(IPrintWriter out, Interpreter interp)
@@ -126,10 +126,6 @@
 		String toName = interp.getArgString("to_name");
 		MailAddress toAddress = toName == null ? new MailAddress(to) : new MailAddress(to, toName);
 
-		NodeNamespace nodeNs = interp.getArgAsNamespace(NodeNamespace.class, "set_headers_for");
-		if (nodeNs != null)
-			ModelHome.setNodeHeaders(mail, nodeNs.node());
-
 		mail.setFrom(fromAddress);
 		mail.setTo(toAddress);
 		if (cc != null)
--- a/src/nabble/view/web/template/NabbleNamespace.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/template/NabbleNamespace.java	Fri Jun 18 17:44:24 2021 -0600
@@ -186,12 +186,6 @@
 			out.print( interp.encode( "/help/Index.jtp" ) );
 		}
 
-		public static final CommandSpec mailing_list_intro = CommandSpec.DO;
-
-		@Command public void mailing_list_intro(IPrintWriter out,ScopedInterpreter<HelpNs> interp) {
-			print(out,interp,Help.mailingListIntro);
-		}
-
 		public static final CommandSpec search = CommandSpec.DO;
 
 		@Command public void search(IPrintWriter out,ScopedInterpreter<HelpNs> interp) {
@@ -221,12 +215,6 @@
 		@Command public void password(IPrintWriter out,ScopedInterpreter<HelpNs> interp) {
 			print(out,interp,Help.password);
 		}
-
-		public static final CommandSpec userid = CommandSpec.DO;
-
-		@Command public void userid(IPrintWriter out,ScopedInterpreter<HelpNs> interp) {
-			print(out,interp,Help.userid);
-		}
 	}
 	private static final HelpsNs helpsNs = new HelpsNs();
 
@@ -521,18 +509,6 @@
 		SubscriptionNamespace subscriptionNs = interp.getArgAsNamespace(SubscriptionNamespace.class,"subscription");
 		out.print( interp.getArg(subscriptionNs,"do") );
 	}
-/*
-not needed yet
-	public static final CommandSpec get_mailing_list = CommandSpec.DO()
-		.parameters("mailing_list")
-		.build()
-	;
-
-	@Command public void get_mailing_list(IPrintWriter out,ScopedInterpreter<MailingListNamespace> interp) {
-		MailingListNamespace ns = interp.getArgAsNamespace(MailingListNamespace.class,"mailing_list");
-		out.print( interp.getArg(ns,"do") );
-	}
-*/
 
 
 	@Command public void anyone_group(IPrintWriter out,Interpreter interp) {
--- a/src/nabble/view/web/template/NodeNamespace.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/template/NodeNamespace.java	Fri Jun 18 17:44:24 2021 -0600
@@ -2,7 +2,6 @@
 
 import fschmidt.util.java.Filter;
 import fschmidt.util.mail.MailAddress;
-import nabble.model.MailingList;
 import nabble.model.ModelException;
 import nabble.model.Node;
 import nabble.model.NodeIterator;
@@ -22,7 +21,6 @@
 import nabble.view.lib.Permissions;
 import nabble.view.web.forum.Permalink;
 import nabble.view.web.forum.Thumbnail;
-import nabble.view.web.mailing_list.MailingListNamespace;
 
 import javax.servlet.ServletException;
 import java.util.ArrayList;
@@ -278,12 +276,6 @@
 		out.print(Permissions.isPrivate(node()));
 	}
 
-	@Command public void is_pending(IPrintWriter out,Interpreter interp) {
-		Node node = node();
-		Node.MailToList mail = node.getMailToList();
-		out.print(mail != null && node.getOwner() instanceof User && mail.isPending());
-	}
-
 	@Command public void descendant_count(IPrintWriter out,Interpreter interp) {
 		out.print( node().getDescendantCount() );
 	}
@@ -370,10 +362,6 @@
 		out.print( interp.encode( "/catalog/ChangeParent.jtp?forum=" + nodeId() ) );
 	}
 
-	@Command public void subscription_instructions_path(IPrintWriter out,Interpreter interp) {
-		out.print( interp.encode( "/mailing_list/SubscribeToMailingList.jtp?node=" + nodeId() ) );
-	}
-
 	@Command public void embed_post_path(IPrintWriter out,Interpreter interp) {
 		out.print( interp.encode( "/embed/EmbedOptions.jtp?node=" + nodeId() ) );
 	}
@@ -382,10 +370,6 @@
 		out.print( interp.encode( "/user/SendEmail.jtp?type=pm&post=" + nodeId() ) );
 	}
 
-	@Command public void unsubscription_instructions_path(IPrintWriter out,Interpreter interp) {
-		out.print( interp.encode( "/mailing_list/UnsubscribeFromMailingList.jtp?node=" + nodeId() ) );
-	}
-
 	@Command public void embedding_options_path(IPrintWriter out,Interpreter interp) {
 		out.print( interp.encode("/embed/EmbedOptions.jtp?node=" + nodeId()) );
 	}
@@ -406,46 +390,6 @@
 	}
 
 
-
-	@Command public void is_mail_to_list(IPrintWriter out,Interpreter interp) {
-		out.print( node().getMailToList() != null );
-	}
-
-
-	public static final CommandSpec get_this_mailing_list_archive = CommandSpec.DO;
-
-	@Command public void get_this_mailing_list_archive(IPrintWriter out,ScopedInterpreter<MailingListNamespace> interp) {
-		out.print(interp.getArg(new MailingListNamespace(node()),"do"));
-	}
-
-	public static final CommandSpec get_associated_mailing_list_archive = CommandSpec.DO;
-
-	@Command public void get_associated_mailing_list_archive(IPrintWriter out,ScopedInterpreter<MailingListNamespace> interp) {
-		MailingList mailingList = node().getAssociatedMailingList();
-		out.print(interp.getArg(new MailingListNamespace(mailingList),"do"));
-	}
-
-	@Command public void is_a_mailing_list_archive(IPrintWriter out,Interpreter interp) {
-		out.print(node().getMailingList() != null);
-	}
-
-	@Command public void is_associated_with_mailing_list_archive(IPrintWriter out,Interpreter interp) {
-		out.print(node().getAssociatedMailingList() != null);
-	}
-
-	@Command public void has_sub_archive(IPrintWriter out,Interpreter interp) {
-		boolean hasSubArchive = false;
-		List<Node> childApps = node().getChildApps(null).get(0, 100);
-		for (Node n : childApps) {
-			if (n.getAssociatedMailingList() != null) {
-				hasSubArchive = true;
-				break;
-			}
-		}
-		out.print(hasSubArchive);
-	}
-
-
 	@Command public void default_meta_description(IPrintWriter out,Interpreter interp) {
 		out.print( Jtp.metaDescription(node()) );
 	}
--- a/src/nabble/view/web/template/UserNamespace.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/template/UserNamespace.java	Fri Jun 18 17:44:24 2021 -0600
@@ -357,7 +357,6 @@
 
 	@Command public void ban(IPrintWriter out, Interpreter interp) {
 		Permissions.ban(user());
-		user().setNoArchive(true);
 		site().update(); // uncache
 	}
 
@@ -365,7 +364,6 @@
 
 	@Command public void unban(IPrintWriter out, Interpreter interp) {
 		Permissions.unban(user());
-		user().setNoArchive(false);
 		site().update(); // uncache
 	}
 
@@ -409,10 +407,6 @@
 		out.print( interp.encode( "/user/RemoveAccount.jtp" ) );
 	}
 
-	@Command public void pending_posts_path(IPrintWriter out,Interpreter interp) {
-		out.print( interp.encode( "/user/UserPendingNodes.jtp" ) );
-	}
-
 	private Map<Long,Long> lastVisitedNodeIds = null;
 
 	private Long lastVisitedNodeId(Interpreter interp,long nodeId) {
--- a/src/nabble/view/web/tools/SpamSearch.java	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/tools/SpamSearch.java	Fri Jun 18 17:44:24 2021 -0600
@@ -102,12 +102,6 @@
  if (node.getDescendantCount() > 1) { 
 		out.print( "\r\n					<span class=\"badge\" style=\"font-weight:bold;background:red;color:white\">Has Replies</span>\r\n				" );
  } 
-		out.print( "\r\n				" );
- Node.MailToList mail = node.getMailToList(); 
-		out.print( "\r\n				" );
- if (mail != null && mail.isPending()) { 
-		out.print( "\r\n					<span class=\"badge\" style=\"font-weight:bold;background:green;color:white\">Pending</span>\r\n				" );
- } 
 		out.print( "\r\n			</div>\r\n		</td>\r\n	</tr>\r\n" );
  } else { 
 		out.print( "\r\n	<tr>\r\n		<td></td>\r\n		<td class=\"grayP\">\r\n			<a href='" );
--- a/src/nabble/view/web/tools/SpamSearch.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ b/src/nabble/view/web/tools/SpamSearch.jtp	Fri Jun 18 17:44:24 2021 -0600
@@ -95,10 +95,6 @@
 							<% if (node.getDescendantCount() > 1) { %>
 								<span class="badge" style="font-weight:bold;background:red;color:white">Has Replies</span>
 							<% } %>
-							<% Node.MailToList mail = node.getMailToList(); %>
-							<% if (mail != null && mail.isPending()) { %>
-								<span class="badge" style="font-weight:bold;background:green;color:white">Pending</span>
-							<% } %>
 						</div>
 					</td>
 				</tr>
--- a/src/nabble/view/web/tools/UploadMbox.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-
-package nabble.view.web.tools;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-
-
-public final class UploadMbox extends HttpServlet {
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(request.getParameter("forum")));
-        MailingList mailingList = forum.getMailingList();
-        String listName = (mailingList == null) ? null : mailingList.getListName();
-        boolean hasListNameSet = listName != null && !"".equals(listName);
-		
-		out.print( "\r\n<html>\r\n<head>\r\n" );
-
-		Shared.title(request,response,"upload mbox file");
-		
-		out.print( "\r\n</head>\r\n<body onload='document.theForm.image.focus();'>\r\n<h2>upload mbox file to " );
-		out.print( (forum.getSubjectHtml()) );
-		out.print( "</h2>\r\n<p>\r\n<form name=\"theForm\" action=\"UploadMbox2.jtp\" method=\"POST\" enctype=\"multipart/form-data\">\r\n<input type=\"hidden\" name=\"forum\" value=\"" );
-		out.print( (forum.getId()) );
-		out.print( "\" />\r\n        " );
-
-            if(!hasListNameSet) {
-            
-		out.print( "\r\n            <font color=\"red\">\r\n            <h3>Mailing list archive does not have ListName set yet!</h3>\r\n            </font>\r\n            " );
-
-            }
-        
-		out.print( "\r\n<p>\r\nMbox File to Upload:\r\n<input name=\"mbox\" type=\"file\" size=\"40\" />\r\n</p>\r\n<p>\r\nor download Mbox from url:\r\n<input name=\"mboxurl\" type=\"text\" size=\"100\" />\r\n</p>\r\n<p>\r\nor read from " );
-		out.print( (getInitParameter("exportDir")) );
-		out.print( "<input name=\"mboxfile\" type=\"text\" size=\"40\" />\r\n</p>\r\n<p>Mail errors to: <input name=\"mailErrorsTo\" size=\"30\" /></p>\r\n<p>Max errors: <input name=\"maxErrors\" value=\"10\" /></p>\r\n<p><input type=\"checkbox\" name=\"runRethread\" value=\"x\" /> rethread after import</p>\r\n<p><input type=\"submit\" value=\"upload mbox file\" /></p>\r\n</form>\r\n</p>\r\n</body>\r\n</html>\r\n" );
-
-	}
-}
-
--- a/src/nabble/view/web/tools/UploadMbox.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-<%
-package nabble.view.web.tools;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import nabble.model.MailingList;
-import nabble.model.ModelHome;
-import nabble.model.Node;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-
-
-public final class UploadMbox extends HttpServlet {
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(request.getParameter("forum")));
-        MailingList mailingList = forum.getMailingList();
-        String listName = (mailingList == null) ? null : mailingList.getListName();
-        boolean hasListNameSet = listName != null && !"".equals(listName);
-		%>
-		<html>
-		<head>
-		<%
-		Shared.title(request,response,"upload mbox file");
-		%>
-		</head>
-		<body onload='document.theForm.image.focus();'>
-		<h2>upload mbox file to <%=forum.getSubjectHtml()%></h2>
-		<p>
-		<form name="theForm" action="UploadMbox2.jtp" method="POST" enctype="multipart/form-data">
-		<input type="hidden" name="forum" value="<%=forum.getId()%>" />
-        <%
-            if(!hasListNameSet) {
-            %>
-            <font color="red">
-            <h3>Mailing list archive does not have ListName set yet!</h3>
-            </font>
-            <%
-            }
-        %>
-		<p>
-		Mbox File to Upload:
-		<input name="mbox" type="file" size="40" />
-		</p>
-		<p>
-		or download Mbox from url:
-		<input name="mboxurl" type="text" size="100" />
-		</p>
-		<p>
-		or read from <%=getInitParameter("exportDir")%><input name="mboxfile" type="text" size="40" />
-		</p>
-		<p>Mail errors to: <input name="mailErrorsTo" size="30" /></p>
-		<p>Max errors: <input name="maxErrors" value="10" /></p>
-		<p><input type="checkbox" name="runRethread" value="x" /> rethread after import</p>
-		<p><input type="submit" value="upload mbox file" /></p>
-		</form>
-		</p>
-		</body>
-		</html>
-		<%
-	}
-}
-%>
--- a/src/nabble/view/web/tools/UploadMbox2.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-
-package nabble.view.web.tools;
-
-import fschmidt.util.java.IoUtils;
-import fschmidt.util.mail.Mail;
-import fschmidt.util.mail.MailAddress;
-import fschmidt.util.mail.MailHome;
-import fschmidt.util.mail.PlainTextContent;
-import nabble.model.MailingList;
-import nabble.model.ModelException;
-import nabble.model.ModelHome;
-import nabble.model.Executors;
-import nabble.model.Node;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.FileUploadException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.net.URL;
-import java.util.Date;
-import java.util.Map;
-
-
-public final class UploadMbox2 extends HttpServlet {
-	private static final Logger logger = LoggerFactory.getLogger(UploadMbox2.class);
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		final Map<String,FileItem> map;
-		try {
-			map = Jtp.getFileItems(request);
-		} catch(FileUploadException e) {
-			throw new RuntimeException(e);
-		}
-		final Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(map.get("forum").getString()));
-		final String mailErrorsTo = map.get("mailErrorsTo").getString();
-		final int maxErrors = Integer.parseInt(map.get("maxErrors").getString());
-		final boolean runRethread = map.get("runRethread") != null;
-		final String exportDir = getInitParameter("exportDir");
-
-		Executors.executeNow(new Runnable(){public void run() {
-			try {
-				StringBuilder buf = new StringBuilder();
-				InputStream in;
-				if (map.get("mbox").getName()!=null && map.get("mbox").getName().length()>0) {
-					in = map.get("mbox").getInputStream();
-				} else if (map.get("mboxurl").getString()!=null && map.get("mboxurl").getString().length()>0) {
-					in = new URL(map.get("mboxurl").getString()).openStream();
-				} else if (map.get("mboxfile").getString()!=null && map.get("mboxfile").getString().length()>0) {
-					in = new FileInputStream(new File(exportDir+map.get("mboxfile").getString()));
-				} else throw new RuntimeException("no mbox file or url defined");
-				File file = File.createTempFile("mbox",null);
-				try {
-					OutputStream out2 = new FileOutputStream(file);
-					IoUtils.copyAll(in,out2);
-					out2.close();
-					in.close();
-					try {
-						MailingList.ImportResult ir = forum.getMailingList().importMbox(file,mailErrorsTo,maxErrors);
-						buf.append("Results from mbox import to forum "+forum.getSubject()+":\n");
-						buf.append("imported "+ir.getImported()+" messages\n");
-						buf.append("errors "+ir.getErrors()+"\n");
-					} catch (ModelException e) {
-						buf.append("Import error:\n");
-						buf.append(e.getMessage());
-						logger.error("",e);
-					}
-					Mail mail = MailHome.newMail();
-					MailAddress to = new MailAddress(mailErrorsTo);
-					mail.setFrom(to);
-					mail.setTo(to);
-					mail.setSentDate(new Date());
-					mail.setContent(new PlainTextContent(buf.toString()));
-					mail.setSubject("mbox import");
-					ModelHome.send(mail);
-
-				} finally {
-					file.delete();
-				}
-			} catch (IOException e) {
-				throw new RuntimeException(e);
-			}
-
-			if(runRethread) {
-				StringBuilder buf = new StringBuilder();
-				buf.append("Rethread procedure scheduled after mbox import for forum '" + forum.getSubject() + "' has finished\n");
-				forum.getMailingList().rethread();
-				Mail mail = MailHome.newMail();
-				MailAddress to = new MailAddress(mailErrorsTo);
-				mail.setFrom(to);
-				mail.setTo(to);
-				mail.setSentDate(new Date());
-				mail.setContent(new PlainTextContent(buf.toString()));
-				mail.setSubject("Rethreading finished");
-				ModelHome.send(mail);
-			}
-
-		}});
-
-		
-		out.print( "\r\n<html>\r\n<head>\r\n" );
-
-		Shared.title(request,response,"uploaded mbox file");
-		
-		out.print( "\r\n</head>\r\n<body>\r\n<h2>uploading mbox file to " );
-		out.print( (forum.getSubjectHtml()) );
-		out.print( "</h2>\r\n<p>Results will be emailed to " );
-		out.print( (mailErrorsTo) );
-		out.print( " after the import has completed.\r\n<p>return to forum: " );
-		out.print( (Jtp.link(forum)) );
-		out.print( "\r\n</body>\r\n</html>\r\n" );
-
-	}
-}
-
--- a/src/nabble/view/web/tools/UploadMbox2.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-<%
-package nabble.view.web.tools;
-
-import fschmidt.util.java.IoUtils;
-import fschmidt.util.mail.Mail;
-import fschmidt.util.mail.MailAddress;
-import fschmidt.util.mail.MailHome;
-import fschmidt.util.mail.PlainTextContent;
-import nabble.model.MailingList;
-import nabble.model.ModelException;
-import nabble.model.ModelHome;
-import nabble.model.Executors;
-import nabble.model.Node;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.FileUploadException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.net.URL;
-import java.util.Date;
-import java.util.Map;
-
-
-public final class UploadMbox2 extends HttpServlet {
-	private static final Logger logger = LoggerFactory.getLogger(UploadMbox2.class);
-
-	protected void service(HttpServletRequest request,HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		final Map<String,FileItem> map;
-		try {
-			map = Jtp.getFileItems(request);
-		} catch(FileUploadException e) {
-			throw new RuntimeException(e);
-		}
-		final Node forum = Jtp.getSiteNotNull(request).getNode(Long.parseLong(map.get("forum").getString()));
-		final String mailErrorsTo = map.get("mailErrorsTo").getString();
-		final int maxErrors = Integer.parseInt(map.get("maxErrors").getString());
-		final boolean runRethread = map.get("runRethread") != null;
-		final String exportDir = getInitParameter("exportDir");
-
-		Executors.executeNow(new Runnable(){public void run() {
-			try {
-				StringBuilder buf = new StringBuilder();
-				InputStream in;
-				if (map.get("mbox").getName()!=null && map.get("mbox").getName().length()>0) {
-					in = map.get("mbox").getInputStream();
-				} else if (map.get("mboxurl").getString()!=null && map.get("mboxurl").getString().length()>0) {
-					in = new URL(map.get("mboxurl").getString()).openStream();
-				} else if (map.get("mboxfile").getString()!=null && map.get("mboxfile").getString().length()>0) {
-					in = new FileInputStream(new File(exportDir+map.get("mboxfile").getString()));
-				} else throw new RuntimeException("no mbox file or url defined");
-				File file = File.createTempFile("mbox",null);
-				try {
-					OutputStream out2 = new FileOutputStream(file);
-					IoUtils.copyAll(in,out2);
-					out2.close();
-					in.close();
-					try {
-						MailingList.ImportResult ir = forum.getMailingList().importMbox(file,mailErrorsTo,maxErrors);
-						buf.append("Results from mbox import to forum "+forum.getSubject()+":\n");
-						buf.append("imported "+ir.getImported()+" messages\n");
-						buf.append("errors "+ir.getErrors()+"\n");
-					} catch (ModelException e) {
-						buf.append("Import error:\n");
-						buf.append(e.getMessage());
-						logger.error("",e);
-					}
-					Mail mail = MailHome.newMail();
-					MailAddress to = new MailAddress(mailErrorsTo);
-					mail.setFrom(to);
-					mail.setTo(to);
-					mail.setSentDate(new Date());
-					mail.setContent(new PlainTextContent(buf.toString()));
-					mail.setSubject("mbox import");
-					ModelHome.send(mail);
-
-				} finally {
-					file.delete();
-				}
-			} catch (IOException e) {
-				throw new RuntimeException(e);
-			}
-
-			if(runRethread) {
-				StringBuilder buf = new StringBuilder();
-				buf.append("Rethread procedure scheduled after mbox import for forum '" + forum.getSubject() + "' has finished\n");
-				forum.getMailingList().rethread();
-				Mail mail = MailHome.newMail();
-				MailAddress to = new MailAddress(mailErrorsTo);
-				mail.setFrom(to);
-				mail.setTo(to);
-				mail.setSentDate(new Date());
-				mail.setContent(new PlainTextContent(buf.toString()));
-				mail.setSubject("Rethreading finished");
-				ModelHome.send(mail);
-			}
-
-		}});
-
-		%>
-		<html>
-		<head>
-		<%
-		Shared.title(request,response,"uploaded mbox file");
-		%>
-		</head>
-		<body>
-		<h2>uploading mbox file to <%=forum.getSubjectHtml()%></h2>
-		<p>Results will be emailed to <%=mailErrorsTo%> after the import has completed.
-		<p>return to forum: <%=Jtp.link(forum)%>
-		</body>
-		</html>
-		<%
-	}
-}
-%>
--- a/src/nabble/view/web/user/UserPendingNodes.java	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-
-package nabble.view.web.user;
-
-import nabble.model.Node;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-import nabble.view.lib.HtmlViewUtils;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-
-public final class UserPendingNodes extends HttpServlet {
-
-	private static final int MAX_ROWS = 20;
-
-	protected void service(HttpServletRequest request, HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		User user = Jtp.getUser(request);
-
-		if ( user == null ) {
-			Jtp.login("You must register/login to edit your profile.", request, response);
-			return;
-		}
-
-		String iRecS = request.getParameter("i");
-		int iRec = iRecS == null? 0 : Integer.valueOf(iRecS);
-
-		List<Node> nodeArray = user.getPendingPosts().get(0, 1000);
-		SearchResults searchResults = cutResults(nodeArray, iRec);
-
-		String title = "Pending Posts of ";
-		title += user.getName();
-
-		String url = "/user/UserPendingNodes.jtp";
-		HtmlViewUtils.GenericPagingPath pagingPath = new HtmlViewUtils.GenericPagingPath(url);
-		
-		out.print( "\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html>\r\n	<head>\r\n		" );
- Shared.title(request, response, title); 
-		out.print( "\r\n	</head>\r\n	<body>\r\n		" );
- Shared.minHeaderGlobal(request, response); 
-		out.print( "\r\n		<table>\r\n			<tr valign=\"top\">\r\n				<td><img src=\"" );
-		out.print( (Shared.getAvatarImageURL(user, false)) );
-		out.print( "\" class=\"avatar light-border-color\" width=100 height=100/></td>\r\n				<td style=\"width:100%\">\r\n					<div class=\"second-font\" style=\"font-size:170%\">\r\n						" );
-		out.print( (user.getNameHtml()) );
-		out.print( "\r\n					</div>\r\n					<div style=\"margin-top:.5em\">\r\n						<a href=\"/template/NamlServlet.jtp?macro=user_profile\">Account Settings</a>\r\n					</div>\r\n				</td>\r\n			</tr>\r\n		</table>\r\n\r\n		<table style=\"border-collapse:collapse;width:100%;margin-top:.5em\">\r\n			<tr>\r\n				<td class=\"title-row light-border-color\" colspan=3>\r\n					<div style=\"float:left;padding-top:.2em\">\r\n						<b>Pending Messages</b>\r\n					</div>\r\n					" );
- HtmlViewUtils.genericPaging(request, response, searchResults.getCount(), iRec, MAX_ROWS, pagingPath, ".4em 0 0 0"); 
-		out.print( "\r\n				</td>\r\n			</tr>\r\n		</table>\r\n\r\n		<style type=\"text/css\">\r\n			table.nodes {\r\n				width:100%;\r\n				border-width: 1px;\r\n				border-style: solid;\r\n				border-collapse:collapse;\r\n				margin-top:.5em;\r\n			}\r\n\r\n			table.nodes td {\r\n				padding:.1em;\r\n			}\r\n\r\n			table.nodes td.header {\r\n				padding: .2em .3em;\r\n				border-bottom-width: 1px;\r\n				border-bottom-style: solid;\r\n			}\r\n		</style>\r\n\r\n		" );
-
-				String[] columns = new String[] { "Message", "Pending Since", "Forum" };
-				
-		out.print( "\r\n\r\n<table class=\"nodes medium-border-color\">\r\n	<tr class=\"shaded-bg-color\" style=\"font-weight: bold\">\r\n		<td class=\"header\" style=\"width:16px\"></td>\r\n		<td class=\"header\">" );
-		out.print( (columns[0]) );
-		out.print( "</td>\r\n		<td class=\"header\">" );
-		out.print( (columns[1]) );
-		out.print( "</td>\r\n		<td class=\"header\">" );
-		out.print( (columns[2]) );
-		out.print( "</td>\r\n	</tr>\r\n	" );
-
-					Node[] nodes = searchResults.getNodes();
-					int i = 0;
-					if (nodes.length > 0) {
-						for (Node node : nodes) {
-							
-		out.print( "\r\n<tr " );
-		out.print( (i++%2==1?"class=\"light-bg-color\"":"") );
-		out.print( ">\r\n	<td align=\"center\">\r\n		" );
-Shared.showPending(out, node);
-		out.print( "\r\n	</td>\r\n	<td style=\"padding:.3em .4em;\">\r\n		<a href=\"" );
-		out.print( (Jtp.url(node)) );
-		out.print( "\">" );
-		out.print( (node.getSubjectHtml()) );
-		out.print( "</a>\r\n	</td>\r\n	<td style=\"padding:.2em\">\r\n		" );
-		out.print( (node.getMailToList() == null? "" : Jtp.formatDateLong(node.getMailToList().getWhenSent())) );
-		out.print( "\r\n	</td>\r\n	<td style=\"padding:.2em\">\r\n		" );
-		out.print( (Jtp.link(node.getApp())) );
-		out.print( "\r\n	</td>\r\n</tr>\r\n" );
-
-						}
-					} else {
-						
-		out.print( "\r\n<tr><td colspan=4 style=\"padding:.3em\">None</td></tr>\r\n" );
-
-					}
-					
-		out.print( "\r\n</table>\r\n" );
- HtmlViewUtils.genericPaging(request, response, searchResults.getCount(), iRec, MAX_ROWS, pagingPath, ".5em 0 0 0"); 
-		out.print( "\r\n\r\n" );
- Shared.footer(request,response); 
-		out.print( "\r\n" );
- Shared.analytics(request,response); 
-		out.print( "\r\n</body>\r\n</html>\r\n" );
-
-	}
-
-	private class SearchResults {
-		private int count;
-		private Node[] nodes;
-
-		public SearchResults() {}
-
-		public SearchResults(int count, Node[] nodes) {
-			this.count = count;
-			this.nodes = nodes;
-		}
-
-		public int getCount() { return count; }
-		public void setCount(int count) { this.count = count; }
-		public Node[] getNodes() { return nodes; }
-		public void setNodes(Node[] nodes) { this.nodes = nodes; }
-	}
-
-	private SearchResults cutResults(List<Node> array, int iRec) {
-		int i = iRec;
-		int count = 0;
-		List<Node> nodes = new ArrayList<Node>();
-		while (count < MAX_ROWS) {
-			if (array.size()-1 < i)
-				break;
-			nodes.add(array.get(i++));
-			count++;
-		}
-		Node[] nodesArray = nodes.toArray(new Node[0]);
-		return new SearchResults(array.size(), nodesArray);
-	}
-}
-
--- a/src/nabble/view/web/user/UserPendingNodes.jtp	Mon Jun 14 15:35:05 2021 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-<%
-package nabble.view.web.user;
-
-import nabble.model.Node;
-import nabble.model.User;
-import nabble.view.lib.Jtp;
-import nabble.view.lib.Shared;
-import nabble.view.lib.HtmlViewUtils;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-
-public final class UserPendingNodes extends HttpServlet {
-
-	private static final int MAX_ROWS = 20;
-
-	protected void service(HttpServletRequest request, HttpServletResponse response)
-		throws ServletException, IOException
-	{
-		PrintWriter out = response.getWriter();
-		User user = Jtp.getUser(request);
-
-		if ( user == null ) {
-			Jtp.login("You must register/login to edit your profile.", request, response);
-			return;
-		}
-
-		String iRecS = request.getParameter("i");
-		int iRec = iRecS == null? 0 : Integer.valueOf(iRecS);
-
-		List<Node> nodeArray = user.getPendingPosts().get(0, 1000);
-		SearchResults searchResults = cutResults(nodeArray, iRec);
-
-		String title = "Pending Posts of ";
-		title += user.getName();
-
-		String url = "/user/UserPendingNodes.jtp";
-		HtmlViewUtils.GenericPagingPath pagingPath = new HtmlViewUtils.GenericPagingPath(url);
-		%>
-		<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-		<html>
-			<head>
-				<% Shared.title(request, response, title); %>
-			</head>
-			<body>
-				<% Shared.minHeaderGlobal(request, response); %>
-				<table>
-					<tr valign="top">
-						<td><img src="<%=Shared.getAvatarImageURL(user, false)%>" class="avatar light-border-color" width=100 height=100/></td>
-						<td style="width:100%">
-							<div class="second-font" style="font-size:170%">
-								<%=user.getNameHtml()%>
-							</div>
-							<div style="margin-top:.5em">
-								<a href="/template/NamlServlet.jtp?macro=user_profile">Account Settings</a>
-							</div>
-						</td>
-					</tr>
-				</table>
-
-				<table style="border-collapse:collapse;width:100%;margin-top:.5em">
-					<tr>
-						<td class="title-row light-border-color" colspan=3>
-							<div style="float:left;padding-top:.2em">
-								<b>Pending Messages</b>
-							</div>
-							<% HtmlViewUtils.genericPaging(request, response, searchResults.getCount(), iRec, MAX_ROWS, pagingPath, ".4em 0 0 0"); %>
-						</td>
-					</tr>
-				</table>
-
-				<style type="text/css">
-					table.nodes {
-						width:100%;
-						border-width: 1px;
-						border-style: solid;
-						border-collapse:collapse;
-						margin-top:.5em;
-					}
-
-					table.nodes td {
-						padding:.1em;
-					}
-
-					table.nodes td.header {
-						padding: .2em .3em;
-						border-bottom-width: 1px;
-						border-bottom-style: solid;
-					}
-				</style>
-
-				<%
-				String[] columns = new String[] { "Message", "Pending Since", "Forum" };
-				%>
-
-				<table class="nodes medium-border-color">
-					<tr class="shaded-bg-color" style="font-weight: bold">
-						<td class="header" style="width:16px"></td>
-						<td class="header"><%=columns[0]%></td>
-						<td class="header"><%=columns[1]%></td>
-						<td class="header"><%=columns[2]%></td>
-					</tr>
-					<%
-					Node[] nodes = searchResults.getNodes();
-					int i = 0;
-					if (nodes.length > 0) {
-						for (Node node : nodes) {
-							%>
-							<tr <%=i++%2==1?"class=\"light-bg-color\"":""%>>
-								<td align="center">
-									<%Shared.showPending(out, node);%>
-								</td>
-								<td style="padding:.3em .4em;">
-									<a href="<%=Jtp.url(node)%>"><%=node.getSubjectHtml()%></a>
-								</td>
-								<td style="padding:.2em">
-									<%=node.getMailToList() == null? "" : Jtp.formatDateLong(node.getMailToList().getWhenSent())%>
-								</td>
-								<td style="padding:.2em">
-									<%=Jtp.link(node.getApp())%>
-								</td>
-							</tr>
-							<%
-						}
-					} else {
-						%>
-						<tr><td colspan=4 style="padding:.3em">None</td></tr>
-						<%
-					}
-					%>
-				</table>
-				<% HtmlViewUtils.genericPaging(request, response, searchResults.getCount(), iRec, MAX_ROWS, pagingPath, ".5em 0 0 0"); %>
-
-				<% Shared.footer(request,response); %>
-				<% Shared.analytics(request,response); %>
-			</body>
-		</html>
-		<%
-	}
-
-	private class SearchResults {
-		private int count;
-		private Node[] nodes;
-
-		public SearchResults() {}
-
-		public SearchResults(int count, Node[] nodes) {
-			this.count = count;
-			this.nodes = nodes;
-		}
-
-		public int getCount() { return count; }
-		public void setCount(int count) { this.count = count; }
-		public Node[] getNodes() { return nodes; }
-		public void setNodes(Node[] nodes) { this.nodes = nodes; }
-	}
-
-	private SearchResults cutResults(List<Node> array, int iRec) {
-		int i = iRec;
-		int count = 0;
-		List<Node> nodes = new ArrayList<Node>();
-		while (count < MAX_ROWS) {
-			if (array.size()-1 < i)
-				break;
-			nodes.add(array.get(i++));
-			count++;
-		}
-		Node[] nodesArray = nodes.toArray(new Node[0]);
-		return new SearchResults(array.size(), nodesArray);
-	}
-}
-%>