diff --git a/src/client/Client.tsx b/src/client/Client.tsx
index e67bd71..2adc0a5 100644
--- a/src/client/Client.tsx
+++ b/src/client/Client.tsx
@@ -25,6 +25,7 @@ export interface IAuth {
 }
 
 export interface ClientState {
+	emailState: string | null;
 	inFlight: {
 		emailContents: Set<string>;
 		emailStubs: Set<string>;
@@ -33,7 +34,9 @@ export interface ClientState {
 	mailboxes: {
 		trash: IMailbox;
 	} | null;
+	mailboxState: string | null;
 	session: ISession | null;
+	threadState: string | null;
 }
 
 class Account implements IAccount {
@@ -69,13 +72,16 @@ export default class Client {
 	callbacks: Array<Callback> = [];
 	jclient: jmapclient.Client | null = null;
 	state: ClientState = {
+		emailState: null,
 		inFlight: {
 			emailContents: new Set(),
 			emailStubs: new Set(),
 			mailboxes: new Set(),
 		},
 		mailboxes: null,
+		mailboxState: null,
 		session: null,
+		threadState: null,
 	};
 
 	// Get the currently active account
@@ -247,8 +253,10 @@ export default class Client {
 						receivedAt: e.receivedAt,
 						subject: e.subject,
 					};
-					this._triggerChange(msg + e.id);
 				});
+				this._triggerChange(msg);
+				//this.state.session.state = response.sessionState;
+				this.state.emailState = response.state;
 			})
 			.catch((x) => {
 				console.error("Failed to get email stub", emailId, x);
@@ -337,13 +345,57 @@ export default class Client {
 			c();
 		});
 	}
+	_onChangedEmail(accountId: string, state: string) {
+		console.log("Email changed", state);
+		if (this.jclient === null) return;
+		if (this.state.session === null) return;
+		const account = this.account(accountId);
+		if (account === null) return;
+		if (this.state.emailState === null) return;
+		const args = {
+			accountId: accountId,
+			sinceState: this.state.emailState,
+		};
+		this.jclient.email_changes(args).then((r) => {
+			console.log("Handle email changes ", r);
+		});
+	}
+	_onChangedMailbox(accountId: string, state: string) {
+		console.log("Mailbox changed", state);
+		if (this.jclient === null) return;
+		if (this.state.session === null) return;
+		const account = this.account(accountId);
+		if (account === null) return;
+		if (this.state.mailboxState === null) return;
+		const args = {
+			accountId: accountId,
+			sinceState: this.state.session.state,
+		};
+		this.jclient.mailbox_changes(args).then((r) => {
+			console.log("Handle mailbox changes ", r);
+		});
+	}
+	_onChangedThread(accountId: string, state: string) {
+		console.log("Thread changed", state);
+		if (this.jclient === null) return;
+		if (this.state.session === null) return;
+		const account = this.account(accountId);
+		if (account === null) return;
+		if (this.state.threadState === null) return;
+		const args = {
+			accountId: accountId,
+			sinceState: this.state.session.state,
+		};
+		this.jclient.thread_changes(args).then((r) => {
+			console.log("Handle thread changes ", r);
+		});
+	}
 	_onSession() {
-		console.log("Session received");
-
 		// For the type checker
 		if (!this.jclient) return;
 
 		const session = this.jclient.getSession();
+		console.log("Session received: ", session);
 		// Subscribe to server-pushed events
 		if (session.eventSourceUrl) {
 			this._subscribeToEventSource(session.eventSourceUrl);
@@ -373,7 +425,28 @@ export default class Client {
 		this.jclient.subscribeToEvents(
 			eventSourceUrl,
 			(type: string, message: PushMessage) => {
-				console.log("Got an event!", type, message);
+				if (type === "ping") {
+					return;
+				}
+				if (type === "state") {
+					console.log("Got an event!", type, message);
+					const stateChange = message as jmaptypes.IStateChange;
+					for (const [accountId, changes] of Object.entries(
+						stateChange.changed,
+					)) {
+						for (const [changeType, state] of Object.entries(changes)) {
+							if (changeType === "Email") {
+								this._onChangedEmail(accountId, state);
+							} else if (changeType === "Mailbox") {
+								this._onChangedMailbox(accountId, state);
+							} else if (changeType === "Thread") {
+								this._onChangedThread(accountId, state);
+							}
+						}
+					}
+				} else {
+					console.log("Not sure what to do with event", type);
+				}
 			},
 		);
 	}
diff --git a/src/client/jmap-client-ts b/src/client/jmap-client-ts
index 160a66c..ee2af71 160000
--- a/src/client/jmap-client-ts
+++ b/src/client/jmap-client-ts
@@ -1 +1 @@
-Subproject commit 160a66caf7f385b18e25f224a64f75f213997bb2
+Subproject commit ee2af71a8e764c1a8153a7dcd71f4085f970243f