comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:7ecd1a4ef557
1 package nabble.view.web.template;
2
3 import fschmidt.util.java.IoUtils;
4 import fschmidt.util.mail.AlternativeMultipartContent;
5 import fschmidt.util.mail.Content;
6 import fschmidt.util.mail.FileAttachmentContent;
7 import fschmidt.util.mail.HtmlTextContent;
8 import fschmidt.util.mail.Mail;
9 import fschmidt.util.mail.MailAddress;
10 import fschmidt.util.mail.MailHome;
11 import fschmidt.util.mail.MixedMultipartContent;
12 import fschmidt.util.mail.PlainTextContent;
13 import fschmidt.util.mail.TextAttachmentContent;
14 import fschmidt.util.mail.TextContent;
15 import nabble.model.FileUpload;
16 import nabble.model.ModelException;
17 import nabble.model.ModelHome;
18 import nabble.model.Node;
19 import nabble.naml.compiler.Command;
20 import nabble.naml.compiler.CommandSpec;
21 import nabble.naml.compiler.Encoder;
22 import nabble.naml.compiler.IPrintWriter;
23 import nabble.naml.compiler.Interpreter;
24 import nabble.naml.compiler.Namespace;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import java.io.ByteArrayInputStream;
29 import java.io.ByteArrayOutputStream;
30 import java.io.FilterInputStream;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.util.ArrayList;
34 import java.util.Date;
35 import java.util.List;
36 import java.util.zip.ZipEntry;
37 import java.util.zip.ZipOutputStream;
38
39
40 @Namespace(
41 name = "email",
42 global = true,
43 transparent = true
44 )
45 public final class EmailNamespace {
46 private static final Logger logger = LoggerFactory.getLogger(EmailNamespace.class);
47
48 private Mail mail = MailHome.newMail();
49 List<Content> attachments = new ArrayList<Content>();
50
51 public static final CommandSpec set_header = CommandSpec.NO_OUTPUT()
52 .parameters("name", "value")
53 .build();
54
55 @Command public void set_header(IPrintWriter out, Interpreter interp) {
56 String name = interp.getArgString("name");
57 String value = interp.getArgString("value");
58 mail.setHeader(name, value);
59 }
60
61 public static final CommandSpec add_text_attachment = CommandSpec.DO()
62 .parameters("subtype", "text", "filename")
63 .build();
64
65 @Command public void add_text_attachment(IPrintWriter out, Interpreter interp) {
66 interp.setEncoder(Encoder.TEXT);
67 String subtype = interp.getArgString("subtype");
68 String text = interp.getArgString("text");
69 String filename = interp.getArgString("filename");
70 attachments.add(new TextAttachmentContent(subtype, text, filename));
71 }
72
73 public static final CommandSpec add_node_as_zip_attachment = CommandSpec.DO()
74 .parameters("node_attr")
75 .dotParameter("node_attr")
76 .build();
77
78 @Command public void add_node_as_zip_attachment(IPrintWriter out, Interpreter interp) {
79 NodeNamespace nn = interp.getArgAsNamespace(NodeNamespace.class, "node_attr");
80 final String filename = nn.node().getSubject() + ".zip";
81 final InputStream zippedNode = buildZip(nn.node());
82 FileAttachmentContent content = new FileAttachmentContent("application", "octet-stream") {
83 public String getFileName() { return filename; }
84 public int getSize() { return -1; }
85 public InputStream getInputStream() { return zippedNode; }
86 public String getContentID() { return null; }
87 };
88 attachments.add(content);
89 }
90
91 public static final CommandSpec send = new CommandSpec.Builder()
92 .parameters("to", "subject", "text_part")
93 .optionalParameters("cc", "bcc", "to_name", "from", "from_name", "html_part", "aol_part", "set_headers_for", "bounce_to", "attachments")
94 .build();
95
96 @Command public void send(IPrintWriter out, Interpreter interp)
97 throws ModelException.EmailFormat
98 {
99 interp.setEncoder(Encoder.TEXT);
100 String to = interp.getArgString("to");
101 if (to == null || !new MailAddress(to).isValid())
102 throw new ModelException.EmailFormat(to);
103
104 String cc = interp.getArgString("cc");
105 if (cc != null && !new MailAddress(cc).isValid())
106 throw new ModelException.EmailFormat(cc);
107
108 String bcc = interp.getArgString("bcc");
109 if (bcc != null && !new MailAddress(bcc).isValid())
110 throw new ModelException.EmailFormat(bcc);
111
112 String fromName = interp.getArgString("from_name");
113 String from = interp.getArgString("from");
114
115 MailAddress fromAddress = from == null ?
116 new MailAddress(ModelHome.noReply, fromName == null ? "Nabble" : fromName) :
117 fromName == null ? new MailAddress(from) : new MailAddress(from, fromName);
118
119 String subject = interp.getArgString("subject");
120 String text = interp.getArgString("text_part");
121 String aol = interp.getArgString("aol_part");
122 interp.setEncoder(Encoder.HTML);
123 String html = interp.getArgString("html_part");
124 interp.setEncoder(Encoder.TEXT);
125
126 String toName = interp.getArgString("to_name");
127 MailAddress toAddress = toName == null ? new MailAddress(to) : new MailAddress(to, toName);
128
129 NodeNamespace nodeNs = interp.getArgAsNamespace(NodeNamespace.class, "set_headers_for");
130 if (nodeNs != null)
131 ModelHome.setNodeHeaders(mail, nodeNs.node());
132
133 mail.setFrom(fromAddress);
134 mail.setTo(toAddress);
135 if (cc != null)
136 mail.setCc(new MailAddress(cc));
137 if (bcc != null)
138 mail.setBcc(new MailAddress(bcc));
139 mail.setSubject(subject);
140 mail.setSentDate(new Date());
141
142 List<Content> alternatives = new ArrayList<Content>();
143 alternatives.add( new PlainTextContent(text) );
144 if( aol != null )
145 alternatives.add( new TextContent("x-aol",aol) );
146 if( html != null )
147 alternatives.add( new HtmlTextContent(html) );
148
149 setMailContents(alternatives);
150
151 String bounceTo = interp.getArgString("bounce_to");
152 if (bounceTo == null)
153 ModelHome.send(mail);
154 else
155 ModelHome.send(mail, bounceTo);
156 }
157
158 private void setMailContents(List<Content> alternatives) {
159 Content body = alternatives.size()==1 ? alternatives.get(0)
160 : new AlternativeMultipartContent(alternatives.toArray(new Content[alternatives.size()]));
161 boolean hasAttachments = attachments != null && attachments.size() > 0;
162 if( !hasAttachments ) {
163 mail.setContent(body);
164 } else {
165 List<Content> contents = new ArrayList<Content>();
166 contents.add(body);
167 for (Content c : attachments) {
168 contents.add(c);
169 }
170 Content[] contentArray = contents.toArray(new Content[contents.size()]);
171 mail.setContent(new MixedMultipartContent(contentArray));
172 }
173 }
174
175 private static InputStream buildZip(final Node node) {
176 return new FilterInputStream(null) {
177
178 @Override public int read(byte b[], int off, int len) throws IOException {
179 checkIn();
180 return super.read(b,off,len);
181 }
182
183 @Override public void close() throws IOException {
184 checkIn();
185 super.close();
186 }
187
188 private void checkIn() {
189 if( in == null ) {
190 ByteArrayOutputStream baos = new ByteArrayOutputStream();
191 ZipOutputStream zout = new ZipOutputStream(baos);
192 try {
193 zout.putNextEntry(new ZipEntry(node.getId() + ".txt"));
194 zout.write(node.getMessage().getRaw().getBytes());
195
196 FileUpload.FileDetails[] details = FileUpload.getFiles(node);
197 for (FileUpload.FileDetails d : details) {
198 String filename = d.getName();
199 InputStream is = FileUpload.getFileContent(node, filename);
200 try {
201 byte[] contents = IoUtils.readAll(is);
202 zout.putNextEntry(new ZipEntry(filename));
203 zout.write(contents);
204 } finally {
205 is.close();
206 }
207 }
208 zout.close();
209 } catch (IOException e) {
210 throw new RuntimeException(e);
211 }
212 in = new ByteArrayInputStream(baos.toByteArray());
213 }
214 }
215 };
216 }
217 }