changeset 44:cc5b7d515580

remove post by email
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 11 Jun 2021 09:43:51 -0600
parents 4d90d48a19ec
children ea757b766baa
files compile_test.sh src/nabble/model/Message.java src/nabble/model/ModelHome.java src/nabble/model/PostByEmail.java src/nabble/model/User.java src/nabble/model/UserImpl.java src/nabble/modules/workgroup/workgroup.naml src/nabble/view/naml/compile_all.naml src/nabble/view/naml/delete_node.naml src/nabble/view/naml/dropdown.naml src/nabble/view/naml/email.naml src/nabble/view/naml/post_by_email.naml src/nabble/view/naml/post_by_email_page.naml src/nabble/view/naml/utilities.naml src/nabble/view/web/template/CompileTest.java src/nabble/view/web/template/NodeNamespace.java src/nabble/view/web/template/UserNamespace.java
diffstat 17 files changed, 4 insertions(+), 743 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/compile_test.sh	Fri Jun 11 09:43:51 2021 -0600
@@ -0,0 +1,2 @@
+. classpath.sh
+java nabble.view.web.template.CompileTest 2>&1 | tee err
--- a/src/nabble/model/Message.java	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/model/Message.java	Fri Jun 11 09:43:51 2021 -0600
@@ -147,10 +147,9 @@
 		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 SUBSCRIPTION = PostByEmail.msgFmt;
 
 		public boolean isMail() {
-			return this==MAILING_LIST || this==SUBSCRIPTION;
+			return this==MAILING_LIST;
 		}
 	}
 
--- a/src/nabble/model/ModelHome.java	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/model/ModelHome.java	Fri Jun 11 09:43:51 2021 -0600
@@ -82,14 +82,6 @@
 		return UserImpl.getUser(id);
 	}
 */
-	public static String getNodeReplyAddress(Node node, User user) {
-		return PostByEmail.getMailAddress(user, node);
-	}
-
-	public static String getUserBouncesAddress(User user) {
-		return PostByEmail.getBouncesAddress(user);
-	}
-
 	public static void setNodeHeaders(Mail mail, Node node) {
 		MailSubsystem.setHeaders(mail, (NodeImpl) node);
 	}
