mirror of
https://github.com/moparisthebest/davmail
synced 2025-03-04 19:29:46 -05:00
EWS: move WebDav code to DavExchangeSession
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1084 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
51936619e3
commit
38f74f5c75
@ -291,21 +291,7 @@ public abstract class ExchangeSession {
|
||||
* @throws NoRouteToHostException on error
|
||||
* @throws UnknownHostException on error
|
||||
*/
|
||||
public boolean isExpired() throws NoRouteToHostException, UnknownHostException {
|
||||
boolean isExpired = false;
|
||||
try {
|
||||
DavGatewayHttpClientFacade.executePropFindMethod(
|
||||
httpClient, URIUtil.encodePath(inboxUrl), 0, DISPLAY_NAME);
|
||||
} catch (UnknownHostException exc) {
|
||||
throw exc;
|
||||
} catch (NoRouteToHostException exc) {
|
||||
throw exc;
|
||||
} catch (IOException e) {
|
||||
isExpired = true;
|
||||
}
|
||||
|
||||
return isExpired;
|
||||
}
|
||||
public abstract boolean isExpired() throws NoRouteToHostException, UnknownHostException;
|
||||
|
||||
/**
|
||||
* Test authentication mode : form based or basic.
|
||||
@ -604,85 +590,7 @@ public abstract class ExchangeSession {
|
||||
* @param messageBody mail body
|
||||
* @throws IOException when unable to create message
|
||||
*/
|
||||
public void createMessage(String folderPath, String messageName, HashMap<String, String> properties, String messageBody) throws IOException {
|
||||
String messageUrl = URIUtil.encodePathQuery(getFolderPath(folderPath) + '/' + messageName + ".EML");
|
||||
PropPatchMethod patchMethod;
|
||||
// create the message first as draft
|
||||
if (properties.containsKey("draft")) {
|
||||
patchMethod = new PropPatchMethod(messageUrl, buildProperties(properties));
|
||||
try {
|
||||
// update message with blind carbon copy and other flags
|
||||
int statusCode = httpClient.executeMethod(patchMethod);
|
||||
if (statusCode != HttpStatus.SC_MULTI_STATUS) {
|
||||
throw new DavMailException("EXCEPTION_UNABLE_TO_CREATE_MESSAGE", messageUrl, statusCode, ' ', patchMethod.getStatusLine());
|
||||
}
|
||||
|
||||
} finally {
|
||||
patchMethod.releaseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
PutMethod putmethod = new PutMethod(messageUrl);
|
||||
putmethod.setRequestHeader("Translate", "f");
|
||||
try {
|
||||
// use same encoding as client socket reader
|
||||
putmethod.setRequestEntity(new ByteArrayRequestEntity(messageBody.getBytes()));
|
||||
int code = httpClient.executeMethod(putmethod);
|
||||
|
||||
if (code != HttpStatus.SC_OK && code != HttpStatus.SC_CREATED) {
|
||||
throw new DavMailException("EXCEPTION_UNABLE_TO_CREATE_MESSAGE", messageUrl, code, ' ', putmethod.getStatusLine());
|
||||
}
|
||||
} finally {
|
||||
putmethod.releaseConnection();
|
||||
}
|
||||
|
||||
// add bcc and other properties
|
||||
if (!properties.isEmpty()) {
|
||||
patchMethod = new PropPatchMethod(messageUrl, buildProperties(properties));
|
||||
try {
|
||||
// update message with blind carbon copy and other flags
|
||||
int statusCode = httpClient.executeMethod(patchMethod);
|
||||
if (statusCode != HttpStatus.SC_MULTI_STATUS) {
|
||||
throw new DavMailException("EXCEPTION_UNABLE_TO_PATCH_MESSAGE", messageUrl, statusCode, ' ', patchMethod.getStatusLine());
|
||||
}
|
||||
|
||||
} finally {
|
||||
patchMethod.releaseConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected List<DavProperty> buildProperties(Map<String, String> properties) {
|
||||
ArrayList<DavProperty> list = new ArrayList<DavProperty>();
|
||||
for (Map.Entry<String, String> entry : properties.entrySet()) {
|
||||
if ("read".equals(entry.getKey())) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("read", URN_SCHEMAS_HTTPMAIL), entry.getValue()));
|
||||
} else if ("junk".equals(entry.getKey())) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("x10830003", SCHEMAS_MAPI_PROPTAG), entry.getValue()));
|
||||
} else if ("flagged".equals(entry.getKey())) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("x10900003", SCHEMAS_MAPI_PROPTAG), entry.getValue()));
|
||||
} else if ("answered".equals(entry.getKey())) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("x10810003", SCHEMAS_MAPI_PROPTAG), entry.getValue()));
|
||||
if ("102".equals(entry.getValue())) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("x10800003", SCHEMAS_MAPI_PROPTAG), "261"));
|
||||
}
|
||||
} else if ("forwarded".equals(entry.getKey())) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("x10810003", SCHEMAS_MAPI_PROPTAG), entry.getValue()));
|
||||
if ("104".equals(entry.getValue())) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("x10800003", SCHEMAS_MAPI_PROPTAG), "262"));
|
||||
}
|
||||
} else if ("bcc".equals(entry.getKey())) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("bcc", Namespace.getNamespace("urn:schemas:mailheader:")), entry.getValue()));
|
||||
} else if ("draft".equals(entry.getKey())) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("x0E070003", SCHEMAS_MAPI_PROPTAG), entry.getValue()));
|
||||
} else if ("deleted".equals(entry.getKey())) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("_x0030_x8570", Namespace.getNamespace("http://schemas.microsoft.com/mapi/id/{00062008-0000-0000-C000-000000000046}/")), entry.getValue()));
|
||||
} else if ("datereceived".equals(entry.getKey())) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("datereceived", URN_SCHEMAS_HTTPMAIL), entry.getValue()));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
public abstract void createMessage(String folderPath, String messageName, HashMap<String, String> properties, String messageBody) throws IOException;
|
||||
|
||||
/**
|
||||
* Update given properties on message.
|
||||
@ -691,23 +599,15 @@ public abstract class ExchangeSession {
|
||||
* @param properties Webdav properties map
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public void updateMessage(Message message, Map<String, String> properties) throws IOException {
|
||||
PropPatchMethod patchMethod = new PropPatchMethod(message.permanentUrl, buildProperties(properties)) {
|
||||
@Override
|
||||
protected void processResponseBody(HttpState httpState, HttpConnection httpConnection) {
|
||||
// ignore response body, sometimes invalid with exchange mapi properties
|
||||
}
|
||||
};
|
||||
try {
|
||||
int statusCode = httpClient.executeMethod(patchMethod);
|
||||
if (statusCode != HttpStatus.SC_MULTI_STATUS) {
|
||||
throw new DavMailException("EXCEPTION_UNABLE_TO_UPDATE_MESSAGE");
|
||||
}
|
||||
public abstract void updateMessage(Message message, Map<String, String> properties) throws IOException;
|
||||
|
||||
} finally {
|
||||
patchMethod.releaseConnection();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Send message to recipients, properties contains bcc recipients and other non MIME flags.
|
||||
* @param properties additional message properties
|
||||
* @param messageBody MIME message body
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public abstract void sendMessage(HashMap<String, String> properties, String messageBody) throws IOException;
|
||||
|
||||
protected static final List<String> POP_MESSAGE_ATTRIBUTES = new ArrayList<String>();
|
||||
|
||||
@ -742,6 +642,12 @@ public abstract class ExchangeSession {
|
||||
IMAP_MESSAGE_ATTRIBUTES.add("date");
|
||||
}
|
||||
|
||||
protected static final List<String> UID_MESSAGE_ATTRIBUTES = new ArrayList<String>();
|
||||
|
||||
static {
|
||||
UID_MESSAGE_ATTRIBUTES.add("uid");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all folder messages.
|
||||
*
|
||||
@ -865,8 +771,7 @@ public abstract class ExchangeSession {
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public List<Folder> getSubFolders(String folderName, boolean recursive) throws IOException {
|
||||
return getSubFolders(folderName,
|
||||
or(equals("folderclass", "IPF.Note"), isNull("folderclass")),
|
||||
return getSubFolders(folderName, or(equals("folderclass", "IPF.Note"), isNull("folderclass")),
|
||||
recursive);
|
||||
}
|
||||
|
||||
@ -902,32 +807,25 @@ public abstract class ExchangeSession {
|
||||
public void purgeOldestTrashAndSentMessages() throws IOException {
|
||||
int keepDelay = Settings.getIntProperty("davmail.keepDelay");
|
||||
if (keepDelay != 0) {
|
||||
purgeOldestFolderMessages(deleteditemsUrl, keepDelay);
|
||||
purgeOldestFolderMessages(TRASH, keepDelay);
|
||||
}
|
||||
// this is a new feature, default is : do nothing
|
||||
int sentKeepDelay = Settings.getIntProperty("davmail.sentKeepDelay");
|
||||
if (sentKeepDelay != 0) {
|
||||
purgeOldestFolderMessages(sentitemsUrl, sentKeepDelay);
|
||||
purgeOldestFolderMessages(SENT, sentKeepDelay);
|
||||
}
|
||||
}
|
||||
|
||||
protected void purgeOldestFolderMessages(String folderUrl, int keepDelay) throws IOException {
|
||||
protected void purgeOldestFolderMessages(String folderPath, int keepDelay) throws IOException {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.add(Calendar.DAY_OF_MONTH, -keepDelay);
|
||||
LOGGER.debug("Delete messages in " + folderUrl + " since " + cal.getTime());
|
||||
LOGGER.debug("Delete messages in " + folderPath + " not modified since " + cal.getTime());
|
||||
|
||||
String searchRequest = "Select \"DAV:uid\"" +
|
||||
" FROM Scope('SHALLOW TRAVERSAL OF \"" + folderUrl + "\"')\n" +
|
||||
" WHERE \"DAV:isfolder\" = False\n" +
|
||||
" AND \"DAV:getlastmodified\" < '" + formatSearchDate(cal.getTime()) + "'\n";
|
||||
MultiStatusResponse[] responses = DavGatewayHttpClientFacade.executeSearchMethod(
|
||||
httpClient, URIUtil.encodePath(folderUrl), searchRequest);
|
||||
MessageList messages = searchMessages(folderPath, UID_MESSAGE_ATTRIBUTES,
|
||||
lt("lastmodified", formatSearchDate(cal.getTime())));
|
||||
|
||||
for (MultiStatusResponse response : responses) {
|
||||
String messageUrl = URIUtil.decode(response.getHref());
|
||||
|
||||
LOGGER.debug("Delete " + messageUrl);
|
||||
DavGatewayHttpClientFacade.executeDeleteMethod(httpClient, URIUtil.encodePath(messageUrl));
|
||||
for (Message message : messages) {
|
||||
message.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@ -995,16 +893,7 @@ public abstract class ExchangeSession {
|
||||
properties.put("bcc", bcc);
|
||||
}
|
||||
|
||||
String messageName = UUID.randomUUID().toString();
|
||||
|
||||
createMessage("Drafts", messageName, properties, mailBuffer.toString());
|
||||
|
||||
String tempUrl = draftsUrl + '/' + messageName + ".EML";
|
||||
MoveMethod method = new MoveMethod(URIUtil.encodePath(tempUrl), URIUtil.encodePath(sendmsgUrl), true);
|
||||
int status = DavGatewayHttpClientFacade.executeHttpMethod(httpClient, method);
|
||||
if (status != HttpStatus.SC_OK) {
|
||||
throw DavGatewayHttpClientFacade.buildHttpException(method);
|
||||
}
|
||||
sendMessage(properties, mailBuffer.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1101,23 +990,7 @@ public abstract class ExchangeSession {
|
||||
* @param folderClass folder class
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public void createFolder(String folderName, String folderClass) throws IOException {
|
||||
String folderPath = getFolderPath(folderName);
|
||||
ArrayList<DavProperty> list = new ArrayList<DavProperty>();
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("outlookfolderclass", Namespace.getNamespace("http://schemas.microsoft.com/exchange/")), folderClass));
|
||||
// standard MkColMethod does not take properties, override PropPatchMethod instead
|
||||
PropPatchMethod method = new PropPatchMethod(URIUtil.encodePath(folderPath), list) {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "MKCOL";
|
||||
}
|
||||
};
|
||||
int status = DavGatewayHttpClientFacade.executeHttpMethod(httpClient, method);
|
||||
// ok or already exists
|
||||
if (status != HttpStatus.SC_MULTI_STATUS && status != HttpStatus.SC_METHOD_NOT_ALLOWED) {
|
||||
throw DavGatewayHttpClientFacade.buildHttpException(method);
|
||||
}
|
||||
}
|
||||
public abstract void createFolder(String folderName, String folderClass) throws IOException;
|
||||
|
||||
/**
|
||||
* Delete Exchange folder.
|
||||
@ -1125,9 +998,7 @@ public abstract class ExchangeSession {
|
||||
* @param folderName logical folder name
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public void deleteFolder(String folderName) throws IOException {
|
||||
DavGatewayHttpClientFacade.executeDeleteMethod(httpClient, URIUtil.encodePath(getFolderPath(folderName)));
|
||||
}
|
||||
public abstract void deleteFolder(String folderName) throws IOException;
|
||||
|
||||
/**
|
||||
* Copy message to target folder
|
||||
@ -1136,22 +1007,7 @@ public abstract class ExchangeSession {
|
||||
* @param targetFolder target folder
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public void copyMessage(Message message, String targetFolder) throws IOException {
|
||||
String targetPath = URIUtil.encodePath(getFolderPath(targetFolder)) + '/' + UUID.randomUUID().toString();
|
||||
CopyMethod method = new CopyMethod(message.permanentUrl, targetPath, false);
|
||||
// allow rename if a message with the same name exists
|
||||
method.addRequestHeader("Allow-Rename", "t");
|
||||
try {
|
||||
int statusCode = httpClient.executeMethod(method);
|
||||
if (statusCode == HttpStatus.SC_PRECONDITION_FAILED) {
|
||||
throw new DavMailException("EXCEPTION_UNABLE_TO_COPY_MESSAGE");
|
||||
} else if (statusCode != HttpStatus.SC_CREATED) {
|
||||
throw DavGatewayHttpClientFacade.buildHttpException(method);
|
||||
}
|
||||
} finally {
|
||||
method.releaseConnection();
|
||||
}
|
||||
}
|
||||
public abstract void copyMessage(Message message, String targetFolder) throws IOException;
|
||||
|
||||
/**
|
||||
* Move folder to target name.
|
||||
@ -1160,39 +1016,9 @@ public abstract class ExchangeSession {
|
||||
* @param targetName target folder name/path
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public void moveFolder(String folderName, String targetName) throws IOException {
|
||||
String folderPath = getFolderPath(folderName);
|
||||
String targetPath = getFolderPath(targetName);
|
||||
MoveMethod method = new MoveMethod(URIUtil.encodePath(folderPath), URIUtil.encodePath(targetPath), false);
|
||||
try {
|
||||
int statusCode = httpClient.executeMethod(method);
|
||||
if (statusCode == HttpStatus.SC_PRECONDITION_FAILED) {
|
||||
throw new DavMailException("EXCEPTION_UNABLE_TO_MOVE_FOLDER");
|
||||
} else if (statusCode != HttpStatus.SC_CREATED) {
|
||||
throw DavGatewayHttpClientFacade.buildHttpException(method);
|
||||
}
|
||||
} finally {
|
||||
method.releaseConnection();
|
||||
}
|
||||
}
|
||||
public abstract void moveFolder(String folderName, String targetName) throws IOException;
|
||||
|
||||
protected void moveToTrash(String encodedMessageUrl) throws IOException {
|
||||
String destination = URIUtil.encodePath(deleteditemsUrl) + '/' + UUID.randomUUID().toString();
|
||||
LOGGER.debug("Deleting : " + encodedMessageUrl + " to " + destination);
|
||||
MoveMethod method = new MoveMethod(encodedMessageUrl, destination, false);
|
||||
method.addRequestHeader("Allow-rename", "t");
|
||||
|
||||
int status = DavGatewayHttpClientFacade.executeHttpMethod(httpClient, method);
|
||||
// do not throw error if already deleted
|
||||
if (status != HttpStatus.SC_CREATED && status != HttpStatus.SC_NOT_FOUND) {
|
||||
throw DavGatewayHttpClientFacade.buildHttpException(method);
|
||||
}
|
||||
if (method.getResponseHeader("Location") != null) {
|
||||
destination = method.getResponseHeader("Location").getValue();
|
||||
}
|
||||
|
||||
LOGGER.debug("Deleted to :" + destination);
|
||||
}
|
||||
protected abstract void moveToTrash(Message message) throws IOException;
|
||||
|
||||
/**
|
||||
* Exchange folder with IMAP properties
|
||||
@ -1688,6 +1514,7 @@ public abstract class ExchangeSession {
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public void delete() throws IOException {
|
||||
LOGGER.debug("Delete " + permanentUrl + " (" + messageUrl + ")");
|
||||
DavGatewayHttpClientFacade.executeDeleteMethod(httpClient, permanentUrl);
|
||||
}
|
||||
|
||||
@ -1702,7 +1529,7 @@ public abstract class ExchangeSession {
|
||||
properties.put("read", "1");
|
||||
updateMessage(this, properties);
|
||||
|
||||
ExchangeSession.this.moveToTrash(permanentUrl);
|
||||
ExchangeSession.this.moveToTrash(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,23 +24,24 @@ import davmail.exception.DavMailException;
|
||||
import davmail.exchange.ExchangeSession;
|
||||
import davmail.http.DavGatewayHttpClientFacade;
|
||||
import davmail.ui.tray.DavGatewayTray;
|
||||
import org.apache.commons.httpclient.HttpMethod;
|
||||
import org.apache.commons.httpclient.HttpStatus;
|
||||
import org.apache.commons.httpclient.URI;
|
||||
import org.apache.commons.httpclient.URIException;
|
||||
import org.apache.commons.httpclient.*;
|
||||
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
|
||||
import org.apache.commons.httpclient.methods.PutMethod;
|
||||
import org.apache.commons.httpclient.util.URIUtil;
|
||||
import org.apache.jackrabbit.webdav.MultiStatusResponse;
|
||||
import org.apache.jackrabbit.webdav.client.methods.CopyMethod;
|
||||
import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
|
||||
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
|
||||
import org.apache.jackrabbit.webdav.property.DavProperty;
|
||||
import org.apache.jackrabbit.webdav.property.DavPropertyName;
|
||||
import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
|
||||
import org.apache.jackrabbit.webdav.property.DavPropertySet;
|
||||
import org.apache.jackrabbit.webdav.client.methods.PropPatchMethod;
|
||||
import org.apache.jackrabbit.webdav.property.*;
|
||||
import org.apache.jackrabbit.webdav.xml.Namespace;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.NoRouteToHostException;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -196,6 +197,26 @@ public class DavExchangeSession extends ExchangeSession {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isExpired() throws NoRouteToHostException, UnknownHostException {
|
||||
boolean isExpired = false;
|
||||
try {
|
||||
DavGatewayHttpClientFacade.executePropFindMethod(
|
||||
httpClient, URIUtil.encodePath(inboxUrl), 0, DISPLAY_NAME);
|
||||
} catch (UnknownHostException exc) {
|
||||
throw exc;
|
||||
} catch (NoRouteToHostException exc) {
|
||||
throw exc;
|
||||
} catch (IOException e) {
|
||||
isExpired = true;
|
||||
}
|
||||
|
||||
return isExpired;
|
||||
}
|
||||
|
||||
protected static class MultiCondition extends ExchangeSession.MultiCondition {
|
||||
protected MultiCondition(Operator operator, Condition... condition) {
|
||||
super(operator, condition);
|
||||
@ -455,6 +476,55 @@ public class DavExchangeSession extends ExchangeSession {
|
||||
return folders;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public void createFolder(String folderName, String folderClass) throws IOException {
|
||||
String folderPath = getFolderPath(folderName);
|
||||
ArrayList<DavProperty> list = new ArrayList<DavProperty>();
|
||||
list.add(Field.createDavProperty("folderclass", folderClass));
|
||||
// standard MkColMethod does not take properties, override PropPatchMethod instead
|
||||
PropPatchMethod method = new PropPatchMethod(URIUtil.encodePath(folderPath), list) {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "MKCOL";
|
||||
}
|
||||
};
|
||||
int status = DavGatewayHttpClientFacade.executeHttpMethod(httpClient, method);
|
||||
// ok or already exists
|
||||
if (status != HttpStatus.SC_MULTI_STATUS && status != HttpStatus.SC_METHOD_NOT_ALLOWED) {
|
||||
throw DavGatewayHttpClientFacade.buildHttpException(method);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void deleteFolder(String folderName) throws IOException {
|
||||
DavGatewayHttpClientFacade.executeDeleteMethod(httpClient, URIUtil.encodePath(getFolderPath(folderName)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void moveFolder(String folderName, String targetName) throws IOException {
|
||||
String folderPath = getFolderPath(folderName);
|
||||
String targetPath = getFolderPath(targetName);
|
||||
MoveMethod method = new MoveMethod(URIUtil.encodePath(folderPath), URIUtil.encodePath(targetPath), false);
|
||||
try {
|
||||
int statusCode = httpClient.executeMethod(method);
|
||||
if (statusCode == HttpStatus.SC_PRECONDITION_FAILED) {
|
||||
throw new DavMailException("EXCEPTION_UNABLE_TO_MOVE_FOLDER");
|
||||
} else if (statusCode != HttpStatus.SC_CREATED) {
|
||||
throw DavGatewayHttpClientFacade.buildHttpException(method);
|
||||
}
|
||||
} finally {
|
||||
method.releaseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
protected String getPropertyIfExists(DavPropertySet properties, String name) {
|
||||
DavProperty property = properties.get(name, EMPTY);
|
||||
if (property == null) {
|
||||
@ -549,4 +619,174 @@ public class DavExchangeSession extends ExchangeSession {
|
||||
Collections.sort(messages);
|
||||
return messages;
|
||||
}
|
||||
|
||||
protected List<DavProperty> buildProperties(Map<String, String> properties) {
|
||||
ArrayList<DavProperty> list = new ArrayList<DavProperty>();
|
||||
for (Map.Entry<String, String> entry : properties.entrySet()) {
|
||||
if ("read".equals(entry.getKey())) {
|
||||
list.add(Field.createDavProperty("read", entry.getValue()));
|
||||
} else if ("junk".equals(entry.getKey())) {
|
||||
list.add(Field.createDavProperty("junk", entry.getValue()));
|
||||
} else if ("flagged".equals(entry.getKey())) {
|
||||
list.add(Field.createDavProperty("flagStatus", entry.getValue()));
|
||||
} else if ("answered".equals(entry.getKey())) {
|
||||
list.add(Field.createDavProperty("lastVerbExecuted", entry.getValue()));
|
||||
if ("102".equals(entry.getValue())) {
|
||||
list.add(Field.createDavProperty("iconIndex", "261"));
|
||||
}
|
||||
} else if ("forwarded".equals(entry.getKey())) {
|
||||
list.add(Field.createDavProperty("lastVerbExecuted", entry.getValue()));
|
||||
if ("104".equals(entry.getValue())) {
|
||||
list.add(Field.createDavProperty("iconIndex", "262"));
|
||||
}
|
||||
} else if ("bcc".equals(entry.getKey())) {
|
||||
list.add(Field.createDavProperty("bcc", entry.getValue()));
|
||||
} else if ("draft".equals(entry.getKey())) {
|
||||
list.add(Field.createDavProperty("messageFlags", entry.getValue()));
|
||||
} else if ("deleted".equals(entry.getKey())) {
|
||||
// TODO: need to test this
|
||||
list.add(Field.createDavProperty("writedeleted", entry.getValue()));
|
||||
} else if ("datereceived".equals(entry.getKey())) {
|
||||
list.add(new DefaultDavProperty(DavPropertyName.create("datereceived", URN_SCHEMAS_HTTPMAIL), entry.getValue()));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create message in specified folder.
|
||||
* Will overwrite an existing message with same subject in the same folder
|
||||
*
|
||||
* @param folderPath Exchange folder path
|
||||
* @param messageName message name
|
||||
* @param properties message properties (flags)
|
||||
* @param messageBody mail body
|
||||
* @throws IOException when unable to create message
|
||||
*/
|
||||
public void createMessage(String folderPath, String messageName, HashMap<String, String> properties, String messageBody) throws IOException {
|
||||
String messageUrl = URIUtil.encodePathQuery(getFolderPath(folderPath) + '/' + messageName + ".EML");
|
||||
PropPatchMethod patchMethod;
|
||||
// create the message first as draft
|
||||
if (properties.containsKey("draft")) {
|
||||
patchMethod = new PropPatchMethod(messageUrl, buildProperties(properties));
|
||||
try {
|
||||
// update message with blind carbon copy and other flags
|
||||
int statusCode = httpClient.executeMethod(patchMethod);
|
||||
if (statusCode != HttpStatus.SC_MULTI_STATUS) {
|
||||
throw new DavMailException("EXCEPTION_UNABLE_TO_CREATE_MESSAGE", messageUrl, statusCode, ' ', patchMethod.getStatusLine());
|
||||
}
|
||||
|
||||
} finally {
|
||||
patchMethod.releaseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
PutMethod putmethod = new PutMethod(messageUrl);
|
||||
putmethod.setRequestHeader("Translate", "f");
|
||||
try {
|
||||
// use same encoding as client socket reader
|
||||
putmethod.setRequestEntity(new ByteArrayRequestEntity(messageBody.getBytes()));
|
||||
int code = httpClient.executeMethod(putmethod);
|
||||
|
||||
if (code != HttpStatus.SC_OK && code != HttpStatus.SC_CREATED) {
|
||||
throw new DavMailException("EXCEPTION_UNABLE_TO_CREATE_MESSAGE", messageUrl, code, ' ', putmethod.getStatusLine());
|
||||
}
|
||||
} finally {
|
||||
putmethod.releaseConnection();
|
||||
}
|
||||
|
||||
// add bcc and other properties
|
||||
if (!properties.isEmpty()) {
|
||||
patchMethod = new PropPatchMethod(messageUrl, buildProperties(properties));
|
||||
try {
|
||||
// update message with blind carbon copy and other flags
|
||||
int statusCode = httpClient.executeMethod(patchMethod);
|
||||
if (statusCode != HttpStatus.SC_MULTI_STATUS) {
|
||||
throw new DavMailException("EXCEPTION_UNABLE_TO_PATCH_MESSAGE", messageUrl, statusCode, ' ', patchMethod.getStatusLine());
|
||||
}
|
||||
|
||||
} finally {
|
||||
patchMethod.releaseConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void updateMessage(Message message, Map<String, String> properties) throws IOException {
|
||||
PropPatchMethod patchMethod = new PropPatchMethod(message.permanentUrl, buildProperties(properties)) {
|
||||
@Override
|
||||
protected void processResponseBody(HttpState httpState, HttpConnection httpConnection) {
|
||||
// ignore response body, sometimes invalid with exchange mapi properties
|
||||
}
|
||||
};
|
||||
try {
|
||||
int statusCode = httpClient.executeMethod(patchMethod);
|
||||
if (statusCode != HttpStatus.SC_MULTI_STATUS) {
|
||||
throw new DavMailException("EXCEPTION_UNABLE_TO_UPDATE_MESSAGE");
|
||||
}
|
||||
|
||||
} finally {
|
||||
patchMethod.releaseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void sendMessage(HashMap<String, String> properties, String messageBody) throws IOException {
|
||||
String messageName = UUID.randomUUID().toString();
|
||||
|
||||
createMessage("Drafts", messageName, properties, messageBody);
|
||||
|
||||
String tempUrl = draftsUrl + '/' + messageName + ".EML";
|
||||
MoveMethod method = new MoveMethod(URIUtil.encodePath(tempUrl), URIUtil.encodePath(sendmsgUrl), true);
|
||||
int status = DavGatewayHttpClientFacade.executeHttpMethod(httpClient, method);
|
||||
if (status != HttpStatus.SC_OK) {
|
||||
throw DavGatewayHttpClientFacade.buildHttpException(method);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void copyMessage(Message message, String targetFolder) throws IOException {
|
||||
String targetPath = URIUtil.encodePath(getFolderPath(targetFolder)) + '/' + UUID.randomUUID().toString();
|
||||
CopyMethod method = new CopyMethod(message.permanentUrl, targetPath, false);
|
||||
// allow rename if a message with the same name exists
|
||||
method.addRequestHeader("Allow-Rename", "t");
|
||||
try {
|
||||
int statusCode = httpClient.executeMethod(method);
|
||||
if (statusCode == HttpStatus.SC_PRECONDITION_FAILED) {
|
||||
throw new DavMailException("EXCEPTION_UNABLE_TO_COPY_MESSAGE");
|
||||
} else if (statusCode != HttpStatus.SC_CREATED) {
|
||||
throw DavGatewayHttpClientFacade.buildHttpException(method);
|
||||
}
|
||||
} finally {
|
||||
method.releaseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void moveToTrash(Message message) throws IOException {
|
||||
String destination = URIUtil.encodePath(deleteditemsUrl) + '/' + UUID.randomUUID().toString();
|
||||
LOGGER.debug("Deleting : " + message.permanentUrl + " to " + destination);
|
||||
MoveMethod method = new MoveMethod(message.permanentUrl, destination, false);
|
||||
method.addRequestHeader("Allow-rename", "t");
|
||||
|
||||
int status = DavGatewayHttpClientFacade.executeHttpMethod(httpClient, method);
|
||||
// do not throw error if already deleted
|
||||
if (status != HttpStatus.SC_CREATED && status != HttpStatus.SC_NOT_FOUND) {
|
||||
throw DavGatewayHttpClientFacade.buildHttpException(method);
|
||||
}
|
||||
if (method.getResponseHeader("Location") != null) {
|
||||
destination = method.getResponseHeader("Location").getValue();
|
||||
}
|
||||
|
||||
LOGGER.debug("Deleted to :" + destination);
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
package davmail.exchange.dav;
|
||||
|
||||
import org.apache.jackrabbit.webdav.property.DavPropertyName;
|
||||
import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
|
||||
import org.apache.jackrabbit.webdav.xml.Namespace;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -94,11 +95,14 @@ public class Field {
|
||||
createField("flagStatus", 0x1090, PropertyType.Integer);//PR_FLAG_STATUS
|
||||
createField("messageFlags", 0x0e07, PropertyType.Integer);//PR_MESSAGE_FLAGS
|
||||
createField("lastVerbExecuted", 0x1081, PropertyType.Integer);//PR_LAST_VERB_EXECUTED
|
||||
createField("iconIndex", 0x1080, PropertyType.Integer);//PR_ICON_INDEX
|
||||
createField(URN_SCHEMAS_HTTPMAIL, "read");
|
||||
//createField("read", 0x0e69, PropertyType.Boolean);//PR_READ
|
||||
createField("deleted", DistinguishedPropertySetType.Common, 0x8570);
|
||||
createField(URN_SCHEMAS_HTTPMAIL, "date"); //PR_CLIENT_SUBMIT_TIME, 0x0039
|
||||
createField("writedeleted", DistinguishedPropertySetType.Common, 0x8570, PropertyType.Integer);
|
||||
createField(URN_SCHEMAS_HTTPMAIL, "date");//PR_CLIENT_SUBMIT_TIME, 0x0039
|
||||
//createField("date", 0x0e06, PropertyType.SystemTime);//PR_MESSAGE_DELIVERY_TIME
|
||||
createField(URN_SCHEMAS_MAILHEADER, "bcc");//PS_INTERNET_HEADERS/bcc
|
||||
|
||||
// IMAP search
|
||||
|
||||
@ -129,6 +133,12 @@ public class Field {
|
||||
fieldMap.put(field.alias, field);
|
||||
}
|
||||
|
||||
protected static void createField(String alias, DistinguishedPropertySetType propertySetType, int propertyTag, PropertyType propertyType) {
|
||||
String name = '{' + distinguishedPropertySetMap.get(propertySetType) + "}/_x" +propertyTypeMap.get(propertyType)+"_x"+Integer.toHexString(propertyTag);
|
||||
Field field = new Field(alias, SCHEMAS_MAPI_ID, name);
|
||||
fieldMap.put(field.alias, field);
|
||||
}
|
||||
|
||||
protected static void createField(Namespace namespace, String name) {
|
||||
Field field = new Field(namespace, name);
|
||||
fieldMap.put(field.alias, field);
|
||||
@ -185,4 +195,8 @@ public class Field {
|
||||
String name = '{' + distinguishedPropertySetMap.get(DistinguishedPropertySetType.InternetHeaders) + "}/" + headerName;
|
||||
return new Field(SCHEMAS_MAPI_STRING, name);
|
||||
}
|
||||
|
||||
public static DefaultDavProperty createDavProperty(String alias, String value) {
|
||||
return new DefaultDavProperty(Field.get(alias).davPropertyName, value);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user