fix: notify new mail again when a push names Email but not EmailDelivery #34

On main every push ran the mail task, whose legacy path notifies the
newest unread inbox mail. Device sync narrowed that to pushes naming
EmailDelivery, so contact and calendar changes never notify. But a
subscription made by an older build listens to Email and Mailbox until
the app is opened again, and a server without EmailDelivery reports
new mail only as those changes. Their new mail no longer showed a
notification while the app was closed.

Email and Mailbox now count as possible mail again, in the native push
router and in the push task alike. A push that names only contact or
calendar types still never takes the mail path.

Checked with the push router and push task tests: an Email or Mailbox
change starts the task and the legacy path notifies the message,
next to the syncs a mixed map asks for.
This commit is contained in:
Linus Rath
2026-09-27 10:20:55 +02:00
parent 11b897177d
commit 41e2bdf922
4 changed files with 78 additions and 7 deletions
@@ -64,6 +64,26 @@ class PushRoutingTest {
assertEquals(setOf("alice-work" to calendar), decision.syncs)
}
@Test
fun `an Email or Mailbox change is possible mail, as a subscription from an older build sends it`() {
for (changed in listOf(
"""{"c":{"Email":"s1","Mailbox":"s2"}}""",
"""{"c":{"Email":"s1"}}""",
"""{"c":{"Mailbox":"s1"}}""",
)) {
val decision = PushRouting.decide(stateChange(changed), routes)
assertTrue("changed=$changed", decision.startMailTask)
assertTrue("changed=$changed", decision.syncs.isEmpty())
}
val mixed = PushRouting.decide(stateChange("""{"team":{"CalendarEvent":"e1"},"c":{"Email":"s1"}}"""), routes)
assertTrue(mixed.startMailTask)
assertEquals(setOf("alice-work" to calendar), mixed.syncs)
// Types that are neither mail nor device sync say nothing about mail.
val other = PushRouting.decide(stateChange("""{"c":{"Thread":"t1","ContactCard":"s1"}}"""), routes)
assertFalse(other.startMailTask)
assertEquals(setOf("alice@example.org" to contacts), other.syncs)
}
@Test
fun `an email push always starts the mail task`() {
val data = mapOf("kind" to "jmap-email-push", "accountId" to "c", "changed" to """{"c":{"EmailDelivery":"s"}}""")