0
|
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 }
|