2006-12-12 18:57:24 -05:00
|
|
|
package davmail.smtp;
|
|
|
|
|
|
|
|
import davmail.AbstractConnection;
|
|
|
|
import davmail.DavGatewayTray;
|
|
|
|
import davmail.exchange.ExchangeSession;
|
|
|
|
import sun.misc.BASE64Decoder;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.net.Socket;
|
|
|
|
import java.util.Date;
|
|
|
|
import java.util.StringTokenizer;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dav Gateway smtp connection implementation
|
|
|
|
*/
|
|
|
|
public class SmtpConnection extends AbstractConnection {
|
|
|
|
protected static final int INITIAL = 0;
|
|
|
|
protected static final int AUTHENTICATED = 1;
|
|
|
|
protected static final int STARTMAIL = 2;
|
|
|
|
protected static final int RECIPIENT = 3;
|
|
|
|
protected static final int MAILDATA = 4;
|
|
|
|
|
|
|
|
// Initialize the streams and start the thread
|
2006-12-14 10:14:18 -05:00
|
|
|
public SmtpConnection(Socket clientSocket) {
|
|
|
|
super(clientSocket);
|
2006-12-12 18:57:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
public void run() {
|
|
|
|
String line;
|
|
|
|
StringTokenizer tokens;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
sendClient("220 DavMail SMTP ready at " + new Date());
|
|
|
|
for (; ;) {
|
|
|
|
line = readClient();
|
|
|
|
// unable to read line, connection closed ?
|
|
|
|
if (line == null) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
tokens = new StringTokenizer(line);
|
|
|
|
if (tokens.hasMoreTokens()) {
|
|
|
|
String command = tokens.nextToken();
|
|
|
|
|
|
|
|
if ("QUIT".equalsIgnoreCase(command)) {
|
|
|
|
sendClient("221 Closing connection");
|
|
|
|
break;
|
|
|
|
} else if ("EHLO".equals(command)) {
|
|
|
|
// inform server that AUTH is supported
|
|
|
|
// actually it is mandatory (only way to get credentials)
|
|
|
|
sendClient("250-AUTH LOGIN PLAIN");
|
|
|
|
sendClient("250 Hello");
|
|
|
|
} else if ("HELO".equals(command)) {
|
|
|
|
sendClient("250 Hello");
|
|
|
|
} else if ("AUTH".equals(command)) {
|
|
|
|
if (tokens.hasMoreElements()) {
|
|
|
|
String authType = tokens.nextToken();
|
|
|
|
if ("PLAIN".equals(authType) && tokens.hasMoreElements()) {
|
|
|
|
decodeCredentials(tokens.nextToken());
|
2006-12-14 10:14:18 -05:00
|
|
|
session = new ExchangeSession();
|
2006-12-12 18:57:24 -05:00
|
|
|
try {
|
|
|
|
session.login(userName, password);
|
|
|
|
sendClient("235 OK Authenticated");
|
|
|
|
state = AUTHENTICATED;
|
|
|
|
} catch (Exception e) {
|
|
|
|
DavGatewayTray.warn("Authentication failed",e);
|
|
|
|
sendClient("554 Authenticated failed");
|
|
|
|
state = INITIAL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
sendClient("451 Error : unknown authentication type");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
sendClient("451 Error : authentication type not specified");
|
|
|
|
}
|
|
|
|
} else if ("MAIL".equals(command)) {
|
|
|
|
if (state == AUTHENTICATED) {
|
|
|
|
state = STARTMAIL;
|
|
|
|
sendClient("250 Sender OK");
|
|
|
|
} else {
|
|
|
|
state = INITIAL;
|
|
|
|
sendClient("503 Bad sequence of commands");
|
|
|
|
}
|
|
|
|
} else if ("RCPT".equals(command)) {
|
|
|
|
if (state == STARTMAIL || state == RECIPIENT) {
|
|
|
|
state = RECIPIENT;
|
|
|
|
sendClient("250 Recipient OK");
|
|
|
|
} else {
|
|
|
|
state = AUTHENTICATED;
|
|
|
|
sendClient("503 Bad sequence of commands");
|
|
|
|
}
|
|
|
|
} else if ("DATA".equals(command)) {
|
|
|
|
if (state == RECIPIENT) {
|
|
|
|
state = MAILDATA;
|
|
|
|
sendClient("354 Start mail input; end with <CRLF>.<CRLF>");
|
|
|
|
|
|
|
|
try {
|
|
|
|
session.sendMessage(in);
|
|
|
|
state = AUTHENTICATED;
|
|
|
|
sendClient("250 Queued mail for delivery");
|
|
|
|
} catch (Exception e) {
|
|
|
|
DavGatewayTray.error("Authentication failed",e);
|
|
|
|
state = AUTHENTICATED;
|
2007-03-14 07:55:37 -04:00
|
|
|
sendClient("451 Error : " +e+" "+ e.getMessage());
|
2006-12-12 18:57:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
state = AUTHENTICATED;
|
|
|
|
sendClient("503 Bad sequence of commands");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
sendClient("500 Unrecognized command");
|
|
|
|
}
|
|
|
|
|
|
|
|
os.flush();
|
|
|
|
}
|
|
|
|
} catch (IOException e) {
|
|
|
|
DavGatewayTray.error("Exception handling client",e);
|
|
|
|
} finally {
|
|
|
|
try {
|
|
|
|
client.close();
|
|
|
|
} catch (IOException e2) {
|
|
|
|
DavGatewayTray.debug("Exception closing client",e2);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (session != null) {
|
|
|
|
session.close();
|
|
|
|
}
|
|
|
|
} catch (IOException e3) {
|
|
|
|
DavGatewayTray.debug("Exception closing gateway",e3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DavGatewayTray.resetIcon();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Decode SMTP credentials
|
|
|
|
*
|
|
|
|
* @param encodedCredentials smtp encoded credentials
|
2007-03-14 07:55:37 -04:00
|
|
|
* @throws java.io.IOException if invalid credentials
|
2006-12-12 18:57:24 -05:00
|
|
|
*/
|
|
|
|
protected void decodeCredentials(String encodedCredentials) throws IOException {
|
|
|
|
BASE64Decoder decoder = new BASE64Decoder();
|
|
|
|
String decodedCredentials = new String(decoder.decodeBuffer(encodedCredentials));
|
|
|
|
int index = decodedCredentials.indexOf((char) 0, 1);
|
|
|
|
if (index > 0) {
|
|
|
|
userName = decodedCredentials.substring(1, index);
|
|
|
|
password = decodedCredentials.substring(index + 1);
|
|
|
|
} else {
|
|
|
|
throw new IOException("Invalid credentials");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|