001: /*
002: * Copyright 2005-2007 Noelios Consulting.
003: *
004: * The contents of this file are subject to the terms of the Common Development
005: * and Distribution License (the "License"). You may not use this file except in
006: * compliance with the License.
007: *
008: * You can obtain a copy of the license at
009: * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
010: * language governing permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL HEADER in each file and
013: * include the License file at http://www.opensource.org/licenses/cddl1.txt If
014: * applicable, add the following below this CDDL HEADER, with the fields
015: * enclosed by brackets "[]" replaced with your own identifying information:
016: * Portions Copyright [yyyy] [name of copyright owner]
017: */
018:
019: package com.noelios.restlet.ext.javamail;
020:
021: import java.io.IOException;
022: import java.net.URI;
023: import java.net.URISyntaxException;
024: import java.util.Date;
025: import java.util.Properties;
026: import java.util.logging.Level;
027:
028: import javax.mail.Message;
029: import javax.mail.MessagingException;
030: import javax.mail.NoSuchProviderException;
031: import javax.mail.Session;
032: import javax.mail.Transport;
033: import javax.mail.internet.AddressException;
034: import javax.mail.internet.InternetAddress;
035: import javax.mail.internet.MimeMessage;
036: import javax.xml.parsers.DocumentBuilder;
037: import javax.xml.parsers.DocumentBuilderFactory;
038: import javax.xml.parsers.ParserConfigurationException;
039:
040: import org.restlet.Client;
041: import org.restlet.data.Method;
042: import org.restlet.data.Protocol;
043: import org.restlet.data.Request;
044: import org.restlet.data.Response;
045: import org.restlet.resource.Representation;
046: import org.w3c.dom.Document;
047: import org.w3c.dom.Element;
048: import org.w3c.dom.NodeList;
049: import org.xml.sax.SAXException;
050:
051: import com.noelios.restlet.ClientHelper;
052: import com.noelios.restlet.Engine;
053:
054: /**
055: * Client connector to a mail server. Currently only the SMTP protocol is
056: * supported. To send an email, specify a SMTP URI as the ressource reference of
057: * the call and use an XML email as the content of the call. An SMTP URI has the
058: * following syntax: smtp://host[:port]<br/> <br/> The default port used is 25
059: * for SMTP and 465 for SMTPS. Use the Call.getSecurity().setLogin() and
060: * setPassword() methods for authentication.<br/> <br/> Sample XML email:<br/>
061: * {@code <?xml version="1.0" encoding="ISO-8859-1" ?>}<br/> {@code <email>}<br/>
062: * {@code <head>}<br/> {@code <subject>Account activation</subject>}<br/>
063: * {@code <from>support@restlet.org</from>}<br/>
064: * {@code <to>user@domain.com</to>}<br/>
065: * {@code <cc>log@restlet.org</cc>}<br/>
066: * {@code </head>}<br/> {@code <body><![CDATA[Your account was sucessfully created!]]></body>}<br/>
067: * {@code </email>}
068: *
069: * @author Jerome Louvel (contact@noelios.com)
070: */
071: public class JavaMailClientHelper extends ClientHelper {
072: /**
073: * Constructor.
074: *
075: * @param client
076: * The client to help.
077: */
078: public JavaMailClientHelper(Client client) {
079: super (client);
080: getProtocols().add(Protocol.SMTP);
081: getProtocols().add(Protocol.SMTP_STARTTLS);
082: getProtocols().add(Protocol.SMTPS);
083: }
084:
085: /**
086: * Creates a high-level request.
087: *
088: * @param smtpURI
089: * The SMTP server's URI (ex: smtp://localhost).
090: * @param email
091: * The email to send (valid XML email).
092: * @param login
093: * Authenticate using this login name.
094: * @param password
095: * Authenticate using this password.
096: */
097: public static Request create(String smtpURI, Representation email,
098: String login, String password) {
099: Request result = create(smtpURI, email);
100: result.getAttributes().put("login", login);
101: result.getAttributes().put("password", password);
102: return result;
103: }
104:
105: /**
106: * Creates a high-level request.
107: *
108: * @param smtpURI
109: * The SMTP server's URI (ex: smtp://localhost).
110: * @param email
111: * The email to send (valid XML email).
112: */
113: public static Request create(String smtpURI, Representation email) {
114: Request result = new Request();
115: result.getClientInfo().setAgent(Engine.VERSION_HEADER);
116: result.setMethod(Method.POST);
117: result.setResourceRef(smtpURI);
118: result.setEntity(email);
119: return result;
120: }
121:
122: /**
123: * Handles a call.
124: *
125: * @param request
126: * The request to handle.
127: * @param response
128: * The response to update.
129: */
130: public void handle(Request request, Response response) {
131: try {
132: // Parse the SMTP URI
133: URI smtpURI = new URI(request.getResourceRef().toString());
134: String smtpHost = smtpURI.getHost();
135: int smtpPort = smtpURI.getPort();
136: // String smtpUserInfo = smtpURI.getUserInfo();
137:
138: Protocol defaultProtocol = getClient().getProtocols()
139: .get(0);
140:
141: if (defaultProtocol != null) {
142: if (smtpPort == -1) {
143: if ((defaultProtocol.equals(Protocol.SMTP))
144: || (defaultProtocol
145: .equals(Protocol.SMTP_STARTTLS))) {
146: // Use the default SMTP port
147: smtpPort = 25;
148: } else if (defaultProtocol.equals(Protocol.SMTPS)) {
149: smtpPort = 465;
150: }
151: }
152:
153: if ((smtpHost == null) || (smtpHost.equals(""))) {
154: throw new IllegalArgumentException(
155: "Invalid SMTP host specified");
156: }
157:
158: // Parse the email to extract necessary info
159: DocumentBuilder docBuilder = DocumentBuilderFactory
160: .newInstance().newDocumentBuilder();
161: Document email = docBuilder.parse(request.getEntity()
162: .getStream());
163:
164: Element root = (Element) email.getElementsByTagName(
165: "email").item(0);
166: Element header = (Element) root.getElementsByTagName(
167: "head").item(0);
168: String subject = header.getElementsByTagName("subject")
169: .item(0).getTextContent();
170: String from = header.getElementsByTagName("from").item(
171: 0).getTextContent();
172:
173: NodeList toList = header.getElementsByTagName("to");
174: String[] to = new String[toList.getLength()];
175: for (int i = 0; i < toList.getLength(); i++) {
176: to[i] = toList.item(i).getTextContent();
177: }
178:
179: NodeList ccList = header.getElementsByTagName("cc");
180: String[] cc = new String[ccList.getLength()];
181: for (int i = 0; i < ccList.getLength(); i++) {
182: cc[i] = ccList.item(i).getTextContent();
183: }
184:
185: NodeList bccList = header.getElementsByTagName("bcc");
186: String[] bcc = new String[bccList.getLength()];
187: for (int i = 0; i < bccList.getLength(); i++) {
188: bcc[i] = bccList.item(i).getTextContent();
189: }
190:
191: String text = root.getElementsByTagName("body").item(0)
192: .getTextContent();
193:
194: // Prepare the connection to the SMTP server
195: Session session = null;
196: Transport transport = null;
197: Properties props = System.getProperties();
198:
199: // Check if authentication required
200: boolean authenticate = ((getLogin(request) != null) && (getPassword(request) != null));
201:
202: // Connect to the SMTP server
203: if (defaultProtocol.equals(Protocol.SMTP)
204: || defaultProtocol
205: .equals(Protocol.SMTP_STARTTLS)) {
206: props.put("mail.smtp.host", smtpHost);
207: props.put("mail.smtp.port", Integer
208: .toString(smtpPort));
209: props.put("mail.smtp.auth", Boolean.toString(
210: authenticate).toLowerCase());
211: props
212: .put(
213: "mail.smtp.starttls.enable",
214: Boolean
215: .toString(
216: getClient()
217: .getProtocols()
218: .get(0)
219: .equals(
220: Protocol.SMTP_STARTTLS))
221: .toLowerCase());
222: session = Session.getDefaultInstance(props);
223: // session.setDebug(true);
224: transport = session.getTransport("smtp");
225: } else if (defaultProtocol.equals(Protocol.SMTPS)) {
226: props.put("mail.smtps.host", smtpHost);
227: props.put("mail.smtps.port", Integer
228: .toString(smtpPort));
229: props.put("mail.smtps.auth", Boolean.toString(
230: authenticate).toLowerCase());
231: session = Session.getDefaultInstance(props);
232: // session.setDebug(true);
233: transport = session.getTransport("smtps");
234: }
235:
236: if (transport != null) {
237: // Check if authentication is needed
238: if (authenticate) {
239: transport.connect(smtpHost, getLogin(request),
240: getPassword(request));
241: } else {
242: transport.connect();
243: }
244:
245: // Actually send the message
246: if (transport.isConnected()) {
247: getLogger()
248: .info(
249: "JavaMail client connection successfully established. Attempting to send the message");
250:
251: // Create a new message
252: Message msg = new MimeMessage(session);
253:
254: // Set the FROM and TO fields
255: msg.setFrom(new InternetAddress(from));
256:
257: for (String element : to) {
258: msg.addRecipient(Message.RecipientType.TO,
259: new InternetAddress(element));
260: }
261:
262: for (String element : cc) {
263: msg.addRecipient(Message.RecipientType.CC,
264: new InternetAddress(element));
265: }
266:
267: for (String element : bcc) {
268: msg.addRecipient(Message.RecipientType.BCC,
269: new InternetAddress(element));
270: }
271:
272: // Set the subject and content text
273: msg.setSubject(subject);
274: msg.setText(text);
275: msg.setSentDate(new Date());
276: msg.saveChanges();
277:
278: // Send the message
279: transport.sendMessage(msg, msg
280: .getAllRecipients());
281: transport.close();
282:
283: getLogger()
284: .info(
285: "JavaMail client successfully sent the message.");
286: }
287: }
288: }
289: } catch (IOException e) {
290: getLogger().log(Level.WARNING, "JavaMail client error", e);
291: } catch (NoSuchProviderException e) {
292: getLogger().log(Level.WARNING, "JavaMail client error", e);
293: } catch (AddressException e) {
294: getLogger().log(Level.WARNING, "JavaMail client error", e);
295: } catch (MessagingException e) {
296: getLogger().log(Level.WARNING, "JavaMail client error", e);
297: } catch (SAXException e) {
298: getLogger().log(Level.WARNING, "JavaMail client error", e);
299: } catch (URISyntaxException e) {
300: getLogger().log(Level.WARNING, "JavaMail client error", e);
301: } catch (ParserConfigurationException e) {
302: getLogger().log(Level.WARNING, "JavaMail client error", e);
303: }
304:
305: }
306:
307: /**
308: * Returns the login stored as an attribute.
309: *
310: * @param request
311: * The high-level request.
312: * @return The high-level request.
313: */
314: private String getLogin(Request request) {
315: return (String) request.getAttributes().get("login");
316: }
317:
318: /**
319: * Returns the password stored as an attribute.
320: *
321: * @param request
322: * The high-level request.
323: * @return The high-level request.
324: */
325: private String getPassword(Request request) {
326: return (String) request.getAttributes().get("password");
327: }
328:
329: }
|