You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ch...@apache.org on 2001/03/22 11:33:01 UTC
cvs commit: jakarta-james/src/org/apache/james/smtpserver SMTPHandlerNew.java
charlesb 01/03/22 02:33:01
Added: src/org/apache/james/pop3server POP3HandlerNew.java
src/org/apache/james/smtpserver SMTPHandlerNew.java
Log:
Added new handlers proposed by Harmeet Bedi, untested
Revision Changes Path
1.1 jakarta-james/src/org/apache/james/pop3server/POP3HandlerNew.java
Index: POP3HandlerNew.java
===================================================================
/*
* 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 file.
*/
package org.apache.james.pop3server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.mail.MessagingException;
import org.apache.avalon.AbstractLoggable;
import org.apache.avalon.ComponentManager;
import org.apache.avalon.ComponentManagerException;
import org.apache.avalon.Composer;
import org.apache.avalon.Context;
import org.apache.avalon.Contextualizable;
import org.apache.avalon.Initializable;
import org.apache.avalon.configuration.Configurable;
import org.apache.avalon.configuration.Configuration;
import org.apache.avalon.configuration.ConfigurationException;
import org.apache.avalon.util.ListUtils;
import org.apache.cornerstone.services.connection.ConnectionHandler;
import org.apache.cornerstone.services.scheduler.PeriodicTimeTrigger;
import org.apache.cornerstone.services.scheduler.Target;
import org.apache.cornerstone.services.scheduler.TimeScheduler;
import org.apache.james.Constants;
import org.apache.james.core.MailImpl;
import org.apache.james.services.MailRepository;
import org.apache.james.services.MailServer;
import org.apache.james.services.UsersRepository;
import org.apache.james.services.UsersStore;
import org.apache.james.util.InternetPrintWriter;
import org.apache.mailet.Mail;
/**
* @author Federico Barbieri <sc...@systemy.it>
* @version 0.9
*/
public class POP3Handler
extends AbstractLoggable
implements ConnectionHandler, Contextualizable, Composer, Configurable, Target {
private String softwaretype = "JAMES POP3 Server " + Constants.SOFTWARE_VERSION;
private ComponentManager compMgr;
private MailServer mailServer;
private MailRepository userInbox;
private UsersRepository users;
private TimeScheduler scheduler;
private int timeout;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private OutputStream outs;
private String remoteHost;
private String remoteIP;
private String servername;
private int state;
private String user;
private Vector userMailbox = new Vector();
private Vector backupUserMailbox;
private static final Mail DELETED = new MailImpl();
private static int AUTHENTICATION_READY = 0;
private static int AUTHENTICATION_USERSET = 1;
private static int TRANSACTION = 2;
private final static String OK_RESPONSE = "+OK";
private final static String ERR_RESPONSE = "-ERR";
public void contextualize( final Context context ) {
servername = (String)context.get( Constants.HELO_NAME );
}
public void configure( final Configuration configuration )
throws ConfigurationException {
timeout = configuration.getChild( "connectiontimeout" ).getValueAsInt( 120000 );
}
public void compose( final ComponentManager componentManager )
throws ComponentManagerException {
mailServer = (MailServer)componentManager.
lookup( "org.apache.james.services.MailServer" );
UsersStore usersStore = (UsersStore)componentManager.
lookup( "org.apache.james.services.UsersStore" );
users = usersStore.getRepository("LocalUsers");
scheduler = (TimeScheduler)componentManager.
lookup( "org.apache.cornerstone.services.scheduler.TimeScheduler" );
}
/**
* Handle a connection.
* This handler is responsible for processing connections as they occur.
*
* @param connection the connection
* @exception IOException if an error reading from socket occurs
* @exception ProtocolException if an error handling connection occurs
*/
public void handleConnection( Socket connection )
throws IOException {
try {
this.socket = connection;
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
outs = socket.getOutputStream();
out = new InternetPrintWriter(outs, true);
remoteHost = socket.getInetAddress ().getHostName ();
remoteIP = socket.getInetAddress ().getHostAddress ();
} catch (Exception e) {
getLogger().error( "Cannot open connection from " + remoteHost +
" (" + remoteIP + "): " + e.getMessage(), e );
}
getLogger().info( "Connection from " + remoteHost + " (" + remoteIP + ")" );
try {
final PeriodicTimeTrigger trigger = new PeriodicTimeTrigger( timeout, -1 );
scheduler.addTrigger( this.toString(), trigger, this );
state = AUTHENTICATION_READY;
user = "unknown";
out.println( OK_RESPONSE + " " + this.servername +
" POP3 server (" + this.softwaretype + ") ready " );
while (parseCommand(in.readLine())) {
scheduler.resetTrigger(this.toString());
}
socket.close();
scheduler.removeTrigger(this.toString());
getLogger().info("Connection closed");
} catch (Exception e) {
out.println(ERR_RESPONSE + " Error closing connection.");
out.flush();
getLogger().error( "Exception during connection from " + remoteHost +
" (" + remoteIP + ") : " + e.getMessage(), e );
try {
socket.close();
} catch (IOException ioe) {
}
}
}
public void targetTriggered( final String triggerName ) {
getLogger().error("Connection timeout on socket");
try {
out.println("Connection timeout. Closing connection");
socket.close();
} catch (IOException e) {
}
}
private void stat() {
userMailbox = new Vector();
userMailbox.addElement(DELETED);
for (Iterator it = userInbox.list(); it.hasNext(); ) {
String key = (String) it.next();
MailImpl mc = userInbox.retrieve(key);
userMailbox.addElement(mc);
}
backupUserMailbox = (Vector) userMailbox.clone();
}
private boolean parseCommand(String commandRaw) {
if (commandRaw == null) return false;
getLogger().info("Command received: " + commandRaw);
String command = commandRaw.trim();
StringTokenizer commandLine = new StringTokenizer(command, " ");
int arguments = commandLine.countTokens();
if (arguments == 0) {
return true;
} else if(arguments > 0) {
command = commandLine.nextToken();
}
String argument = (String) null;
if(arguments > 1) {
argument = commandLine.nextToken();
}
String argument1 = (String) null;
if(arguments > 2) {
argument1 = commandLine.nextToken();
}
if (command.equalsIgnoreCase("USER"))
doUSER(command,argument,argument1);
else if (command.equalsIgnoreCase("PASS"))
doPASS(command,argument,argument1);
else if (command.equalsIgnoreCase("STAT"))
doSTAT(command,argument,argument1);
else if (command.equalsIgnoreCase("LIST"))
doLIST(command,argument,argument1);
else if (command.equalsIgnoreCase("UIDL"))
doUIDL(command,argument,argument1);
else if (command.equalsIgnoreCase("RSET"))
doRSET(command,argument,argument1);
else if (command.equalsIgnoreCase("DELE"))
doDELE(command,argument,argument1);
else if (command.equalsIgnoreCase("NOOP"))
doNOOP(command,argument,argument1);
else if (command.equalsIgnoreCase("RETR"))
doRETR(command,argument,argument1);
else if (command.equalsIgnoreCase("TOP"))
doTOP(command,argument,argument1);
else if (command.equalsIgnoreCase("QUIT"))
doQUIT(command,argument,argument1);
else
doUnknownCmd(command,argument,argument1);
return (command.equalsIgnoreCase("QUIT") == false);
}
private void doUSER(String command,String argument,String argument1) {
if (state == AUTHENTICATION_READY && argument != null) {
user = argument;
state = AUTHENTICATION_USERSET;
out.println(OK_RESPONSE);
} else {
out.println(ERR_RESPONSE);
}
}
private void doPASS(String command,String argument,String argument1) {
if (state == AUTHENTICATION_USERSET && argument != null) {
String passArg = argument;
if (users.test(user, passArg)) {
state = TRANSACTION;
out.println(OK_RESPONSE + " Welcome " + user);
userInbox = mailServer.getUserInbox(user);
stat();
} else {
state = AUTHENTICATION_READY;
out.println(ERR_RESPONSE + " Authentication failed.");
}
} else {
out.println(ERR_RESPONSE);
}
}
private void doSTAT(String command,String argument,String argument1) {
if (state == TRANSACTION) {
long size = 0;
int count = 0;
try {
for (Enumeration e = userMailbox.elements(); e.hasMoreElements(); ) {
MailImpl mc = (MailImpl) e.nextElement();
if (mc != DELETED) {
size += mc.getSize();
count++;
}
}
out.println(OK_RESPONSE + " " + count + " " + size);
} catch (MessagingException me) {
out.println(ERR_RESPONSE);
}
} else {
out.println(ERR_RESPONSE);
}
}
private void doLIST(String command,String argument,String argument1) {
if (state == TRANSACTION) {
if (argument == null) {
long size = 0;
int count = 0;
try {
for (Enumeration e = userMailbox.elements(); e.hasMoreElements(); ) {
MailImpl mc = (MailImpl) e.nextElement();
if (mc != DELETED) {
size += mc.getSize();
count++;
}
}
out.println(OK_RESPONSE + " " + count + " " + size);
count = 0;
for (Enumeration e = userMailbox.elements(); e.hasMoreElements(); count++) {
MailImpl mc = (MailImpl) e.nextElement();
if (mc != DELETED) {
out.println(count + " " + mc.getSize());
}
}
out.println(".");
} catch (MessagingException me) {
out.println(ERR_RESPONSE);
}
} else {
int num = 0;
try {
num = Integer.parseInt(argument);
MailImpl mc = (MailImpl) userMailbox.elementAt(num);
if (mc != DELETED) {
out.println(OK_RESPONSE + " " + num + " " + mc.getSize());
} else {
out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
}
} catch (ArrayIndexOutOfBoundsException npe) {
out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
} catch (NumberFormatException nfe) {
out.println(ERR_RESPONSE + " " + argument + " is not a valid number");
} catch (MessagingException me) {
out.println(ERR_RESPONSE);
}
}
} else {
out.println(ERR_RESPONSE);
}
}
private void doUIDL(String command,String argument,String argument1) {
if (state == TRANSACTION) {
if (argument == null) {
out.println(OK_RESPONSE + " unique-id listing follows");
int count = 0;
for (Enumeration e = userMailbox.elements(); e.hasMoreElements(); count++) {
MailImpl mc = (MailImpl) e.nextElement();
if (mc != DELETED) {
out.println(count + " " + mc.getName());
}
}
out.println(".");
} else {
int num = 0;
try {
num = Integer.parseInt(argument);
MailImpl mc = (MailImpl) userMailbox.elementAt(num);
if (mc != DELETED) {
out.println(OK_RESPONSE + " " + num + " " + mc.getName());
} else {
out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
}
} catch (ArrayIndexOutOfBoundsException npe) {
out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
} catch (NumberFormatException nfe) {
out.println(ERR_RESPONSE + " " + argument + " is not a valid number");
}
}
} else {
out.println(ERR_RESPONSE);
}
}
private void doRSET(String command,String argument,String argument1) {
if (state == TRANSACTION) {
stat();
out.println(OK_RESPONSE);
} else {
out.println(ERR_RESPONSE);
}
}
private void doDELE(String command,String argument,String argument1) {
if (state == TRANSACTION) {
int num = 0;
try {
num = Integer.parseInt(argument);
} catch (Exception e) {
out.println(ERR_RESPONSE + " Usage: DELE [mail number]");
return;
}
try {
MailImpl mc = (MailImpl) userMailbox.elementAt(num);
if (mc == DELETED) {
out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
} else {
userMailbox.setElementAt(DELETED, num);
out.println(OK_RESPONSE + " Message removed");
}
} catch (ArrayIndexOutOfBoundsException iob) {
out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
}
} else {
out.println(ERR_RESPONSE);
}
}
private void doNOOP(String command,String argument,String argument1) {
if (state == TRANSACTION) {
out.println(OK_RESPONSE);
} else {
out.println(ERR_RESPONSE);
}
}
private void doRETR(String command,String argument,String argument1) {
if (state == TRANSACTION) {
int num = 0;
try {
num = Integer.parseInt(argument.trim());
} catch (Exception e) {
out.println(ERR_RESPONSE + " Usage: RETR [mail number]");
return;
}
//?May be written as
//return parseCommand("TOP " + num + " " + Integer.MAX_VALUE);?
try {
MailImpl mc = (MailImpl) userMailbox.elementAt(num);
if (mc != DELETED) {
out.println(OK_RESPONSE + " Message follows");
mc.writeMessageTo(outs);
out.println();
out.println(".");
} else {
out.println(ERR_RESPONSE + " Message (" + num + ") deleted.");
}
} catch (IOException ioe) {
out.println(ERR_RESPONSE + " Error while retrieving message.");
} catch (MessagingException me) {
out.println(ERR_RESPONSE + " Error while retrieving message.");
} catch (ArrayIndexOutOfBoundsException iob) {
out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
}
// -------------------------------------------?
} else {
out.println(ERR_RESPONSE);
}
}
private void doTOP(String command,String argument,String argument1) {
if (state == TRANSACTION) {
int num = 0;
int lines = 0;
try {
num = Integer.parseInt(argument);
lines = Integer.parseInt(argument1);
} catch (NumberFormatException nfe) {
out.println(ERR_RESPONSE + " Usage: TOP [mail number] [Line number]");
return;
}
try {
MailImpl mc = (MailImpl) userMailbox.elementAt(num);
if (mc != DELETED) {
out.println(OK_RESPONSE + " Message follows");
for (Enumeration e = mc.getMessage().getAllHeaderLines(); e.hasMoreElements(); ) {
out.println(e.nextElement());
}
out.println("");
mc.writeContentTo(outs, lines);
out.println(".");
} else {
out.println(ERR_RESPONSE + " Message (" + num + ") already deleted.");
}
} catch (IOException ioe) {
out.println(ERR_RESPONSE + " Error while retrieving message.");
} catch (MessagingException me) {
out.println(ERR_RESPONSE + " Error while retrieving message.");
} catch (ArrayIndexOutOfBoundsException iob) {
out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
}
} else {
out.println(ERR_RESPONSE);
}
}
private void doQUIT(String command,String argument,String argument1) {
if (state == AUTHENTICATION_READY || state == AUTHENTICATION_USERSET) {
return;
}
List toBeRemoved = ListUtils.subtract(backupUserMailbox, userMailbox);
try {
for (Iterator it = toBeRemoved.iterator(); it.hasNext(); ) {
MailImpl mc = (MailImpl) it.next();
userInbox.remove(mc.getName());
}
out.println(OK_RESPONSE + " Apache James POP3 Server signing off.");
} catch (Exception ex) {
out.println(ERR_RESPONSE + " Some deleted messages were not removed");
getLogger().error("Some deleted messages were not removed: " + ex.getMessage());
}
}
private void doUnknownCmd(String command,String argument,String argument1) {
out.println(ERR_RESPONSE);
}
}
1.1 jakarta-james/src/org/apache/james/smtpserver/SMTPHandlerNew.java
Index: SMTPHandlerNew.java
===================================================================
/*
* 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 file.
*/
package org.apache.james.smtpserver;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import org.apache.avalon.AbstractLoggable;
import org.apache.avalon.ComponentManager;
import org.apache.avalon.ComponentManagerException;
import org.apache.avalon.Composer;
import org.apache.avalon.Context;
import org.apache.avalon.Contextualizable;
import org.apache.avalon.Initializable;
import org.apache.avalon.configuration.Configurable;
import org.apache.avalon.configuration.Configuration;
import org.apache.avalon.configuration.ConfigurationException;
import org.apache.cornerstone.services.connection.ConnectionHandler;
import org.apache.cornerstone.services.scheduler.PeriodicTimeTrigger;
import org.apache.cornerstone.services.scheduler.Target;
import org.apache.cornerstone.services.scheduler.TimeScheduler;
import org.apache.james.*;
import org.apache.james.core.*;
import org.apache.james.services.MailServer;
import org.apache.james.util.*;
import org.apache.mailet.*;
/**
* This handles an individual incoming message. It handles regular SMTP
* commands, and when it receives a message, adds it to the spool.
* @author Serge Knystautas <se...@lokitech.com>
* @author Federico Barbieri <sc...@systemy.it>
* @version 0.9
*/
public class SMTPHandler
extends AbstractLoggable
implements ConnectionHandler, Contextualizable, Composer, Configurable, Target {
public final static String SERVER_NAME = "SERVER_NAME";
public final static String SERVER_TYPE = "SERVER_TYPE";
public final static String REMOTE_NAME = "REMOTE_NAME";
public final static String REMOTE_IP = "REMOTE_IP";
public final static String NAME_GIVEN = "NAME_GIVEN";
public final static String CURRENT_HELO_MODE = "CURRENT_HELO_MODE";
public final static String SENDER = "SENDER_ADDRESS";
public final static String RCPT_VECTOR = "RCPT_VECTOR";
public final static String SMTP_ID = "SMTP_ID";
public final static char[] SMTPTerminator = {'\r','\n','.','\r','\n'};
private Socket socket;
private DataInputStream in;
private PrintWriter out;
private String remoteHost;
private String remoteHostGiven;
private String remoteIP;
private String messageID;
private String smtpID;
private Configuration conf;
private TimeScheduler scheduler;
private MailServer mailServer;
private String servername;
private String softwaretype = "JAMES SMTP Server " + Constants.SOFTWARE_VERSION;
private static long count;
private Hashtable state = new Hashtable();
private Random random = new Random();
private int timeout;
public void configure(Configuration conf) throws ConfigurationException {
this.conf = conf;
timeout = conf.getChild( "connectiontimeout" ).getValueAsInt( 120000 );
}
public void contextualize( final Context context ) {
servername = (String)context.get( Constants.HELO_NAME );
}
public void compose( final ComponentManager componentManager )
throws ComponentManagerException {
mailServer = (MailServer)componentManager.lookup("org.apache.james.services.MailServer");
scheduler = (TimeScheduler)componentManager.
lookup("org.apache.cornerstone.services.scheduler.TimeScheduler");
}
/**
* Handle a connection.
* This handler is responsible for processing connections as they occur.
*
* @param connection the connection
* @exception IOException if an error reading from socket occurs
* @exception ProtocolException if an error handling connection occurs
*/
public void handleConnection( Socket connection )
throws IOException {
try {
this.socket = connection;
final InputStream bufferedInput =
new BufferedInputStream( socket.getInputStream(), 1024 );
in = new DataInputStream( bufferedInput );
out = new InternetPrintWriter(socket.getOutputStream(), true);
remoteHost = socket.getInetAddress ().getHostName ();
remoteIP = socket.getInetAddress ().getHostAddress ();
smtpID = Math.abs(random.nextInt() % 1024) + "";
state.clear();
state.put(SERVER_NAME, this.servername );
state.put(SERVER_TYPE, this.softwaretype );
state.put(REMOTE_NAME, remoteHost);
state.put(REMOTE_IP, remoteIP);
state.put(SMTP_ID, smtpID);
} catch (Exception e) {
getLogger().error("Cannot open connection from " + remoteHost + " (" + remoteIP + "): " + e.getMessage(), e );
throw new RuntimeException("Cannot open connection from " + remoteHost + " (" + remoteIP + "): " + e.getMessage());
}
getLogger().info("Connection from " + remoteHost + " (" + remoteIP + ")");
try {
// Initially greet the connector
// Format is: Sat, 24 Jan 1998 13:16:09 -0500
final PeriodicTimeTrigger trigger = new PeriodicTimeTrigger( timeout, -1 );
scheduler.addTrigger( this.toString(), trigger, this );
out.println("220 " + this.servername + " SMTP Server (" + softwaretype + ") ready " + RFC822DateFormat.toString(new Date()));
while (parseCommand(in.readLine())) {
scheduler.resetTrigger(this.toString());
}
socket.close();
scheduler.removeTrigger(this.toString());
} catch (SocketException se) {
getLogger().debug("Socket to " + remoteHost + " closed remotely.", se );
} catch ( InterruptedIOException iioe ) {
getLogger().debug( "Socket to " + remoteHost + " timeout.", iioe );
} catch ( IOException ioe ) {
getLogger().debug( "Exception handling socket to " + remoteHost + ":"
+ ioe.getMessage(), ioe );
} catch (Exception e) {
getLogger().debug( "Exception opening socket: " + e.getMessage(), e );
} finally {
try {
socket.close();
} catch (IOException e) {
getLogger().error("Exception closing socket: " + e.getMessage());
}
}
}
public void targetTriggered( final String triggerName ) {
getLogger().error("Connection timeout on socket");
try {
out.println("Connection timeout. Closing connection");
socket.close();
} catch (IOException e) {
}
}
private void resetState() {
state.clear();
state.put(SERVER_NAME, this.servername );
state.put(SERVER_TYPE, this.softwaretype );
state.put(REMOTE_NAME, remoteHost);
state.put(REMOTE_IP, remoteIP);
state.put(SMTP_ID, smtpID);
}
private boolean parseCommand(String command)
throws Exception {
if (command == null) return false;
getLogger().info("Command received: " + command);
StringTokenizer commandLine = new StringTokenizer(command.trim(), " :");
int arguments = commandLine.countTokens();
if (arguments == 0) {
return true;
} else if(arguments > 0) {
command = commandLine.nextToken();
}
String argument = (String) null;
if(arguments > 1) {
argument = commandLine.nextToken();
}
String argument1 = (String) null;
if(arguments > 2) {
argument1 = commandLine.nextToken();
}
if (command.equalsIgnoreCase("HELO"))
doHELO(command,argument,argument1);
else if (command.equalsIgnoreCase("EHLO"))
doEHLO(command,argument,argument1);
else if (command.equalsIgnoreCase("MAIL"))
doMAIL(command,argument,argument1);
else if (command.equalsIgnoreCase("RCPT"))
doRCPT(command,argument,argument1);
else if (command.equalsIgnoreCase("NOOP"))
doNOOP(command,argument,argument1);
else if (command.equalsIgnoreCase("RSET"))
doRSET(command,argument,argument1);
else if (command.equalsIgnoreCase("DATA"))
doDATA(command,argument,argument1);
else if (command.equalsIgnoreCase("QUIT"))
doQUIT(command,argument,argument1);
else
doUnknownCmd(command,argument,argument1);
return (command.equalsIgnoreCase("QUIT") == false);
}
private void doHELO(String command,String argument,String argument1) {
if (state.containsKey(CURRENT_HELO_MODE)) {
out.println("250 " + state.get(SERVER_NAME) + " Duplicate HELO/EHLO");
} else if (argument == null) {
out.println("501 domain address required: " + command);
} else {
state.put(CURRENT_HELO_MODE, command);
state.put(NAME_GIVEN, argument);
out.println("250 " + state.get(SERVER_NAME) + " Hello " + argument +
" (" + state.get(REMOTE_NAME) +
" [" + state.get(REMOTE_IP) + "])");
}
}
private void doEHLO(String command,String argument,String argument1) {
doHELO(command,argument,argument1);
}
private void doMAIL(String command,String argument,String argument1) {
if (state.containsKey(SENDER)) {
out.println("503 Sender already specified");
} else if (argument == null || !argument.equalsIgnoreCase("FROM")
|| argument1 == null) {
out.println("501 Usage: MAIL FROM:<sender>");
} else {
String sender = argument1.trim();
if (!sender.startsWith("<") || !sender.endsWith(">")) {
out.println("501 Syntax error in parameters or arguments");
getLogger().error("Error parsing sender address: " + sender
+ ": did not start and end with < >");
return;
}
MailAddress senderAddress = null;
//Remove < and >
sender = sender.substring(1, sender.length() - 1);
try {
senderAddress = new MailAddress(sender);
} catch (Exception pe) {
out.println("501 Syntax error in parameters or arguments");
getLogger().error("Error parsing sender address: " + sender
+ ": " + pe.getMessage());
return;
}
state.put(SENDER, senderAddress);
out.println("250 Sender <" + sender + "> OK");
}
}
private void doRCPT(String command,String argument,String argument1) {
if (!state.containsKey(SENDER)) {
out.println("503 Need MAIL before RCPT");
} else if (argument == null || !argument.equalsIgnoreCase("TO") || argument1 == null) {
out.println("501 Usage: RCPT TO:<recipient>");
} else {
Collection rcptColl = (Collection) state.get(RCPT_VECTOR);
if (rcptColl == null) {
rcptColl = new Vector();
}
String recipient = argument1.trim();
if (!recipient.startsWith("<") || !recipient.endsWith(">")) {
out.println("Syntax error in parameters or arguments");
getLogger().error("Error parsing recipient address: "
+ recipient
+ ": did not start and end with < >");
return;
}
MailAddress recipientAddress = null;
//Remove < and >
recipient = recipient.substring(1, recipient.length() - 1);
try {
recipientAddress = new MailAddress(recipient);
} catch (Exception pe) {
out.println("501 Syntax error in parameters or arguments");
getLogger().error("Error parsing recipient address: "
+ recipient + ": " + pe.getMessage());
return;
}
rcptColl.add(recipientAddress);
state.put(RCPT_VECTOR, rcptColl);
out.println("250 Recipient <" + recipient + "> OK");
}
}
private void doNOOP(String command,String argument,String argument1) {
out.println("250 OK");
}
private void doRSET(String command,String argument,String argument1) {
resetState();
out.println("250 OK");
}
private void doDATA(String command,String argument,String argument1) {
if (!state.containsKey(SENDER)) {
out.println("503 No sender specified");
} else if (!state.containsKey(RCPT_VECTOR)) {
out.println("503 No recipients specified");
} else {
out.println("354 Ok Send data ending with <CRLF>.<CRLF>");
try {
// parse headers
InputStream msgIn = new CharTerminatedInputStream(in, SMTPTerminator);
MailHeaders headers = new MailHeaders(msgIn);
// if headers do not contains minimum REQUIRED headers fields add them
if (!headers.isSet("Date")) {
headers.setHeader("Date", RFC822DateFormat.toString (new Date ()));
}
/*
We no longer add To as this in practice is not set (from what I've seen)
if (!headers.isSet("To")) {
headers.setHeader("To", );
}
*/
if (!headers.isSet("From")) {
headers.setHeader("From", state.get(SENDER).toString());
}
String received = "from " + state.get(REMOTE_NAME) + " ([" + state.get(REMOTE_IP)
+ "])\r\n by " + this.servername + " ("
+ softwaretype + ") with SMTP ID " + state.get(SMTP_ID);
if (((Collection)state.get(RCPT_VECTOR)).size () == 1) {
//Only indicate a recipient if they're the only recipient
//(prevents email address harvesting and large headers in bulk email)
received += "\r\n for <"
+ ((Vector)state.get(RCPT_VECTOR)).elementAt(0).toString() + ">";
}
received += ";\r\n " + RFC822DateFormat.toString (new Date ());
headers.addHeader ("Received", received);
// headers.setReceivedStamp("Unknown", (String) serverNames.elementAt(0));
ByteArrayInputStream headersIn = new ByteArrayInputStream(headers.toByteArray());
MailImpl mail = new MailImpl(mailServer.getId(), (MailAddress)state.get(SENDER),
(Vector)state.get(RCPT_VECTOR),
new SequenceInputStream(headersIn, msgIn));
mail.setRemoteHost((String)state.get(REMOTE_NAME));
mail.setRemoteAddr((String)state.get(REMOTE_IP));
mailServer.sendMail(mail);
} catch (MessagingException me) {
out.println("451 Error processing message: " + me.getMessage());
getLogger().error("Error processing message: "
+ me.getMessage());
return;
}
getLogger().info("Mail sent to Mail Server");
resetState();
out.println("250 Message received");
}
}
private void doQUIT(String command,String argument,String argument1) {
out.println("221 " + state.get(SERVER_NAME) + " Service closing transmission channel");
}
private void doUnknownCmd(String command,String argument,String argument1) {
out.println("500 " + state.get(SERVER_NAME) + " Syntax error, command unrecognized: " +
command);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: james-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: james-dev-help@jakarta.apache.org