All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sunlabs.brazil.handler.SMTPHandler Maven / Gradle / Ivy

The newest version!
/*
 * SMTPHandler.java
 *
 * Brazil project web application toolkit,
 * export version: 2.3 
 * Copyright (c) 2000-2007 Sun Microsystems, Inc.
 *
 * Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License Version 
 * 1.0 (the "License"). You may not use this file except in compliance with 
 * the License. A copy of the License is included as the file "license.terms",
 * and also available at http://www.sun.com/
 * 
 * The Original Code is from:
 *    Brazil project web application toolkit release 2.3.
 * The Initial Developer of the Original Code is: suhler.
 * Portions created by suhler are Copyright (C) Sun Microsystems, Inc.
 * All Rights Reserved.
 * 
 * Contributor(s): cstevens, suhler.
 *
 * Version:  2.9
 * Created by suhler on 00/01/11
 * Last modified by suhler on 07/01/29 15:36:24
 *
 * Version Histories:
 *
 * 2.9 07/01/29-15:36:24 (suhler)
 *   remove unused imports
 *
 * 2.8 06/11/13-15:04:29 (suhler)
 *   move MatchString to package "util" from "handler"
 *
 * 2.7 06/01/06-16:41:31 (suhler)
 *   bug fix: always pass in Server, for detailed debugging, rework  stuff
 *
 * 2.6 05/12/23-19:53:32 (suhler)
 *   eliminate bogus warning
 *
 * 2.5 05/01/11-09:56:31 (suhler)
 *   don't look for param tags outside of   ... 
 *
 * 2.4 04/10/28-12:47:51 (suhler)
 *   doc fixes
 *
 * 2.3 04/10/27-13:33:45 (suhler)
 *   - better documentation
 *   - better diagnostics
 *
 * 2.2 03/08/01-16:18:11 (suhler)
 *   fixes for javadoc
 *
 * 2.1 02/10/01-16:36:28 (suhler)
 *   version change
 *
 * 1.18 02/05/01-11:22:02 (suhler)
 *   fix sccs version info
 *
 * 1.17 02/04/25-14:08:31 (suhler)
 *   don't re-check server connection when used as a template
 *
 * 1.16 02/03/06-09:15:41 (suhler)
 *   don't "ping" email server on each template page
 *
 * 1.15 01/11/21-11:42:46 (suhler)
 *   doc fixes
 *
 * 1.14 01/08/14-16:37:57 (suhler)
 *   doc lint
 *
 * 1.13 01/07/23-15:52:17 (suhler)
 *   Use StringMaps instead of Hashtables to preserver header order.
 *
 * 1.12 01/07/20-12:05:51 (suhler)
 *   Stupid typo (that any reasonable test woul'a caught).
 *
 * 1.11 01/07/20-11:32:17 (suhler)
 *   MatchUrl -> MatchString
 *
 * 1.10 01/07/17-14:16:04 (suhler)
 *   use MatchUrl
 *
 * 1.9 01/07/16-16:44:58 (suhler)
 *   use new template convenience methods
 *
 * 1.8 01/07/12-14:25:12 (suhler)
 *   added the capability to do:
 *   
 *    ...
 *   
 *   to add additional email headers.
 *
 * 1.7 01/06/29-11:24:41 (suhler)
 *   May also function as a template for sending email
 *
 * 1.6 01/01/14-14:51:10 (suhler)
 *   stupif bug
 *
 * 1.5 00/12/11-13:28:31 (suhler)
 *   add class=props for automatic property extraction
 *
 * 1.4 00/07/07-17:01:47 (suhler)
 *   remove System.out.println(s)
 *
 * 1.3 00/05/31-13:47:35 (suhler)
 *   doc cleanup
 *
 * 1.2 00/04/20-11:50:27 (cstevens)
 *   copyright.
 *
 * 1.2 70/01/01-00:00:02 (Codemgr)
 *   SunPro Code Manager data about conflicts, renames, etc...
 *   Name history : 1 0 handlers/SMTPHandler.java
 *
 * 1.1 00/01/11-10:41:08 (suhler)
 *   date and time created 00/01/11 10:41:08 by suhler
 *
 */

