Mercurial Hosting > nabble
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()); + } + } + }; + } +}