--- a/src/nabble/model/PostByEmail.java	Fri Jun 11 15:28:26 2021 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,431 +0,0 @@
-package nabble.model;
-
-import fschmidt.db.DbDatabase;
-import fschmidt.util.mail.Mail;
-import fschmidt.util.mail.MailAddress;
-import fschmidt.util.mail.MailException;
-import fschmidt.util.mail.MailHome;
-import fschmidt.util.mail.MailIterator;
-import fschmidt.util.mail.PlainTextContent;
-import fschmidt.util.mail.Pop3Server;
-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.compiler.Template;
-import nabble.naml.compiler.TemplatePrintWriter;
-import nabble.naml.namespaces.BasicNamespace;
-import nabble.naml.namespaces.TemplateException;
-import nabble.view.lib.Permissions;
-import nabble.view.web.template.NabbleNamespace;
-import nabble.view.web.template.NodeNamespace;
-import nabble.view.web.template.UserNamespace;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Collections;
-import java.util.Date;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-
-@Namespace (
-	name = "post_by_email",
-	global = true
-)
-public final class PostByEmail {
-	private static final Logger logger = LoggerFactory.getLogger(PostByEmail.class);
-
-	// I would like to get rid of this.
-	static final MailMessageFormat msgFmt = new MailMessageFormat('s', "subscription");
-
-	private static final Pop3Server pop3Server = (Pop3Server)Init.get("subscriptionsPop3Server");
-
-	static {
-		if (Init.hasDaemons) {
-			runSubscriptions();
-		}
-	}
-
-	private static class Lazy {
-		static final String emailPrefix;
-		static final String emailSuffix;
-		static final Pattern pattern;
-		static {
-			String addrSpec = pop3Server.getUsername();
-			int ind = addrSpec.indexOf('@');
-			emailPrefix = addrSpec.substring(0, ind) + "+";
-			emailSuffix = addrSpec.substring(ind);
-			pattern = Pattern.compile(
-					"\\+s(\\d+)n(\\d+)h(\\d+)" + Pattern.quote(emailSuffix),
-					Pattern.CASE_INSENSITIVE);
-		}
-	}
-
-	private static void runSubscriptions() {
-		if (pop3Server == null) {
-			logger.error("Subscriptions: no pop3 specified for subscriptions");
-			return;
-		}
-		Executors.scheduleWithFixedDelay(new Runnable() {
-
-			public void run() {
-				try {
-					processSubscriptions();
-					processBounces();
-				} catch(MailException e) {
-					logger.error("mail processing",e);
-				}
-			}
-
-		}, 10, 10, TimeUnit.SECONDS );
-		logger.info("Subscriptions: pop3 reading thread started");
-	}
-
-	private static void processSubscriptions() {
-		MailIterator mails = pop3Server.getMail();
-		try {
-			while (mails.hasNext()) {
-				Mail mail = mails.next();
-				try {
-					new PostByEmail(mail).processMessage();
-				} catch (Exception e) {
-					logger.error("mail:\n"+mail.getRawInput(),e);
-				}
-			}
-		} finally {
-			mails.close();
-		}
-	}
-
-
-	// begin non-static part
-
-	private final Mail mail;
-	private String email;
-	private String messageId;
-	private String address;
-	private NodeImpl repliedToNode;
-	private NodeImpl postedNode;
-	private UserImpl mailAuthor;
-
-	private PostByEmail(Mail mail) {
-		this.mail = mail;
-	}
-
-	private void processMessage() {
-		if( MailSubsystem.getReturnPath(mail).equals("") ) {
-			logger.info("ignoring bounce");
-			return;
-		}
-
-		email = mail.getFrom().getAddrSpec();
-
-		String[] messageIds = mail.getHeader("Message-Id"); // returns both Id and ID
-		messageId = messageIds!=null && messageIds.length==1 ? MailSubsystem.stripBrackets(messageIds[0]) : null;
-
-		String[] a = mail.getHeader("Envelope-To");
-		if (a == null)
-			a = mail.getHeader("X-Original-To"); // postfix
-		if (a == null)
-			a = mail.getHeader("X-Delivered-to"); // fastmail
-		if (a.length > 1)
-			a = new String[] { a[0] };
-		for( String s : a[0].split(",") ) {
-			address = s.trim();
-			Matcher matcher = Lazy.pattern.matcher(address);
-			if( matcher.find() ) {
-				long siteId = Long.valueOf(matcher.group(1));
-				SiteImpl site = SiteKey.getInstance(siteId).site();
-				if( site != null ) {
-					long nodeId = Long.valueOf(matcher.group(2));
-					repliedToNode = site.getNodeImpl(nodeId);
-					if( repliedToNode != null ) {
-						if( repliedToNode.getAssociatedMailingList() != null) {
-							sendFailureMail( "Nabble", failureMessagePrefix() + "You can't post by email to a mailing list archive." );
-							continue;
-						}
-						mailAuthor = site.getUserImplFromEmail(email);
-						if( mailAuthor != null && !generateHash(mailAuthor,repliedToNode).equals(matcher.group(3)) )
-							mailAuthor = null;
-						callNaml();
-						continue;
-					}
-				}
-			}
-//System.out.println("qqqqqqqqqqqqqqqqqqqqqqqqqqqqqq "+address);
-			sendFailureMail( "Nabble", failureMessagePrefix() + "No forum exists for this address." );
-		}
-	}
-
-	private void callNaml() {
-		Site site = repliedToNode.getSite();
-		Template template = site.getTemplate( "post by email",
-			BasicNamespace.class, NabbleNamespace.class, PostByEmail.class
-		);
-		template.run( TemplatePrintWriter.NULL, Collections.<String,Object>emptyMap(),
-			new BasicNamespace(template), new NabbleNamespace(site), this
-		);
-	}
-
-	private String failureMessagePrefix() {
-		return
-			"Delivery to the following recipient failed permanently:\n\n"
-			+ "    " + address + "\n\n"
-		;
-	}
-
-	private void sendFailureMail(String fromName,String failureMessage) {
-/* why?
-		MailSubsystem.bounce(mail,
-			"Delivery to the following recipient failed permanently:\n\n    "
-			+ address + "\n\n"
-			+ failureMessage + "\n"
-		);
-*/
-		Mail bounce = MailHome.newMail();
-		bounce.setFrom( new MailAddress(ModelHome.noReply,fromName) );
-		bounce.setTo( new MailAddress(email) );
-		bounce.setSubject( "Delivery Status Notification (Failure)" );
-		bounce.setHeader( "X-Failed-Recipients", mail.getHeader("Envelope-To") );
-		StringBuilder content = new StringBuilder();
-		content
-			.append( failureMessage ).append( "\n\n" )
-			.append( "----- Original message -----\n\n" )
-			.append( mail.getRawInput() )
-		;
-		bounce.setContent(new PlainTextContent(content.toString()));
-		ModelHome.send(bounce);
-		logger.warn("bouncing subscription mail for "+email);
-	}
-
-	private UserImpl mailAuthor() throws TemplateException {
-		if( mailAuthor==null )
-			throw TemplateException.newInstance("subscription_processing_bad_user");
-		return mailAuthor;
-	}
-
-	private void saveToPost() throws TemplateException {
-		logger.info("Processing email from: " + address);
-
-		Date date = mail.getSentDate();
-		Date now = new Date();
-		if (date == null || date.compareTo(now) > 0 || date.getTime() < 0) {
-			date = now;
-		}
-
-		String subject = mail.getSubject();
-		if (subject == null || subject.trim().length() == 0)
-			subject = "(no subject)";
-
-		String message = mail.getRawInput();
-		message = message.replace("\000","");  // postgres can't handle 0
-		if( !msgFmt.isOk(message) )
-			throw TemplateException.newInstance("bad_mail");
-		UserImpl mailAuthor = mailAuthor();
-
-		logger.info("Making a post from a message from " + address);
-		DbDatabase db = repliedToNode.siteKey.getDb();
-		db.beginTransaction();
-		try {
-			postedNode = NodeImpl.newChildNode(Node.Kind.POST, mailAuthor, subject, message, msgFmt, repliedToNode);
-			postedNode.setWhenCreated(date);
-			if( messageId != null )
-				postedNode.setMessageID(messageId);
-
-			postedNode.checkNewPostLimit();
-
-			postedNode.insert(true);
-
-			db.commitTransaction();
-		} catch(ModelException e) {
-			logger.error("Subscription processing failed: " + mail.getRawInput(), e);
-		} finally {
-			db.endTransaction();
-		}
-	}
-
-	// naml
-
-	public static final CommandSpec thread_by_subject = new CommandSpec.Builder()
-		.parameters("prefixes")
-		.build()
-	;
-
-	@Command public void thread_by_subject(IPrintWriter out,Interpreter interp) {
-		if( repliedToNode.getKind() == Node.Kind.APP )
-			return;
-		String subject = mail.getSubject();
-		if (subject == null)
-			return;
-		String prefixes = interp.getArgString("prefixes");
-		Pattern prefixRegex = MailingLists.prefixRegex(prefixes);
-		if( MailingLists.normalizeSubject(subject,prefixRegex).equals(MailingLists.normalizeSubject(repliedToNode.getSubject(),prefixRegex)) )
-			return;
-		NodeImpl app = repliedToNode.getAppImpl();
-		if( app != null )
-			repliedToNode = app;
-	}
-
-	@Command public void new_post_subject(IPrintWriter out,Interpreter interp) {
-		out.print(mail.getSubject());
-	}
-
-	public static final CommandSpec set_new_post_subject = new CommandSpec.Builder()
-		.dotParameter("subject")
-		.build()
-	;
-
-	@Command public void set_new_post_subject(IPrintWriter out,Interpreter interp) {
-		String newSubject = interp.getArgString("subject");
-		mail.setSubject(newSubject);
-	}
-
-
-	public static final CommandSpec save_to_post = CommandSpec.NO_OUTPUT;
-
-	@Command public void save_to_post(IPrintWriter out,Interpreter interp) throws TemplateException {
-		saveToPost();
-	}
-
-	public static final CommandSpec send_failure_mail = CommandSpec.NO_OUTPUT()
-		.dotParameter("text")
-		.optionalParameters("from")
-		.build()
-	;
-
-	@Command public void send_failure_mail(IPrintWriter out,Interpreter interp) {
-		String from = interp.getArgString("from");
-		if( from == null )
-			from = "Nabble";
-		String msg = interp.getArgString("text");
-		sendFailureMail(from,msg);
-	}
-
-	@Command public void email_from(IPrintWriter out,Interpreter interp) throws TemplateException {
-		out.print( email );
-	}
-
-	@Command public void email_to(IPrintWriter out,Interpreter interp) throws TemplateException {
-		out.print( address );
-	}
-
-	public static final CommandSpec replied_to_node = CommandSpec.DO;
-
-	@Command public void replied_to_node(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
-		out.print( interp.getArg( new NodeNamespace(repliedToNode), "do" ) );
-	}
-
-	public static final CommandSpec posted_node = CommandSpec.DO;
-
-	@Command public void posted_node(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
-		out.print( interp.getArg( new NodeNamespace(postedNode), "do" ) );
-	}
-
-	public static final CommandSpec mail_author = CommandSpec.DO;
-
-	@Command public void mail_author(IPrintWriter out,ScopedInterpreter<UserNamespace> interp)
-		throws TemplateException
-	{
-		out.print( interp.getArg( new UserNamespace(mailAuthor()), "do" ) );
-	}
-
-	// end non-static part
-
-
-	static String getMailAddress(User user, Node node) {
-		Site site = user.getSite();
-		if( !node.getSite().equals(site) )
-			throw new RuntimeException();
-		return
-			Lazy.emailPrefix
-			+ 's' + site.getId()
-			+ 'n' + node.getId()
-			+ 'h' + generateHash(user,node)
-			+ Lazy.emailSuffix
-		;
-	}
-
-
-	private static String generateHash(User user,Node node) {
-		int h = user.hashCode();
-		h = 31*h + node.hashCode();
-		h = 31*h + 23;
-		return Integer.toString(Math.abs(h)%100);
-	}
-
-
-
-
-
-
-
-	private static final Pop3Server bouncesPop3Server = (Pop3Server)Init.get("subscriptionBouncesPop3Server");
-
-	private static class LazyBounces {
-		static final String emailPrefix;
-		static final String emailSuffix;
-		static final Pattern pattern;
-		static {
-			String addrSpec = bouncesPop3Server.getUsername();
-			int ind = addrSpec.indexOf('@');
-			emailPrefix = addrSpec.substring(0, ind) + "+";
-			emailSuffix = addrSpec.substring(ind);
-			pattern = Pattern.compile(
-				"\\+s(\\d+)u(\\d+)" + Pattern.quote(emailSuffix)
-				, Pattern.CASE_INSENSITIVE
-			);
-		}
-	}
-
-	private static synchronized void processBounces() {
-		if( bouncesPop3Server == null ) {
-			logger.error("subscriptionBouncesPop3Server not defined");
-			System.exit(-1);
-		}
-		MailIterator mails = bouncesPop3Server.getMail();
-		try {
-			while( mails.hasNext() ) {
-				Mail mail = mails.next();
-				try {
-					processBounce(mail);
-				} catch (Exception e) {
-					logger.error("mail:\n"+mail.getRawInput(),e);
-				}
-			}
-		} finally {
-			mails.close();
-		}
-	}
-
-	private static void processBounce(Mail mail) {
-		String[] envTo = mail.getHeader("Envelope-To");
-		if (envTo == null)
-			envTo = mail.getHeader("X-Original-To"); // postfix
-		if (envTo == null)
-			envTo = mail.getHeader("X-Delivered-to"); // fastmail
-		String originalTo = envTo[0];
-		Matcher matcher = LazyBounces.pattern.matcher(originalTo);
-		if( !matcher.find() )
-			throw new RuntimeException("invalid email: "+originalTo);
-		long siteId = Long.parseLong( matcher.group(1) );
-		long userId = Long.parseLong( matcher.group(2) );
-		SiteImpl site = SiteKey.getInstance(siteId).site();
-		UserImpl user = site.getUserImpl(userId);
-		user.bounced();
-		logger.info(""+user+" has "+user.getBounces()+" bounces");
-	}
-
-	static String getBouncesAddress(User user) {
-		return
-			LazyBounces.emailPrefix
-			+ 's' + user.getSite().getId()
-			+ 'u' + user.getId()
-			+ LazyBounces.emailSuffix
-		;
-	}
-
-}
--- a/src/nabble/model/User.java	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/model/User.java	Fri Jun 11 09:43:51 2021 -0600
@@ -40,8 +40,6 @@
 	public Subscription getSubscription(Node node);
 	public Subscription subscribe(Node node,Subscription.To to,Subscription.Type type);
 
-	public String getDecoratedAddress(Node node);
-
 	public void deactivate();
 	public boolean isDeactivated();
 
--- a/src/nabble/model/UserImpl.java	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/model/UserImpl.java	Fri Jun 11 09:43:51 2021 -0600
@@ -851,10 +851,6 @@
 	}
 
 
-	public String getDecoratedAddress(Node node) {
-		return PostByEmail.getMailAddress(this, node);
-	}
-
 	public void saveAvatar(BufferedImage smallImage,BufferedImage bigImage) throws ModelException {
 		if( !db().isInTransaction() ) {
 			db().beginTransaction();
--- a/src/nabble/modules/workgroup/workgroup.naml	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/modules/workgroup/workgroup.naml	Fri Jun 11 09:43:51 2021 -0600
@@ -378,17 +378,6 @@
 	</n.if.both>
 </macro>
 
-<override_macro name="save_post_by_email" requires="post_by_email" unindent="true">
-	<n.overridden />
-	<n.if.posted_node.topic_or_app.is_assigned>
-		<then.if.posted_node.topic_node.assignee.equals.posted_node.owner>
-			<then.if.replied_to_node.owner.can_be_assigned_to.posted_node.topic_node>
-				<then.posted_node.topic_node.assign assignee="[n.replied_to_node.owner/]" priority="[n.posted_node.topic_node.priority/]" />
-			</then.if.replied_to_node.owner.can_be_assigned_to.posted_node.topic_node>
-		</then.if.posted_node.topic_node.assignee.equals.posted_node.owner>
-	</n.if.posted_node.topic_or_app.is_assigned>
-</override_macro>
-
 
 // from permissions
 
--- a/src/nabble/view/naml/compile_all.naml	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/view/naml/compile_all.naml	Fri Jun 11 09:43:51 2021 -0600
@@ -59,10 +59,6 @@
 	nabble.view.web.template.SubscriptionNamespace
 </macro>
 
-<macro name="post_by_email_namespace_class">
-	nabble.model.PostByEmail
-</macro>
-
 <macro name="node_page_namespace_class">
 	nabble.view.web.template.NodePageNamespace
 </macro>
@@ -137,7 +133,6 @@
 	<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="post_by_email_page" namespaces="[n.standard_classes/]" />
 	<n.compile macro="subscribe" namespaces="[n.standard_classes/]" />
 	<n.compile macro="subscribe_by_code" namespaces="[n.standard_classes/]" />
 	<n.compile macro="subscription_saved" namespaces="[n.standard_classes/]" />
@@ -220,7 +215,6 @@
 	<n.compile macro="notify_subscribers" namespaces="[n.base_classes/],[n.node_namespace_class/]" />
 	<n.compile macro="digest email" namespaces="[n.base_classes/],[n.node_list_namespace_class/],[n.subscription_namespace_class/]" />
 
-	<n.compile macro="post by email" namespaces="[n.base_classes/],[n.post_by_email_namespace_class/]" />
 	<n.compile macro="backup email" namespaces="[n.base_classes/]" />
 	<n.compile macro="site deletion email" namespaces="[n.base_classes/]" />
 
--- a/src/nabble/view/naml/delete_node.naml	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/view/naml/delete_node.naml	Fri Jun 11 09:43:51 2021 -0600
@@ -58,7 +58,6 @@
 							<to_name.current_user.name/>
 							<subject><t>Deleted posts</t></subject>
 							<text_part.deleted_nodes_text/>
-							<bounce_to.current_user.bounces_address/>
 						</n.send>
 					</n.new_email.>
 				</then>
--- a/src/nabble/view/naml/dropdown.naml	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/view/naml/dropdown.naml	Fri Jun 11 09:43:51 2021 -0600
@@ -6,7 +6,6 @@
 		loadOnClick="/template/NamlServlet.jtp?macro=app_dropdown_later&node=[n.id/]"
 	>
 		<n.menu_subscription/>
-		<n.menu_post_by_email/>
 
 		<n.menu_separator/>
 
@@ -52,7 +51,6 @@
 	<n.javascript_response/>
 	<n.get_node_from_parameter.>
 		<n.menu_subscription/>
-		<n.menu_post_by_email/>
 
 		<n.menu_edit_name_and_description/>
 		<n.menu_change_type/>
@@ -228,26 +226,6 @@
 	</n.if.is_in_command>
 </macro>
 
-<macro name="menu_post_by_email" requires="node">
-	<n.if.not.is_associated_with_mailing_list_archive>
-		<then>
-			<n.if.is_in_command name="dropdown">
-				<then>
-					dropdown.add('postByEmail', '<n.javascript_string_encode.post_by_email_link/>', 'display:none');
-				</then>
-				<else>
-					<n.set_local_node.this_node/>
-					<n.if.visitor.can_create_topic_in.local_node>
-						<then>
-							NabbleDropdown.show('postByEmail');
-						</then>
-					</n.if.visitor.can_create_topic_in.local_node>
-				</else>
-			</n.if.is_in_command>
-		</then>
-	</n.if.not.is_associated_with_mailing_list_archive>
-</macro>
-
 <macro name="menu_edit_name_and_description" requires="node">
 	<n.if.is_in_command name="dropdown">
 		<then>
--- a/src/nabble/view/naml/email.naml	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/view/naml/email.naml	Fri Jun 11 09:43:51 2021 -0600
@@ -31,13 +31,11 @@
 			<n.send>
 				<to.local_subscription.user.user_email/>
 				<to_name.local_subscription.user.name/>
-				<from.local_subscription.user.reply_address_for.local_node/>
 				<from_name><n.local_node.owner.name/> [via <n.root_node.subject/>]</from_name>
 				<subject.local_node.subject/>
 				<text_part.text_part/>
 				<html_part.html_part/>
 				<set_headers_for.local_node/>
-				<bounce_to.local_subscription.user.bounces_address/>
 			</n.send>
 		</n.new_email.>
 	</n.block.>
@@ -49,13 +47,11 @@
 			<n.send>
 				<to.topic_assignee.user_email/>
 				<to_name.topic_assignee.name/>
-				<from.topic_assignee.reply_address_for.page_node/>
 				<from_name><n.page_node.owner.name/> [via <n.root_node.subject/>]</from_name>
 				<subject.page_node.subject/>
 				<text_part.assign_text/>
 				<html_part.assign_html/>
 				<set_headers_for.page_node/>
-				<bounce_to.topic_assignee.bounces_address/>
 			</n.send>
 		</then.new_email.>
 	</n.if.topic_assignee.can_view.page_node>
@@ -72,7 +68,6 @@
 			<subject><n.local_subscription.node.subject/> - <t>Digest Email</t></subject>
 			<text_part.local_subscription.digest_text/>
 			<html_part.local_subscription.digest_html/>
-			<bounce_to.local_subscription.user.bounces_address/>
 		</n.send>
 	</n.new_email.>
 </macro>
@@ -87,9 +82,7 @@
 
 	<n.page_node.text_email_message_with_signature />
 	_______________________________________________
-	<t>If you reply to this email, your message will be added to the discussion below</t>:
 	<n.page_node.url/>
-	<n.start_new_topic_line/>
 	<n.unsubscribe_line format="text"/>
 </macro>
 
@@ -106,11 +99,9 @@
 	<br/>
 	<hr noshade="noshade" size="1" color="#cccccc" />
 	<div style="color:#444; font: 12px tahoma,geneva,helvetica,arial,sans-serif;">
-		<div style="font-weight:bold"><t>If you reply to this email, your message will be added to the discussion below</t>:</div>
 		<a href="[n.page_node.url/]"><n.page_node.url/></a>
 	</div>
 	<div style="color:#666; font: 11px tahoma,geneva,helvetica,arial,sans-serif;margin-top:.4em;line-height:1.5em">
-		<n.start_new_topic_line append="[br/]"/>
 		<n.unsubscribe_line format="html"/><br/>
 		<n.macro_viewer_email_link macro="instant_html"/>
 	</div>
@@ -157,16 +148,6 @@
 	</n.string_list.>
 </macro>
 
-<macro name="start_new_topic_line" parameters="append" requires="subscription, node_page">
-    <n.set_local_user.this_subscription.user/>
-    <n.set_local_node.page_node.get_app_node/>
-    <n.if.both condition1="[n.local_user.has_subscription_to_descentants_of.local_node/]" condition2="[n.local_user.can_reply_to.local_node/]">
-        <then>
-            <t>To start a new topic under <t.location.local_node.subject/>, email <t.p2.local_node.user_address email="[n.local_user.user_email/]"/></t> <n.hide_null.append/>
-        </then>
-    </n.if.both>
-</macro>
-
 <macro name="unsubscribe_line" parameters="format" requires="subscription">
 	<n.if.equal value1="[n.format/]" value2="html">
 		<then><t>To unsubscribe from <t.location.node.subject/></t>, <a href="[n.unsubscribe_by_code_url/]"><t>click here</t></a>.</then>
--- a/src/nabble/view/naml/post_by_email.naml	Fri Jun 11 15:28:26 2021 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-<macro name="post by email" requires="post_by_email" unindent="true">
-	<n.catch_exception. id="save-block">
-		<n.save_post_by_email />
-	</n.catch_exception.>
-	<n.format_error.handle_exception. for="save-block">
-		<n.exception. name="subscription_processing_bad_user">
-			<n.send_standard_failure_mail.>
-				This email address only works for the registered Nabble user who it is assigned to, and you (<n.email_from/>) are not that user.
-			</n.send_standard_failure_mail.>
-		</n.exception.>
-		<n.exception. name="banned">
-			<n.send_standard_failure_mail.>
-				Your email to <n.email_to/> has been rejected because you are not allowed to post to <n.replied_to_node.url/> . Please contact the owner about permissions or visit the Nabble Support forum.
-			</n.send_standard_failure_mail.>
-		</n.exception.>
-		<n.exception. name="bad_mail">
-			<n.send_standard_failure_mail.>
-				Your email to <n.email_to/> couldn't be parsed.
-			</n.send_standard_failure_mail.>
-		</n.exception.>
-	</n.format_error.handle_exception.>
-</macro>
-
-<macro name="save_post_by_email" requires="post_by_email" unindent="true">
-	<n.fix_threading/>
-	<n.if.not.mail_author.can_post_under.replied_to_node>
-		<then.throw_template_exception name="banned" />
-	</n.if.not.mail_author.can_post_under.replied_to_node>
-	<n.save_to_post/>
-</macro>
-
-<macro name="fix_threading" requires="post_by_email">
-	<n.thread_by_subject prefixes="[n.prefixes/]" />
-</macro>
-
-<macro name="prefixes" requires="post_by_email">
-	re|aw|res|fwd|答复
-</macro>
-
-<macro name="send_standard_failure_mail" dot_parameter="text" requires="post_by_email" unindent="true">
-	<n.send_failure_mail.>
-		Delivery to the following recipient failed permanently:
-
-		<n.nop/>    <n.email_to/>
-
-		<n.text/>
-	</n.send_failure_mail.>
-</macro>
--- a/src/nabble/view/naml/post_by_email_page.naml	Fri Jun 11 15:28:26 2021 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-<macro name="post_by_email_page" requires="servlet">
-	<n.node_page.>
-		<n.if.is_submitted_form>
-			<then>
-				<n.catch_exception. id="send-email-block">
-					<n.send_email_address/>
-				</n.catch_exception.>
-			</then>
-		</n.if.is_submitted_form>
-		<n.html>
-			<head>
-				<n.title.><t>Post by Email</t></n.title.>
-			</head>
-			<body>
-				<n.edit_header first_text="[t]Post by Email[/t]" second_text="[n.page_node.subject/]" />
-	
-				<n.if.is_submitted_form>
-					<then>
-						<n.if.has_exception for="send-email-block">
-							<then>
-								<n.show_email_error/>
-							</then>
-							<else>
-								<table class="info-message" style="width:100%;padding:.5em">
-									<tr>
-										<td><img src="/images/success.png"/></td>
-										<td style="width:100%;font-weight:bold"><t>An email has been sent to you.</t></td>
-									</tr>
-								</table>
-							</else>
-						</n.if.has_exception>
-					</then>
-				</n.if.is_submitted_form>
-	
-				<div style="margin:1em 0 2em">
-					<n.if.visitor.is_anonymous>
-						<then>
-							<t>To prevent spam, the email address to use when posting by email is <b>unique</b> for each user.</t>
-							<t>To see which email address you should use to post, please <n.login_link.>login</n.login_link.> or <n.register_link.>register</n.register_link.>.</t>
-							<n.if.page_node.only_members_can_create_topics>
-								<then>
-									<t>You will need authorization to post new topics in <t.location.page_node.subject/>, so in addition to registering you will have to be
-									approved by the administrators.</t>
-								</then>
-								<else>
-									<t>If you don't want to register yet, just enter the email address from which you intend to post,
-									and your personal address will be emailed to you.</t>
-									<div class="second-font big-title" style="margin:1.2em 0 .2em">
-										<t>Enter your email address</t>
-									</div>
-									<n.form.>
-										<input type="hidden" name="node" value="[n.page_node.id/]"/>
-										<input type="hidden" name="action" value="send"/>
-										<input type="text" size="40" maxlength="80" name="email"/><br/>
-										<input type="submit" value="[t]Send email to me[/t]" style="margin-top:.5em"/>
-									</n.form.>
-								</else>
-							</n.if.page_node.only_members_can_create_topics>
-						</then>
-						<else> 
-							<n.if.either condition1="[n.not.page_node.only_members_can_create_topics/]" condition2="[n.visitor.can_create_topic_in.page_node/]">
-								<then>
-									<t>Instead of posting via the web interface, you can also post new topics by sending emails to the following email address:</t>
-									<div style="padding:1em">
-										<span class="info-message rounded bold" style="padding:.4em .3em">
-											<n.page_node.subject/>
-											&lt;<span class="weak-color" style="font-weight:bold"><n.page_node.user_address email="[n.visitor.user_email/]"/></span>&gt;
-										</span>
-									</div>
-									<table style="width:60em">
-										<tr valign="top">
-											<td><img src="/images/icon_alert_sm.png"/></td>
-											<td>
-												<t>Note that this address is unique to you and only accepts emails sent from <t.address><b><n.visitor.user_email/></b></t.address>.
-												The purpose of this design is to help prevent spam.</t>
-											</td>
-										</tr>
-									</table>
-								</then>
-								<else>
-									<t>Sorry, but only members can post messages under <t.app.page_node.subject/>.</t><br/>
-									<t>Please contact the administrators if you need help.</t>
-								</else>
-							</n.if.either>
-						</else>
-					</n.if.visitor.is_anonymous>
-				</div>
-				&laquo; <n.page_node.node_link text="[t]Go back[/t]"/>
-			</body>
-		</n.html>
-	</n.node_page.>
-</macro>
-
-<macro name="show_email_error">
-	<n.format_error.handle_exception. for="send-email-block">
-		<n.exception. name="invalid_email">
-			<t>Enter a valid email address.</t>
-		</n.exception.>
-	</n.format_error.handle_exception.>
-</macro>
-
-<macro name="send_email_address" requires="node_page,servlet" unindent="true">
-	<n.new_email.>
-		<n.send>
-			<to><n.get_parameter name="email"/></to>
-			<subject><t>Email for <t.app.page_node.subject/></t></subject>
-			<text_part>
-				<t>Dear user,</t>
-
-				<t>As you requested, the email address to post new topics under <t.app.page_node.subject/> is:</t>
-
-				<n.page_node.subject/> &lt;<n.page_node.user_address email="[n.get_parameter name='email'/]"/>&gt;
-
-				<t>Note that this address is unique to you and only accepts emails sent from <t.address.get_parameter name="email"/>.
-				The purpose of this design is to help prevent spam.</t>
-
-				<t>Visit <t.app.page_node.subject/> at:</t>
-				<n.page_node.url/>
-
-				<t>If you didn't request this email or have no idea why you received it, please ignore it. It might have been a mistake from someone else.</t>
-
-				<t>Sincerely,</t>
-				<t>The Nabble team</t>
-				________________________________________
-				<t>Free Embeddable <t.app.page_node.view_name/></t> powered by Nabble
-				<n.nabble_homepage/>
-			</text_part>
-			<html_part>
-				<t>Dear user,</t><br/>
-				<br/>
-				<t>As you requested, the email address to post new topics under <t.app><b><n.page_node.subject/></b></t.app> is:</t>
-				<div style="background-color:#FFFADB;border:#EDDD79 solid 1px;margin:1.2em 0;padding:.5em">
-				<n.page_node.subject/> &lt;<n.page_node.user_address email="[n.get_parameter name='email'/]"/>&gt;
-				</div>
-				<t>Note that this address is unique to you and only accepts emails sent from <t.address.get_parameter name="email"/>.
-				The purpose of this design is to help prevent spam.</t><br/>
-				<br/>
-				<t>Visit <t.app.page_node.subject/> at:</t><br/>
-				<n.page_node.url/><br/>
-				<br/>
-				<t>If you didn't request this email or have no idea why you received it, please ignore it. It might have been a mistake from someone else.</t>
-				<br/>
-				<br/>
-				<t>Sincerely,</t><br/>
-				<t>The Nabble team</t><br/>
-				________________________________________<br/>
-				<t>Free Embeddable <t.app.page_node.view_name/></t> powered by Nabble<br/>
-				<n.nabble_homepage/><br/><br/>
-			</html_part>
-		</n.send>
-	</n.new_email.>
-</macro>
--- a/src/nabble/view/naml/utilities.naml	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/view/naml/utilities.naml	Fri Jun 11 09:43:51 2021 -0600
@@ -506,16 +506,6 @@
 	</n.encode_url.>
 </macro>
 
-<macro name="post_by_email_link" requires="node" dot_parameter="text" parameters="title, class">
-	<a href="[n.post_by_email_path/]" class="[n.class/]" rel="nofollow" title="[n.title/]"><n.default. to="[t]Post by email[/t]"><n.text/></n.default.></a>
-</macro>
-
-<macro name="post_by_email_path" requires="node">
-	<n.encode_url.>
-		/template/NamlServlet.jtp?macro=post_by_email_page&node=<n.id/>
-	</n.encode_url.>
-</macro>
-
 <macro name="edit_subject_and_message_link" requires="node" dot_parameter="text" parameters="title, class">
 	<a href="[n.edit_subject_and_message_path/]" class="[n.class/]" rel="nofollow" title="[n.title/]"><n.default. to="[t]Edit name & description[/t]"><n.text/></n.default.></a>
 </macro>
--- a/src/nabble/view/web/template/CompileTest.java	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/view/web/template/CompileTest.java	Fri Jun 11 09:43:51 2021 -0600
@@ -79,7 +79,7 @@
 		testModule("blackcow", HacksModule.INSTANCE, new String[] { "topic" });
 
 		logger.info("----- Languages -----");
-		String[] langMacros = new String[] { "topic", "view_app", "user_nodes", "send bookmark email", "post_by_email_page" };
+		String[] langMacros = new String[] { "topic", "view_app", "user_nodes", "send bookmark email" };
 		String[] langModules = new String[] { "lang_pt_br", "lang_ch_si", "lang_ch_tr", "lang_fr_fr", "lang_sv", "lang_es", "lang_cs_cz", "lang_ell", "lang_tu", "lang_pl", "lang_rus_ru" };
 		for (String lang : langModules) {
 			testModule(lang, langMacros);
--- a/src/nabble/view/web/template/NodeNamespace.java	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/view/web/template/NodeNamespace.java	Fri Jun 11 09:43:51 2021 -0600
@@ -833,18 +833,6 @@
 		}
 	}
 
-	public static final CommandSpec user_address = new CommandSpec.Builder()
-		.parameters("email")
-		.build()
-	;
-
-	@Command public void user_address(IPrintWriter out,Interpreter interp) {
-		Node node = node();
-		String email = interp.getArgString("email");
-		User user = node.getSite().getOrCreateUser(email);
-		out.print( user.getDecoratedAddress(node) );
-	}
-
 
 	@Command public void default_rows_per_page(IPrintWriter out,Interpreter interp) {
 		out.print( Jtp.getDefaultRowsPerPage(node().getType()) );
--- a/src/nabble/view/web/template/UserNamespace.java	Fri Jun 11 15:28:26 2021 +0300
+++ b/src/nabble/view/web/template/UserNamespace.java	Fri Jun 11 09:43:51 2021 -0600
@@ -213,20 +213,6 @@
 		out.print( nodeNs.node().getOwner().equals(person()) );
 	}
 
-    public static final CommandSpec reply_address_for = new CommandSpec.Builder()
-		.dotParameter("node")
-		.build()
-	;
-
-	@Command public void reply_address_for(IPrintWriter out,Interpreter interp) {
-		NodeNamespace nodeNs = interp.getArgAsNamespace(NodeNamespace.class,"node");
-		out.print( ModelHome.getNodeReplyAddress(nodeNs.node(), user()) );
-	}
-
-	@Command public void bounces_address(IPrintWriter out,Interpreter interp) {
-		out.print( ModelHome.getUserBouncesAddress(user()) );
-	}
-
 	public static final CommandSpec as_user_page = CommandSpec.DO;
 
 	@Command public void as_user_page(IPrintWriter out,ScopedInterpreter<UserPageNamespace> interp) {