package sunlabs.brazil.handler;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Hashtable;
import java.util.StringTokenizer;
import sunlabs.brazil.server.Handler;
import sunlabs.brazil.server.Request;
import sunlabs.brazil.server.Server;
import sunlabs.brazil.util.MatchString;
import sunlabs.brazil.util.StringMap;

import sunlabs.brazil.template.RewriteContext;
import sunlabs.brazil.template.Template;

/**
 * Handler (or template) for Sending an email message via SMTP.
 * The following server properties are used:
 * 
*
prefix, suffix, glob, match *
Specify the URL that triggers this handler. * (See {@link MatchString}). *
host
The mail host (e.g. listening on the SMTP port). * Defaults to "localhost". *
*

* Template to send an email message via SMTP. *

* The <sendmail> tag looks for the attributes: *
*
to
The message recipient(s) [required] * Recipients are be delimited by one or more * commas (,), spaces or tabs. * This is the actual destination list. If "To:" headers are * desired, they should be incorporated using * <param> tags (see below). *
from
The originator [required] *
body
The text message [optional] *
subject
The subject [optional] *
* If an error occurred communicating with the smtp server, * the property [prefix].error will contain the * error message. *

* There are 2 ways of using the sendmail template: *

    *
  1. <sendmail from=... to=... body=... subject=... /> *
  2. <sendmail from=... to=... body=... subject=... > *
    <param name=... value=... > *
    ... *
    <param name=... value=... > * </sendmail> *
* The second method is useful when additonal email headers are * required. Each param tag adds an additional header * to the email message. There may be multiple headers of the same * name, and their order is preserved. *

* When a singleton tag is used, * the To: header is filled in to match the actual * recipients. * If you need to specify cc, bcc, or other * mail headers use param tags. *

* Note:
* The to attribute, which is required, * specifies the actual recipients. When to is specified * as part of a param tag, it is the recipient list presented * to the email recipient, which may have nothing to do wih the actual * recipients. In the singleton case, they are made the same. *

* Send an email message based on the query data *

*

* Query parameters: *

*
to
To address. Multible addresses should be delimited * by spaces or commas. *
from
From address *
message
Message *
subject
Subject *
* Either the message or subject may be null, but not both. * * @author Stephen Uhler * @version @(#)SMTPHandler.java 2.9 */ public class SMTPHandler extends Template implements Handler { String mailHost; // host with smtp listener String me; // my host name MatchString isMine; // check for matching url boolean checkConnection = true; boolean inSendmail; // are we in the scope of a sendmail tag? public boolean init(Server server, String prefix) { mailHost = server.props.getProperty(prefix + "host", "localhost"); me = server.hostName; isMine = new MatchString(prefix, server.props); inSendmail=false; /* * Make sure we can communicate with the host */ if (checkConnection) { try { Socket sock = new Socket(mailHost,25); DataInputStream in = new DataInputStream( new BufferedInputStream(sock.getInputStream())); String line = in.readLine(); in.close(); sock.close(); server.log(Server.LOG_DIAGNOSTIC, prefix, line); if (line.startsWith("220")) { return true; } else { return false; } } catch (IOException e) { server.log(Server.LOG_WARNING, prefix, "Can't contanct SMTP server: " + e); return false; } } else { return true; } } public boolean respond(Request request) throws IOException { if (!isMine.match(request.url)) { return false; } Hashtable data = request.getQueryData(); Hashtable subj = new Hashtable(1); String to = (String) data.get("to"); String from = (String) data.get("from"); String subject = (String) data.get("subject"); String message = (String) data.get("message"); if (to==null || from==null || (subject==null && message==null)) { request.sendError(400, "Missing query parameters"); return true; } if (subject == null) { subject = "(none)"; } subj.put("subject", subject); smtp(me, mailHost, from, to, message, headers, request.server); request.props.put(mailHost, "sent"); // ?? return false; } String to; String from; String body; String subject; StringMap headers; boolean sent; public boolean init(RewriteContext hr) { checkConnection = false; sent = true; headers = new StringMap(); super.init(hr); mailHost=hr.request.props.getProperty(hr.prefix + "host", "localhost"); me = hr.server.hostName; return true; } /** * set-up an email message for sending. If this is a singleton * tag, then send the mail. */ public void tag_sendmail(RewriteContext hr) { inSendmail=true; debug(hr); hr.killToken(); to = hr.get("to"); from = hr.get("from"); body = hr.get("body"); subject = hr.get("subject"); headers.clear(); if (hr.isSingleton()) { sent = true; if (subject != null) { headers.add("Subject", subject); } headers.add("To", to); // add to recipient list try { smtp(me, mailHost, from, to, body, headers, hr.server); } catch (IOException e) { hr.request.props.put(hr.prefix + ".error", "Can't send mail: " + e.getMessage()); } } else { sent = false; } } /** * If we haven't sent the mail yet - send it. */ public void tag_slash_sendmail(RewriteContext hr) { inSendmail=false; debug(hr); hr.killToken(); if (!sent) { sent = true; if (subject != null) { headers.add("Subject", subject); } try { smtp(me, mailHost, from, to, body, headers, hr.server); } catch (IOException e) { hr.request.props.put(hr.prefix + ".error", "Can't send mail: " + e.getMessage()); } } else { debug(hr, "Checking: mail already sent!"); } } /** * If we run off the end of the page, but there is email pending * to be sent, send it anyway. */ public boolean done(RewriteContext hr) { if (!sent) { tag_slash_sendmail(hr); } return true; } /** * Add an additional email header. * Headers are added in the order in which they are processed. * The special header "body" changes the body value instead. *

* look for: <param name="..." value="...>. * Which will add the email header: name: value. *

* The name "body" is special, and will cause the email body to be replaced. */ public void tag_param(RewriteContext hr) { if (!inSendmail) { return; } debug(hr); hr.killToken(); String name = hr.get("name"); String value = hr.get("value"); if ("body".equals(name)) { body = value; } else { headers.add(name, value); } } /** * Send an email message via smtp - simple version. * @param fromHost the hostname of the sender (may be null) * @param smtpHost the SMTP host (whose smtp daemon to contact) * @param from who the email is from * @param to a space delimited list of recepients * @param body The message body * @param headers message headers (may be null) * @throws IOException, if any errors occured (yuk) * * Either the headers Or body may be null, but not both. */ public static void smtp(String fromHost, String smtpHost, String from, String to, String body, StringMap headers) throws IOException { smtp(fromHost, smtpHost, from, to, body, headers, null); } public static void smtp(String fromHost, String smtpHost, String from, String to, String body, StringMap headers, Server server) throws IOException { Socket sock = null; DataInputStream in = null; DataOutputStream out = null; if (server != null) { server.log(Server.LOG_DIAGNOSTIC, "smtp", "sending email..."); } try { sock = new Socket(smtpHost,25); in = new DataInputStream( new BufferedInputStream(sock.getInputStream())); out = new DataOutputStream( new BufferedOutputStream(sock.getOutputStream())); /* Do the protocol - in line */ send(in, out, null, "220", server); if (fromHost != null) { send(in, out, "HELO " + fromHost, "250", server); } send(in, out, "MAIL FROM:<" + from + ">", "250", server); StringTokenizer st = new StringTokenizer(to, ", \t"); while (st.hasMoreTokens()) { send(in, out, "RCPT TO:<" + st.nextToken() + ">", "250", server); } send(in, out, "DATA", "354", server); if (headers != null) { for (int i = 0; i < headers.size(); i++) { String header = headers.getKey(i) + ": " + headers.get(i); out.writeBytes(header + "\r\n"); if (server != null) { server.log(Server.LOG_DIAGNOSTIC, " -> ", header); } } } out.writeBytes("\r\n"); if (body != null) { out.writeBytes(body); if (server != null) { server.log(Server.LOG_DIAGNOSTIC, " -> ", body); } } out.writeBytes("\r\n.\r\nQUIT\r\n"); out.flush(); } finally { try { in.close(); out.close(); sock.close(); } catch (Exception e) {} } } /** * Do a transaction with SMTP server */ private static void send(DataInputStream in, DataOutputStream out, String msg, String expect, Server server) throws IOException { if (msg != null) { out.writeBytes(msg + "\r\n"); out.flush(); if (server != null) { server.log(Server.LOG_DIAGNOSTIC, " -> ", msg); } } String line = in.readLine(); if (server != null) { server.log(Server.LOG_DIAGNOSTIC, " <- ", line); } if (!line.startsWith(expect)) { if (server != null) { server.log(Server.LOG_DIAGNOSTIC, "smtp", "Oops, should start with: " + expect); } throw new IOException(line); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy