mirror of
https://github.com/moparisthebest/davmail
synced 2025-02-28 09:21:49 -05:00
IMAP: Check folder ctag and reload messages as needed, ignore RECENT search PARAMETER, allow quoted and unquoted message id on search
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@480 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
d3aa687124
commit
72a8ad7374
@ -69,6 +69,7 @@ public class ExchangeSession {
|
|||||||
FOLDER_PROPERTIES.add("DAV:hassubs");
|
FOLDER_PROPERTIES.add("DAV:hassubs");
|
||||||
FOLDER_PROPERTIES.add("DAV:nosubs");
|
FOLDER_PROPERTIES.add("DAV:nosubs");
|
||||||
FOLDER_PROPERTIES.add("urn:schemas:httpmail:unreadcount");
|
FOLDER_PROPERTIES.add("urn:schemas:httpmail:unreadcount");
|
||||||
|
FOLDER_PROPERTIES.add("http://schemas.microsoft.com/repl/contenttag");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static final Vector<String> CONTENT_TAG = new Vector<String>();
|
protected static final Vector<String> CONTENT_TAG = new Vector<String>();
|
||||||
@ -114,6 +115,7 @@ public class ExchangeSession {
|
|||||||
* The session is not actually established until a call to login()
|
* The session is not actually established until a call to login()
|
||||||
*
|
*
|
||||||
* @param poolKey session pool key
|
* @param poolKey session pool key
|
||||||
|
* @throws java.io.IOException on error
|
||||||
*/
|
*/
|
||||||
ExchangeSession(ExchangeSessionFactory.PoolKey poolKey) throws IOException {
|
ExchangeSession(ExchangeSessionFactory.PoolKey poolKey) throws IOException {
|
||||||
this.poolKey = poolKey;
|
this.poolKey = poolKey;
|
||||||
@ -659,6 +661,9 @@ public class ExchangeSession {
|
|||||||
if ("unreadcount".equals(property.getLocalName())) {
|
if ("unreadcount".equals(property.getLocalName())) {
|
||||||
folder.unreadCount = Integer.parseInt(property.getPropertyAsString());
|
folder.unreadCount = Integer.parseInt(property.getPropertyAsString());
|
||||||
}
|
}
|
||||||
|
if ("contenttag".equals(property.getLocalName())) {
|
||||||
|
folder.contenttag = property.getPropertyAsString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (href.endsWith("/")) {
|
if (href.endsWith("/")) {
|
||||||
href = href.substring(0, href.length() - 1);
|
href = href.substring(0, href.length() - 1);
|
||||||
@ -843,6 +848,27 @@ public class ExchangeSession {
|
|||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check folder ctag and reload messages as needed
|
||||||
|
*
|
||||||
|
* @param currentFolder current folder
|
||||||
|
* @return current folder or new refreshed folder
|
||||||
|
* @throws IOException on error
|
||||||
|
*/
|
||||||
|
public Folder refreshFolder(Folder currentFolder) throws IOException {
|
||||||
|
Folder newFolder = getFolder(currentFolder.folderName);
|
||||||
|
if (currentFolder.contenttag == null || !currentFolder.contenttag.equals(newFolder.contenttag)) {
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug("Contenttag changed on " + currentFolder.folderName + " "
|
||||||
|
+ currentFolder.contenttag + " => " + newFolder.contenttag + ", reloading messages");
|
||||||
|
}
|
||||||
|
newFolder.loadMessages();
|
||||||
|
return newFolder;
|
||||||
|
} else {
|
||||||
|
return currentFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void createFolder(String folderName) throws IOException {
|
public void createFolder(String folderName) throws IOException {
|
||||||
String folderPath = getFolderPath(folderName);
|
String folderPath = getFolderPath(folderName);
|
||||||
PropPatchMethod method = new PropPatchMethod(URIUtil.encodePath(folderPath)) {
|
PropPatchMethod method = new PropPatchMethod(URIUtil.encodePath(folderPath)) {
|
||||||
@ -914,12 +940,14 @@ public class ExchangeSession {
|
|||||||
LOGGER.debug("Deleted to :" + destination);
|
LOGGER.debug("Deleted to :" + destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Folder {
|
public class Folder {
|
||||||
public String folderUrl;
|
public String folderUrl;
|
||||||
public int unreadCount;
|
public int unreadCount;
|
||||||
public boolean hasChildren;
|
public boolean hasChildren;
|
||||||
public boolean noInferiors;
|
public boolean noInferiors;
|
||||||
public String folderName;
|
public String folderName;
|
||||||
|
public String contenttag;
|
||||||
|
public ExchangeSession.MessageList messages;
|
||||||
|
|
||||||
public String getFlags() {
|
public String getFlags() {
|
||||||
if (noInferiors) {
|
if (noInferiors) {
|
||||||
@ -930,6 +958,26 @@ public class ExchangeSession {
|
|||||||
return "\\HasNoChildren";
|
return "\\HasNoChildren";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void loadMessages() throws IOException {
|
||||||
|
messages = getAllMessages(folderUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return messages.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getUidNext() {
|
||||||
|
return messages.get(messages.size() - 1).getImapUid() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getImapUid(int index) {
|
||||||
|
return messages.get(index).getImapUid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message get(int index) {
|
||||||
|
return messages.get(index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Message implements Comparable {
|
public class Message implements Comparable {
|
||||||
|
@ -28,7 +28,6 @@ import java.text.ParseException;
|
|||||||
public class ImapConnection extends AbstractConnection {
|
public class ImapConnection extends AbstractConnection {
|
||||||
|
|
||||||
ExchangeSession.Folder currentFolder;
|
ExchangeSession.Folder currentFolder;
|
||||||
ExchangeSession.MessageList messages;
|
|
||||||
|
|
||||||
// Initialize the streams and start the thread
|
// Initialize the streams and start the thread
|
||||||
public ImapConnection(Socket clientSocket) {
|
public ImapConnection(Socket clientSocket) {
|
||||||
@ -136,14 +135,14 @@ public class ImapConnection extends AbstractConnection {
|
|||||||
if (tokens.hasMoreTokens()) {
|
if (tokens.hasMoreTokens()) {
|
||||||
String folderName = BASE64MailboxDecoder.decode(tokens.nextToken());
|
String folderName = BASE64MailboxDecoder.decode(tokens.nextToken());
|
||||||
currentFolder = session.getFolder(folderName);
|
currentFolder = session.getFolder(folderName);
|
||||||
messages = session.getAllMessages(currentFolder.folderUrl);
|
currentFolder.loadMessages();
|
||||||
sendClient("* " + messages.size() + " EXISTS");
|
sendClient("* " + currentFolder.size() + " EXISTS");
|
||||||
sendClient("* " + messages.size() + " RECENT");
|
sendClient("* " + currentFolder.size() + " RECENT");
|
||||||
sendClient("* OK [UIDVALIDITY 1]");
|
sendClient("* OK [UIDVALIDITY 1]");
|
||||||
if (messages.size() == 0) {
|
if (currentFolder.size() == 0) {
|
||||||
sendClient("* OK [UIDNEXT " + 1 + "]");
|
sendClient("* OK [UIDNEXT " + 1 + "]");
|
||||||
} else {
|
} else {
|
||||||
sendClient("* OK [UIDNEXT " + (messages.get(messages.size() - 1).getImapUid() + 1) + "]");
|
sendClient("* OK [UIDNEXT " + currentFolder.getUidNext() + "]");
|
||||||
}
|
}
|
||||||
sendClient("* FLAGS (\\Answered \\Deleted \\Draft \\Flagged \\Seen $Forwarded Junk)");
|
sendClient("* FLAGS (\\Answered \\Deleted \\Draft \\Flagged \\Seen $Forwarded Junk)");
|
||||||
sendClient("* OK [PERMANENTFLAGS (\\Answered \\Deleted \\Draft \\Flagged \\Seen $Forwarded Junk \\*)]");
|
sendClient("* OK [PERMANENTFLAGS (\\Answered \\Deleted \\Draft \\Flagged \\Seen $Forwarded Junk \\*)]");
|
||||||
@ -190,6 +189,7 @@ public class ImapConnection extends AbstractConnection {
|
|||||||
if (currentFolder == null) {
|
if (currentFolder == null) {
|
||||||
sendClient(commandId + " NO no folder selected");
|
sendClient(commandId + " NO no folder selected");
|
||||||
} else {
|
} else {
|
||||||
|
currentFolder = session.refreshFolder(currentFolder);
|
||||||
UIDRangeIterator uidRangeIterator = new UIDRangeIterator(tokens.nextToken());
|
UIDRangeIterator uidRangeIterator = new UIDRangeIterator(tokens.nextToken());
|
||||||
String parameters = null;
|
String parameters = null;
|
||||||
if (tokens.hasMoreTokens()) {
|
if (tokens.hasMoreTokens()) {
|
||||||
@ -248,6 +248,7 @@ public class ImapConnection extends AbstractConnection {
|
|||||||
sendClient(commandId + " OK SEARCH completed");
|
sendClient(commandId + " OK SEARCH completed");
|
||||||
|
|
||||||
} else if ("store".equalsIgnoreCase(subcommand)) {
|
} else if ("store".equalsIgnoreCase(subcommand)) {
|
||||||
|
currentFolder = session.refreshFolder(currentFolder);
|
||||||
UIDRangeIterator UIDRangeIterator = new UIDRangeIterator(tokens.nextToken());
|
UIDRangeIterator UIDRangeIterator = new UIDRangeIterator(tokens.nextToken());
|
||||||
String action = tokens.nextToken();
|
String action = tokens.nextToken();
|
||||||
String flags = tokens.nextToken();
|
String flags = tokens.nextToken();
|
||||||
@ -259,6 +260,7 @@ public class ImapConnection extends AbstractConnection {
|
|||||||
sendClient(commandId + " OK STORE completed");
|
sendClient(commandId + " OK STORE completed");
|
||||||
} else if ("copy".equalsIgnoreCase(subcommand)) {
|
} else if ("copy".equalsIgnoreCase(subcommand)) {
|
||||||
try {
|
try {
|
||||||
|
currentFolder = session.refreshFolder(currentFolder);
|
||||||
UIDRangeIterator UIDRangeIterator = new UIDRangeIterator(tokens.nextToken());
|
UIDRangeIterator UIDRangeIterator = new UIDRangeIterator(tokens.nextToken());
|
||||||
String targetName = BASE64MailboxDecoder.decode(tokens.nextToken());
|
String targetName = BASE64MailboxDecoder.decode(tokens.nextToken());
|
||||||
while (UIDRangeIterator.hasNext()) {
|
while (UIDRangeIterator.hasNext()) {
|
||||||
@ -360,9 +362,9 @@ public class ImapConnection extends AbstractConnection {
|
|||||||
if (currentFolder != null) {
|
if (currentFolder != null) {
|
||||||
DavGatewayTray.debug(command + " on " + currentFolder.folderName);
|
DavGatewayTray.debug(command + " on " + currentFolder.folderName);
|
||||||
currentFolder = session.getFolder(currentFolder.folderName);
|
currentFolder = session.getFolder(currentFolder.folderName);
|
||||||
messages = session.getAllMessages(currentFolder.folderUrl);
|
currentFolder.loadMessages();
|
||||||
sendClient("* " + messages.size() + " EXISTS");
|
sendClient("* " + currentFolder.size() + " EXISTS");
|
||||||
sendClient("* " + messages.size() + " RECENT");
|
sendClient("* " + currentFolder.size() + " RECENT");
|
||||||
}
|
}
|
||||||
sendClient(commandId + " OK " + command + " completed");
|
sendClient(commandId + " OK " + command + " completed");
|
||||||
} else if ("subscribe".equalsIgnoreCase(command) || "unsubscribe".equalsIgnoreCase(command)) {
|
} else if ("subscribe".equalsIgnoreCase(command) || "unsubscribe".equalsIgnoreCase(command)) {
|
||||||
@ -373,26 +375,26 @@ public class ImapConnection extends AbstractConnection {
|
|||||||
String folderName = BASE64MailboxDecoder.decode(encodedFolderName);
|
String folderName = BASE64MailboxDecoder.decode(encodedFolderName);
|
||||||
ExchangeSession.Folder folder = session.getFolder(folderName);
|
ExchangeSession.Folder folder = session.getFolder(folderName);
|
||||||
// must retrieve messages
|
// must retrieve messages
|
||||||
ExchangeSession.MessageList localMessages = session.getAllMessages(folder.folderUrl);
|
folder.loadMessages();
|
||||||
String parameters = tokens.nextToken();
|
String parameters = tokens.nextToken();
|
||||||
StringBuilder answer = new StringBuilder();
|
StringBuilder answer = new StringBuilder();
|
||||||
StringTokenizer parametersTokens = new StringTokenizer(parameters);
|
StringTokenizer parametersTokens = new StringTokenizer(parameters);
|
||||||
while (parametersTokens.hasMoreTokens()) {
|
while (parametersTokens.hasMoreTokens()) {
|
||||||
String token = parametersTokens.nextToken();
|
String token = parametersTokens.nextToken();
|
||||||
if ("MESSAGES".equalsIgnoreCase(token)) {
|
if ("MESSAGES".equalsIgnoreCase(token)) {
|
||||||
answer.append("MESSAGES ").append(localMessages.size()).append(" ");
|
answer.append("MESSAGES ").append(folder.size()).append(" ");
|
||||||
}
|
}
|
||||||
if ("RECENT".equalsIgnoreCase(token)) {
|
if ("RECENT".equalsIgnoreCase(token)) {
|
||||||
answer.append("RECENT ").append(localMessages.size()).append(" ");
|
answer.append("RECENT ").append(folder.size()).append(" ");
|
||||||
}
|
}
|
||||||
if ("UIDNEXT".equalsIgnoreCase(token)) {
|
if ("UIDNEXT".equalsIgnoreCase(token)) {
|
||||||
if (localMessages.size() == 0) {
|
if (folder.size() == 0) {
|
||||||
answer.append("UIDNEXT 1 ");
|
answer.append("UIDNEXT 1 ");
|
||||||
} else {
|
} else {
|
||||||
if (localMessages.size() == 0) {
|
if (folder.size() == 0) {
|
||||||
answer.append("UIDNEXT 1 ");
|
answer.append("UIDNEXT 1 ");
|
||||||
} else {
|
} else {
|
||||||
answer.append("UIDNEXT ").append((localMessages.get(localMessages.size() - 1).getImapUid() + 1)).append(" ");
|
answer.append("UIDNEXT ").append(folder.getUidNext()).append(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,85 +464,87 @@ public class ImapConnection extends AbstractConnection {
|
|||||||
private void handleFetch(ExchangeSession.Message message, int currentIndex, String parameters) throws IOException {
|
private void handleFetch(ExchangeSession.Message message, int currentIndex, String parameters) throws IOException {
|
||||||
StringBuilder buffer = new StringBuilder();
|
StringBuilder buffer = new StringBuilder();
|
||||||
buffer.append("* ").append(currentIndex).append(" FETCH (UID ").append(message.getImapUid());
|
buffer.append("* ").append(currentIndex).append(" FETCH (UID ").append(message.getImapUid());
|
||||||
boolean bodystructure = false;
|
if (parameters != null) {
|
||||||
StringTokenizer paramTokens = new StringTokenizer(parameters);
|
boolean bodystructure = false;
|
||||||
while (paramTokens.hasMoreTokens()) {
|
StringTokenizer paramTokens = new StringTokenizer(parameters);
|
||||||
String param = paramTokens.nextToken();
|
while (paramTokens.hasMoreTokens()) {
|
||||||
if ("FLAGS".equals(param)) {
|
String param = paramTokens.nextToken();
|
||||||
buffer.append(" FLAGS (").append(message.getImapFlags()).append(")");
|
if ("FLAGS".equals(param)) {
|
||||||
} else if ("BODYSTRUCTURE".equals(param)) {
|
buffer.append(" FLAGS (").append(message.getImapFlags()).append(")");
|
||||||
if (parameters.indexOf("BODY.") >= 0) {
|
} else if ("BODYSTRUCTURE".equals(param)) {
|
||||||
// Apple Mail: send structure with body, need exact RFC822.SIZE
|
if (parameters.indexOf("BODY.") >= 0) {
|
||||||
bodystructure = true;
|
// Apple Mail: send structure with body, need exact RFC822.SIZE
|
||||||
} else {
|
bodystructure = true;
|
||||||
// thunderbird : send BODYSTRUCTURE
|
} else {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
// thunderbird : send BODYSTRUCTURE
|
||||||
message.write(baos);
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
appendBodyStructure(buffer, baos);
|
message.write(baos);
|
||||||
}
|
appendBodyStructure(buffer, baos);
|
||||||
} else if ("INTERNALDATE".equals(param) && message.date != null && message.date.length() > 0) {
|
}
|
||||||
try {
|
} else if ("INTERNALDATE".equals(param) && message.date != null && message.date.length() > 0) {
|
||||||
SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
try {
|
||||||
dateParser.setTimeZone(ExchangeSession.GMT_TIMEZONE);
|
SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
||||||
Date date = dateParser.parse(message.date);
|
dateParser.setTimeZone(ExchangeSession.GMT_TIMEZONE);
|
||||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss Z", Locale.ENGLISH);
|
Date date = dateParser.parse(message.date);
|
||||||
buffer.append(" INTERNALDATE \"").append(dateFormatter.format(date)).append("\"");
|
SimpleDateFormat dateFormatter = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss Z", Locale.ENGLISH);
|
||||||
} catch (ParseException e) {
|
buffer.append(" INTERNALDATE \"").append(dateFormatter.format(date)).append("\"");
|
||||||
throw new IOException("Invalid date: " + message.date);
|
} catch (ParseException e) {
|
||||||
}
|
throw new IOException("Invalid date: " + message.date);
|
||||||
} else if ("BODY.PEEK[HEADER]".equals(param) || param.startsWith("BODY.PEEK[HEADER")) {
|
}
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
} else if ("BODY.PEEK[HEADER]".equals(param) || param.startsWith("BODY.PEEK[HEADER")) {
|
||||||
PartOutputStream partOutputStream = new PartOutputStream(baos, true, false, 0);
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
message.write(partOutputStream);
|
PartOutputStream partOutputStream = new PartOutputStream(baos, true, false, 0);
|
||||||
baos.close();
|
message.write(partOutputStream);
|
||||||
buffer.append(" RFC822.SIZE ").append(partOutputStream.size);
|
baos.close();
|
||||||
if ("BODY.PEEK[HEADER]".equals(param)) {
|
buffer.append(" RFC822.SIZE ").append(partOutputStream.size);
|
||||||
buffer.append(" BODY[HEADER] {");
|
if ("BODY.PEEK[HEADER]".equals(param)) {
|
||||||
} else {
|
buffer.append(" BODY[HEADER] {");
|
||||||
buffer.append(" BODY[HEADER.FIELDS ()] {");
|
} else {
|
||||||
}
|
buffer.append(" BODY[HEADER.FIELDS ()] {");
|
||||||
buffer.append(baos.size()).append("}");
|
}
|
||||||
sendClient(buffer.toString());
|
buffer.append(baos.size()).append("}");
|
||||||
os.write(baos.toByteArray());
|
sendClient(buffer.toString());
|
||||||
os.flush();
|
os.write(baos.toByteArray());
|
||||||
buffer.setLength(0);
|
os.flush();
|
||||||
} else if (param.startsWith("BODY[]") || param.startsWith("BODY.PEEK[]") || "BODY.PEEK[TEXT]".equals(param)) {
|
buffer.setLength(0);
|
||||||
// parse buffer size
|
} else if (param.startsWith("BODY[]") || param.startsWith("BODY.PEEK[]") || "BODY.PEEK[TEXT]".equals(param)) {
|
||||||
int startIndex = 0;
|
// parse buffer size
|
||||||
int ltIndex = param.indexOf('<');
|
int startIndex = 0;
|
||||||
if (ltIndex >= 0) {
|
int ltIndex = param.indexOf('<');
|
||||||
int dotIndex = param.indexOf('.', ltIndex);
|
if (ltIndex >= 0) {
|
||||||
if (dotIndex >= 0) {
|
int dotIndex = param.indexOf('.', ltIndex);
|
||||||
startIndex = Integer.parseInt(param.substring(ltIndex + 1, dotIndex));
|
if (dotIndex >= 0) {
|
||||||
// ignore buffer size
|
startIndex = Integer.parseInt(param.substring(ltIndex + 1, dotIndex));
|
||||||
|
// ignore buffer size
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
boolean writeHeaders = true;
|
boolean writeHeaders = true;
|
||||||
int rfc822size;
|
int rfc822size;
|
||||||
if ("BODY.PEEK[TEXT]".equals(param)) {
|
if ("BODY.PEEK[TEXT]".equals(param)) {
|
||||||
writeHeaders = false;
|
writeHeaders = false;
|
||||||
|
}
|
||||||
|
PartOutputStream bodyOutputStream = new PartOutputStream(baos, writeHeaders, true, startIndex);
|
||||||
|
message.write(bodyOutputStream);
|
||||||
|
rfc822size = bodyOutputStream.size;
|
||||||
|
baos.close();
|
||||||
|
DavGatewayTray.debug("Message RFC822 size: " + rfc822size + " buffer size:" + baos.size());
|
||||||
|
if (bodystructure) {
|
||||||
|
// Apple Mail: need to build full bodystructure
|
||||||
|
appendBodyStructure(buffer, baos);
|
||||||
|
}
|
||||||
|
buffer.append(" RFC822.SIZE ").append(rfc822size).append(" ").append("BODY[]");
|
||||||
|
// partial
|
||||||
|
if (startIndex > 0) {
|
||||||
|
buffer.append('<').append(startIndex).append('>');
|
||||||
|
}
|
||||||
|
buffer.append(" {").append(baos.size()).append("}");
|
||||||
|
sendClient(buffer.toString());
|
||||||
|
os.write(baos.toByteArray());
|
||||||
|
os.flush();
|
||||||
|
buffer.setLength(0);
|
||||||
}
|
}
|
||||||
PartOutputStream bodyOutputStream = new PartOutputStream(baos, writeHeaders, true, startIndex);
|
|
||||||
message.write(bodyOutputStream);
|
|
||||||
rfc822size = bodyOutputStream.size;
|
|
||||||
baos.close();
|
|
||||||
DavGatewayTray.debug("Message RFC822 size: " + rfc822size + " buffer size:" + baos.size());
|
|
||||||
if (bodystructure) {
|
|
||||||
// Apple Mail: need to build full bodystructure
|
|
||||||
appendBodyStructure(buffer, baos);
|
|
||||||
}
|
|
||||||
buffer.append(" RFC822.SIZE ").append(rfc822size).append(" ").append("BODY[]");
|
|
||||||
// partial
|
|
||||||
if (startIndex > 0) {
|
|
||||||
buffer.append('<').append(startIndex).append('>');
|
|
||||||
}
|
|
||||||
buffer.append(" {").append(baos.size()).append("}");
|
|
||||||
sendClient(buffer.toString());
|
|
||||||
os.write(baos.toByteArray());
|
|
||||||
os.flush();
|
|
||||||
buffer.setLength(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffer.append(")");
|
buffer.append(")");
|
||||||
@ -698,7 +702,7 @@ public class ImapConnection extends AbstractConnection {
|
|||||||
} else if ("HEADER".equals(token)) {
|
} else if ("HEADER".equals(token)) {
|
||||||
String headerName = tokens.nextToken().toLowerCase();
|
String headerName = tokens.nextToken().toLowerCase();
|
||||||
String value = tokens.nextToken();
|
String value = tokens.nextToken();
|
||||||
if ("message-id".equals(headerName)) {
|
if ("message-id".equals(headerName) && !value.startsWith("<")) {
|
||||||
value = "<" + value + ">";
|
value = "<" + value + ">";
|
||||||
}
|
}
|
||||||
conditions.append(operator).append("\"urn:schemas:mailheader:").append(headerName).append("\"='").append(value).append("'");
|
conditions.append(operator).append("\"urn:schemas:mailheader:").append(headerName).append("\"='").append(value).append("'");
|
||||||
@ -721,10 +725,10 @@ public class ImapConnection extends AbstractConnection {
|
|||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
throw new IOException("Invalid search parameters");
|
throw new IOException("Invalid search parameters");
|
||||||
}
|
}
|
||||||
} else if ("OLD".equals(token)) {
|
} else if ("OLD".equals(token) || "RECENT".equals(token)) {
|
||||||
// ignore
|
// ignore
|
||||||
} else {
|
} else {
|
||||||
throw new IOException("Invalid search parameters");
|
throw new IOException("Invalid search parameter: " + token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -763,9 +767,9 @@ public class ImapConnection extends AbstractConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void expunge(boolean silent) throws IOException {
|
protected void expunge(boolean silent) throws IOException {
|
||||||
if (messages != null) {
|
if (currentFolder.messages != null) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (ExchangeSession.Message message : messages) {
|
for (ExchangeSession.Message message : currentFolder.messages) {
|
||||||
index++;
|
index++;
|
||||||
if (message.deleted) {
|
if (message.deleted) {
|
||||||
message.delete();
|
message.delete();
|
||||||
@ -976,23 +980,23 @@ public class ImapConnection extends AbstractConnection {
|
|||||||
} else {
|
} else {
|
||||||
startUid = endUid = convertToLong(currentRange);
|
startUid = endUid = convertToLong(currentRange);
|
||||||
}
|
}
|
||||||
while (currentIndex < messages.size() && messages.get(currentIndex).getImapUid() < startUid) {
|
while (currentIndex < currentFolder.size() && currentFolder.getImapUid(currentIndex) < startUid) {
|
||||||
currentIndex++;
|
currentIndex++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentIndex = messages.size();
|
currentIndex = currentFolder.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
while (currentIndex < messages.size() && messages.get(currentIndex).getImapUid() > endUid) {
|
while (currentIndex < currentFolder.size() && currentFolder.getImapUid(currentIndex) > endUid) {
|
||||||
skipToStartUid();
|
skipToStartUid();
|
||||||
}
|
}
|
||||||
return currentIndex < messages.size();
|
return currentIndex < currentFolder.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExchangeSession.Message next() {
|
public ExchangeSession.Message next() {
|
||||||
ExchangeSession.Message message = messages.get(currentIndex++);
|
ExchangeSession.Message message = currentFolder.get(currentIndex++);
|
||||||
long uid = message.getImapUid();
|
long uid = message.getImapUid();
|
||||||
if (uid < startUid || uid > endUid) {
|
if (uid < startUid || uid > endUid) {
|
||||||
throw new RuntimeException("Message uid " + uid + " not in range " + startUid + ":" + endUid);
|
throw new RuntimeException("Message uid " + uid + " not in range " + startUid + ":" + endUid);
|
||||||
@ -1034,23 +1038,23 @@ public class ImapConnection extends AbstractConnection {
|
|||||||
} else {
|
} else {
|
||||||
startUid = endUid = convertToLong(currentRange);
|
startUid = endUid = convertToLong(currentRange);
|
||||||
}
|
}
|
||||||
while (currentIndex < messages.size() && (currentIndex + 1) < startUid) {
|
while (currentIndex < currentFolder.size() && (currentIndex + 1) < startUid) {
|
||||||
currentIndex++;
|
currentIndex++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentIndex = messages.size();
|
currentIndex = currentFolder.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
while (currentIndex < messages.size() && (currentIndex + 1) > endUid) {
|
while (currentIndex < currentFolder.size() && (currentIndex + 1) > endUid) {
|
||||||
skipToStartUid();
|
skipToStartUid();
|
||||||
}
|
}
|
||||||
return currentIndex < messages.size();
|
return currentIndex < currentFolder.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExchangeSession.Message next() {
|
public ExchangeSession.Message next() {
|
||||||
return messages.get(currentIndex++);
|
return currentFolder.get(currentIndex++);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user