Experimental NOTIFY support (RFC 5465)

pull/190/head
M66B 4 years ago
parent ab0144bd42
commit 9e0e786fb6

@ -2819,7 +2819,9 @@ Reformatting and displaying such messages will take too long. You can try to use
<a name="faq125"></a>
**(125) What are the current experimental features?**
* ...
* [IMAP NOTIFY](https://tools.ietf.org/html/rfc5465) support
NOTIFY support means that notifications of *subscribed* folders will be requested and when a notification is received that the folder will be synchronized.
<br />

@ -1,7 +1,7 @@
apply plugin: 'com.android.application'
apply plugin: 'com.bugsnag.android.gradle'
def getVersionCode = { -> return 1412 }
def getVersionCode = { -> return 1413 }
def getReleaseName = { -> return "\"Bambiraptor\"" }
// https://en.wikipedia.org/wiki/List_of_dinosaur_genera

@ -3627,7 +3627,14 @@ public class IMAPFolder extends Folder implements UIDFolder, ResponseHandler {
} else if (ir.keyEquals("RECENT")) {
// update 'recent'
recent = ir.getNumber();
}
} else if (ir.keyEquals("STATUS"))
try {
String mailbox = ir.readAtomString();
Folder f = store.getFolder(mailbox);
notifyFolderChangeListeners(f);
} catch (Throwable ex) {
eu.faircode.email.Log.e(ex);
}
}
/**

@ -388,6 +388,8 @@ public class ApplicationEx extends Application implements SharedPreferences.OnSh
editor.remove("tcp_keep_alive");
else if (version < 1407)
editor.remove("print_html_confirmed");
else if (version < 1413)
editor.remove("experiments");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !BuildConfig.DEBUG)
editor.remove("background_service");

@ -49,8 +49,13 @@ import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.preference.PreferenceManager;
import com.sun.mail.iap.Argument;
import com.sun.mail.iap.ProtocolException;
import com.sun.mail.iap.Response;
import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.IMAPStore;
import com.sun.mail.imap.protocol.IMAPProtocol;
import com.sun.mail.imap.protocol.IMAPResponse;
import java.text.DateFormat;
import java.util.ArrayList;
@ -139,7 +144,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
"sync_shared_folders",
"prefer_ip4", "tcp_keep_alive", "ssl_harden", // force reconnect
"badge", "unseen_ignored", // force update badge/widget
"protocol", "debug", // force reconnect
"experiments", "debug", "protocol", // force reconnect
"auth_plain",
"auth_login",
"auth_sasl"
@ -944,6 +949,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
// Debug
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean experiments = prefs.getBoolean("experiments", false);
boolean debug = (prefs.getBoolean("debug", false) || BuildConfig.DEBUG);
final EmailService iservice = new EmailService(
@ -1035,6 +1041,8 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
if (!capIdle || account.poll_interval < OPTIMIZE_KEEP_ALIVE_INTERVAL)
optimizeAccount(account, "IDLE");
final boolean capNotify = (experiments && iservice.hasCapability("NOTIFY"));
db.account().setAccountState(account.id, "connected");
db.account().setAccountError(account.id, null);
db.account().setAccountWarning(account.id, null);
@ -1096,6 +1104,21 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
wlFolder.release();
}
}
@Override
public void folderChanged(FolderEvent e) {
try {
wlFolder.acquire();
String name = e.getFolder().getFullName();
EntityLog.log(ServiceSynchronize.this, "Folder changed=" + name);
EntityFolder folder = db.folder().getFolderByName(account.id, name);
if (folder != null)
EntityOperation.sync(ServiceSynchronize.this, folder.id, false);
} finally {
wlFolder.release();
}
}
});
// Update folder list
@ -1290,6 +1313,40 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
if (sync && folder.selectable)
EntityOperation.sync(this, folder.id, false);
if (capNotify && EntityFolder.INBOX.equals(folder.type))
ifolder.doCommand(new IMAPFolder.ProtocolCommand() {
@Override
public Object doCommand(IMAPProtocol protocol) throws ProtocolException {
EntityLog.log(ServiceSynchronize.this, account.name + " NOTIFY enable");
// https://tools.ietf.org/html/rfc5465
Argument arg = new Argument();
arg.writeAtom("SET STATUS (subscribed (MessageNew MessageExpunge FlagChange))");
Response[] responses = protocol.command("NOTIFY", arg);
if (responses.length == 0)
throw new ProtocolException("No response");
if (!responses[responses.length - 1].isOK())
throw new ProtocolException(responses[responses.length - 1]);
for (int i = 0; i < responses.length - 1; i++) {
EntityLog.log(ServiceSynchronize.this, account.name + " " + responses[i]);
if (responses[i] instanceof IMAPResponse) {
IMAPResponse ir = (IMAPResponse) responses[i];
if (ir.keyEquals("STATUS")) {
String mailbox = ir.readAtomString();
EntityFolder f = db.folder().getFolderByName(account.id, mailbox);
if (f != null)
EntityOperation.sync(ServiceSynchronize.this, f.id, false);
}
}
}
return null;
}
});
} else {
mapFolders.put(folder, null);
db.folder().setFolderState(folder.id, null);

@ -1469,6 +1469,10 @@ public abstract class Folder implements AutoCloseable {
store.notifyFolderRenamedListeners(this, folder);
}
protected void notifyFolderChangeListeners(Folder folder) {
store.notifyFolderListeners(FolderEvent.CHANGED, folder);
}
// Vector of MessageCount listeners
private volatile Vector<MessageCountListener> messageCountListeners = null;

@ -46,6 +46,8 @@ public class FolderEvent extends MailEvent {
/** The folder was renamed. */
public static final int RENAMED = 3;
public static final int CHANGED = 4;
/**
* The event type.
*
@ -140,5 +142,7 @@ public class FolderEvent extends MailEvent {
((FolderListener)listener).folderDeleted(this);
else if (type == RENAMED)
((FolderListener)listener).folderRenamed(this);
else if (type == CHANGED)
((FolderListener)listener).folderChanged(this);
}
}

@ -45,4 +45,6 @@ public interface FolderListener extends java.util.EventListener {
* @param e the FolderEvent
*/
public void folderRenamed(FolderEvent e);
public void folderChanged(FolderEvent e);
}

Loading…
Cancel
Save