mirror of
https://github.com/moparisthebest/davmail
synced 2024-12-13 03:02:22 -05:00
IMAP message list and fetch now working
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@302 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
09de523391
commit
f2e19291ab
@ -61,10 +61,21 @@ public class ExchangeSession {
|
||||
WELL_KNOWN_FOLDERS.add("urn:schemas:httpmail:calendar");
|
||||
}
|
||||
|
||||
public static final HashMap<String, String> PRIORITIES = new HashMap<String, String>();
|
||||
|
||||
static {
|
||||
PRIORITIES.put("-2", "5 (Lowest)");
|
||||
PRIORITIES.put("-1", "4 (Low)");
|
||||
PRIORITIES.put("1", "2 (High)");
|
||||
PRIORITIES.put("2", "1 (Highest)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Date parser from Exchange format
|
||||
* Date parser/formatter from Exchange format
|
||||
*/
|
||||
private final SimpleDateFormat dateFormatter;
|
||||
private final SimpleDateFormat dateParser;
|
||||
|
||||
|
||||
/**
|
||||
* Various standard mail boxes Urls
|
||||
@ -102,6 +113,10 @@ public class ExchangeSession {
|
||||
// SimpleDateFormat are not thread safe, need to create one instance for
|
||||
// each session
|
||||
dateFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
|
||||
|
||||
dateParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
|
||||
dateParser.setTimeZone(GMT_TIMEZONE);
|
||||
|
||||
LOGGER.debug("Session " + this + " created");
|
||||
}
|
||||
|
||||
@ -513,6 +528,23 @@ public class ExchangeSession {
|
||||
message.size = Integer.parseInt(prop.getPropertyAsString());
|
||||
} else if ("uid".equals(localName)) {
|
||||
message.uid = prop.getPropertyAsString();
|
||||
} else if ("date".equals(prop.getLocalName())) {
|
||||
message.date = prop.getPropertyAsString();
|
||||
} else if ("message-id".equals(prop.getLocalName())) {
|
||||
message.messageId = prop.getPropertyAsString();
|
||||
} else if ("from".equals(prop.getLocalName())) {
|
||||
message.from = prop.getPropertyAsString();
|
||||
} else if ("to".equals(prop.getLocalName())) {
|
||||
message.to = prop.getPropertyAsString();
|
||||
} else if ("cc".equals(prop.getLocalName())) {
|
||||
message.cc = prop.getPropertyAsString();
|
||||
} else if ("subject".equals(prop.getLocalName())) {
|
||||
message.subject = prop.getPropertyAsString();
|
||||
} else if ("priority".equals(prop.getLocalName())) {
|
||||
String priorityLabel = PRIORITIES.get(prop.getPropertyAsString());
|
||||
if (priorityLabel != null) {
|
||||
message.priority = priorityLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -538,6 +570,7 @@ public class ExchangeSession {
|
||||
String folderUrl = getFolderPath(folderName);
|
||||
List<Message> messages = new ArrayList<Message>();
|
||||
String searchRequest = "Select \"DAV:uid\", \"http://schemas.microsoft.com/mapi/proptag/x0e080003\"" +
|
||||
" ,\"urn:schemas:mailheader:from\",\"urn:schemas:mailheader:to\",\"urn:schemas:mailheader:cc\",\"urn:schemas:httpmail:subject\",\"urn:schemas:mailheader:date\",\"urn:schemas:mailheader:message-id\",\"urn:schemas:httpmail:priority\""+
|
||||
" FROM Scope('SHALLOW TRAVERSAL OF \"" + folderUrl + "\"')\n" +
|
||||
" WHERE \"DAV:ishidden\" = False AND \"DAV:isfolder\" = False\n" +
|
||||
" ORDER BY \"urn:schemas:httpmail:date\" ASC";
|
||||
@ -552,11 +585,12 @@ public class ExchangeSession {
|
||||
return messages;
|
||||
}
|
||||
|
||||
public List<Folder> getSubFolders(String folderName) throws IOException {
|
||||
public List<Folder> getSubFolders(String folderName,boolean recursive) throws IOException {
|
||||
String mode = recursive?"DEEP":"SHALLOW";
|
||||
List<Folder> folders = new ArrayList<Folder>();
|
||||
String searchRequest = "Select \"DAV:nosubs\", \"DAV:hassubs\"," +
|
||||
" \"DAV:hassubs\",\"urn:schemas:httpmail:unreadcount\"" +
|
||||
" FROM Scope('SHALLOW TRAVERSAL OF \"" + getFolderPath(folderName) + "\"')\n" +
|
||||
" FROM Scope('"+mode+" TRAVERSAL OF \"" + getFolderPath(folderName) + "\"')\n" +
|
||||
" WHERE \"DAV:ishidden\" = False AND \"DAV:isfolder\" = True \n";
|
||||
Enumeration folderEnum = DavGatewayHttpClientFacade.executeSearchMethod(wdr.retrieveSessionInstance(), mailPath, searchRequest);
|
||||
|
||||
@ -585,7 +619,13 @@ public class ExchangeSession {
|
||||
if ("unreadcount".equals(property.getLocalName())) {
|
||||
folder.unreadCount = Integer.parseInt(property.getPropertyAsString());
|
||||
}
|
||||
|
||||
if ("getlastmodified".equals(property.getLocalName())) {
|
||||
try {
|
||||
folder.lastModified = dateParser.parse(property.getPropertyAsString()).getTime();
|
||||
} catch (ParseException e) {
|
||||
LOGGER.error("Unable to parse date: "+e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (href.endsWith("/")) {
|
||||
href = href.substring(0, href.length()-1);
|
||||
@ -757,6 +797,7 @@ public class ExchangeSession {
|
||||
reqProps.add("DAV:nosubs");
|
||||
reqProps.add("DAV:objectcount");
|
||||
reqProps.add("urn:schemas:httpmail:unreadcount");
|
||||
reqProps.add("DAV:getlastmodified");
|
||||
Enumeration folderEnum = wdr.propfindMethod(folder.folderUrl, 0, reqProps);
|
||||
|
||||
if (folderEnum.hasMoreElements()) {
|
||||
@ -772,6 +813,7 @@ public class ExchangeSession {
|
||||
public int unreadCount;
|
||||
public boolean hasChildren;
|
||||
public boolean noInferiors;
|
||||
public long lastModified;
|
||||
|
||||
public String getFlags() {
|
||||
if (noInferiors) {
|
||||
@ -788,6 +830,13 @@ public class ExchangeSession {
|
||||
public String messageUrl;
|
||||
public String uid;
|
||||
public int size;
|
||||
public String from;
|
||||
public String date;
|
||||
public String messageId;
|
||||
public String subject;
|
||||
public String priority;
|
||||
public String cc;
|
||||
public String to;
|
||||
|
||||
public void write(OutputStream os) throws IOException {
|
||||
HttpMethod method = null;
|
||||
|
@ -6,6 +6,7 @@ import java.net.SocketException;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.List;
|
||||
import java.io.IOException;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import davmail.AbstractConnection;
|
||||
import davmail.tray.DavGatewayTray;
|
||||
@ -50,6 +51,10 @@ public class ImapConnection extends AbstractConnection {
|
||||
&& nextToken.charAt(nextToken.length() - 1) != '"') {
|
||||
nextToken.append(' ').append(super.nextToken());
|
||||
}
|
||||
while (hasMoreTokens() && nextToken.length() > 0 && nextToken.charAt(0) == '('
|
||||
&& nextToken.charAt(nextToken.length() - 1) != ')') {
|
||||
nextToken.append(' ').append(super.nextToken());
|
||||
}
|
||||
return nextToken.toString();
|
||||
}
|
||||
};
|
||||
@ -103,24 +108,26 @@ public class ImapConnection extends AbstractConnection {
|
||||
if (state != AUTHENTICATED) {
|
||||
sendClient(commandId + " BAD command authentication required");
|
||||
} else {
|
||||
if ("lsub".equalsIgnoreCase(command)) {
|
||||
sendClient(commandId + " OK LSUB completed");
|
||||
} else if ("list".equalsIgnoreCase(command)) {
|
||||
if ("lsub".equalsIgnoreCase(command) || "list".equalsIgnoreCase(command)) {
|
||||
if (tokens.hasMoreTokens()) {
|
||||
String folderContext = BASE64MailboxDecoder.decode(removeQuotes(tokens.nextToken()));
|
||||
if (tokens.hasMoreTokens()) {
|
||||
String folderQuery = folderContext + BASE64MailboxDecoder.decode(removeQuotes(tokens.nextToken()));
|
||||
if (folderQuery.endsWith("%")) {
|
||||
List<ExchangeSession.Folder> folders = session.getSubFolders(folderQuery.substring(0, folderQuery.length() - 1));
|
||||
if (folderQuery.endsWith("%/%")) {
|
||||
folderQuery = folderQuery.substring(0, folderQuery.length() - 2);
|
||||
}
|
||||
if (folderQuery.endsWith("%") || folderQuery.endsWith("*")) {
|
||||
boolean recursive = folderQuery.endsWith("*");
|
||||
List<ExchangeSession.Folder> folders = session.getSubFolders(folderQuery.substring(0, folderQuery.length() - 1), recursive);
|
||||
for (ExchangeSession.Folder folder : folders) {
|
||||
sendClient("* LIST (" + folder.getFlags() + ") \"/\" \"" + BASE64MailboxEncoder.encode(folder.folderUrl) + "\"");
|
||||
sendClient("* " + command + " (" + folder.getFlags() + ") \"/\" \"" + BASE64MailboxEncoder.encode(folder.folderUrl) + "\"");
|
||||
}
|
||||
sendClient(commandId + " OK LIST completed");
|
||||
sendClient(commandId + " OK " + command + " completed");
|
||||
} else {
|
||||
ExchangeSession.Folder folder = session.getFolder(folderQuery);
|
||||
if (folder != null) {
|
||||
sendClient("* LIST (" + folder.getFlags() + ") \"/\" \"" + BASE64MailboxEncoder.encode(folder.folderUrl) + "\"");
|
||||
sendClient(commandId + " OK LIST completed");
|
||||
sendClient("* " + command + " (" + folder.getFlags() + ") \"/\" \"" + BASE64MailboxEncoder.encode(folder.folderUrl) + "\"");
|
||||
sendClient(commandId + " OK " + command + " completed");
|
||||
} else {
|
||||
sendClient(commandId + " NO Folder not found");
|
||||
}
|
||||
@ -138,11 +145,11 @@ public class ImapConnection extends AbstractConnection {
|
||||
messages = session.getAllMessages(currentFolder.folderUrl);
|
||||
sendClient("* " + currentFolder.objectCount + " EXISTS");
|
||||
sendClient("* " + currentFolder.objectCount + " RECENT");
|
||||
sendClient("* OK [UIDVALIDITY " + System.currentTimeMillis() + "]");
|
||||
sendClient("* OK [UIDVALIDITY " + currentFolder.lastModified + "]");
|
||||
sendClient("* OK [UIDNEXT " + (currentFolder.objectCount + 1) + "]");
|
||||
sendClient("* FLAGS (\\Answered \\Deleted \\Draft \\Flagged \\Seen)");
|
||||
sendClient("* OK [PERMANENTFLAGS (\\Answered \\Deleted \\Draft \\Flagged \\Seen)]");
|
||||
sendClient("* [UNSEEN 1] first unseen message in inbox");
|
||||
sendClient("* FLAGS (\\Answered \\Deleted \\Draft \\Flagged \\Seen $Forwarded $MDNSent Forwarded $Junk $NotJunk Junk JunkRecorded NonJunk NotJunk)");
|
||||
sendClient("* OK [PERMANENTFLAGS (\\Answered \\Deleted \\Draft \\Flagged \\Seen $Forwarded $MDNSent Forwarded \\*)] junk-related flags are not permanent");
|
||||
//sendClient("* [UNSEEN 1] first unseen message in inbox");
|
||||
sendClient(commandId + " OK [READ-WRITE] " + command + " completed");
|
||||
} else {
|
||||
sendClient(commandId + " BAD command unrecognized");
|
||||
@ -166,17 +173,60 @@ public class ImapConnection extends AbstractConnection {
|
||||
} else if ("uid".equalsIgnoreCase(command)) {
|
||||
if (tokens.hasMoreTokens() && "fetch".equalsIgnoreCase(tokens.nextToken())) {
|
||||
if (tokens.hasMoreTokens()) {
|
||||
String parameter = tokens.nextToken();
|
||||
String messageParameter = tokens.nextToken();
|
||||
if (currentFolder == null) {
|
||||
sendClient(commandId + " NO no folder selected");
|
||||
}
|
||||
if ("1:*".equals(parameter)) {
|
||||
for (int i = 0; i < currentFolder.objectCount; i++) {
|
||||
sendClient("* FETCH (UID " + (i + 1) + " FLAGS (\\Recent))");
|
||||
int startIndex;
|
||||
int endIndex;
|
||||
int colonIndex = messageParameter.indexOf(":");
|
||||
if (colonIndex < 0) {
|
||||
startIndex = endIndex = Integer.parseInt(messageParameter);
|
||||
} else {
|
||||
startIndex = Integer.parseInt(messageParameter.substring(0, colonIndex));
|
||||
if (messageParameter.endsWith("*")) {
|
||||
endIndex = messages.size();
|
||||
} else {
|
||||
endIndex = Integer.parseInt(messageParameter.substring(colonIndex + 1));
|
||||
}
|
||||
}
|
||||
if ("1:*".equals(messageParameter)) {
|
||||
int count = 0;
|
||||
for (ExchangeSession.Message message : messages) {
|
||||
count++;
|
||||
sendClient("* " + count + " FETCH (UID " + count + " FLAGS (\\Seen))");
|
||||
}
|
||||
sendClient(commandId + " OK UID FETCH completed");
|
||||
} else {
|
||||
sendClient(commandId + " BAD command unrecognized");
|
||||
if (tokens.hasMoreTokens()) {
|
||||
String parameters = tokens.nextToken();
|
||||
for (int messageIndex = startIndex; messageIndex <= endIndex; messageIndex++) {
|
||||
ExchangeSession.Message message = messages.get(messageIndex - 1);
|
||||
|
||||
if ("(BODYSTRUCTURE)".equals(parameters)) {
|
||||
sendClient("* " + messageIndex + " FETCH (BODYSTRUCTURE (\"TEXT\" \"PLAIN\" (\"CHARSET\" \"windows-1252\") NIL NIL \"QUOTED-PRINTABLE\" " + message.size + " 50 NIL NIL NIL NIL))");
|
||||
} else if (parameters.indexOf("BODY[]") >= 0) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
message.write(baos);
|
||||
baos.close();
|
||||
|
||||
sendClient("* " + messageIndex + " FETCH (UID " + messageIndex + " RFC822.SIZE " + baos.size() + " BODY[]<0>" +
|
||||
" {" + baos.size() + "}");
|
||||
message.write(os);
|
||||
sendClient(")");
|
||||
} else {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
message.write(baos);
|
||||
baos.close();
|
||||
sendClient("* " + messageIndex + " FETCH (UID " + messageIndex + " RFC822.SIZE " + baos.size() + " BODY[HEADER.FIELDS (FROM TO CC SUBJECT DATE MESSAGE-ID PRIORITY X-PRIORITY REFERENCES NEWSGROUPS IN-REPLY-TO CONTENT-TYPE)" +
|
||||
"] {" + baos.size() + "}");
|
||||
message.write(os);
|
||||
sendClient(" FLAGS (\\Seen))");
|
||||
}
|
||||
}
|
||||
sendClient(commandId + " OK FETCH completed");
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sendClient(commandId + " BAD command unrecognized");
|
||||
@ -191,15 +241,17 @@ public class ImapConnection extends AbstractConnection {
|
||||
if (tokens.hasMoreTokens()) {
|
||||
String parameters = tokens.nextToken();
|
||||
if ("(BODYSTRUCTURE)".equals(parameters)) {
|
||||
sendClient("* "+messageIndex+" FETCH (BODYSTRUCTURE (\"TEXT\" \"PLAIN\" (\"CHARSET\" \"windows-1252\") NIL NIL \"QUOTED-PRINTABLE\" "+message.size+" 50 NIL NIL NIL NIL))");
|
||||
sendClient("* " + messageIndex + " FETCH (BODYSTRUCTURE (\"TEXT\" \"PLAIN\" (\"CHARSET\" \"windows-1252\") NIL NIL \"QUOTED-PRINTABLE\" " + message.size + " 50 NIL NIL NIL NIL))");
|
||||
sendClient(commandId + " OK FETCH completed");
|
||||
} else {
|
||||
sendClient("* "+messageIndex+" 1 FETCH (BODY[TEXT]<0> {" + message.size + "}");
|
||||
sendClient("* " + messageIndex + " 1 FETCH (BODY[TEXT]<0> {" + message.size + "}");
|
||||
message.write(os);
|
||||
sendClient(commandId + " OK FETCH completed");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ("noop".equalsIgnoreCase(command)) {
|
||||
sendClient(commandId + " OK NOOP completed");
|
||||
} else {
|
||||
sendClient(commandId + " BAD command unrecognized");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user