diff src/nabble/view/web/template/EmailNamespace.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children 72765b66e2c3
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/nabble/view/web/template/EmailNamespace.java	Thu Mar 21 19:15:52 2019 -0600
@@ -0,0 +1,217 @@
+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", "set_headers_for", "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);
+
+		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)
+			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());
+				}
+			}
+		};
+	}
+}