IMAP: experimental implementation of header only FETCH, do not download full message content and send approximate RFC822.SIZE (MAPI size)

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1961 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2012-05-16 16:07:35 +00:00
parent d6092e10df
commit 08abcc0514
7 changed files with 110 additions and 40 deletions

View File

@ -40,10 +40,7 @@ import org.htmlcleaner.TagNode;
import javax.imageio.ImageIO;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimePart;
import javax.mail.internet.*;
import javax.mail.util.SharedByteArrayInputStream;
import java.awt.image.BufferedImage;
import java.io.*;
@ -1798,6 +1795,23 @@ public abstract class ExchangeSession {
return mimeMessage;
}
public Enumeration getMatchingHeaderLines(String[] headerNames) throws MessagingException, IOException {
Enumeration result = null;
if (mimeMessage == null) {
// message not loaded, try to get headers only
InputStream headers = getMimeHeaders();
if (headers != null) {
result = new InternetHeaders(headers).getMatchingHeaderLines(headerNames);
}
}
if (result == null) {
result = getMimeMessage().getMatchingHeaderLines(headerNames);
}
return result;
}
protected abstract InputStream getMimeHeaders();
/**
* Get message body size.
*

View File

@ -1078,6 +1078,21 @@ public class DavExchangeSession extends ExchangeSession {
public String getPermanentId() {
return permanentUrl;
}
@Override
protected InputStream getMimeHeaders() {
InputStream result = null;
try {
String messageHeaders = getItemProperty(permanentUrl, "messageheaders");
if (messageHeaders != null) {
result = new ByteArrayInputStream(messageHeaders.getBytes("UTF-8"));
}
} catch (Exception e) {
LOGGER.warn(e.getMessage());
}
return result;
}
}
@ -1132,7 +1147,7 @@ public class DavExchangeSession extends ExchangeSession {
if (!"photo".equals(key)) {
propertyValues.add(Field.createPropertyValue(key, entry.getValue()));
if (key.startsWith("email")) {
propertyValues.add(Field.createPropertyValue(key+"type", "SMTP"));
propertyValues.add(Field.createPropertyValue(key + "type", "SMTP"));
}
}
}
@ -1309,31 +1324,10 @@ public class DavExchangeSession extends ExchangeSession {
protected byte[] getICSFromInternetContentProperty() throws IOException, DavException, MessagingException {
byte[] result = null;
// PropFind PR_INTERNET_CONTENT
DavPropertyNameSet davPropertyNameSet = new DavPropertyNameSet();
davPropertyNameSet.add(Field.getPropertyName("internetContent"));
PropFindMethod propFindMethod = new PropFindMethod(encodeAndFixUrl(permanentUrl), davPropertyNameSet, 0);
try {
try {
DavGatewayHttpClientFacade.executeHttpMethod(httpClient, propFindMethod);
} catch (UnknownHostException e) {
propFindMethod.releaseConnection();
// failover for misconfigured Exchange server, replace host name in url
restoreHostName = true;
propFindMethod = new PropFindMethod(encodeAndFixUrl(permanentUrl), davPropertyNameSet, 0);
DavGatewayHttpClientFacade.executeHttpMethod(httpClient, propFindMethod);
}
MultiStatus responses = propFindMethod.getResponseBodyAsMultiStatus();
if (responses.getResponses().length > 0) {
DavPropertySet properties = responses.getResponses()[0].getProperties(HttpStatus.SC_OK);
String propertyValue = getPropertyIfExists(properties, "internetContent");
if (propertyValue != null) {
byte[] byteArray = Base64.decodeBase64(propertyValue.getBytes());
result = getICS(new ByteArrayInputStream(byteArray));
}
}
} finally {
propFindMethod.releaseConnection();
String propertyValue = getItemProperty(permanentUrl, "internetContent");
if (propertyValue != null) {
byte[] byteArray = Base64.decodeBase64(propertyValue.getBytes());
result = getICS(new ByteArrayInputStream(byteArray));
}
return result;
}
@ -1940,7 +1934,7 @@ public class DavExchangeSession extends ExchangeSession {
}
protected String getURLPropertyIfExists(DavPropertySet properties, String alias) throws URIException {
String result = getPropertyIfExists(properties, alias);
String result = getPropertyIfExists(properties, alias);
if (result != null) {
result = URIUtil.decode(result);
}
@ -2059,6 +2053,7 @@ public class DavExchangeSession extends ExchangeSession {
* Common item properties
*/
protected static final Set<String> ITEM_PROPERTIES = new HashSet<String>();
static {
ITEM_PROPERTIES.add("etag");
ITEM_PROPERTIES.add("displayname");
@ -2114,7 +2109,7 @@ public class DavExchangeSession extends ExchangeSession {
boolean caldavEnableLegacyTasks = Settings.getBooleanProperty("davmail.caldavEnableLegacyTasks", false);
if (caldavEnableLegacyTasks) {
// return tasks created in calendar folder
return or(isNull("instancetype"),
return or(isNull("instancetype"),
isEqualTo("instancetype", 1),
and(isEqualTo("instancetype", 0), dateCondition));
} else {
@ -2974,6 +2969,33 @@ public class DavExchangeSession extends ExchangeSession {
LOGGER.debug("Deleted to :" + destination);
}
protected String getItemProperty(String permanentUrl, String propertyName) throws IOException, DavException, MessagingException {
String result = null;
DavPropertyNameSet davPropertyNameSet = new DavPropertyNameSet();
davPropertyNameSet.add(Field.getPropertyName(propertyName));
PropFindMethod propFindMethod = new PropFindMethod(encodeAndFixUrl(permanentUrl), davPropertyNameSet, 0);
try {
try {
DavGatewayHttpClientFacade.executeHttpMethod(httpClient, propFindMethod);
} catch (UnknownHostException e) {
propFindMethod.releaseConnection();
// failover for misconfigured Exchange server, replace host name in url
restoreHostName = true;
propFindMethod = new PropFindMethod(encodeAndFixUrl(permanentUrl), davPropertyNameSet, 0);
DavGatewayHttpClientFacade.executeHttpMethod(httpClient, propFindMethod);
}
MultiStatus responses = propFindMethod.getResponseBodyAsMultiStatus();
if (responses.getResponses().length > 0) {
DavPropertySet properties = responses.getResponses()[0].getProperties(HttpStatus.SC_OK);
result = getPropertyIfExists(properties, propertyName);
}
} finally {
propFindMethod.releaseConnection();
}
return result;
}
protected String convertDateFromExchange(String exchangeDateValue) throws DavMailException {
String zuluDateValue = null;
if (exchangeDateValue != null) {
@ -3002,7 +3024,7 @@ public class DavExchangeSession extends ExchangeSession {
priorityToImportanceMap.put("9", "low");
}
protected String convertPriorityFromExchange(String exchangeImportanceValue) {
protected String convertPriorityFromExchange(String exchangeImportanceValue) {
String value = null;
if (exchangeImportanceValue != null) {
value = importanceToPriorityMap.get(exchangeImportanceValue);
@ -3010,7 +3032,7 @@ public class DavExchangeSession extends ExchangeSession {
return value;
}
protected String convertPriorityToExchange(String vTodoPriorityValue) {
protected String convertPriorityToExchange(String vTodoPriorityValue) {
String value = null;
if (vTodoPriorityValue != null) {
value = priorityToImportanceMap.get(vTodoPriorityValue);

View File

@ -143,6 +143,7 @@ public class Field {
createField(URN_SCHEMAS_HTTPMAIL, "subject"); // DistinguishedPropertySetType.InternetHeaders/Subject/String
//createField("subject", 0x0037, PropertyType.String);//PR_SUBJECT
createField("body", 0x1000, PropertyType.String);//PR_BODY
createField("messageheaders", 0x007D, PropertyType.String);// PR_TRANSPORT_MESSAGE_HEADERS
createField(URN_SCHEMAS_HTTPMAIL, "from");
//createField("from", DistinguishedPropertySetType.PublicStrings, 0x001f);//urn:schemas:httpmail:from
createField(URN_SCHEMAS_MAILHEADER, "to"); // DistinguishedPropertySetType.InternetHeaders/To/String

View File

@ -41,10 +41,7 @@ import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.util.SharedByteArrayInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.SocketException;
import java.text.ParseException;
@ -368,6 +365,26 @@ public class EwsExchangeSession extends ExchangeSession {
public String getPermanentId() {
return itemId.id;
}
@Override
protected InputStream getMimeHeaders() {
InputStream result = null;
try {
GetItemMethod getItemMethod = new GetItemMethod(BaseShape.ID_ONLY, itemId, false);
getItemMethod.addAdditionalProperty(Field.get("messageheaders"));
executeMethod(getItemMethod);
EWSMethod.Item item = getItemMethod.getResponseItem();
String messageHeaders = item.get(Field.get("messageheaders").getResponseName());
if (messageHeaders != null) {
result = new ByteArrayInputStream(messageHeaders.getBytes("UTF-8"));
}
} catch (Exception e) {
LOGGER.warn(e.getMessage());
}
return result;
}
}
/**

View File

@ -79,6 +79,8 @@ public final class Field {
FIELD_MAP.put("cc", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.InternetHeaders, "cc"));
FIELD_MAP.put("from", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.InternetHeaders, "from"));
FIELD_MAP.put("messageheaders", new ExtendedFieldURI(0x007D, ExtendedFieldURI.PropertyType.String)); // PR_TRANSPORT_MESSAGE_HEADERS
FIELD_MAP.put("contentclass", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.InternetHeaders, "content-class"));
FIELD_MAP.put("message-id", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.InternetHeaders, "message-id"));

View File

@ -713,7 +713,14 @@ public class ImapConnection extends AbstractConnection {
if ("FLAGS".equals(param)) {
buffer.append(" FLAGS (").append(message.getImapFlags()).append(')');
} else if ("RFC822.SIZE".equals(param)) {
buffer.append(" RFC822.SIZE ").append(message.getMimeMessageSize());
int size;
if (parameters.indexOf("BODY.PEEK[HEADER.FIELDS (") >= 0) {
// Header request, send approximate size
size = message.size;
} else {
size = message.getMimeMessageSize();
}
buffer.append(" RFC822.SIZE ").append(size);
} else if ("ENVELOPE".equals(param)) {
appendEnvelope(buffer, message);
} else if ("BODYSTRUCTURE".equals(param)) {
@ -769,11 +776,12 @@ public class ImapConnection extends AbstractConnection {
if (requestedHeaders != null) {
// OSX Lion special flags request
if (requestedHeaders.length == 1 && "content-class".equals(requestedHeaders[0]) && message.contentClass != null) {
baos.write("Content-class: ".getBytes("UTF-8"));
baos.write(message.contentClass.getBytes("UTF-8"));
baos.write(13);
baos.write(10);
} else {
Enumeration headerEnumeration = message.getMimeMessage().getMatchingHeaderLines(requestedHeaders);
Enumeration headerEnumeration = message.getMatchingHeaderLines(requestedHeaders);
while (headerEnumeration.hasMoreElements()) {
baos.write(((String) headerEnumeration.nextElement()).getBytes("UTF-8"));
baos.write(13);

View File

@ -388,4 +388,10 @@ public class TestImap extends AbstractImapTestCase {
writeLine(". FETCH 1:* (FLAGS UID BODY.PEEK[HEADER.FIELDS (content-class)])");
assertEquals(". OK FETCH completed", readFullAnswer("."));
}
public void testFetchHeadersThunderbird() throws IOException {
testSelectInbox();
writeLine(". FETCH 1:* (UID RFC822.SIZE FLAGS BODY.PEEK[HEADER.FIELDS (From To Cc Bcc Subject Date Message-ID Priority X-Priority References Newsgroups In-Reply-To Content-Type)])");
assertEquals(". OK FETCH completed", readFullAnswer("."));
}
}