Main source tree import

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@3 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2006-12-12 23:57:24 +00:00
parent 93241202ce
commit 0351a49c9d
15 changed files with 2255 additions and 0 deletions

View File

@ -0,0 +1,80 @@
package davmail;
import davmail.exchange.ExchangeSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
/**
* Generic connection common to pop3 and smtp implementations
*/
public class AbstractConnection extends Thread {
protected Socket client;
protected BufferedReader in;
protected OutputStream os;
// exchange server url
protected String url;
// user name and password initialized through connection
protected String userName = null;
protected String password = null;
// connection state
protected int state = 0;
// Exchange session proxy
protected ExchangeSession session;
// Initialize the streams and start the thread
public AbstractConnection(String url, Socket clientSocket) {
this.url = url;
client = clientSocket;
try {
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
os = client.getOutputStream();
} catch (IOException e) {
try {
client.close();
} catch (IOException e2) {
DavGatewayTray.error("Exception while getting socket streams",e2);
}
DavGatewayTray.error("Exception while getting socket streams", e);
return;
}
// start the thread
this.start();
}
public void sendClient(String message) throws IOException {
sendClient(null, message);
}
public void sendClient(String prefix, String message) throws IOException {
StringBuffer logBuffer = new StringBuffer("> ");
if (prefix != null) {
logBuffer.append(prefix);
os.write(prefix.getBytes());
}
logBuffer.append(message);
DavGatewayTray.debug(logBuffer.toString());
os.write(message.getBytes());
os.write('\r');
os.write('\n');
os.flush();
}
/**
* Read a line from the client connection.
* Log message to stdout
* @return command line or null
* @throws IOException
*/
public String readClient() throws IOException {
String line = in.readLine();
DavGatewayTray.debug("< "+line);
DavGatewayTray.switchIcon();
return line;
}
}

View File

@ -0,0 +1,63 @@
package davmail;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
/**
* Generic abstract server common to SMTP and POP3 implementations
*/
public abstract class AbstractServer extends Thread {
protected int port;
protected String url;
protected ServerSocket serverSocket;
/**
* Create a ServerSocket to listen for connections.
* Start the thread.
*/
public AbstractServer(String url, int port) {
this.port = port;
this.url = url;
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
fail(e, "Exception creating server socket");
}
}
// Exit with an error message, when an exception occurs.
public static void fail(Exception e, String msg) {
System.err.println(msg + ": " + e);
System.exit(1);
}
/**
* The body of the server thread. Loop forever, listening for and
* accepting connections from clients. For each connection,
* create a Connection object to handle communication through the
* new Socket.
*/
public void run() {
try {
//noinspection InfiniteLoopStatement
while (true) {
Socket clientSocket = serverSocket.accept();
DavGatewayTray.debug("Connection from " + clientSocket.getInetAddress() + " on port " + port);
// only accept localhost connections for security reasons
if (clientSocket.getInetAddress().toString().indexOf("127.0.0.1") > 0) {
createConnectionHandler(url, clientSocket);
} else {
clientSocket.close();
DavGatewayTray.warn("Connection from external client refused");
}
System.gc();
}
} catch (IOException e) {
fail(e, "Exception while listening for connections");
}
}
public abstract void createConnectionHandler(String url, Socket clientSocket);
}

View File

@ -0,0 +1,52 @@
package davmail;
import davmail.imap.ImapServer;
import davmail.pop.PopServer;
import davmail.smtp.SmtpServer;
/**
* DavGateway main class
*/
public class DavGateway {
protected static final String USAGE_MESSAGE = "Usage : java davmail.DavGateway url [smtplistenport] [pop3listenport] [imaplistenport]";
/**
* Start the gateway, listen on spécified smtp and pop3 ports
*/
public static void main(String[] args) {
int smtpPort = SmtpServer.DEFAULT_PORT;
int popPort = PopServer.DEFAULT_PORT;
int imapPort = ImapServer.DEFAULT_PORT;
String url;
if (args.length >= 1) {
url = args[0];
try {
if (args.length >= 2) {
smtpPort = Integer.parseInt(args[1]);
}
if (args.length >= 3) {
popPort = Integer.parseInt(args[2]);
}
if (args.length >= 4) {
imapPort = Integer.parseInt(args[3]);
}
DavGatewayTray.init();
SmtpServer smtpServer = new SmtpServer(url, smtpPort);
PopServer popServer = new PopServer(url, popPort);
ImapServer imapServer = new ImapServer(url, imapPort);
smtpServer.start();
popServer.start();
imapServer.start();
DavGatewayTray.info("Listening on ports " + smtpPort + " "+popPort+" "+imapPort);
} catch (NumberFormatException e) {
System.out.println(DavGateway.USAGE_MESSAGE);
}
} else {
System.out.println(DavGateway.USAGE_MESSAGE);
}
}
}

View File

