view src/nabble/view/web/template/EmailNamespace.java @ 47:72765b66e2c3

remove mailing list code
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 18 Jun 2021 17:44:24 -0600
parents 7ecd1a4ef557
children f7665d62c5cd
line wrap: on
line source

package nabble.view.web.template;

import fschmidt.util.java.IoUtils;
import fschmidt.util.mail.AlternativeMultipartContent;
import fschmidt.util.mail.Content;
import fschmidt.util.mail.FileAttachmentContent;
import fschmidt.util.mail.HtmlTextContent;
import fschmidt.util.mail.Mail;
import fschmidt.util.mail.MailAddress;
import fschmidt.util.mail.MailHome;
import fschmidt.util.mail.MixedMultipartContent;
import fschmidt.util.mail.PlainTextContent;
import fschmidt.util.mail.TextAttachmentContent;
import fschmidt.util.mail.TextContent;
import nabble.model.FileUpload;
import nabble.model.ModelException;
import nabble.model.ModelHome;
import nabble.model.Node;
import nabble.naml.compiler.Command;
import nabble.naml.compiler.CommandSpec;
import nabble.naml.compiler.Encoder;
import nabble.naml.compiler.IPrintWriter;
import nabble.naml.compiler.Interpreter;
import nabble.naml.compiler.Namespace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


@Namespace(
		name = "email",
		global = true,
		transparent = true
)
public final class EmailNamespace {
	private static final Logger logger = LoggerFactory.getLogger(EmailNamespace.class);

	private Mail mail = MailHome.newMail();
	List<Content> attachments = new ArrayList<Content>();

	public static final CommandSpec set_header = CommandSpec.NO_OUTPUT()
		.parameters("name", "value")
		.build();

	@Command public void set_header(IPrintWriter out, Interpreter interp) {
		String name = interp.getArgString("name");
		String value = interp.getArgString("value");
		mail.setHeader(name, value);
	}

	public static final CommandSpec add_text_attachment = CommandSpec.DO()
		.parameters("subtype", "text", "filename")
		.build();

	@Command public void add_text_attachment(IPrintWriter out, Interpreter interp) {
		interp.setEncoder(Encoder.TEXT);
		String subtype = interp.getArgString("subtype");
		String text = interp.getArgString("text");
		String filename = interp.getArgString("filename");
		attachments.add(new TextAttachmentContent(subtype, text, filename));
	}

	public static final CommandSpec add_node_as_zip_attachment = CommandSpec.DO()
		.parameters("node_attr")
		.dotParameter("node_attr")
		.build();

	@Command public void add_node_as_zip_attachment(IPrintWriter out, Interpreter interp) {
		NodeNamespace nn = interp.getArgAsNamespace(NodeNamespace.class, "node_attr");
		final String filename = nn.node().getSubject() + ".zip";
		final InputStream zippedNode = buildZip(nn.node());
		FileAttachmentContent content = new FileAttachmentContent("application", "octet-stream") {
			public String getFileName() { return filename; }
			public int getSize() { return -1; }
			public InputStream getInputStream() { return zippedNode; }
			public String getContentID() { return null; }
		};
		attachments.add(content);
	}

	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", "bounce_to", "attachments")
		.build();

	@Command public void send(IPrintWriter out, Interpreter interp)
			throws ModelException.EmailFormat
	{
		interp.setEncoder(Encoder.TEXT);
		String to = interp.getArgString("to");
		if (to == null || !new MailAddress(to).isValid())
			throw new ModelException.EmailFormat(to);

		String cc = interp.getArgString("cc");
		if (cc != null && !new MailAddress(cc).isValid())
			throw new ModelException.EmailFormat(cc);

		String bcc = interp.getArgString("bcc");
		if (bcc != null && !new MailAddress(bcc).isValid())
			throw new ModelException.EmailFormat(bcc);

		String fromName = interp.getArgString("from_name");
		String from = interp.getArgString("from");

		MailAddress fromAddress = from == null ?
				new MailAddress(ModelHome.noReply, fromName == null ? "Nabble" : fromName) :
				fromName == null ? new MailAddress(from) : new MailAddress(from, fromName);

		String subject = interp.getArgString("subject");
		String text = interp.getArgString("text_part");
		String aol = interp.getArgString("aol_part");
		interp.setEncoder(Encoder.HTML);
		String html = interp.getArgString("html_part");
		interp.setEncoder(Encoder.TEXT);

		String toName = interp.getArgString("to_name");
		MailAddress toAddress = toName == null ? new MailAddress(to) : new MailAddress(to, toName);

		mail.setFrom(fromAddress);
		mail.setTo(toAddress);
		if (cc != null)
			mail.setCc(new MailAddress(cc));
		if (bcc != null)
			mail.setBcc(new MailAddress(bcc));
		mail.setSubject(subject);
		mail.setSentDate(new Date());

		List<Content> alternatives = new ArrayList<Content>();
		alternatives.add( new PlainTextContent(text) );
		if( aol != null )
			alternatives.add( new TextContent("x-aol",aol) );
		if( html != null )
			alternatives.add( new HtmlTextContent(html) );

		setMailContents(alternatives);

		String bounceTo = interp.getArgString("bounce_to");
		if (bounceTo == null)
			ModelHome.send(mail);
		else
			ModelHome.send(mail, bounceTo);
	}

	private void setMailContents(List<Content> alternatives) {
		Content body = alternatives.size()==1 ? alternatives.get(0)
				: new AlternativeMultipartContent(alternatives.toArray(new Content[alternatives.size()]));
		boolean hasAttachments = attachments != null && attachments.size() > 0;
		if( !hasAttachments ) {
			mail.setContent(body);
		} else {
			List<Content> contents = new ArrayList<Content>();
			contents.add(body);
			for (Content c : attachments) {
				contents.add(c);
			}
			Content[] contentArray = contents.toArray(new Content[contents.size()]);
			mail.setContent(new MixedMultipartContent(contentArray));
		}
	}

	private static InputStream buildZip(final Node node) {
		return new FilterInputStream(null) {

			@Override public int read(byte b[], int off, int len) throws IOException {
				checkIn();
				return super.read(b,off,len);
			}

			@Override public void close() throws IOException {
				checkIn();
				super.close();
			}

			private void checkIn() {
				if( in == null ) {
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					ZipOutputStream zout = new ZipOutputStream(baos);
					try {
						zout.putNextEntry(new ZipEntry(node.getId() + ".txt"));
						zout.write(node.getMessage().getRaw().getBytes());

						FileUpload.FileDetails[] details = FileUpload.getFiles(node);
						for (FileUpload.FileDetails d : details) {
							String filename = d.getName();
							InputStream is = FileUpload.getFileContent(node, filename);
							try {
								byte[] contents = IoUtils.readAll(is);
								zout.putNextEntry(new ZipEntry(filename));
								zout.write(contents);
							} finally {
								is.close();
							}
						}
						zout.close();
					} catch (IOException e) {
						throw new RuntimeException(e);
					}
					in = new ByteArrayInputStream(baos.toByteArray());
				}
			}
		};
	}
}