Skip to content

Commit

Permalink
jmap_mail.c: support both nanosecond-based and guid-based EMAILIDs
Browse files Browse the repository at this point in the history
triggered by conv.db version

NOTE: this still needs a test to make sure v1 still works
  • Loading branch information
ksmurchison committed Mar 5, 2025
1 parent 997d5c0 commit 534ea7b
Show file tree
Hide file tree
Showing 10 changed files with 195 additions and 102 deletions.
2 changes: 1 addition & 1 deletion cassandane/Cassandane/Cyrus/Expunge.pm
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ sub test_auditlog_size
}

sub test_allowdeleted
:AllowDeleted :DelayedExpunge :min_version_3_1
:AllowDeleted :DelayedExpunge :Conversations
{
my ($self, $folder, %params) = @_;

Expand Down
15 changes: 12 additions & 3 deletions cassandane/Cassandane/Cyrus/Reconstruct.pm
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,8 @@ sub test_downgrade_upgrade
}

sub test_upgrade_v19_to_v20
:MailboxLegacyDirs :NoAltNameSpace :Replication :needs_component_replication
:MailboxLegacyDirs :NoAltNameSpace :Conversations
:Replication :needs_component_replication
{
my ($self) = @_;

Expand All @@ -655,18 +656,26 @@ sub test_upgrade_v19_to_v20
$self->{instance}->run_command({ cyrus => 1 }, 'reconstruct', '-G', '-q');
$self->{replica}->run_command({ cyrus => 1 }, 'reconstruct', '-G', '-q');

xlog $self, "Upgrade master to version 20";
xlog $self, "Upgrade master to mailbox version 20";
$self->{instance}->run_command({ cyrus => 1 }, 'reconstruct', '-V', 'max');

xlog $self, "Upgrade master to conv.db version 2";
$self->{instance}->run_command({ cyrus => 1 },
'ctl_conversationsdb', '-U', '-r');

# replicate new version to old version
$self->run_replication();

# check_replication() will fail here due to the internaldate.nsec annotation
# being present on the replica but NOT on the master

xlog $self, "Upgrade replica to version 20";
xlog $self, "Upgrade replica to mailbox version 20";
$self->{replica}->run_command({ cyrus => 1 }, 'reconstruct', '-V', 'max');

xlog $self, "Upgrade replica to conv.db version 2";
$self->{instance}->run_command({ cyrus => 1 },
'ctl_conversationsdb', '-U', '-r');

$self->run_replication();
$self->check_replication('cassandane');

Expand Down
23 changes: 15 additions & 8 deletions imap/caldav_alarm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1601,21 +1601,28 @@ static int find_scheduled_email(const char *emailid,
struct conversations_state *cstate = NULL;
int r;

if (emailid[0] != JMAP_EMAILID_PREFIX ||
strlen(emailid) != JMAP_EMAILID_SIZE - 1) {
return IMAP_NOTFOUND;
}

r = conversations_open_user(frock->userid, 1/*shared*/, &cstate);
if (r) {
syslog(LOG_ERR, "IOERROR: failed to open conversations for user %s",
frock->userid);
return r;
}

char guid[2*MESSAGE_GUID_SIZE+1];
r = conversations_jmapid_guidrep_lookup(cstate, emailid + 1, guid);
if (!r) r = conversations_guid_foreach(cstate, guid, find_sched_cb, frock);
const char *guid = NULL;
if (emailid[0] == JMAP_EMAILID_PREFIX) {
static char guidrep[2*MESSAGE_GUID_SIZE+1];

if (strlen(emailid) == JMAP_EMAILID_SIZE - 1 &&
!conversations_jmapid_guidrep_lookup(cstate, emailid + 1, guidrep))
guid = guidrep;
}
else if (emailid[0] == JMAP_LEGACY_EMAILID_PREFIX) {
if (strlen(emailid) == JMAP_LEGACY_EMAILID_SIZE - 1)
guid = emailid + 1;
}
if (!guid) return IMAP_NOTFOUND;

r = conversations_guid_foreach(cstate, guid, find_sched_cb, frock);
conversations_commit(&cstate);

if (r == IMAP_OK_COMPLETED) r = 0;
Expand Down
2 changes: 1 addition & 1 deletion imap/conversations.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ typedef bit64 conversation_id_t;
struct index_record;
struct mailbox;

#define CONVERSATIONS_VERSION 1
#define CONVERSATIONS_VERSION 2
#define CONVERSATIONS_KEY_VERSION 0
#define CONVERSATIONS_STATUS_VERSION 0
#define CONVERSATIONS_RECORD_VERSION 1
Expand Down
26 changes: 20 additions & 6 deletions imap/index.c
Original file line number Diff line number Diff line change
Expand Up @@ -4537,12 +4537,26 @@ static int index_fetchreply(struct index_state *state, uint32_t msgno,
sepchar = ' ';
}
if (fetchitems & FETCH_EMAILID) {
struct buf emailid = BUF_INITIALIZER;
buf_putc(&emailid, 'S');
NANOSEC_TO_JMAPID(&emailid, TIMESPEC_TO_NANOSEC(&record.internaldate));
prot_printf(state->out, "%cEMAILID (%s)", sepchar, buf_cstring(&emailid));
buf_free(&emailid);
sepchar = ' ';
struct conversations_state *cstate = mailbox_get_cstate(state->mailbox);
if (!cstate) {
xsyslog(LOG_ERR, "could not read conversations state",
"mboxid=<%s>", mailbox_uniqueid(state->mailbox));
}
else {
struct buf emailid = BUF_INITIALIZER;
if (cstate->version < 2) {
buf_putc(&emailid, 'M');
buf_appendmap(&emailid, message_guid_encode(&record.guid), 24);
}
else {
buf_putc(&emailid, 'S');
NANOSEC_TO_JMAPID(&emailid,
TIMESPEC_TO_NANOSEC(&record.internaldate));
}
prot_printf(state->out, "%cEMAILID (%s)", sepchar, buf_cstring(&emailid));
buf_free(&emailid);
sepchar = ' ';
}
}
if ((fetchitems & FETCH_CID) &&
config_getswitch(IMAPOPT_CONVERSATIONS)) {
Expand Down
5 changes: 3 additions & 2 deletions imap/jmap_blob.c
Original file line number Diff line number Diff line change
Expand Up @@ -849,8 +849,9 @@ static int jmap_blob_lookup(jmap_req_t *req)
}

case DATATYPE_EMAIL: {
char emailid[JMAP_EMAILID_SIZE];
jmap_set_emailid_from_timespec(&internaldate, emailid);
char emailid[JMAP_MAX_EMAILID_SIZE];
jmap_set_emailid(req->cstate->version, &guid,
0, &internaldate, emailid);
strarray_add(ids, emailid);
break;
}
Expand Down
Loading

0 comments on commit 534ea7b

Please sign in to comment.