@ -0,0 +1,145 @@
package davmail;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.net.URL;
/**
* Tray icon handler
*/
public class DavGatewayTray {
protected static final Logger logger = Logger.getLogger("davmail");
// lock for synchronized block
protected static final Object lock = new Object();
protected static TrayIcon trayIcon = null;
protected static Image image = null;
protected static Image image2 = null;
public static void switchIcon() {
try {
synchronized (lock) {
if (trayIcon.getImage() == image) {
trayIcon.setImage(image2);
} else {
trayIcon.setImage(image);
}
}
} catch (NoClassDefFoundError e) {
// ignore, jdk <= 1.6
}
}
public static void resetIcon() {
try {
synchronized (lock) {
trayIcon.setImage(image);
}
} catch (NoClassDefFoundError e) {
// ignore, jdk <= 1.6
}
}
protected static void displayMessage(String message, Priority priority) {
synchronized (lock) {
if (trayIcon != null) {
TrayIcon.MessageType messageType = null;
if (priority == Priority.INFO) {
messageType = TrayIcon.MessageType.INFO;
} else if (priority == Priority.WARN) {
messageType = TrayIcon.MessageType.WARNING;
} else if (priority == Priority.ERROR) {
messageType = TrayIcon.MessageType.ERROR;
}
if (messageType != null) {
trayIcon.displayMessage("DavMail gateway", message, messageType);
}
trayIcon.setToolTip("DavMail gateway \n"+message);
}
logger.log(priority, message);
}
}
public static void debug(String message) {
displayMessage(message, Priority.DEBUG);
}
public static void info(String message) {
displayMessage(message, Priority.INFO);
}
public static void warn(String message) {
displayMessage(message, Priority.WARN);
}
public static void error(String message) {
displayMessage(message, Priority.ERROR);
}
public static void debug(String message, Exception e) {
debug(message + " " + e + " " + e.getMessage());
}
public static void info(String message, Exception e) {
info(message + " " + e + " " + e.getMessage());
}
public static void warn(String message, Exception e) {
warn(message + " " + e + " " + e.getMessage());
}
public static void error(String message, Exception e) {
error(message + " " + e + " " + e.getMessage());
}
public static void init() {
try {
if (SystemTray.isSupported()) {
// get the SystemTray instance
SystemTray tray = SystemTray.getSystemTray();
// load an image
ClassLoader classloader = DavGatewayTray.class.getClassLoader();
URL imageUrl = classloader.getResource("tray.png");
image = Toolkit.getDefaultToolkit().getImage(imageUrl);
URL imageUrl2 = classloader.getResource("tray2.png");
image2 = Toolkit.getDefaultToolkit().getImage(imageUrl2);
// create a action listener to listen for default action executed on the tray icon
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
SystemTray.getSystemTray().remove(trayIcon);
System.exit(0);
}
};
// create a popup menu
PopupMenu popup = new PopupMenu();
// create menu item for the default action
MenuItem defaultItem = new MenuItem("Exit");
defaultItem.addActionListener(listener);
popup.add(defaultItem);
/// ... add other items
// construct a TrayIcon
trayIcon = new TrayIcon(image, "DavMail Gateway", popup);
// set the TrayIcon properties
trayIcon.addActionListener(listener);
// ...
// add the tray image
try {
tray.add(trayIcon);
} catch (AWTException e) {
System.err.println(e);
}
}
} catch (NoClassDefFoundError e) {
DavGatewayTray.warn("JDK 1.6 needed for system tray support");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
package davmail.exchange;
import java.io.*;
import java.util.List;
import org.jdom.*;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.jdom.xpath.XPath;
public class XmlDocument {
private Document document;
public String getAttribute(String xpath) {
String result = null;
try {
XPath xpathExpr = XPath.newInstance(xpath);
Attribute attribute = (Attribute) xpathExpr.selectSingleNode(
document);
if (attribute != null) {
result = attribute.getValue();
}
} catch (JDOMException ex) {
// TODO handle exception
}
return result;
}
public String getValue(String xpath) {
String result = null;
try {
XPath xpathExpr = XPath.newInstance(xpath);
Element element = (Element) xpathExpr.selectSingleNode(document);
if (element != null) {
result = element.getText();
}
} catch (JDOMException ex) {
// TODO handle exception
}
return result;
}
public String getXmlValue(String xpath) {
String result = null;
try {
XPath xpathExpr = XPath.newInstance(xpath);
Element element = (Element) xpathExpr.selectSingleNode(document);
if (element != null) {
XMLOutputter outputter = new XMLOutputter();
StringWriter xmlWriter = new StringWriter();
outputter.output(element, xmlWriter);
result = xmlWriter.toString();
}
} catch (IOException ex) {
// TODO handle exception
} catch (JDOMException ex) {
// TODO handle exception
}
return result;
}
public List getContent(String xpath) {
List result = null;
XPath xpathExpr;
try {
xpathExpr = XPath.newInstance(xpath);
Element element = (Element) xpathExpr.selectSingleNode(document);
if (element != null) {
result = element.getContent();
}
} catch (JDOMException ex) {
// TODO handle exception
}
return result;
}
public List<Attribute> getNodes(String xpath) {
List<Attribute> result = null;
try {
XPath xpathExpr = XPath.newInstance(xpath);
result = xpathExpr.selectNodes(document);
} catch (JDOMException ex) {
// TODO handle exception
}
return result;
}
public String toString() {
if (document == null) {
return null;
}
StringWriter writer = new StringWriter();
XMLOutputter outputter = new XMLOutputter();
outputter.setFormat(Format.getPrettyFormat());
try {
outputter.output(document, writer);
} catch (IOException ex) {
// TODO : handle exception
}
return writer.toString();
}
public XmlDocument() {
}
public void load(String location) throws JDOMException, IOException {
document = new SAXBuilder().build(location);
}
public void load(InputStream stream, String dtd) throws JDOMException, IOException {
document = new SAXBuilder().build(stream, dtd);
}
public void load(Document value) throws JDOMException, IOException {
document = value;
}
public String toString(Element element) {
if (document == null) {
return null;
}
StringWriter writer = new StringWriter();
XMLOutputter outputter = new XMLOutputter();
outputter.setFormat(Format.getPrettyFormat());
try {
outputter.output(element, writer);
} catch (IOException ex) {
// TODO: handle Exception
}
return writer.toString();
}
}

View File

@ -0,0 +1,185 @@
package davmail.imap;
import java.net.Socket;
import java.util.StringTokenizer;
import java.util.List;
import java.io.IOException;
import davmail.AbstractConnection;
import davmail.DavGatewayTray;
import davmail.exchange.ExchangeSession;
/**
* Dav Gateway smtp connection implementation.
* Still alpha code : need to find a way to handle message ids
*/
public class ImapConnection extends AbstractConnection {
protected static final int INITIAL = 0;
protected static final int AUTHENTICATED = 1;
// Initialize the streams and start the thread
public ImapConnection(String url, Socket clientSocket) {
super(url, clientSocket);
}
public void run() {
String line;
StringTokenizer tokens;
try {
sendClient("* OK Davmail Imap Server ready");
for (; ;) {
line = readClient();
// unable to read line, connection closed ?
if (line == null) {
break;
}
tokens = new StringTokenizer(line);
if (tokens.hasMoreTokens()) {
String commandId = tokens.nextToken();
if (tokens.hasMoreTokens()) {
String command = tokens.nextToken();
if ("LOGOUT".equalsIgnoreCase(command)) {
sendClient("* BYE Closing connection");
sendClient(commandId + " OK Completed");
break;
}
if ("capability".equalsIgnoreCase(command)) {
sendClient("* CAPABILITY IMAP4REV1");
sendClient(commandId + " OK CAPABILITY completed");
} else if ("login".equalsIgnoreCase(command)) {
parseCredentials(tokens);
session = new ExchangeSession(url);
try {
session.login(userName, password);
sendClient(commandId + " OK Authenticated");
state = AUTHENTICATED;
} catch (Exception e) {
DavGatewayTray.error("Authentication failed",e);
sendClient(commandId + " NO LOGIN failed");
state = INITIAL;
}
} else {
if (state != AUTHENTICATED) {
sendClient(commandId + " BAD command authentication required");
} else {
if ("lsub".equalsIgnoreCase(command)) {
/* TODO : implement
2 lsub "" "*"
* LSUB () "/" INBOX/sent-mail
* LSUB () "/" Trash
* LSUB () "/" INBOX/spam
* LSUB () "/" Envoy&AOk-s
* LSUB () "/" Drafts
2 OK LSUB completed
*/
sendClient(commandId + " OK LSUB completed");
} else if ("list".equalsIgnoreCase(command)) {
/* TODO : implement
*/
sendClient(commandId + " OK LIST completed");
} else if ("select".equalsIgnoreCase(command)) {
if (tokens.hasMoreTokens()) {
String folderName = removeQuotes(tokens.nextToken());
ExchangeSession.Folder folder = session.selectFolder(folderName);
sendClient("* " + folder.childCount + " EXISTS");
sendClient("* " + folder.unreadCount + " RECENT");
// TODO : implement, compute session message ids
//sendClient("* [UNSEEN 1] first unseen message in inbox");
sendClient(commandId + " OK [READ-WRITE] SELECT completed");
} else {
sendClient(commandId + " BAD command unrecognized");
}
} else if ("uid".equalsIgnoreCase(command)) {
if (tokens.hasMoreTokens() && "fetch".equalsIgnoreCase(tokens.nextToken())) {
if (tokens.hasMoreTokens()) {
String parameter = tokens.nextToken();
if ("1:*".equals(parameter)) {
List<ExchangeSession.Message> messages = session.getAllMessages();
for (ExchangeSession.Message message : messages) {
sendClient("* FETCH (UID " + message.uid + " FLAGS ())");
}
sendClient(commandId + " OK UID FETCH completed");
} else {
sendClient(commandId + " BAD command unrecognized");
}
} else {
sendClient(commandId + " BAD command unrecognized");
}
} else {
sendClient(commandId + " BAD command unrecognized");
}
} else {
sendClient(commandId + " BAD command unrecognized");
}
}
}
} else {
sendClient(commandId + " BAD missing command");
}
} else {
sendClient("BAD Null 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
*/
protected void parseCredentials(StringTokenizer tokens) throws IOException {
if (tokens.hasMoreTokens()) {
userName = removeQuotes(tokens.nextToken());
} else {
throw new IOException("Invalid credentials");
}
if (tokens.hasMoreTokens()) {
password = removeQuotes(tokens.nextToken());
} else {
throw new IOException("Invalid credentials");
}
int backslashindex = userName.indexOf("\\");
if (backslashindex > 0) {
userName = userName.substring(0, backslashindex) + userName.substring(backslashindex + 1);
}
}
protected String removeQuotes(String value) {
String result = value;
if (result.startsWith("\"")) {
result = result.substring(1);
}
if (result.endsWith("\"")) {
result = result.substring(0, result.length() - 1);
}
return result;
}
public void sendMessage(StringBuffer buffer) throws Exception {
// TODO implement
}
}

View File

@ -0,0 +1,26 @@
package davmail.imap;
import java.net.Socket;
import davmail.AbstractServer;
/**
* Pop3 server
*/
public class ImapServer extends AbstractServer {
public final static int DEFAULT_PORT = 143;
/**
* Create a ServerSocket to listen for connections.
* Start the thread.
*/
public ImapServer(String url, int port) {
super(url, (port == 0) ? ImapServer.DEFAULT_PORT : port);
}
public void createConnectionHandler(String url, Socket clientSocket) {
new ImapConnection(url, clientSocket);
}
}

View File

@ -0,0 +1,212 @@
package davmail.pop;
import davmail.AbstractConnection;
import davmail.DavGatewayTray;
import davmail.exchange.ExchangeSession;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.*;
import java.io.IOException;
/**
* Dav Gateway pop connection implementation
*/
public class PopConnection extends AbstractConnection {
protected static final int INITIAL = 0;
protected static final int USER = 1;
protected static final int AUTHENTICATED = 2;
private List<ExchangeSession.Message> messages;
// Initialize the streams and start the thread
public PopConnection(String url, Socket clientSocket) {
super(url, clientSocket);
}
public long getTotalMessagesLength() {
int result = 0;
for (ExchangeSession.Message message : messages) {
result += message.size;
}
return result;
}
public void printList() throws IOException {
int i = 1;
for (ExchangeSession.Message message : messages) {
sendClient(i++ + " " + message.size);
}
sendClient(".");
}
public void printUidList() throws IOException {
int i = 1;
for (ExchangeSession.Message message : messages) {
sendClient(i++ + " " + message.uid);
}
sendClient(".");
}
public void run() {
String line;
StringTokenizer tokens;
try {
sendOK("DavMail POP 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)) {
sendOK("Bye");
break;
} else if ("USER".equalsIgnoreCase(command)) {
userName = null;
password = null;
session = null;
if (tokens.hasMoreTokens()) {
userName = tokens.nextToken();
sendOK("USER : " + userName);
state = USER;
} else {
sendERR("invalid syntax");
state = INITIAL;
}
} else if ("PASS".equalsIgnoreCase(command)) {
if (state != USER) {
sendERR("invalid state");
state = INITIAL;
} else if (!tokens.hasMoreTokens()) {
sendERR("invalid syntax");
} else {
password = tokens.nextToken();
try {
session = new ExchangeSession(url);
session.login(userName, password);
messages = session.getAllMessages();
sendOK("PASS");
state = AUTHENTICATED;
} catch (UnknownHostException e) {
DavGatewayTray.error("Connection failed",e);
sendERR("Connection failed : "+e+" "+e.getMessage());
// close connection
break;
} catch (Exception e) {
DavGatewayTray.error("Authentication failed",e);
sendERR("authentication failed : "+e+" "+e.getMessage());
}
}
} else if ("CAPA".equalsIgnoreCase(command)) {
sendERR("unknown command");
} else if (state != AUTHENTICATED) {
sendERR("invalid state not authenticated");
} else {
if ("STAT".equalsIgnoreCase(command)) {
sendOK(messages.size() + " " +
getTotalMessagesLength());
} else if ("LIST".equalsIgnoreCase(command)) {
sendOK(messages.size() +
" messages (" + getTotalMessagesLength() +
" octets)");
printList();
} else if ("UIDL".equalsIgnoreCase(command)) {
sendOK(messages.size() +
" messages (" + getTotalMessagesLength() +
" octets)");
printUidList();
} else if ("RETR".equalsIgnoreCase(command)) {
if (tokens.hasMoreTokens()) {
try {
int messageNumber = Integer.valueOf(tokens.
nextToken()) - 1;
sendOK("");
messages.get(messageNumber).write(os);
sendClient("");
sendClient(".");
} catch (Exception e) {
DavGatewayTray.error("Error retreiving message",e);
sendERR("error retreiving message " + e.getMessage());
}
} else {
sendERR("invalid message number");
}
} else if ("DELE".equalsIgnoreCase(command)) {
if (tokens.hasMoreTokens()) {
try {
int messageNumber = Integer.valueOf(tokens.
nextToken()) - 1;
messages.get(messageNumber).delete();
sendOK("DELETE");
} catch (Exception e) {
DavGatewayTray.error("Error deleting message",e);
sendERR("error deleting message");
}
} else {
sendERR("invalid message number");
}
} else if ("TOP".equalsIgnoreCase(command)) {
try {
int firstMessage = Integer.valueOf(tokens.
nextToken()) - 1;
int lastMessage = Integer.valueOf(tokens.
nextToken()) - 1;
for (int i = firstMessage; i <= lastMessage; i++) {
messages.get(i).printHeaders(os);
sendClient("");
sendClient(".");
}
sendOK("TOP");
} catch (Exception e) {
sendERR("error retreiving top of messages");
}
} else if ("RSET".equalsIgnoreCase(command)) {
sendOK("RSET");
} else {
sendERR("unknown command");
}
}
} else {
sendERR("unknown 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();
}
public void sendOK(String message) throws IOException {
sendClient("+OK ", message);
}
public void sendERR(String message) throws IOException {
sendClient("-ERR ", message);
}
}

View File

@ -0,0 +1,26 @@
package davmail.pop;
import davmail.AbstractServer;
import java.net.Socket;
/**
* Pop3 server
*/
public class PopServer extends AbstractServer {
public final static int DEFAULT_PORT = 110;
/**
* Create a ServerSocket to listen for connections.
* Start the thread.
*/
public PopServer(String url, int port) {
super(url, (port == 0) ? PopServer.DEFAULT_PORT : port);
}
public void createConnectionHandler(String url, Socket clientSocket) {
new PopConnection(url, clientSocket);
}
}

View File

@ -0,0 +1,158 @@
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
public SmtpConnection(String url, Socket clientSocket) {
super(url, clientSocket);
}
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());
session = new ExchangeSession(url);
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;
sendClient("451 Error : " + e.getMessage());
}
} 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
* @throws java.io.IOException
*/
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");
}
}
}

View File

@ -0,0 +1,22 @@
package davmail.smtp;
import java.net.Socket;
import davmail.AbstractServer;
public class SmtpServer extends AbstractServer {
public final static int DEFAULT_PORT = 25;
/**
* Create a ServerSocket to listen for connections.
* Start the thread.
*/
public SmtpServer(String url, int port) {
super(url, (port == 0) ? SmtpServer.DEFAULT_PORT : port);
}
public void createConnectionHandler(String url, Socket clientSocket) {
new SmtpConnection(url, clientSocket);
}
}

22
src/java/log4j.properties Normal file
View File

@ -0,0 +1,22 @@
# Set root logger level to DEBUG and its only appender to ConsoleAppender.
log4j.rootLogger=DEBUG, ConsoleAppender, FileAppender
log4j.logger.httpclient.wire=WARN, ConsoleAppender
log4j.logger.org.apache.commons.httpclient=WARN, ConsoleAppender
# ConsoleAppender is set to be a ConsoleAppender.
log4j.appender.ConsoleAppender=org.apache.log4j.ConsoleAppender
# ConsoleAppender uses PatternLayout.
log4j.appender.ConsoleAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.ConsoleAppender.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
#log4j.appender.FileAppender=org.apache.log4j.FileAppender
log4j.appender.FileAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.FileAppender.DatePattern='.'yyyy-MM-dd
# Path and name of log file
log4j.appender.FileAppender.File=davmail.log
# ConsoleAppender uses PatternLayout.
log4j.appender.FileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.FileAppender.layout.ConversionPattern=%d{ISO8601} - %m%n

BIN
src/java/tray.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

BIN
src/java/tray2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB