From 1162d54bf696a65a29bcc937616f28ed0ad765a3 Mon Sep 17 00:00:00 2001 From: mguessan Date: Fri, 23 Jul 2010 08:58:39 +0000 Subject: [PATCH] IMAP: add uidNext MAPI property (not available under Exchange 2003) git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@1254 3d1905a2-6b24-0410-a738-b14d5a86fcbd --- .../davmail/exchange/ExchangeSession.java | 15 ++++++-- .../exchange/dav/DavExchangeSession.java | 3 ++ src/java/davmail/exchange/dav/Field.java | 35 ++++++++++--------- .../exchange/ews/EwsExchangeSession.java | 11 +++++- src/java/davmail/exchange/ews/Field.java | 33 +++++++++-------- .../exchange/TestExchangeSessionMessage.java | 6 ++++ 6 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/java/davmail/exchange/ExchangeSession.java b/src/java/davmail/exchange/ExchangeSession.java index 964ef047..c1e5196d 100644 --- a/src/java/davmail/exchange/ExchangeSession.java +++ b/src/java/davmail/exchange/ExchangeSession.java @@ -187,6 +187,12 @@ public abstract class ExchangeSession { LOGGER.debug("Session " + this + " created"); } + /** + * Format date to exchange search format. + * + * @param date date object + * @return formatted search date + */ public static String formatSearchDate(Date date) { SimpleDateFormat dateFormatter = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS, Locale.ENGLISH); dateFormatter.setTimeZone(GMT_TIMEZONE); @@ -1095,6 +1101,10 @@ public abstract class ExchangeSession { * Folder etag (to detect folder object changes). */ public String etag; + /** + * Next IMAP uid + */ + public int uidNext; /** * Folder message list, empty before loadMessages call. */ @@ -1392,7 +1402,7 @@ public abstract class ExchangeSession { // load and parse message mimeBody = new SharedByteArrayInputStream(getContent(this)); mimeMessage = new MimeMessage(null, mimeBody); - LOGGER.debug("Downloaded message content for " + imapUid + " (" + mimeBody.available() + ')'); + LOGGER.debug("Downloaded full message content for IMAP UID " + imapUid + " (" + mimeBody.available() + " bytes)"); } } } @@ -1456,7 +1466,6 @@ public abstract class ExchangeSession { * @throws IOException on error */ public void delete() throws IOException { - LOGGER.debug("Delete " + permanentUrl + " (" + messageUrl + ')'); deleteMessage(this); } @@ -1760,7 +1769,7 @@ public abstract class ExchangeSession { if ("true".equals(get("haspicture"))) { try { ContactPhoto contactPhoto = getContactPhoto(this); - writer.appendProperty("PHOTO;TYPE=\"" + contactPhoto.contentType + "\";ENCODING=\"b\"", contactPhoto.content); + writer.appendProperty("PHOTO;BASE64;TYPE=\"" + contactPhoto.contentType + "\";ENCODING=\"b\"", contactPhoto.content); } catch (IOException e) { LOGGER.warn("Unable to get photo from contact " + this.get("cn")); } diff --git a/src/java/davmail/exchange/dav/DavExchangeSession.java b/src/java/davmail/exchange/dav/DavExchangeSession.java index 125a5a14..64259693 100644 --- a/src/java/davmail/exchange/dav/DavExchangeSession.java +++ b/src/java/davmail/exchange/dav/DavExchangeSession.java @@ -887,6 +887,8 @@ public class DavExchangeSession extends ExchangeSession { folder.ctag = getPropertyIfExists(properties, "contenttag"); folder.etag = getPropertyIfExists(properties, "lastmodified"); + folder.uidNext = getIntPropertyIfExists(properties, "uidNext"); + // replace well known folder names if (href.startsWith(inboxUrl)) { folder.folderPath = href.replaceFirst(inboxUrl, INBOX); @@ -933,6 +935,7 @@ public class DavExchangeSession extends ExchangeSession { FOLDER_PROPERTIES.add("unreadcount"); FOLDER_PROPERTIES.add("contenttag"); FOLDER_PROPERTIES.add("lastmodified"); + FOLDER_PROPERTIES.add("uidNext"); } protected static final DavPropertyNameSet FOLDER_PROPERTIES_NAME_SET = new DavPropertyNameSet(); diff --git a/src/java/davmail/exchange/dav/Field.java b/src/java/davmail/exchange/dav/Field.java index 05b52b43..ea0a6752 100644 --- a/src/java/davmail/exchange/dav/Field.java +++ b/src/java/davmail/exchange/dav/Field.java @@ -83,11 +83,11 @@ public class Field { protected static final Map propertyTypeMap = new HashMap(); static { - propertyTypeMap.put(PropertyType.Long, "0003"); - propertyTypeMap.put(PropertyType.Boolean, "000b"); - propertyTypeMap.put(PropertyType.SystemTime, "0040"); + propertyTypeMap.put(PropertyType.Integer, "0003"); // PT_INT + propertyTypeMap.put(PropertyType.Boolean, "000b"); // PT_BOOLEAN + propertyTypeMap.put(PropertyType.SystemTime, "0040"); // PT_SYSTIME propertyTypeMap.put(PropertyType.String, "001f"); // 001f is PT_UNICODE_STRING, 001E is PT_STRING - propertyTypeMap.put(PropertyType.Binary, "0102"); + propertyTypeMap.put(PropertyType.Binary, "0102"); // PT_BINARY } @SuppressWarnings({"UnusedDeclaration"}) @@ -117,19 +117,22 @@ public class Field { createField(URN_SCHEMAS_HTTPMAIL, "unreadcount"); createField(SCHEMAS_REPL, "contenttag"); + createField("uidNext", 0x6751, PropertyType.Integer);// PR_ARTICLE_NUM_NEXT + createField("highestUid", 0x6752, PropertyType.Integer);// PR_IMAP_LAST_ARTICLE_ID + createField(DAV, "isfolder"); // item uid, do not use as search parameter, see http://support.microsoft.com/kb/320749 createField(DAV, "uid"); // based on PR_RECORD_KEY // POP and IMAP message - createField("messageSize", 0x0e08, PropertyType.Long);//PR_MESSAGE_SIZE - createField("imapUid", 0x0e23, PropertyType.Long);//PR_INTERNET_ARTICLE_NUMBER - createField("junk", 0x1083, PropertyType.Long); - createField("flagStatus", 0x1090, PropertyType.Long);//PR_FLAG_STATUS - createField("messageFlags", 0x0e07, PropertyType.Long);//PR_MESSAGE_FLAGS - createField("lastVerbExecuted", 0x1081, PropertyType.Long);//PR_LAST_VERB_EXECUTED - createField("iconIndex", 0x1080, PropertyType.Long);//PR_ICON_INDEX + createField("messageSize", 0x0e08, PropertyType.Integer);//PR_MESSAGE_SIZE + createField("imapUid", 0x0e23, PropertyType.Integer);//PR_INTERNET_ARTICLE_NUMBER + createField("junk", 0x1083, PropertyType.Integer); + 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, "deleted", PropertyType.String); @@ -140,8 +143,8 @@ public class Field { createField(URN_SCHEMAS_HTTPMAIL, "datereceived");//PR_MESSAGE_DELIVERY_TIME, 0x0E06 // unused: force message encoding - createField("messageFormat", 0x5909, PropertyType.Long);//PR_MSG_EDITOR_FORMAT EDITOR_FORMAT_PLAINTEXT = 1 EDITOR_FORMAT_HTML = 2 - createField("mailOverrideFormat", 0x5909, PropertyType.Long);//PR_INETMAIL_OVERRIDE_FORMAT ENCODING_PREFERENCE = 2 BODY_ENCODING_TEXT_AND_HTML = 1 ENCODING_MIME = 4 + createField("messageFormat", 0x5909, PropertyType.Integer);//PR_MSG_EDITOR_FORMAT EDITOR_FORMAT_PLAINTEXT = 1 EDITOR_FORMAT_HTML = 2 + createField("mailOverrideFormat", 0x5909, PropertyType.Integer);//PR_INETMAIL_OVERRIDE_FORMAT ENCODING_PREFERENCE = 2 BODY_ENCODING_TEXT_AND_HTML = 1 ENCODING_MIME = 4 // IMAP search @@ -260,7 +263,7 @@ public class Field { // contact private flags createField("private", DistinguishedPropertySetType.Common, 0x8506, "private", PropertyType.Boolean); // True/False - createField("sensitivity", 0x0036, PropertyType.Long); // PR_SENSITIVITY SENSITIVITY_PRIVATE = 2, SENSITIVITY_PERSONAL = 1, SENSITIVITY_NONE = 0 + createField("sensitivity", 0x0036, PropertyType.Integer); // PR_SENSITIVITY SENSITIVITY_PRIVATE = 2, SENSITIVITY_PERSONAL = 1, SENSITIVITY_NONE = 0 createField("haspicture", DistinguishedPropertySetType.Address, 0x8015, "haspicture", PropertyType.Boolean); // True/False @@ -272,7 +275,7 @@ public class Field { createField(DAV, "ishidden"); createField("attachmentContactPhoto", 0x7FFF, PropertyType.Boolean); // PR_ATTACHMENT_CONTACTPHOTO - createField("renderingPosition", 0x370B, PropertyType.Long);// PR_RENDERING_POSITION + createField("renderingPosition", 0x370B, PropertyType.Integer);// PR_RENDERING_POSITION } protected static String toHexString(int propertyTag) { @@ -383,7 +386,7 @@ public class Field { // a few type based flags isMultivalued = propertyType != null && propertyType.toString().endsWith("Array"); - isIntValue = propertyType == PropertyType.Integer || propertyType == PropertyType.Long || propertyType == PropertyType.Short; + isIntValue = propertyType == PropertyType.Long || propertyType == PropertyType.Integer || propertyType == PropertyType.Short; isBooleanValue = propertyType == PropertyType.Boolean; this.uri = namespace.getURI() + name; diff --git a/src/java/davmail/exchange/ews/EwsExchangeSession.java b/src/java/davmail/exchange/ews/EwsExchangeSession.java index f0c7add9..d2ae37fe 100644 --- a/src/java/davmail/exchange/ews/EwsExchangeSession.java +++ b/src/java/davmail/exchange/ews/EwsExchangeSession.java @@ -191,6 +191,7 @@ public class EwsExchangeSession extends ExchangeSession { @Override public void deleteMessage(ExchangeSession.Message message) throws IOException { + LOGGER.debug("Delete " + message.permanentUrl); DeleteItemMethod deleteItemMethod = new DeleteItemMethod(((EwsExchangeSession.Message) message).itemId, DeleteType.HardDelete); executeMethod(deleteItemMethod); } @@ -488,6 +489,8 @@ public class EwsExchangeSession extends ExchangeSession { FOLDER_PROPERTIES.add(Field.get("ctag")); FOLDER_PROPERTIES.add(Field.get("unread")); FOLDER_PROPERTIES.add(Field.get("hassubs")); + FOLDER_PROPERTIES.add(Field.get("uidNext")); + FOLDER_PROPERTIES.add(Field.get("highestUid")); } protected Folder buildFolder(EWSMethod.Item item) { @@ -500,6 +503,7 @@ public class EwsExchangeSession extends ExchangeSession { folder.unreadCount = item.getInt(Field.get("unread").getResponseName()); folder.hasChildren = item.getBoolean(Field.get("hassubs").getResponseName()); // noInferiors not implemented + folder.uidNext = item.getInt(Field.get("uidNext").getResponseName()); return folder; } @@ -973,7 +977,12 @@ public class EwsExchangeSession extends ExchangeSession { contactPhoto = new ContactPhoto(); contactPhoto.content = getAttachmentMethod.getResponseItem().get("Content"); - contactPhoto.contentType = attachment.contentType; + if (attachment.contentType == null) { + contactPhoto.contentType = "image/jpeg"; + } else { + contactPhoto.contentType = attachment.contentType; + } + } } diff --git a/src/java/davmail/exchange/ews/Field.java b/src/java/davmail/exchange/ews/Field.java index 496fdc68..43772811 100644 --- a/src/java/davmail/exchange/ews/Field.java +++ b/src/java/davmail/exchange/ews/Field.java @@ -43,10 +43,13 @@ public class Field { FIELD_MAP.put("hassubs", new ExtendedFieldURI(0x360a, ExtendedFieldURI.PropertyType.Boolean)); // PR_SUBFOLDERS FIELD_MAP.put("folderDisplayName", new UnindexedFieldURI("folder:DisplayName")); + FIELD_MAP.put("uidNext", new ExtendedFieldURI(0x6751, ExtendedFieldURI.PropertyType.Integer)); // PR_ARTICLE_NUM_NEXT + FIELD_MAP.put("highestUid", new ExtendedFieldURI(0x6752, ExtendedFieldURI.PropertyType.Integer)); // PR_IMAP_LAST_ARTICLE_ID + FIELD_MAP.put("permanenturl", new ExtendedFieldURI(0x670E, ExtendedFieldURI.PropertyType.String)); //PR_FLAT_URL_NAME FIELD_MAP.put("instancetype", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.PublicStrings, "urn:schemas:calendar:instancetype")); FIELD_MAP.put("dtstart", new ExtendedFieldURI(0x10C3, ExtendedFieldURI.PropertyType.SystemTime)); - FIELD_MAP.put("dtstart", new ExtendedFieldURI(0x10C4, ExtendedFieldURI.PropertyType.SystemTime)); + FIELD_MAP.put("dtend", new ExtendedFieldURI(0x10C4, ExtendedFieldURI.PropertyType.SystemTime)); FIELD_MAP.put("mimeContent", new UnindexedFieldURI("item:MimeContent")); @@ -98,10 +101,22 @@ public class Field { FIELD_MAP.put("co", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x8049, ExtendedFieldURI.PropertyType.String)); FIELD_MAP.put("department", new ExtendedFieldURI(0x3A18, ExtendedFieldURI.PropertyType.String)); - FIELD_MAP.put("email1", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x8084, ExtendedFieldURI.PropertyType.String)); - FIELD_MAP.put("email2", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x8094, ExtendedFieldURI.PropertyType.String)); - FIELD_MAP.put("email3", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x80A4, ExtendedFieldURI.PropertyType.String)); + FIELD_MAP.put("email1", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x8083, ExtendedFieldURI.PropertyType.String)); // Email1EmailAddress + FIELD_MAP.put("email2", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x8093, ExtendedFieldURI.PropertyType.String)); // Email2EmailAddress + FIELD_MAP.put("email3", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x80A3, ExtendedFieldURI.PropertyType.String)); // Email3EmailAddress + /* + FIELD_MAP.put("email1", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x8084, ExtendedFieldURI.PropertyType.String)); // Email1OriginalDisplayName + FIELD_MAP.put("email2", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x8094, ExtendedFieldURI.PropertyType.String)); // Email2OriginalDisplayName + FIELD_MAP.put("email3", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x80A4, ExtendedFieldURI.PropertyType.String)); // Email3OriginalDisplayName + */ + + /* + FIELD_MAP.put("email1", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x8080, ExtendedFieldURI.PropertyType.String)); // Email1DisplayName + FIELD_MAP.put("email2", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x8090, ExtendedFieldURI.PropertyType.String)); // Email2DisplayName + FIELD_MAP.put("email3", new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.Address, 0x80A0, ExtendedFieldURI.PropertyType.String)); // Email3DisplayName + */ + FIELD_MAP.put("facsimiletelephonenumber", new ExtendedFieldURI(0x3A24, ExtendedFieldURI.PropertyType.String)); FIELD_MAP.put("givenName", new ExtendedFieldURI(0x3A06, ExtendedFieldURI.PropertyType.String)); @@ -173,16 +188,6 @@ public class Field { return field; } - /** - * Get Mime header field. - * - * @param headerName header name - * @return field object - */ - public static FieldURI getHeader(String headerName) { - return new ExtendedFieldURI(ExtendedFieldURI.DistinguishedPropertySetType.InternetHeaders, headerName); - } - /** * Create property update field * diff --git a/src/test/davmail/exchange/TestExchangeSessionMessage.java b/src/test/davmail/exchange/TestExchangeSessionMessage.java index fa70dbbb..c8a16c9f 100644 --- a/src/test/davmail/exchange/TestExchangeSessionMessage.java +++ b/src/test/davmail/exchange/TestExchangeSessionMessage.java @@ -38,6 +38,7 @@ public class TestExchangeSessionMessage extends AbstractExchangeSessionTestCase MimeMessage mimeMessage = createMimeMessage(); messageName = UUID.randomUUID().toString()+".EML"; HashMap properties = new HashMap(); + properties.put("draft", "0"); session.createMessage("testfolder", messageName, properties, getMimeBody(mimeMessage)); } @@ -83,6 +84,11 @@ public class TestExchangeSessionMessage extends AbstractExchangeSessionTestCase session.processItem("testfolder", messageName); } + public void testFolderUidNext() throws IOException, MessagingException { + ExchangeSession.Folder folder = session.getFolder("testfolder"); + assertTrue(folder.uidNext > 0); + } + public void testDeleteMessage() throws IOException { session.deleteMessage(message); ExchangeSession.MessageList messageList = session.searchMessages("testfolder");