mirror of
https://github.com/moparisthebest/davmail
synced 2024-12-12 10:42:21 -05:00
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:
parent
93241202ce
commit
0351a49c9d
80
src/java/davmail/AbstractConnection.java
Normal file
80
src/java/davmail/AbstractConnection.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
63
src/java/davmail/AbstractServer.java
Normal file
63
src/java/davmail/AbstractServer.java
Normal 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);
|
||||
}
|
||||
|
52
src/java/davmail/DavGateway.java
Normal file
52
src/java/davmail/DavGateway.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
145
src/java/davmail/DavGatewayTray.java
Normal file
145
src/java/davmail/DavGatewayTray.java
Normal 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");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
1125
src/java/davmail/exchange/ExchangeSession.java
Normal file
1125
src/java/davmail/exchange/ExchangeSession.java
Normal file
File diff suppressed because it is too large
Load Diff
139
src/java/davmail/exchange/XmlDocument.java
Normal file
139
src/java/davmail/exchange/XmlDocument.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
185
src/java/davmail/imap/ImapConnection.java
Normal file
185
src/java/davmail/imap/ImapConnection.java
Normal 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
|
||||
}
|
||||
}
|
||||
|
26
src/java/davmail/imap/ImapServer.java
Normal file
26
src/java/davmail/imap/ImapServer.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
212
src/java/davmail/pop/PopConnection.java
Normal file
212
src/java/davmail/pop/PopConnection.java
Normal 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);
|
||||
}
|
||||
}
|
26
src/java/davmail/pop/PopServer.java
Normal file
26
src/java/davmail/pop/PopServer.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
158
src/java/davmail/smtp/SmtpConnection.java
Normal file
158
src/java/davmail/smtp/SmtpConnection.java
Normal 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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
22
src/java/davmail/smtp/SmtpServer.java
Normal file
22
src/java/davmail/smtp/SmtpServer.java
Normal 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
22
src/java/log4j.properties
Normal 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
BIN
src/java/tray.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 823 B |
BIN
src/java/tray2.png
Normal file
BIN
src/java/tray2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Loading…
Reference in New Issue
Block a user