|
Ant example source code file (MailMessage.java)
The MailMessage.java source code/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ /* * The original version of this class was donated by Jason Hunter, * who wrote the class as part of the com.oreilly.servlet * package for his book "Java Servlet Programming" (O'Reilly). * See http://www.servlets.com. * */ package org.apache.tools.mail; import java.io.IOException; import java.io.PrintStream; import java.io.BufferedOutputStream; import java.io.OutputStream; import java.net.Socket; import java.net.InetAddress; import java.util.Vector; import java.util.Enumeration; /** * A class to help send SMTP email. * This class is an improvement on the sun.net.smtp.SmtpClient class * found in the JDK. This version has extra functionality, and can be used * with JVMs that did not extend from the JDK. It's not as robust as * the JavaMail Standard Extension classes, but it's easier to use and * easier to install, and has an Open Source license. * <p> * It can be used like this: * <blockquote>* String mailhost = "localhost"; // or another mail host * String from = "Mail Message Servlet <MailMessage@server.com>"; * String to = "to@you.com"; * String cc1 = "cc1@you.com"; * String cc2 = "cc2@you.com"; * String bcc = "bcc@you.com"; * * MailMessage msg = new MailMessage(mailhost); * msg.setPort(25); * msg.from(from); * msg.to(to); * msg.cc(cc1); * msg.cc(cc2); * msg.bcc(bcc); * msg.setSubject("Test subject"); * PrintStream out = msg.getPrintStream(); * * Enumeration enum = req.getParameterNames(); * while (enum.hasMoreElements()) { * String name = (String)enum.nextElement(); * String value = req.getParameter(name); * out.println(name + " = " + value); * } * * msg.sendAndClose(); * </pre> * <p> * Be sure to set the from address, then set the recepient * addresses, then set the subject and other headers, then get the * PrintStream, then write the message, and finally send and close. * The class does minimal error checking internally; it counts on the mail * host to complain if there's any malformatted input or out of order * execution. * <p> * An attachment mechanism based on RFC 1521 could be implemented on top of * this class. In the meanwhile, JavaMail is the best solution for sending * email with attachments. * <p> * Still to do: * <ul> * <li>Figure out how to close the connection in case of error * </ul> * * @version 1.1, 2000/03/19, added angle brackets to address, helps some servers * version 1.0, 1999/12/29 */ public class MailMessage { /** default mailhost */ public static final String DEFAULT_HOST = "localhost"; /** default port for SMTP: 25 */ public static final int DEFAULT_PORT = 25; /** host name for the mail server */ private String host; /** host port for the mail server */ private int port = DEFAULT_PORT; /** sender email address */ private String from; /** list of email addresses to reply to */ private Vector replyto; /** list of email addresses to send to */ private Vector to; /** list of email addresses to cc to */ private Vector cc; /** headers to send in the mail */ private Vector headersKeys; private Vector headersValues; private MailPrintStream out; private SmtpResponseReader in; private Socket socket; private static final int OK_READY = 220; private static final int OK_HELO = 250; private static final int OK_FROM = 250; private static final int OK_RCPT_1 = 250; private static final int OK_RCPT_2 = 251; private static final int OK_DATA = 354; private static final int OK_DOT = 250; private static final int OK_QUIT = 221; /** * Constructs a new MailMessage to send an email. * Use localhost as the mail server with port 25. * * @exception IOException if there's any problem contacting the mail server */ public MailMessage() throws IOException { this(DEFAULT_HOST, DEFAULT_PORT); } /** * Constructs a new MailMessage to send an email. * Use the given host as the mail server with port 25. * * @param host the mail server to use * @exception IOException if there's any problem contacting the mail server */ public MailMessage(String host) throws IOException { this(host, DEFAULT_PORT); } /** * Constructs a new MailMessage to send an email. * Use the given host and port as the mail server. * * @param host the mail server to use * @param port the port to connect to * @exception IOException if there's any problem contacting the mail server */ public MailMessage(String host, int port) throws IOException { this.port = port; this.host = host; replyto = new Vector(); to = new Vector(); cc = new Vector(); headersKeys = new Vector(); headersValues = new Vector(); connect(); sendHelo(); } /** * Set the port to connect to the SMTP host. * @param port the port to use for connection. * @see #DEFAULT_PORT */ public void setPort(int port) { this.port = port; } /** * Sets the from address. Also sets the "From" header. This method should * be called only once. * @param from the from address * @exception IOException if there's any problem reported by the mail server */ public void from(String from) throws IOException { sendFrom(from); this.from = from; } /** * Sets the replyto address * This method may be * called multiple times. * @param rto the replyto address * */ public void replyto(String rto) { this.replyto.addElement(rto); } /** * Sets the to address. Also sets the "To" header. This method may be * called multiple times. * * @param to the to address * @exception IOException if there's any problem reported by the mail server */ public void to(String to) throws IOException { sendRcpt(to); this.to.addElement(to); } /** * Sets the cc address. Also sets the "Cc" header. This method may be * called multiple times. * * @param cc the cc address * @exception IOException if there's any problem reported by the mail server */ public void cc(String cc) throws IOException { sendRcpt(cc); this.cc.addElement(cc); } /** * Sets the bcc address. Does NOT set any header since it's a *blind* copy. * This method may be called multiple times. * * @param bcc the bcc address * @exception IOException if there's any problem reported by the mail server */ public void bcc(String bcc) throws IOException { sendRcpt(bcc); // No need to keep track of Bcc'd addresses } /** * Sets the subject of the mail message. Actually sets the "Subject" * header. * @param subj the subject of the mail message */ public void setSubject(String subj) { setHeader("Subject", subj); } /** * Sets the named header to the given value. RFC 822 provides the rules for * what text may constitute a header name and value. * @param name name of the header * @param value contents of the header */ public void setHeader(String name, String value) { // Blindly trust the user doesn't set any invalid headers headersKeys.add(name); headersValues.add(value); } /** * Returns a PrintStream that can be used to write the body of the message. * A stream is used since email bodies are byte-oriented. A writer can * be wrapped on top if necessary for internationalization. * This is actually done in Message.java * * @return a printstream containing the data and the headers of the email * @exception IOException if there's any problem reported by the mail server * @see org.apache.tools.ant.taskdefs.email.Message */ public PrintStream getPrintStream() throws IOException { setFromHeader(); setReplyToHeader(); setToHeader(); setCcHeader(); setHeader("X-Mailer", "org.apache.tools.mail.MailMessage (ant.apache.org)"); sendData(); flushHeaders(); return out; } // RFC 822 s4.1: "From:" header must be sent // We rely on error checking by the MTA void setFromHeader() { setHeader("From", from); } // RFC 822 s4.1: "Reply-To:" header is optional void setReplyToHeader() { if (!replyto.isEmpty()) { setHeader("Reply-To", vectorToList(replyto)); } } void setToHeader() { if (!to.isEmpty()) { setHeader("To", vectorToList(to)); } } void setCcHeader() { if (!cc.isEmpty()) { setHeader("Cc", vectorToList(cc)); } } String vectorToList(Vector v) { StringBuffer buf = new StringBuffer(); Enumeration e = v.elements(); while (e.hasMoreElements()) { buf.append(e.nextElement()); if (e.hasMoreElements()) { buf.append(", "); } } return buf.toString(); } void flushHeaders() throws IOException { // RFC 822 s4.1: // "Header fields are NOT required to occur in any particular order, // except that the message body MUST occur AFTER the headers" // (the same section specifies a reccommended order, which we ignore) for (int i = 0; i < headersKeys.size(); i++) { String name = (String) headersKeys.elementAt(i); String value = (String) headersValues.elementAt(i); out.println(name + ": " + value); } out.println(); out.flush(); } /** * Sends the message and closes the connection to the server. * The MailMessage object cannot be reused. * * @exception IOException if there's any problem reported by the mail server */ public void sendAndClose() throws IOException { try { sendDot(); sendQuit(); } finally { disconnect(); } } // Make a limited attempt to extract a sanitized email address // Prefer text in <brackets>, ignore anything in (parentheses) static String sanitizeAddress(String s) { int paramDepth = 0; int start = 0; int end = 0; int len = s.length(); for (int i = 0; i < len; i++) { char c = s.charAt(i); if (c == '(') { paramDepth++; if (start == 0) { end = i; // support "address (name)" } } else if (c == ')') { paramDepth--; if (end == 0) { start = i + 1; // support "(name) address" } } else if (paramDepth == 0 && c == '<') { start = i + 1; } else if (paramDepth == 0 && c == '>') { end = i; } } if (end == 0) { end = len; } return s.substring(start, end); } // * * * * * Raw protocol methods below here * * * * * void connect() throws IOException { socket = new Socket(host, port); out = new MailPrintStream( new BufferedOutputStream( socket.getOutputStream())); in = new SmtpResponseReader(socket.getInputStream()); getReady(); } void getReady() throws IOException { String response = in.getResponse(); int[] ok = {OK_READY}; if (!isResponseOK(response, ok)) { throw new IOException( "Didn't get introduction from server: " + response); } } void sendHelo() throws IOException { String local = InetAddress.getLocalHost().getHostName(); int[] ok = {OK_HELO}; send("HELO " + local, ok); } void sendFrom(String from) throws IOException { int[] ok = {OK_FROM}; send("MAIL FROM: " + "<" + sanitizeAddress(from) + ">", ok); } void sendRcpt(String rcpt) throws IOException { int[] ok = {OK_RCPT_1, OK_RCPT_2}; send("RCPT TO: " + "<" + sanitizeAddress(rcpt) + ">", ok); } void sendData() throws IOException { int[] ok = {OK_DATA}; send("DATA", ok); } void sendDot() throws IOException { int[] ok = {OK_DOT}; send("\r\n.", ok); // make sure dot is on new line } void sendQuit() throws IOException { int[] ok = {OK_QUIT}; try { send("QUIT", ok); } catch (IOException e) { throw new ErrorInQuitException(e); } } void send(String msg, int[] ok) throws IOException { out.rawPrint(msg + "\r\n"); // raw supports <CRLF>. |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.