001 package com.saelist.command;
002
003 import org.apache.log4j.*;
004 import java.io.*;
005 import java.net.*;
006 import java.util.*;
007 import com.saelist.stx.*;
008 import com.saelist.stx.parser.*;
009 import com.saelist.util.*;
010
011 import javax.mail.*;
012 import javax.mail.internet.*;
013 import javax.activation.*;
014
015 /**
016 Sends messages in a structured text file to email recipients.
017 * See the schema file for exact format of the message file.
018 */
019 public class SmtpCommand extends AbstractCommand {
020
021 protected static Logger logger = Logger.getLogger("com.saelist.command.SmtpCommand");
022
023 /**
024 *
025 */
026 public void execute() throws CommandException {
027
028 Writer sentbox = null;
029 Writer problembox = null;
030
031 try {
032
033 Properties props = System.getProperties();
034 props.put("file.encoding", "UTF-8");
035 props.put("mail.smtp.host", config.eval("smpt/host"));
036 Session session = Session.getDefaultInstance(props, null);
037 session.setDebug("true".equals(config.eval("smtp/debug")));
038
039 // Add any messages in outbox to config.
040
041 if(config.select1("storage/out-box") != null) {
042 Pair outbox = LstxParser.parse(Strings.loadFile(config.eval1("storage/out-box")));
043 // System.out.println("outbox=" + outbox);
044 for(Iterator messages = outbox.select("message"); messages.hasNext(); )
045 config.add(((Pair) messages.next()).copy());
046 }
047
048 // Open the sentbox and the problem box if specified.
049
050 if(config.select1("storage/sent-box") != null)
051 sentbox = new BufferedWriter(new FileWriter(config.eval1("storage/sent-box")));
052 if(config.select1("storage/problem-box") != null)
053 problembox = new BufferedWriter(new FileWriter(config.eval1("storage/problem-box")));
054
055 // Send each message.
056
057 for(Iterator messages = config.select("message"); messages.hasNext(); ) {
058 Exception exception = null;
059 Pair message = (Pair) messages.next();
060 try {
061 MimeMessage mimeMessage = new MimeMessage(session);
062 mimeMessage.setFrom(new InternetAddress(message.eval("from")));
063 addAddresses(mimeMessage, Message.RecipientType.TO, message.select("to/*"));
064 addAddresses(mimeMessage, Message.RecipientType.CC, message.select("cc/*"));
065 addAddresses(mimeMessage, Message.RecipientType.BCC, message.select("bcc/*"));
066 mimeMessage.setSubject(message.eval("subject"), "UTF-8");
067 mimeMessage.setContent(createContent(message));
068 mimeMessage.setSentDate(new Date());
069 mimeMessage.setHeader("X-Mailer", getClass().getName());
070
071 Transport.send(mimeMessage);
072
073
074 if(sentbox != null)
075 store(sentbox, message);
076
077 } catch(AddressException e) {
078 exception = e;
079 } catch(MessagingException e) {
080 exception = e;
081 } catch(UnsupportedEncodingException e) {
082 exception = e;
083 }
084
085 //Log any message level problem and store a failed message in the problem box.
086
087 if(exception != null) {
088 logger.error(exception);
089 if(problembox != null) {
090 Pair msg = message.copy();
091 Pair status = new Pair(message, "status");
092 Pair value = new Pair(status, exception.toString());
093 status.add(value);
094 msg.add(status);
095 store(problembox, msg);
096 }
097 }
098 }
099
100 } catch(IOException e) {
101
102 // Let the caller handle session level problems.
103 throw new CommandException(e);
104
105 } finally {
106 try {
107 if(sentbox != null) {
108 sentbox.flush();
109 sentbox.close();
110 }
111 if(problembox != null) {
112 problembox.flush();
113 problembox.close();
114 }
115 } catch(IOException e) {
116 throw new CommandException(e);
117 }
118 }
119 }
120
121 private void store(Writer box, Pair message) throws IOException {
122 Pair root = new Pair(null, "root");
123 root.add(message.copy());
124 LstxParser.unParse(box, root);
125 }
126
127 private void addAddresses(MimeMessage mimeMessage, Message.RecipientType type, Iterator recipients) throws AddressException, MessagingException {
128 while(recipients.hasNext())
129 mimeMessage.addRecipients(type, InternetAddress.parse(((Pair) recipients.next()).getText()));
130 }
131
132 private Multipart createContent(Pair message) throws UnsupportedEncodingException, MessagingException {
133
134 Multipart multipart = new MimeMultipart();
135
136 // Add the body text
137
138 MimeBodyPart part = new MimeBodyPart();
139
140 if("true".equals(message.eval("is-html"))) {
141 part.setContent(concat(message.select("text/*")), "text/html;charset=UTF-8");
142 part.setHeader("Content-Type", "text/html;charset=UTF-8");
143 part.setHeader("Content-Transfer-Encoding", "8bit");
144 } else
145 part.setText(concat(message.select("text/*")), "UTF-8");
146
147 multipart.addBodyPart(part);
148
149 // Add the attachements
150
151 for(Iterator attatchments = message.select("attachment/*"); attatchments.hasNext(); ) {
152 String attachment = ((Pair) attatchments.next()).getText();
153 File file = new File(attachment);
154 part = new MimeBodyPart();
155 DataSource source = new FileDataSource(attachment);
156 part.setDataHandler(new DataHandler(source));
157 // part.setHeader("Content-Type", "applications/msword");
158 part.setFileName(file.getName());
159 multipart.addBodyPart(part);
160 }
161
162 return multipart;
163
164 }
165
166 /** Concatenate the texts of the incoming pairs separating with linefeeds. */
167 private String concat(Iterator lines) {
168 String text = "";
169 while(lines.hasNext())
170 text += ((Pair) lines.next()).getText() + "\n";
171 return text;
172 }
173
174 }