IMAP: Implement copy and delete actions on messages and folders
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@313 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
8ec93490fb
commit
61b3f9c7a5
|
@ -16,6 +16,7 @@ import org.apache.webdav.lib.WebdavResource;
|
||||||
import org.apache.webdav.lib.methods.MoveMethod;
|
import org.apache.webdav.lib.methods.MoveMethod;
|
||||||
import org.apache.webdav.lib.methods.PropPatchMethod;
|
import org.apache.webdav.lib.methods.PropPatchMethod;
|
||||||
import org.apache.webdav.lib.methods.SearchMethod;
|
import org.apache.webdav.lib.methods.SearchMethod;
|
||||||
|
import org.apache.webdav.lib.methods.CopyMethod;
|
||||||
import org.htmlcleaner.CommentToken;
|
import org.htmlcleaner.CommentToken;
|
||||||
import org.htmlcleaner.HtmlCleaner;
|
import org.htmlcleaner.HtmlCleaner;
|
||||||
import org.htmlcleaner.TagNode;
|
import org.htmlcleaner.TagNode;
|
||||||
|
@ -545,7 +546,7 @@ public class ExchangeSession {
|
||||||
} else if ("message-id".equals(prop.getLocalName())) {
|
} else if ("message-id".equals(prop.getLocalName())) {
|
||||||
message.messageId = prop.getPropertyAsString();
|
message.messageId = prop.getPropertyAsString();
|
||||||
if (message.messageId.startsWith("<") && message.messageId.endsWith(">")) {
|
if (message.messageId.startsWith("<") && message.messageId.endsWith(">")) {
|
||||||
message.messageId = message.messageId.substring(1, message.messageId.length()-1);
|
message.messageId = message.messageId.substring(1, message.messageId.length() - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -849,6 +850,27 @@ public class ExchangeSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void copyMessage(String messageUrl, String targetName) throws IOException {
|
||||||
|
String targetPath = getFolderPath(targetName) + messageUrl.substring(messageUrl.lastIndexOf('/'));
|
||||||
|
CopyMethod method = new CopyMethod(URIUtil.encodePath(messageUrl),
|
||||||
|
URIUtil.encodePath(targetPath));
|
||||||
|
method.setOverwrite(false);
|
||||||
|
method.addRequestHeader("Allow-Rename", "t");
|
||||||
|
try {
|
||||||
|
int statusCode = wdr.retrieveSessionInstance().executeMethod(method);
|
||||||
|
if (statusCode == HttpStatus.SC_PRECONDITION_FAILED) {
|
||||||
|
throw new HttpException("Unable to move message, target already exists");
|
||||||
|
} else if (statusCode != HttpStatus.SC_CREATED) {
|
||||||
|
HttpException ex = new HttpException();
|
||||||
|
ex.setReasonCode(method.getStatusCode());
|
||||||
|
ex.setReason(method.getStatusText());
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
method.releaseConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void moveFolder(String folderName, String targetName) throws IOException {
|
public void moveFolder(String folderName, String targetName) throws IOException {
|
||||||
String folderPath = getFolderPath(folderName);
|
String folderPath = getFolderPath(folderName);
|
||||||
String targetPath = getFolderPath(targetName);
|
String targetPath = getFolderPath(targetName);
|
||||||
|
@ -897,6 +919,7 @@ public class ExchangeSession {
|
||||||
public int size;
|
public int size;
|
||||||
public String messageId;
|
public String messageId;
|
||||||
public boolean read;
|
public boolean read;
|
||||||
|
public boolean deleted;
|
||||||
|
|
||||||
public long getUidAsLong() {
|
public long getUidAsLong() {
|
||||||
byte[] decodedValue = Base64.decode(uid.getBytes());
|
byte[] decodedValue = Base64.decode(uid.getBytes());
|
||||||
|
@ -910,6 +933,17 @@ public class ExchangeSession {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getImapFlags() {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
if (read) {
|
||||||
|
buffer.append("\\Seen ");
|
||||||
|
}
|
||||||
|
if (deleted) {
|
||||||
|
buffer.append("\\Deleted");
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public void write(OutputStream os) throws IOException {
|
public void write(OutputStream os) throws IOException {
|
||||||
HttpMethod method = null;
|
HttpMethod method = null;
|
||||||
BufferedReader reader = null;
|
BufferedReader reader = null;
|
||||||
|
@ -989,7 +1023,7 @@ public class ExchangeSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(Object message) {
|
public int compareTo(Object message) {
|
||||||
return (int)(getUidAsLong()-((Message)message).getUidAsLong());
|
return (int) (getUidAsLong() - ((Message) message).getUidAsLong());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1263,6 +1297,23 @@ public class ExchangeSession {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void deleteFolder(String path) throws IOException {
|
||||||
|
wdr.deleteMethod(getFolderPath(path));
|
||||||
|
int status = wdr.getStatusCode();
|
||||||
|
if (status != HttpStatus.SC_OK) {
|
||||||
|
HttpException ex = new HttpException();
|
||||||
|
ex.setReasonCode(status);
|
||||||
|
ex.setReason(wdr.getStatusMessage());
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int deleteMessage(String path) throws IOException {
|
||||||
|
wdr.deleteMethod(path);
|
||||||
|
return wdr.getStatusCode();
|
||||||
|
}
|
||||||
|
|
||||||
public int deleteEvent(String path) throws IOException {
|
public int deleteEvent(String path) throws IOException {
|
||||||
wdr.deleteMethod(calendarUrl + "/" + URIUtil.decode(path));
|
wdr.deleteMethod(calendarUrl + "/" + URIUtil.decode(path));
|
||||||
return wdr.getStatusCode();
|
return wdr.getStatusCode();
|
||||||
|
|
|
@ -142,6 +142,8 @@ public class ImapConnection extends AbstractConnection {
|
||||||
sendClient(commandId + " BAD missing folder argument");
|
sendClient(commandId + " BAD missing folder argument");
|
||||||
}
|
}
|
||||||
} else if ("select".equalsIgnoreCase(command) || "examine".equalsIgnoreCase(command)) {
|
} else if ("select".equalsIgnoreCase(command) || "examine".equalsIgnoreCase(command)) {
|
||||||
|
// first purge previous folder
|
||||||
|
expunge();
|
||||||
if (tokens.hasMoreTokens()) {
|
if (tokens.hasMoreTokens()) {
|
||||||
String folderName = BASE64MailboxDecoder.decode(tokens.nextToken());
|
String folderName = BASE64MailboxDecoder.decode(tokens.nextToken());
|
||||||
currentFolder = session.getFolder(folderName);
|
currentFolder = session.getFolder(folderName);
|
||||||
|
@ -182,6 +184,14 @@ public class ImapConnection extends AbstractConnection {
|
||||||
} catch (HttpException e) {
|
} catch (HttpException e) {
|
||||||
sendClient(commandId + " NO " + e.getReason());
|
sendClient(commandId + " NO " + e.getReason());
|
||||||
}
|
}
|
||||||
|
} else if ("delete".equalsIgnoreCase(command)) {
|
||||||
|
String folderName = BASE64MailboxDecoder.decode(tokens.nextToken());
|
||||||
|
try {
|
||||||
|
session.deleteFolder(folderName);
|
||||||
|
sendClient(commandId + " OK delete completed");
|
||||||
|
} catch (HttpException e) {
|
||||||
|
sendClient(commandId + " NO " + e.getReason());
|
||||||
|
}
|
||||||
} else if ("uid".equalsIgnoreCase(command)) {
|
} else if ("uid".equalsIgnoreCase(command)) {
|
||||||
if (tokens.hasMoreTokens()) {
|
if (tokens.hasMoreTokens()) {
|
||||||
String subcommand = tokens.nextToken();
|
String subcommand = tokens.nextToken();
|
||||||
|
@ -222,7 +232,7 @@ public class ImapConnection extends AbstractConnection {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (ExchangeSession.Message message : messages) {
|
for (ExchangeSession.Message message : messages) {
|
||||||
count++;
|
count++;
|
||||||
sendClient("* " + count + " FETCH (UID " + message.getUidAsLong() + " FLAGS (" + (message.read ? "\\Seen" : "") + "))");
|
sendClient("* " + count + " FETCH (UID " + message.getUidAsLong() + " FLAGS (" + (message.getImapFlags()) + "))");
|
||||||
}
|
}
|
||||||
sendClient(commandId + " OK UID FETCH completed");
|
sendClient(commandId + " OK UID FETCH completed");
|
||||||
} else {
|
} else {
|
||||||
|
@ -255,7 +265,7 @@ public class ImapConnection extends AbstractConnection {
|
||||||
"] {" + baos.size() + "}");
|
"] {" + baos.size() + "}");
|
||||||
os.write(baos.toByteArray());
|
os.write(baos.toByteArray());
|
||||||
os.flush();
|
os.flush();
|
||||||
sendClient(" FLAGS (" + (message.read ? "\\Seen" : "") + "))");
|
sendClient(" FLAGS (" + (message.getImapFlags()) + "))");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,6 +317,8 @@ public class ImapConnection extends AbstractConnection {
|
||||||
if ("\\Seen".equals(flag)) {
|
if ("\\Seen".equals(flag)) {
|
||||||
properties.put("read", "1");
|
properties.put("read", "1");
|
||||||
message.read = true;
|
message.read = true;
|
||||||
|
} else if ("\\Deleted".equals(flag)) {
|
||||||
|
message.deleted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,10 +327,20 @@ public class ImapConnection extends AbstractConnection {
|
||||||
for (ExchangeSession.Message currentMessage : messages) {
|
for (ExchangeSession.Message currentMessage : messages) {
|
||||||
index++;
|
index++;
|
||||||
if (currentMessage == message) {
|
if (currentMessage == message) {
|
||||||
sendClient("* " + index + " FETCH (UID " + message.getUidAsLong() + " FLAGS (" + (message.read ? "\\Seen" : "") + "))");
|
sendClient("* " + index + " FETCH (UID " + message.getUidAsLong() + " FLAGS (" + (message.getImapFlags()) + "))");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendClient(commandId + " OK STORE completed");
|
sendClient(commandId + " OK STORE completed");
|
||||||
|
} else if ("copy".equalsIgnoreCase(subcommand)) {
|
||||||
|
long uid = Long.parseLong(tokens.nextToken());
|
||||||
|
ExchangeSession.Message message = messages.getByUid(uid);
|
||||||
|
String targetName = BASE64MailboxDecoder.decode(tokens.nextToken());
|
||||||
|
try {
|
||||||
|
session.copyMessage(message.messageUrl, targetName);
|
||||||
|
sendClient(commandId + " OK rename completed");
|
||||||
|
} catch (HttpException e) {
|
||||||
|
sendClient(commandId + " NO " + e.getReason());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sendClient(commandId + " BAD command unrecognized");
|
sendClient(commandId + " BAD command unrecognized");
|
||||||
|
@ -372,6 +394,7 @@ public class ImapConnection extends AbstractConnection {
|
||||||
sendClient(commandId + " OK APPEND completed");
|
sendClient(commandId + " OK APPEND completed");
|
||||||
} else if ("noop".equalsIgnoreCase(command) || "check".equalsIgnoreCase(command)) {
|
} else if ("noop".equalsIgnoreCase(command) || "check".equalsIgnoreCase(command)) {
|
||||||
if (currentFolder != null) {
|
if (currentFolder != null) {
|
||||||
|
expunge();
|
||||||
currentFolder = session.getFolder(currentFolder.folderName);
|
currentFolder = session.getFolder(currentFolder.folderName);
|
||||||
messages = session.getAllMessages(currentFolder.folderUrl);
|
messages = session.getAllMessages(currentFolder.folderUrl);
|
||||||
sendClient("* " + currentFolder.objectCount + " EXISTS");
|
sendClient("* " + currentFolder.objectCount + " EXISTS");
|
||||||
|
@ -409,6 +432,19 @@ public class ImapConnection extends AbstractConnection {
|
||||||
DavGatewayTray.resetIcon();
|
DavGatewayTray.resetIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void expunge() throws IOException {
|
||||||
|
if (messages != null) {
|
||||||
|
int index = 0;
|
||||||
|
for (ExchangeSession.Message message : messages) {
|
||||||
|
index++;
|
||||||
|
if (message.deleted) {
|
||||||
|
session.deleteMessage(message.messageUrl);
|
||||||
|
sendClient("* "+index+" EXPUNGE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode IMAP credentials
|
* Decode IMAP credentials
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue