git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271203 13f79535-47bb-0310-9956-ffa450edef68master
@@ -1,409 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.ant.taskdefs; | |||
import java.io.BufferedInputStream; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.PrintStream; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import java.util.StringTokenizer; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.ant.Task; | |||
import org.apache.tools.mail.MailMessage; | |||
/** | |||
* A task to send SMTP email. <p> | |||
* | |||
* | |||
* <tableborder="1" cellpadding="3" cellspacing="0"> | |||
* | |||
* <trbgcolor="#CCCCFF"> | |||
* | |||
* <th> | |||
* Attribute | |||
* </th> | |||
* | |||
* <th> | |||
* Description | |||
* </th> | |||
* | |||
* <th> | |||
* Required | |||
* </th> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* from | |||
* </td> | |||
* | |||
* <td> | |||
* Email address of sender. | |||
* </td> | |||
* | |||
* <td> | |||
* Yes | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* mailhost | |||
* </td> | |||
* | |||
* <td> | |||
* Host name of the mail server. | |||
* </td> | |||
* | |||
* <td> | |||
* No, default to "localhost" | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* toList | |||
* </td> | |||
* | |||
* <td> | |||
* Comma-separated list of recipients. | |||
* </td> | |||
* | |||
* <td> | |||
* Yes | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* subject | |||
* </td> | |||
* | |||
* <td> | |||
* Email subject line. | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* files | |||
* </td> | |||
* | |||
* <td> | |||
* Filename(s) of text to send in the body of the email. Multiple files | |||
* are comma-separated. | |||
* </td> | |||
* | |||
* <tdrowspan="2"> | |||
* One of these two attributes | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* message | |||
* </td> | |||
* | |||
* <td> | |||
* Message to send inthe body of the email. | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* </table> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* includefilenames | |||
* </td> | |||
* | |||
* <td> | |||
* Includes filenames before file contents when set to true. | |||
* </td> | |||
* | |||
* <td> | |||
* No, default is <I>false</I> | |||
* </td> | |||
* | |||
* </tr> | |||
* <p> | |||
* | |||
* | |||
* | |||
* @author glenn_twiggs@bmc.com | |||
* @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a> | |||
*/ | |||
public class SendEmail extends Task | |||
{ | |||
private String mailhost = "localhost"; | |||
private int mailport = MailMessage.DEFAULT_PORT; | |||
private ArrayList files = new ArrayList(); | |||
/** | |||
* failure flag | |||
*/ | |||
private boolean failOnError = true; | |||
private String from; | |||
private boolean includefilenames; | |||
private String message; | |||
private String subject; | |||
private String toList; | |||
/** | |||
* Creates new SendEmail | |||
*/ | |||
public SendEmail() | |||
{ | |||
} | |||
/** | |||
* Sets the FailOnError attribute of the MimeMail object | |||
* | |||
* @param failOnError The new FailOnError value | |||
* @since 1.5 | |||
*/ | |||
public void setFailOnError( boolean failOnError ) | |||
{ | |||
this.failOnError = failOnError; | |||
} | |||
/** | |||
* Sets the file parameter of this build task. | |||
* | |||
* @param filenames Filenames to include as the message body of this email. | |||
*/ | |||
public void setFiles( String filenames ) | |||
throws TaskException | |||
{ | |||
StringTokenizer t = new StringTokenizer( filenames, ", " ); | |||
while( t.hasMoreTokens() ) | |||
{ | |||
files.add( resolveFile( t.nextToken() ) ); | |||
} | |||
} | |||
/** | |||
* Sets the from parameter of this build task. | |||
* | |||
* @param from Email address of sender. | |||
*/ | |||
public void setFrom( String from ) | |||
{ | |||
this.from = from; | |||
} | |||
/** | |||
* Sets Includefilenames attribute | |||
* | |||
* @param includefilenames Set to true if file names are to be included. | |||
* @since 1.5 | |||
*/ | |||
public void setIncludefilenames( boolean includefilenames ) | |||
{ | |||
this.includefilenames = includefilenames; | |||
} | |||
/** | |||
* Sets the mailhost parameter of this build task. | |||
* | |||
* @param mailhost Mail host name. | |||
*/ | |||
public void setMailhost( String mailhost ) | |||
{ | |||
this.mailhost = mailhost; | |||
} | |||
/** | |||
* Sets the mailport parameter of this build task. | |||
* | |||
* @param value mail port name. | |||
*/ | |||
public void setMailport( Integer value ) | |||
{ | |||
this.mailport = value.intValue(); | |||
} | |||
/** | |||
* Sets the message parameter of this build task. | |||
* | |||
* @param message Message body of this email. | |||
*/ | |||
public void setMessage( String message ) | |||
{ | |||
this.message = message; | |||
} | |||
/** | |||
* Sets the subject parameter of this build task. | |||
* | |||
* @param subject Subject of this email. | |||
*/ | |||
public void setSubject( String subject ) | |||
{ | |||
this.subject = subject; | |||
} | |||
/** | |||
* Sets the toList parameter of this build task. | |||
* | |||
* @param toList Comma-separated list of email recipient addreses. | |||
*/ | |||
public void setToList( String toList ) | |||
{ | |||
this.toList = toList; | |||
} | |||
/** | |||
* Executes this build task. | |||
* | |||
* @throws TaskException if there is an error during task execution. | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
try | |||
{ | |||
MailMessage mailMessage = new MailMessage( mailhost ); | |||
mailMessage.setPort( mailport ); | |||
if( from != null ) | |||
{ | |||
mailMessage.from( from ); | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Attribute \"from\" is required." ); | |||
} | |||
if( toList != null ) | |||
{ | |||
StringTokenizer t = new StringTokenizer( toList, ", ", false ); | |||
while( t.hasMoreTokens() ) | |||
{ | |||
mailMessage.to( t.nextToken() ); | |||
} | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Attribute \"toList\" is required." ); | |||
} | |||
if( subject != null ) | |||
{ | |||
mailMessage.setSubject( subject ); | |||
} | |||
if( !files.isEmpty() ) | |||
{ | |||
PrintStream out = mailMessage.getPrintStream(); | |||
for( Iterator e = files.iterator(); e.hasNext(); ) | |||
{ | |||
File file = (File)e.next(); | |||
if( file.exists() && file.canRead() ) | |||
{ | |||
int bufsize = 1024; | |||
int length; | |||
byte[] buf = new byte[ bufsize ]; | |||
if( includefilenames ) | |||
{ | |||
String filename = file.getName(); | |||
int filenamelength = filename.length(); | |||
out.println( filename ); | |||
for( int star = 0; star < filenamelength; star++ ) | |||
{ | |||
out.print( '=' ); | |||
} | |||
out.println(); | |||
} | |||
BufferedInputStream in = null; | |||
try | |||
{ | |||
in = new BufferedInputStream( | |||
new FileInputStream( file ), bufsize ); | |||
while( ( length = in.read( buf, 0, bufsize ) ) != -1 ) | |||
{ | |||
out.write( buf, 0, length ); | |||
} | |||
if( includefilenames ) | |||
{ | |||
out.println(); | |||
} | |||
} | |||
finally | |||
{ | |||
if( in != null ) | |||
{ | |||
try | |||
{ | |||
in.close(); | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
} | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
throw new TaskException( "File \"" + file.getName() | |||
+ "\" does not exist or is not readable." ); | |||
} | |||
} | |||
} | |||
else if( message != null ) | |||
{ | |||
PrintStream out = mailMessage.getPrintStream(); | |||
out.print( message ); | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Attribute \"file\" or \"message\" is required." ); | |||
} | |||
getLogger().info( "Sending email" ); | |||
mailMessage.sendAndClose(); | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
String err = "IO error sending mail " + ioe.toString(); | |||
if( failOnError ) | |||
{ | |||
throw new TaskException( err, ioe ); | |||
} | |||
else | |||
{ | |||
getLogger().error( err ); | |||
} | |||
} | |||
} | |||
} |
@@ -1,535 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.mail; | |||
import java.io.BufferedOutputStream; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.PrintStream; | |||
import java.net.InetAddress; | |||
import java.net.Socket; | |||
import java.util.ArrayList; | |||
import java.util.Enumeration; | |||
import java.util.Hashtable; | |||
import java.util.Iterator; | |||
/** | |||
* 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><pre> | |||
* 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(); | |||
* | |||
* Iterator enum = req.getParameterNames(); | |||
* while (enum.hasNext()) { | |||
* String name = (String)enum.next(); | |||
* String value = req.getParameter(name); | |||
* out.println(name + " = " + value); | |||
* } | |||
* | |||
* msg.sendAndClose(); | |||
* </pre></blockquote> <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> | |||
* | |||
* | |||
* @author Jason Hunter | |||
* @version 1.1, 2000/03/19, added angle brackets to address, helps some servers | |||
* version 1.0, 1999/12/29 | |||
*/ | |||
public class MailMessage | |||
{ | |||
/** | |||
* default port for SMTP: 25 | |||
*/ | |||
public final static int DEFAULT_PORT = 25; | |||
/** | |||
* host port for the mail server | |||
*/ | |||
private int port = DEFAULT_PORT; | |||
/** | |||
* list of email addresses to cc to | |||
*/ | |||
private ArrayList cc; | |||
/** | |||
* sender email address | |||
*/ | |||
private String from; | |||
/** | |||
* headers to send in the mail | |||
*/ | |||
private Hashtable headers; | |||
/** | |||
* host name for the mail server | |||
*/ | |||
private String host; | |||
private SmtpResponseReader in; | |||
private MailPrintStream out; | |||
private Socket socket; | |||
/** | |||
* list of email addresses to send to | |||
*/ | |||
private ArrayList to; | |||
/** | |||
* Constructs a new MailMessage to send an email. Use localhost as the mail | |||
* server. | |||
* | |||
* @exception IOException if there's any problem contacting the mail server | |||
*/ | |||
public MailMessage() | |||
throws IOException | |||
{ | |||
this( "localhost" ); | |||
} | |||
/** | |||
* Constructs a new MailMessage to send an email. Use the given host as the | |||
* mail server. | |||
* | |||
* @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 = host; | |||
to = new ArrayList(); | |||
cc = new ArrayList(); | |||
headers = new Hashtable(); | |||
setHeader( "X-Mailer", "org.apache.tools.mail.MailMessage (jakarta.apache.org)" ); | |||
connect(); | |||
sendHelo(); | |||
} | |||
// 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 ); | |||
} | |||
/** | |||
* 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 The new Header value | |||
* @param value The new Header value | |||
*/ | |||
public void setHeader( String name, String value ) | |||
{ | |||
// Blindly trust the user doesn't set any invalid headers | |||
headers.put( name, value ); | |||
} | |||
/** | |||
* 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 subject of the mail message. Actually sets the "Subject" header. | |||
* | |||
* @param subj The new Subject value | |||
*/ | |||
public void setSubject( String subj ) | |||
{ | |||
headers.put( "Subject", subj ); | |||
} | |||
/** | |||
* 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 could be | |||
* wrapped on top if necessary for internationalization. | |||
* | |||
* @return The PrintStream value | |||
* @exception IOException if there's any problem reported by the mail server | |||
*/ | |||
public PrintStream getPrintStream() | |||
throws IOException | |||
{ | |||
setFromHeader(); | |||
setToHeader(); | |||
setCcHeader(); | |||
sendData(); | |||
flushHeaders(); | |||
return out; | |||
} | |||
/** | |||
* Sets the bcc address. Does NOT set any header since it's a *blind* copy. | |||
* This method may be called multiple times. | |||
* | |||
* @param bcc Description of Parameter | |||
* @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 cc address. Also sets the "Cc" header. This method may be called | |||
* multiple times. | |||
* | |||
* @param cc Description of Parameter | |||
* @exception IOException if there's any problem reported by the mail server | |||
*/ | |||
public void cc( String cc ) | |||
throws IOException | |||
{ | |||
sendRcpt( cc ); | |||
this.cc.add( cc ); | |||
} | |||
/** | |||
* Sets the from address. Also sets the "From" header. This method should be | |||
* called only once. | |||
* | |||
* @param from Description of Parameter | |||
* @exception IOException if there's any problem reported by the mail server | |||
*/ | |||
public void from( String from ) | |||
throws IOException | |||
{ | |||
sendFrom( from ); | |||
this.from = from; | |||
} | |||
/** | |||
* 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 | |||
{ | |||
sendDot(); | |||
sendQuit(); | |||
disconnect(); | |||
} | |||
/** | |||
* Sets the to address. Also sets the "To" header. This method may be called | |||
* multiple times. | |||
* | |||
* @param to Description of Parameter | |||
* @exception IOException if there's any problem reported by the mail server | |||
*/ | |||
public void to( String to ) | |||
throws IOException | |||
{ | |||
sendRcpt( to ); | |||
this.to.add( to ); | |||
} | |||
void setCcHeader() | |||
{ | |||
setHeader( "Cc", vectorToList( cc ) ); | |||
} | |||
void setFromHeader() | |||
{ | |||
setHeader( "From", from ); | |||
} | |||
void setToHeader() | |||
{ | |||
setHeader( "To", vectorToList( to ) ); | |||
} | |||
void getReady() | |||
throws IOException | |||
{ | |||
String response = in.getResponse(); | |||
int[] ok = {220}; | |||
if( !isResponseOK( response, ok ) ) | |||
{ | |||
throw new IOException( | |||
"Didn't get introduction from server: " + response ); | |||
} | |||
} | |||
boolean isResponseOK( String response, int[] ok ) | |||
{ | |||
// Check that the response is one of the valid codes | |||
for( int i = 0; i < ok.length; i++ ) | |||
{ | |||
if( response.startsWith( "" + ok[ i ] ) ) | |||
{ | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
// * * * * * 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 disconnect() | |||
throws IOException | |||
{ | |||
if( out != null ) | |||
{ | |||
out.close(); | |||
} | |||
if( in != null ) | |||
{ | |||
in.close(); | |||
} | |||
if( socket != null ) | |||
{ | |||
socket.close(); | |||
} | |||
} | |||
void flushHeaders() | |||
throws IOException | |||
{ | |||
// XXX Should I care about order here? | |||
Enumeration e = headers.keys(); | |||
while( e.hasMoreElements() ) | |||
{ | |||
String name = (String)e.nextElement(); | |||
String value = (String)headers.get( name ); | |||
out.println( name + ": " + value ); | |||
} | |||
out.println(); | |||
out.flush(); | |||
} | |||
void send( String msg, int[] ok ) | |||
throws IOException | |||
{ | |||
out.rawPrint( msg + "\r\n" );// raw supports <CRLF>.<CRLF> | |||
//System.out.println("S: " + msg); | |||
String response = in.getResponse(); | |||
//System.out.println("R: " + response); | |||
if( !isResponseOK( response, ok ) ) | |||
{ | |||
throw new IOException( | |||
"Unexpected reply to command: " + msg + ": " + response ); | |||
} | |||
} | |||
void sendData() | |||
throws IOException | |||
{ | |||
int[] ok = {354}; | |||
send( "DATA", ok ); | |||
} | |||
void sendDot() | |||
throws IOException | |||
{ | |||
int[] ok = {250}; | |||
send( "\r\n.", ok );// make sure dot is on new line | |||
} | |||
void sendFrom( String from ) | |||
throws IOException | |||
{ | |||
int[] ok = {250}; | |||
send( "MAIL FROM: " + "<" + sanitizeAddress( from ) + ">", ok ); | |||
} | |||
void sendHelo() | |||
throws IOException | |||
{ | |||
String local = InetAddress.getLocalHost().getHostName(); | |||
int[] ok = {250}; | |||
send( "HELO " + local, ok ); | |||
} | |||
void sendQuit() | |||
throws IOException | |||
{ | |||
int[] ok = {221}; | |||
send( "QUIT", ok ); | |||
} | |||
void sendRcpt( String rcpt ) | |||
throws IOException | |||
{ | |||
int[] ok = {250, 251}; | |||
send( "RCPT TO: " + "<" + sanitizeAddress( rcpt ) + ">", ok ); | |||
} | |||
String vectorToList( ArrayList v ) | |||
{ | |||
StringBuffer buf = new StringBuffer(); | |||
Iterator e = v.iterator(); | |||
while( e.hasNext() ) | |||
{ | |||
buf.append( e.next() ); | |||
if( e.hasNext() ) | |||
{ | |||
buf.append( ", " ); | |||
} | |||
} | |||
return buf.toString(); | |||
} | |||
} | |||
// This PrintStream subclass makes sure that <CRLF>. becomes <CRLF>.. | |||
// per RFC 821. It also ensures that new lines are always \r\n. | |||
// | |||
class MailPrintStream extends PrintStream | |||
{ | |||
int lastChar; | |||
public MailPrintStream( OutputStream out ) | |||
{ | |||
super( out, true );// deprecated, but email is byte-oriented | |||
} | |||
// Mac does \n\r, but that's tough to distinguish from Windows \r\n\r\n. | |||
// Don't tackle that problem right now. | |||
public void write( int b ) | |||
{ | |||
if( b == '\n' && lastChar != '\r' ) | |||
{ | |||
rawWrite( '\r' );// ensure always \r\n | |||
rawWrite( b ); | |||
} | |||
else if( b == '.' && lastChar == '\n' ) | |||
{ | |||
rawWrite( '.' );// add extra dot | |||
rawWrite( b ); | |||
} | |||
else | |||
{ | |||
rawWrite( b ); | |||
} | |||
lastChar = b; | |||
} | |||
public void write( byte buf[], int off, int len ) | |||
{ | |||
for( int i = 0; i < len; i++ ) | |||
{ | |||
write( buf[ off + i ] ); | |||
} | |||
} | |||
void rawPrint( String s ) | |||
{ | |||
int len = s.length(); | |||
for( int i = 0; i < len; i++ ) | |||
{ | |||
rawWrite( s.charAt( i ) ); | |||
} | |||
} | |||
void rawWrite( int b ) | |||
{ | |||
super.write( b ); | |||
} | |||
} | |||
@@ -1,105 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.mail; | |||
import java.io.BufferedReader; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.InputStreamReader; | |||
/** | |||
* A wrapper around the raw input from the SMTP server that assembles multi line | |||
* responses into a single String. <p> | |||
* | |||
* The same rules used here would apply to FTP and other Telnet based protocols | |||
* as well.</p> | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
*/ | |||
public class SmtpResponseReader | |||
{ | |||
protected BufferedReader reader = null; | |||
private StringBuffer result = new StringBuffer(); | |||
/** | |||
* Wrap this input stream. | |||
* | |||
* @param in Description of Parameter | |||
*/ | |||
public SmtpResponseReader( InputStream in ) | |||
{ | |||
reader = new BufferedReader( new InputStreamReader( in ) ); | |||
} | |||
/** | |||
* Read until the server indicates that the response is complete. | |||
* | |||
* @return Responsecode (3 digits) + Blank + Text from all response line | |||
* concatenated (with blanks replacing the \r\n sequences). | |||
* @exception IOException Description of Exception | |||
*/ | |||
public String getResponse() | |||
throws IOException | |||
{ | |||
result.setLength( 0 ); | |||
String line = reader.readLine(); | |||
if( line != null && line.length() >= 3 ) | |||
{ | |||
result.append( line.substring( 0, 3 ) ); | |||
result.append( " " ); | |||
} | |||
while( line != null ) | |||
{ | |||
append( line ); | |||
if( !hasMoreLines( line ) ) | |||
{ | |||
break; | |||
} | |||
line = reader.readLine(); | |||
} | |||
return result.toString().trim(); | |||
} | |||
/** | |||
* Closes the underlying stream. | |||
* | |||
* @exception IOException Description of Exception | |||
*/ | |||
public void close() | |||
throws IOException | |||
{ | |||
reader.close(); | |||
} | |||
/** | |||
* Should we expect more input? | |||
* | |||
* @param line Description of Parameter | |||
* @return Description of the Returned Value | |||
*/ | |||
protected boolean hasMoreLines( String line ) | |||
{ | |||
return line.length() > 3 && line.charAt( 3 ) == '-'; | |||
} | |||
/** | |||
* Append the text from this line of the resonse. | |||
* | |||
* @param line Description of Parameter | |||
*/ | |||
private void append( String line ) | |||
{ | |||
if( line.length() > 4 ) | |||
{ | |||
result.append( line.substring( 4 ) ); | |||
result.append( " " ); | |||
} | |||
} | |||
} |
@@ -1,409 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.ant.taskdefs; | |||
import java.io.BufferedInputStream; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.PrintStream; | |||
import java.util.ArrayList; | |||
import java.util.Iterator; | |||
import java.util.StringTokenizer; | |||
import org.apache.myrmidon.api.TaskException; | |||
import org.apache.tools.ant.Task; | |||
import org.apache.tools.mail.MailMessage; | |||
/** | |||
* A task to send SMTP email. <p> | |||
* | |||
* | |||
* <tableborder="1" cellpadding="3" cellspacing="0"> | |||
* | |||
* <trbgcolor="#CCCCFF"> | |||
* | |||
* <th> | |||
* Attribute | |||
* </th> | |||
* | |||
* <th> | |||
* Description | |||
* </th> | |||
* | |||
* <th> | |||
* Required | |||
* </th> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* from | |||
* </td> | |||
* | |||
* <td> | |||
* Email address of sender. | |||
* </td> | |||
* | |||
* <td> | |||
* Yes | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* mailhost | |||
* </td> | |||
* | |||
* <td> | |||
* Host name of the mail server. | |||
* </td> | |||
* | |||
* <td> | |||
* No, default to "localhost" | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* toList | |||
* </td> | |||
* | |||
* <td> | |||
* Comma-separated list of recipients. | |||
* </td> | |||
* | |||
* <td> | |||
* Yes | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* subject | |||
* </td> | |||
* | |||
* <td> | |||
* Email subject line. | |||
* </td> | |||
* | |||
* <td> | |||
* No | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* files | |||
* </td> | |||
* | |||
* <td> | |||
* Filename(s) of text to send in the body of the email. Multiple files | |||
* are comma-separated. | |||
* </td> | |||
* | |||
* <tdrowspan="2"> | |||
* One of these two attributes | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* message | |||
* </td> | |||
* | |||
* <td> | |||
* Message to send inthe body of the email. | |||
* </td> | |||
* | |||
* </tr> | |||
* | |||
* </table> | |||
* | |||
* <tr> | |||
* | |||
* <td> | |||
* includefilenames | |||
* </td> | |||
* | |||
* <td> | |||
* Includes filenames before file contents when set to true. | |||
* </td> | |||
* | |||
* <td> | |||
* No, default is <I>false</I> | |||
* </td> | |||
* | |||
* </tr> | |||
* <p> | |||
* | |||
* | |||
* | |||
* @author glenn_twiggs@bmc.com | |||
* @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a> | |||
*/ | |||
public class SendEmail extends Task | |||
{ | |||
private String mailhost = "localhost"; | |||
private int mailport = MailMessage.DEFAULT_PORT; | |||
private ArrayList files = new ArrayList(); | |||
/** | |||
* failure flag | |||
*/ | |||
private boolean failOnError = true; | |||
private String from; | |||
private boolean includefilenames; | |||
private String message; | |||
private String subject; | |||
private String toList; | |||
/** | |||
* Creates new SendEmail | |||
*/ | |||
public SendEmail() | |||
{ | |||
} | |||
/** | |||
* Sets the FailOnError attribute of the MimeMail object | |||
* | |||
* @param failOnError The new FailOnError value | |||
* @since 1.5 | |||
*/ | |||
public void setFailOnError( boolean failOnError ) | |||
{ | |||
this.failOnError = failOnError; | |||
} | |||
/** | |||
* Sets the file parameter of this build task. | |||
* | |||
* @param filenames Filenames to include as the message body of this email. | |||
*/ | |||
public void setFiles( String filenames ) | |||
throws TaskException | |||
{ | |||
StringTokenizer t = new StringTokenizer( filenames, ", " ); | |||
while( t.hasMoreTokens() ) | |||
{ | |||
files.add( resolveFile( t.nextToken() ) ); | |||
} | |||
} | |||
/** | |||
* Sets the from parameter of this build task. | |||
* | |||
* @param from Email address of sender. | |||
*/ | |||
public void setFrom( String from ) | |||
{ | |||
this.from = from; | |||
} | |||
/** | |||
* Sets Includefilenames attribute | |||
* | |||
* @param includefilenames Set to true if file names are to be included. | |||
* @since 1.5 | |||
*/ | |||
public void setIncludefilenames( boolean includefilenames ) | |||
{ | |||
this.includefilenames = includefilenames; | |||
} | |||
/** | |||
* Sets the mailhost parameter of this build task. | |||
* | |||
* @param mailhost Mail host name. | |||
*/ | |||
public void setMailhost( String mailhost ) | |||
{ | |||
this.mailhost = mailhost; | |||
} | |||
/** | |||
* Sets the mailport parameter of this build task. | |||
* | |||
* @param value mail port name. | |||
*/ | |||
public void setMailport( Integer value ) | |||
{ | |||
this.mailport = value.intValue(); | |||
} | |||
/** | |||
* Sets the message parameter of this build task. | |||
* | |||
* @param message Message body of this email. | |||
*/ | |||
public void setMessage( String message ) | |||
{ | |||
this.message = message; | |||
} | |||
/** | |||
* Sets the subject parameter of this build task. | |||
* | |||
* @param subject Subject of this email. | |||
*/ | |||
public void setSubject( String subject ) | |||
{ | |||
this.subject = subject; | |||
} | |||
/** | |||
* Sets the toList parameter of this build task. | |||
* | |||
* @param toList Comma-separated list of email recipient addreses. | |||
*/ | |||
public void setToList( String toList ) | |||
{ | |||
this.toList = toList; | |||
} | |||
/** | |||
* Executes this build task. | |||
* | |||
* @throws TaskException if there is an error during task execution. | |||
*/ | |||
public void execute() | |||
throws TaskException | |||
{ | |||
try | |||
{ | |||
MailMessage mailMessage = new MailMessage( mailhost ); | |||
mailMessage.setPort( mailport ); | |||
if( from != null ) | |||
{ | |||
mailMessage.from( from ); | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Attribute \"from\" is required." ); | |||
} | |||
if( toList != null ) | |||
{ | |||
StringTokenizer t = new StringTokenizer( toList, ", ", false ); | |||
while( t.hasMoreTokens() ) | |||
{ | |||
mailMessage.to( t.nextToken() ); | |||
} | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Attribute \"toList\" is required." ); | |||
} | |||
if( subject != null ) | |||
{ | |||
mailMessage.setSubject( subject ); | |||
} | |||
if( !files.isEmpty() ) | |||
{ | |||
PrintStream out = mailMessage.getPrintStream(); | |||
for( Iterator e = files.iterator(); e.hasNext(); ) | |||
{ | |||
File file = (File)e.next(); | |||
if( file.exists() && file.canRead() ) | |||
{ | |||
int bufsize = 1024; | |||
int length; | |||
byte[] buf = new byte[ bufsize ]; | |||
if( includefilenames ) | |||
{ | |||
String filename = file.getName(); | |||
int filenamelength = filename.length(); | |||
out.println( filename ); | |||
for( int star = 0; star < filenamelength; star++ ) | |||
{ | |||
out.print( '=' ); | |||
} | |||
out.println(); | |||
} | |||
BufferedInputStream in = null; | |||
try | |||
{ | |||
in = new BufferedInputStream( | |||
new FileInputStream( file ), bufsize ); | |||
while( ( length = in.read( buf, 0, bufsize ) ) != -1 ) | |||
{ | |||
out.write( buf, 0, length ); | |||
} | |||
if( includefilenames ) | |||
{ | |||
out.println(); | |||
} | |||
} | |||
finally | |||
{ | |||
if( in != null ) | |||
{ | |||
try | |||
{ | |||
in.close(); | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
} | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
throw new TaskException( "File \"" + file.getName() | |||
+ "\" does not exist or is not readable." ); | |||
} | |||
} | |||
} | |||
else if( message != null ) | |||
{ | |||
PrintStream out = mailMessage.getPrintStream(); | |||
out.print( message ); | |||
} | |||
else | |||
{ | |||
throw new TaskException( "Attribute \"file\" or \"message\" is required." ); | |||
} | |||
getLogger().info( "Sending email" ); | |||
mailMessage.sendAndClose(); | |||
} | |||
catch( IOException ioe ) | |||
{ | |||
String err = "IO error sending mail " + ioe.toString(); | |||
if( failOnError ) | |||
{ | |||
throw new TaskException( err, ioe ); | |||
} | |||
else | |||
{ | |||
getLogger().error( err ); | |||
} | |||
} | |||
} | |||
} |
@@ -1,535 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.mail; | |||
import java.io.BufferedOutputStream; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.PrintStream; | |||
import java.net.InetAddress; | |||
import java.net.Socket; | |||
import java.util.ArrayList; | |||
import java.util.Enumeration; | |||
import java.util.Hashtable; | |||
import java.util.Iterator; | |||
/** | |||
* 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><pre> | |||
* 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(); | |||
* | |||
* Iterator enum = req.getParameterNames(); | |||
* while (enum.hasNext()) { | |||
* String name = (String)enum.next(); | |||
* String value = req.getParameter(name); | |||
* out.println(name + " = " + value); | |||
* } | |||
* | |||
* msg.sendAndClose(); | |||
* </pre></blockquote> <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> | |||
* | |||
* | |||
* @author Jason Hunter | |||
* @version 1.1, 2000/03/19, added angle brackets to address, helps some servers | |||
* version 1.0, 1999/12/29 | |||
*/ | |||
public class MailMessage | |||
{ | |||
/** | |||
* default port for SMTP: 25 | |||
*/ | |||
public final static int DEFAULT_PORT = 25; | |||
/** | |||
* host port for the mail server | |||
*/ | |||
private int port = DEFAULT_PORT; | |||
/** | |||
* list of email addresses to cc to | |||
*/ | |||
private ArrayList cc; | |||
/** | |||
* sender email address | |||
*/ | |||
private String from; | |||
/** | |||
* headers to send in the mail | |||
*/ | |||
private Hashtable headers; | |||
/** | |||
* host name for the mail server | |||
*/ | |||
private String host; | |||
private SmtpResponseReader in; | |||
private MailPrintStream out; | |||
private Socket socket; | |||
/** | |||
* list of email addresses to send to | |||
*/ | |||
private ArrayList to; | |||
/** | |||
* Constructs a new MailMessage to send an email. Use localhost as the mail | |||
* server. | |||
* | |||
* @exception IOException if there's any problem contacting the mail server | |||
*/ | |||
public MailMessage() | |||
throws IOException | |||
{ | |||
this( "localhost" ); | |||
} | |||
/** | |||
* Constructs a new MailMessage to send an email. Use the given host as the | |||
* mail server. | |||
* | |||
* @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 = host; | |||
to = new ArrayList(); | |||
cc = new ArrayList(); | |||
headers = new Hashtable(); | |||
setHeader( "X-Mailer", "org.apache.tools.mail.MailMessage (jakarta.apache.org)" ); | |||
connect(); | |||
sendHelo(); | |||
} | |||
// 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 ); | |||
} | |||
/** | |||
* 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 The new Header value | |||
* @param value The new Header value | |||
*/ | |||
public void setHeader( String name, String value ) | |||
{ | |||
// Blindly trust the user doesn't set any invalid headers | |||
headers.put( name, value ); | |||
} | |||
/** | |||
* 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 subject of the mail message. Actually sets the "Subject" header. | |||
* | |||
* @param subj The new Subject value | |||
*/ | |||
public void setSubject( String subj ) | |||
{ | |||
headers.put( "Subject", subj ); | |||
} | |||
/** | |||
* 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 could be | |||
* wrapped on top if necessary for internationalization. | |||
* | |||
* @return The PrintStream value | |||
* @exception IOException if there's any problem reported by the mail server | |||
*/ | |||
public PrintStream getPrintStream() | |||
throws IOException | |||
{ | |||
setFromHeader(); | |||
setToHeader(); | |||
setCcHeader(); | |||
sendData(); | |||
flushHeaders(); | |||
return out; | |||
} | |||
/** | |||
* Sets the bcc address. Does NOT set any header since it's a *blind* copy. | |||
* This method may be called multiple times. | |||
* | |||
* @param bcc Description of Parameter | |||
* @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 cc address. Also sets the "Cc" header. This method may be called | |||
* multiple times. | |||
* | |||
* @param cc Description of Parameter | |||
* @exception IOException if there's any problem reported by the mail server | |||
*/ | |||
public void cc( String cc ) | |||
throws IOException | |||
{ | |||
sendRcpt( cc ); | |||
this.cc.add( cc ); | |||
} | |||
/** | |||
* Sets the from address. Also sets the "From" header. This method should be | |||
* called only once. | |||
* | |||
* @param from Description of Parameter | |||
* @exception IOException if there's any problem reported by the mail server | |||
*/ | |||
public void from( String from ) | |||
throws IOException | |||
{ | |||
sendFrom( from ); | |||
this.from = from; | |||
} | |||
/** | |||
* 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 | |||
{ | |||
sendDot(); | |||
sendQuit(); | |||
disconnect(); | |||
} | |||
/** | |||
* Sets the to address. Also sets the "To" header. This method may be called | |||
* multiple times. | |||
* | |||
* @param to Description of Parameter | |||
* @exception IOException if there's any problem reported by the mail server | |||
*/ | |||
public void to( String to ) | |||
throws IOException | |||
{ | |||
sendRcpt( to ); | |||
this.to.add( to ); | |||
} | |||
void setCcHeader() | |||
{ | |||
setHeader( "Cc", vectorToList( cc ) ); | |||
} | |||
void setFromHeader() | |||
{ | |||
setHeader( "From", from ); | |||
} | |||
void setToHeader() | |||
{ | |||
setHeader( "To", vectorToList( to ) ); | |||
} | |||
void getReady() | |||
throws IOException | |||
{ | |||
String response = in.getResponse(); | |||
int[] ok = {220}; | |||
if( !isResponseOK( response, ok ) ) | |||
{ | |||
throw new IOException( | |||
"Didn't get introduction from server: " + response ); | |||
} | |||
} | |||
boolean isResponseOK( String response, int[] ok ) | |||
{ | |||
// Check that the response is one of the valid codes | |||
for( int i = 0; i < ok.length; i++ ) | |||
{ | |||
if( response.startsWith( "" + ok[ i ] ) ) | |||
{ | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
// * * * * * 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 disconnect() | |||
throws IOException | |||
{ | |||
if( out != null ) | |||
{ | |||
out.close(); | |||
} | |||
if( in != null ) | |||
{ | |||
in.close(); | |||
} | |||
if( socket != null ) | |||
{ | |||
socket.close(); | |||
} | |||
} | |||
void flushHeaders() | |||
throws IOException | |||
{ | |||
// XXX Should I care about order here? | |||
Enumeration e = headers.keys(); | |||
while( e.hasMoreElements() ) | |||
{ | |||
String name = (String)e.nextElement(); | |||
String value = (String)headers.get( name ); | |||
out.println( name + ": " + value ); | |||
} | |||
out.println(); | |||
out.flush(); | |||
} | |||
void send( String msg, int[] ok ) | |||
throws IOException | |||
{ | |||
out.rawPrint( msg + "\r\n" );// raw supports <CRLF>.<CRLF> | |||
//System.out.println("S: " + msg); | |||
String response = in.getResponse(); | |||
//System.out.println("R: " + response); | |||
if( !isResponseOK( response, ok ) ) | |||
{ | |||
throw new IOException( | |||
"Unexpected reply to command: " + msg + ": " + response ); | |||
} | |||
} | |||
void sendData() | |||
throws IOException | |||
{ | |||
int[] ok = {354}; | |||
send( "DATA", ok ); | |||
} | |||
void sendDot() | |||
throws IOException | |||
{ | |||
int[] ok = {250}; | |||
send( "\r\n.", ok );// make sure dot is on new line | |||
} | |||
void sendFrom( String from ) | |||
throws IOException | |||
{ | |||
int[] ok = {250}; | |||
send( "MAIL FROM: " + "<" + sanitizeAddress( from ) + ">", ok ); | |||
} | |||
void sendHelo() | |||
throws IOException | |||
{ | |||
String local = InetAddress.getLocalHost().getHostName(); | |||
int[] ok = {250}; | |||
send( "HELO " + local, ok ); | |||
} | |||
void sendQuit() | |||
throws IOException | |||
{ | |||
int[] ok = {221}; | |||
send( "QUIT", ok ); | |||
} | |||
void sendRcpt( String rcpt ) | |||
throws IOException | |||
{ | |||
int[] ok = {250, 251}; | |||
send( "RCPT TO: " + "<" + sanitizeAddress( rcpt ) + ">", ok ); | |||
} | |||
String vectorToList( ArrayList v ) | |||
{ | |||
StringBuffer buf = new StringBuffer(); | |||
Iterator e = v.iterator(); | |||
while( e.hasNext() ) | |||
{ | |||
buf.append( e.next() ); | |||
if( e.hasNext() ) | |||
{ | |||
buf.append( ", " ); | |||
} | |||
} | |||
return buf.toString(); | |||
} | |||
} | |||
// This PrintStream subclass makes sure that <CRLF>. becomes <CRLF>.. | |||
// per RFC 821. It also ensures that new lines are always \r\n. | |||
// | |||
class MailPrintStream extends PrintStream | |||
{ | |||
int lastChar; | |||
public MailPrintStream( OutputStream out ) | |||
{ | |||
super( out, true );// deprecated, but email is byte-oriented | |||
} | |||
// Mac does \n\r, but that's tough to distinguish from Windows \r\n\r\n. | |||
// Don't tackle that problem right now. | |||
public void write( int b ) | |||
{ | |||
if( b == '\n' && lastChar != '\r' ) | |||
{ | |||
rawWrite( '\r' );// ensure always \r\n | |||
rawWrite( b ); | |||
} | |||
else if( b == '.' && lastChar == '\n' ) | |||
{ | |||
rawWrite( '.' );// add extra dot | |||
rawWrite( b ); | |||
} | |||
else | |||
{ | |||
rawWrite( b ); | |||
} | |||
lastChar = b; | |||
} | |||
public void write( byte buf[], int off, int len ) | |||
{ | |||
for( int i = 0; i < len; i++ ) | |||
{ | |||
write( buf[ off + i ] ); | |||
} | |||
} | |||
void rawPrint( String s ) | |||
{ | |||
int len = s.length(); | |||
for( int i = 0; i < len; i++ ) | |||
{ | |||
rawWrite( s.charAt( i ) ); | |||
} | |||
} | |||
void rawWrite( int b ) | |||
{ | |||
super.write( b ); | |||
} | |||
} | |||
@@ -1,105 +0,0 @@ | |||
/* | |||
* Copyright (C) The Apache Software Foundation. All rights reserved. | |||
* | |||
* This software is published under the terms of the Apache Software License | |||
* version 1.1, a copy of which has been included with this distribution in | |||
* the LICENSE.txt file. | |||
*/ | |||
package org.apache.tools.mail; | |||
import java.io.BufferedReader; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.io.InputStreamReader; | |||
/** | |||
* A wrapper around the raw input from the SMTP server that assembles multi line | |||
* responses into a single String. <p> | |||
* | |||
* The same rules used here would apply to FTP and other Telnet based protocols | |||
* as well.</p> | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
*/ | |||
public class SmtpResponseReader | |||
{ | |||
protected BufferedReader reader = null; | |||
private StringBuffer result = new StringBuffer(); | |||
/** | |||
* Wrap this input stream. | |||
* | |||
* @param in Description of Parameter | |||
*/ | |||
public SmtpResponseReader( InputStream in ) | |||
{ | |||
reader = new BufferedReader( new InputStreamReader( in ) ); | |||
} | |||
/** | |||
* Read until the server indicates that the response is complete. | |||
* | |||
* @return Responsecode (3 digits) + Blank + Text from all response line | |||
* concatenated (with blanks replacing the \r\n sequences). | |||
* @exception IOException Description of Exception | |||
*/ | |||
public String getResponse() | |||
throws IOException | |||
{ | |||
result.setLength( 0 ); | |||
String line = reader.readLine(); | |||
if( line != null && line.length() >= 3 ) | |||
{ | |||
result.append( line.substring( 0, 3 ) ); | |||
result.append( " " ); | |||
} | |||
while( line != null ) | |||
{ | |||
append( line ); | |||
if( !hasMoreLines( line ) ) | |||
{ | |||
break; | |||
} | |||
line = reader.readLine(); | |||
} | |||
return result.toString().trim(); | |||
} | |||
/** | |||
* Closes the underlying stream. | |||
* | |||
* @exception IOException Description of Exception | |||
*/ | |||
public void close() | |||
throws IOException | |||
{ | |||
reader.close(); | |||
} | |||
/** | |||
* Should we expect more input? | |||
* | |||
* @param line Description of Parameter | |||
* @return Description of the Returned Value | |||
*/ | |||
protected boolean hasMoreLines( String line ) | |||
{ | |||
return line.length() > 3 && line.charAt( 3 ) == '-'; | |||
} | |||
/** | |||
* Append the text from this line of the resonse. | |||
* | |||
* @param line Description of Parameter | |||
*/ | |||
private void append( String line ) | |||
{ | |||
if( line.length() > 4 ) | |||
{ | |||
result.append( line.substring( 4 ) ); | |||
result.append( " " ); | |||
} | |||
} | |||
} |