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:
parent
d6092e10df
commit
08abcc0514
|
@ -40,10 +40,7 @@ import org.htmlcleaner.TagNode;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
import javax.mail.internet.InternetAddress;
|
import javax.mail.internet.*;
|
||||||
import javax.mail.internet.MimeMessage;
|
|
||||||
import javax.mail.internet.MimeMultipart;
|
|
||||||
import javax.mail.internet.MimePart;
|
|
||||||
import javax.mail.util.SharedByteArrayInputStream;
|
import javax.mail.util.SharedByteArrayInputStream;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
@ -1798,6 +1795,23 @@ public abstract class ExchangeSession {
|
||||||
return mimeMessage;
|
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.
|
* Get message body size.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1078,6 +1078,21 @@ public class DavExchangeSession extends ExchangeSession {
|
||||||
public String getPermanentId() {
|
public String getPermanentId() {
|
||||||
return permanentUrl;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1309,32 +1324,11 @@ public class DavExchangeSession extends ExchangeSession {
|
||||||
protected byte[] getICSFromInternetContentProperty() throws IOException, DavException, MessagingException {
|
protected byte[] getICSFromInternetContentProperty() throws IOException, DavException, MessagingException {
|
||||||
byte[] result = null;
|
byte[] result = null;
|
||||||
// PropFind PR_INTERNET_CONTENT
|
// PropFind PR_INTERNET_CONTENT
|
||||||
DavPropertyNameSet davPropertyNameSet = new DavPropertyNameSet();
|
String propertyValue = getItemProperty(permanentUrl, "internetContent");
|
||||||
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) {
|
if (propertyValue != null) {
|
||||||
byte[] byteArray = Base64.decodeBase64(propertyValue.getBytes());
|
byte[] byteArray = Base64.decodeBase64(propertyValue.getBytes());
|
||||||
result = getICS(new ByteArrayInputStream(byteArray));
|
result = getICS(new ByteArrayInputStream(byteArray));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
propFindMethod.releaseConnection();
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2059,6 +2053,7 @@ public class DavExchangeSession extends ExchangeSession {
|
||||||
* Common item properties
|
* Common item properties
|
||||||
*/
|
*/
|
||||||
protected static final Set<String> ITEM_PROPERTIES = new HashSet<String>();
|
protected static final Set<String> ITEM_PROPERTIES = new HashSet<String>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ITEM_PROPERTIES.add("etag");
|
ITEM_PROPERTIES.add("etag");
|
||||||
ITEM_PROPERTIES.add("displayname");
|
ITEM_PROPERTIES.add("displayname");
|
||||||
|
@ -2974,6 +2969,33 @@ public class DavExchangeSession extends ExchangeSession {
|
||||||
LOGGER.debug("Deleted to :" + destination);
|
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 {
|
protected String convertDateFromExchange(String exchangeDateValue) throws DavMailException {
|
||||||
String zuluDateValue = null;
|
String zuluDateValue = null;
|
||||||
if (exchangeDateValue != null) {
|
if (exchangeDateValue != null) {
|
||||||
|
|
|
@ -143,6 +143,7 @@ public class Field {
|
||||||
createField(URN_SCHEMAS_HTTPMAIL, "subject"); // DistinguishedPropertySetType.InternetHeaders/Subject/String
|
createField(URN_SCHEMAS_HTTPMAIL, "subject"); // DistinguishedPropertySetType.InternetHeaders/Subject/String
|
||||||
//createField("subject", 0x0037, PropertyType.String);//PR_SUBJECT
|
//createField("subject", 0x0037, PropertyType.String);//PR_SUBJECT
|
||||||
createField("body", 0x1000, PropertyType.String);//PR_BODY
|
createField("body", 0x1000, PropertyType.String);//PR_BODY
|
||||||
|
createField("messageheaders", 0x007D, PropertyType.String);// PR_TRANSPORT_MESSAGE_HEADERS
|
||||||
createField(URN_SCHEMAS_HTTPMAIL, "from");
|
createField(URN_SCHEMAS_HTTPMAIL, "from");
|
||||||
//createField("from", DistinguishedPropertySetType.PublicStrings, 0x001f);//urn:schemas:httpmail:from
|
//createField("from", DistinguishedPropertySetType.PublicStrings, 0x001f);//urn:schemas:httpmail:from
|
||||||
createField(URN_SCHEMAS_MAILHEADER, "to"); // DistinguishedPropertySetType.InternetHeaders/To/String
|
createField(URN_SCHEMAS_MAILHEADER, "to"); // DistinguishedPropertySetType.InternetHeaders/To/String
|
||||||
|
|
|
@ -41,10 +41,7 @@ import javax.mail.Session;
|
||||||
import javax.mail.internet.InternetAddress;
|
import javax.mail.internet.InternetAddress;
|
||||||
import javax.mail.internet.MimeMessage;
|
import javax.mail.internet.MimeMessage;
|
||||||
import javax.mail.util.SharedByteArrayInputStream;
|
import javax.mail.util.SharedByteArrayInputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.*;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
@ -368,6 +365,26 @@ public class EwsExchangeSession extends ExchangeSession {
|
||||||
public String getPermanentId() {
|
public String getPermanentId() {
|
||||||
return itemId.id;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -79,6 +79,8 @@ public final class Field {
|
||||||
FIELD_MAP.put("cc", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.InternetHeaders, "cc"));
|
FIELD_MAP.put("cc", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.InternetHeaders, "cc"));
|
||||||
FIELD_MAP.put("from", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.InternetHeaders, "from"));
|
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("contentclass", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.InternetHeaders, "content-class"));
|
||||||
FIELD_MAP.put("message-id", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.InternetHeaders, "message-id"));
|
FIELD_MAP.put("message-id", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.InternetHeaders, "message-id"));
|
||||||
|
|
||||||
|
|
|
@ -713,7 +713,14 @@ public class ImapConnection extends AbstractConnection {
|
||||||
if ("FLAGS".equals(param)) {
|
if ("FLAGS".equals(param)) {
|
||||||
buffer.append(" FLAGS (").append(message.getImapFlags()).append(')');
|
buffer.append(" FLAGS (").append(message.getImapFlags()).append(')');
|
||||||
} else if ("RFC822.SIZE".equals(param)) {
|
} 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)) {
|
} else if ("ENVELOPE".equals(param)) {
|
||||||
appendEnvelope(buffer, message);
|
appendEnvelope(buffer, message);
|
||||||
} else if ("BODYSTRUCTURE".equals(param)) {
|
} else if ("BODYSTRUCTURE".equals(param)) {
|
||||||
|
@ -769,11 +776,12 @@ public class ImapConnection extends AbstractConnection {
|
||||||
if (requestedHeaders != null) {
|
if (requestedHeaders != null) {
|
||||||
// OSX Lion special flags request
|
// OSX Lion special flags request
|
||||||
if (requestedHeaders.length == 1 && "content-class".equals(requestedHeaders[0]) && message.contentClass != null) {
|
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(message.contentClass.getBytes("UTF-8"));
|
||||||
baos.write(13);
|
baos.write(13);
|
||||||
baos.write(10);
|
baos.write(10);
|
||||||
} else {
|
} else {
|
||||||
Enumeration headerEnumeration = message.getMimeMessage().getMatchingHeaderLines(requestedHeaders);
|
Enumeration headerEnumeration = message.getMatchingHeaderLines(requestedHeaders);
|
||||||
while (headerEnumeration.hasMoreElements()) {
|
while (headerEnumeration.hasMoreElements()) {
|
||||||
baos.write(((String) headerEnumeration.nextElement()).getBytes("UTF-8"));
|
baos.write(((String) headerEnumeration.nextElement()).getBytes("UTF-8"));
|
||||||
baos.write(13);
|
baos.write(13);
|
||||||
|
|
|
@ -388,4 +388,10 @@ public class TestImap extends AbstractImapTestCase {
|
||||||
writeLine(". FETCH 1:* (FLAGS UID BODY.PEEK[HEADER.FIELDS (content-class)])");
|
writeLine(". FETCH 1:* (FLAGS UID BODY.PEEK[HEADER.FIELDS (content-class)])");
|
||||||
assertEquals(". OK FETCH completed", readFullAnswer("."));
|
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("."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue