mirror of
https://github.com/moparisthebest/davmail
synced 2025-01-06 03:08:02 -05:00
IMAP: implement store by id and ENVELOPE
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@801 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
24d7399555
commit
1d3cd69a7e
@ -287,7 +287,7 @@ public class ExchangeSession {
|
||||
if (path.startsWith("/")) {
|
||||
// path is absolute, replace method path
|
||||
uri.setPath(path);
|
||||
} else if (path.startsWith("http://") || path.startsWith("https://")){
|
||||
} else if (path.startsWith("http://") || path.startsWith("https://")) {
|
||||
return path;
|
||||
} else {
|
||||
// relative path, build new path
|
||||
@ -1100,8 +1100,8 @@ public class ExchangeSession {
|
||||
/**
|
||||
* Create Exchange folder with given folder class.
|
||||
*
|
||||
* @param folderName logical folder name
|
||||
* @param folderClass folder class
|
||||
* @param folderName logical folder name
|
||||
* @param folderClass folder class
|
||||
* @throws IOException on error
|
||||
*/
|
||||
public void createFolder(String folderName, String folderClass) throws IOException {
|
||||
@ -1350,6 +1350,11 @@ public class ExchangeSession {
|
||||
*/
|
||||
public boolean forwarded;
|
||||
|
||||
/**
|
||||
* Message content parsed in a MIME message.
|
||||
*/
|
||||
protected MimeMessage mimeMessage;
|
||||
|
||||
/**
|
||||
* IMAP uid , unique in folder (x0e230003)
|
||||
*
|
||||
@ -1453,6 +1458,15 @@ public class ExchangeSession {
|
||||
}
|
||||
}
|
||||
|
||||
public MimeMessage getMimeMessage() throws IOException, MessagingException {
|
||||
if (mimeMessage == null) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
write(baos);
|
||||
mimeMessage = new MimeMessage(null, new ByteArrayInputStream(baos.toByteArray()));
|
||||
}
|
||||
return mimeMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete message.
|
||||
*
|
||||
|
@ -30,11 +30,9 @@ import davmail.exchange.ExchangeSessionFactory;
|
||||
import davmail.ui.tray.DavGatewayTray;
|
||||
import org.apache.commons.httpclient.HttpException;
|
||||
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.internet.MimeMultipart;
|
||||
import javax.mail.internet.MimeBodyPart;
|
||||
import javax.mail.internet.MimePart;
|
||||
import javax.mail.internet.*;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Address;
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
@ -278,13 +276,7 @@ public class ImapConnection extends AbstractConnection {
|
||||
UIDRangeIterator uidRangeIterator = new UIDRangeIterator(tokens.nextToken());
|
||||
String action = tokens.nextToken();
|
||||
String flags = tokens.nextToken();
|
||||
while (uidRangeIterator.hasNext()) {
|
||||
DavGatewayTray.switchIcon();
|
||||
ExchangeSession.Message message = uidRangeIterator.next();
|
||||
updateFlags(message, action, flags);
|
||||
sendClient("* " + (uidRangeIterator.currentIndex) + " FETCH (UID " + message.getImapUid() + " FLAGS (" + (message.getImapFlags()) + "))");
|
||||
}
|
||||
sendClient(commandId + " OK STORE completed");
|
||||
handleStore(commandId, uidRangeIterator, action, flags);
|
||||
} else if ("copy".equalsIgnoreCase(subcommand)) {
|
||||
try {
|
||||
UIDRangeIterator uidRangeIterator = new UIDRangeIterator(tokens.nextToken());
|
||||
@ -333,6 +325,11 @@ public class ImapConnection extends AbstractConnection {
|
||||
sendClient(commandId + " OK FETCH completed");
|
||||
}
|
||||
|
||||
} else if ("store".equalsIgnoreCase(command)) {
|
||||
RangeIterator rangeIterator = new RangeIterator(tokens.nextToken());
|
||||
String action = tokens.nextToken();
|
||||
String flags = tokens.nextToken();
|
||||
handleStore(commandId, rangeIterator, action, flags);
|
||||
|
||||
} else if ("append".equalsIgnoreCase(command)) {
|
||||
String folderName = BASE64MailboxDecoder.decode(tokens.nextToken());
|
||||
@ -506,6 +503,8 @@ public class ImapConnection extends AbstractConnection {
|
||||
String param = paramTokens.nextToken();
|
||||
if ("FLAGS".equals(param)) {
|
||||
buffer.append(" FLAGS (").append(message.getImapFlags()).append(')');
|
||||
} else if ("ENVELOPE".equals(param)) {
|
||||
appendEnvelope(buffer, message);
|
||||
} else if ("BODYSTRUCTURE".equals(param)) {
|
||||
if (parameters.indexOf("BODY.") >= 0) {
|
||||
// Apple Mail: send structure with body, need exact RFC822.SIZE
|
||||
@ -596,6 +595,17 @@ public class ImapConnection extends AbstractConnection {
|
||||
sendClient(buffer.toString());
|
||||
}
|
||||
|
||||
protected void handleStore(String commandId, AbstractRangeIterator rangeIterator, String action, String flags) throws IOException {
|
||||
while (rangeIterator.hasNext()) {
|
||||
DavGatewayTray.switchIcon();
|
||||
ExchangeSession.Message message = rangeIterator.next();
|
||||
updateFlags(message, action, flags);
|
||||
sendClient("* " + (rangeIterator.getCurrentIndex()) + " FETCH (UID " + message.getImapUid() + " FLAGS (" + (message.getImapFlags()) + "))");
|
||||
}
|
||||
sendClient(commandId + " OK STORE completed");
|
||||
}
|
||||
|
||||
|
||||
protected List<Long> handleSearch(IMAPTokenizer tokens) throws IOException {
|
||||
List<Long> uidList = new ArrayList<Long>();
|
||||
SearchConditions conditions = new SearchConditions();
|
||||
@ -642,13 +652,88 @@ public class ImapConnection extends AbstractConnection {
|
||||
return uidList;
|
||||
}
|
||||
|
||||
protected void appendEnvelope(StringBuilder buffer, ExchangeSession.Message message) throws IOException {
|
||||
buffer.append(" ENVELOPE (");
|
||||
|
||||
try {
|
||||
MimeMessage mimeMessage = message.getMimeMessage();
|
||||
// Fake envelope for date, subject, from, sender, reply-to, to, cc, bcc,in-reply-to, message-id
|
||||
appendEnvelopeHeader(buffer, mimeMessage.getHeader("Date"));
|
||||
appendEnvelopeHeader(buffer, mimeMessage.getHeader("Subject"));
|
||||
appendMailEnvelopeHeader(buffer, mimeMessage.getHeader("From", ","));
|
||||
appendMailEnvelopeHeader(buffer, mimeMessage.getHeader("Sender", ","));
|
||||
appendMailEnvelopeHeader(buffer, mimeMessage.getHeader("Reply-To", ","));
|
||||
appendMailEnvelopeHeader(buffer, mimeMessage.getHeader("CC", ","));
|
||||
appendMailEnvelopeHeader(buffer, mimeMessage.getHeader("BCC", ","));
|
||||
appendMailEnvelopeHeader(buffer, mimeMessage.getHeader("In-Reply-To", ","));
|
||||
appendEnvelopeHeader(buffer, mimeMessage.getHeader("Messagee-Id"));
|
||||
|
||||
} catch (MessagingException me) {
|
||||
DavGatewayTray.warn(me);
|
||||
// send fake envelope
|
||||
buffer.append(" nil nil nil nil nil nil nil nil nil nil");
|
||||
}
|
||||
buffer.append(')');
|
||||
}
|
||||
|
||||
protected void appendEnvelopeHeader(StringBuilder buffer, String[] value) {
|
||||
buffer.append(' ');
|
||||
if (value != null && value.length > 0) {
|
||||
try {
|
||||
buffer.append('"');
|
||||
// TODO: replace with MimeUtility.unfold
|
||||
buffer.append(MimeUtility.decodeText(value[0]).replaceAll("\r\n", ""));
|
||||
buffer.append('"');
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
DavGatewayTray.warn(e);
|
||||
buffer.append("nil");
|
||||
}
|
||||
} else {
|
||||
buffer.append("nil");
|
||||
}
|
||||
}
|
||||
|
||||
protected void appendMailEnvelopeHeader(StringBuilder buffer, String value) {
|
||||
buffer.append(' ');
|
||||
if (value != null) {
|
||||
try {
|
||||
InternetAddress[] addresses = InternetAddress.parseHeader(value, false);
|
||||
buffer.append('(');
|
||||
for (InternetAddress address : addresses) {
|
||||
buffer.append('(');
|
||||
String personal = address.getPersonal();
|
||||
if (personal != null) {
|
||||
buffer.append('"').append(personal).append('"');
|
||||
} else {
|
||||
buffer.append("nil");
|
||||
}
|
||||
buffer.append(" nil ");
|
||||
String mail = address.getAddress();
|
||||
int atIndex = mail.indexOf('@');
|
||||
if (atIndex >= 0) {
|
||||
buffer.append('"').append(mail.substring(0, atIndex)).append('"');
|
||||
buffer.append(' ');
|
||||
buffer.append('"').append(mail.substring(atIndex + 1)).append('"');
|
||||
} else {
|
||||
buffer.append("nil nil");
|
||||
}
|
||||
buffer.append(')');
|
||||
}
|
||||
buffer.append(')');
|
||||
} catch (AddressException e) {
|
||||
DavGatewayTray.warn(e);
|
||||
buffer.append("nil");
|
||||
}
|
||||
} else {
|
||||
buffer.append("nil");
|
||||
}
|
||||
}
|
||||
|
||||
protected void appendBodyStructure(StringBuilder buffer, ExchangeSession.Message message) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
message.write(baos);
|
||||
|
||||
buffer.append(" BODYSTRUCTURE ");
|
||||
try {
|
||||
MimeMessage mimeMessage = new MimeMessage(null, new ByteArrayInputStream(baos.toByteArray()));
|
||||
MimeMessage mimeMessage = message.getMimeMessage();
|
||||
Object mimeBody = mimeMessage.getContent();
|
||||
if (mimeBody instanceof MimeMultipart) {
|
||||
buffer.append('(');
|
||||
@ -674,16 +759,12 @@ public class ImapConnection extends AbstractConnection {
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
DavGatewayTray.warn(e);
|
||||
// dump message in log
|
||||
DavGatewayTray.debug(new BundleMessage("LOG_MESSAGE", new String(baos.toByteArray())));
|
||||
// failover: send default bodystructure
|
||||
buffer.append("(\"TEXT\" \"PLAIN\" (\"CHARSET\" \"US-ASCII\") NIL NIL NIL ").append(baos.size()).append(" NIL)");
|
||||
buffer.append("(\"TEXT\" \"PLAIN\" (\"CHARSET\" \"US-ASCII\") NIL NIL NIL NIL NIL)");
|
||||
} catch (MessagingException me) {
|
||||
DavGatewayTray.warn(me);
|
||||
// dump message in log
|
||||
DavGatewayTray.debug(new BundleMessage("LOG_MESSAGE", new String(baos.toByteArray())));
|
||||
// failover: send default bodystructure
|
||||
buffer.append("(\"TEXT\" \"PLAIN\" (\"CHARSET\" \"US-ASCII\") NIL NIL NIL ").append(baos.size()).append(" NIL)");
|
||||
buffer.append("(\"TEXT\" \"PLAIN\" (\"CHARSET\" \"US-ASCII\") NIL NIL NIL NIL NIL)");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1138,9 +1219,16 @@ public class ImapConnection extends AbstractConnection {
|
||||
}
|
||||
}
|
||||
|
||||
protected class UIDRangeIterator implements Iterator<ExchangeSession.Message> {
|
||||
final String[] ranges;
|
||||
protected abstract class AbstractRangeIterator implements Iterator<ExchangeSession.Message> {
|
||||
int currentIndex;
|
||||
|
||||
protected int getCurrentIndex() {
|
||||
return currentIndex;
|
||||
}
|
||||
}
|
||||
|
||||
protected class UIDRangeIterator extends AbstractRangeIterator {
|
||||
final String[] ranges;
|
||||
int currentRangeIndex;
|
||||
long startUid;
|
||||
long endUid;
|
||||
@ -1219,9 +1307,8 @@ public class ImapConnection extends AbstractConnection {
|
||||
}
|
||||
}
|
||||
|
||||
protected class RangeIterator implements Iterator<ExchangeSession.Message> {
|
||||
protected class RangeIterator extends AbstractRangeIterator {
|
||||
final String[] ranges;
|
||||
int currentIndex;
|
||||
int currentRangeIndex;
|
||||
long startUid;
|
||||
long endUid;
|
||||
|
Loading…
Reference in New Issue
Block a user