Skip to content

Commit 24ecc8e

Browse files
committed
store transport ID for IMAP session
1 parent 2bbcdcf commit 24ecc8e

File tree

4 files changed

+84
-39
lines changed

4 files changed

+84
-39
lines changed

src/imap.rs

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,19 @@ impl Imap {
409409
})
410410
.await
411411
.context("Failed to enable IMAP compression")?;
412-
Session::new(compressed_session, capabilities, resync_request_sender)
412+
Session::new(
413+
compressed_session,
414+
capabilities,
415+
resync_request_sender,
416+
self.transport_id,
417+
)
413418
} else {
414-
Session::new(session, capabilities, resync_request_sender)
419+
Session::new(
420+
session,
421+
capabilities,
422+
resync_request_sender,
423+
self.transport_id,
424+
)
415425
};
416426

417427
// Store server ID in the context to display in account info.
@@ -590,8 +600,9 @@ impl Imap {
590600
folder: &str,
591601
folder_meaning: FolderMeaning,
592602
) -> Result<(usize, bool)> {
593-
let uid_validity = get_uidvalidity(context, folder).await?;
594-
let old_uid_next = get_uid_next(context, folder).await?;
603+
let transport_id = self.transport_id;
604+
let uid_validity = get_uidvalidity(context, transport_id, folder).await?;
605+
let old_uid_next = get_uid_next(context, transport_id, folder).await?;
595606
info!(
596607
context,
597608
"fetch_new_msg_batch({folder}): UIDVALIDITY={uid_validity}, UIDNEXT={old_uid_next}."
@@ -782,7 +793,7 @@ impl Imap {
782793
prefetch_uid_next < mailbox_uid_next
783794
};
784795
if new_uid_next > old_uid_next {
785-
set_uid_next(context, folder, new_uid_next).await?;
796+
set_uid_next(context, self.transport_id, folder, new_uid_next).await?;
786797
}
787798

788799
info!(context, "{} mails read from \"{}\".", read_cnt, folder);
@@ -862,6 +873,7 @@ impl Session {
862873
let folder_exists = self
863874
.select_with_uidvalidity(context, folder, create)
864875
.await?;
876+
let transport_id = self.transport_id();
865877
if folder_exists {
866878
let mut list = self
867879
.uid_fetch("1:*", RFC724MID_UID)
@@ -894,13 +906,14 @@ impl Session {
894906
msgs.len(),
895907
);
896908

897-
uid_validity = get_uidvalidity(context, folder).await?;
909+
uid_validity = get_uidvalidity(context, transport_id, folder).await?;
898910
} else {
899911
warn!(context, "resync_folder_uids: No folder {folder}.");
900912
uid_validity = 0;
901913
}
902914

903-
let transport_id = 1; // FIXME
915+
let transport_id = self.transport_id();
916+
904917
// Write collected UIDs to SQLite database.
905918
context
906919
.sql
@@ -1237,11 +1250,12 @@ impl Session {
12371250
return Ok(());
12381251
}
12391252

1253+
let transport_id = self.transport_id();
12401254
let mut updated_chat_ids = BTreeSet::new();
1241-
let uid_validity = get_uidvalidity(context, folder)
1255+
let uid_validity = get_uidvalidity(context, transport_id, folder)
12421256
.await
12431257
.with_context(|| format!("failed to get UID validity for folder {folder}"))?;
1244-
let mut highest_modseq = get_modseq(context, folder)
1258+
let mut highest_modseq = get_modseq(context, transport_id, folder)
12451259
.await
12461260
.with_context(|| format!("failed to get MODSEQ for folder {folder}"))?;
12471261
let mut list = self
@@ -1293,7 +1307,7 @@ impl Session {
12931307
self.new_mail = true;
12941308
}
12951309

1296-
set_modseq(context, folder, highest_modseq)
1310+
set_modseq(context, transport_id, folder, highest_modseq)
12971311
.await
12981312
.with_context(|| format!("failed to set MODSEQ for folder {folder}"))?;
12991313
if !updated_chat_ids.is_empty() {
@@ -2422,8 +2436,12 @@ pub(crate) async fn markseen_on_imap_table(context: &Context, message_id: &str)
24222436
/// uid_next is the next unique identifier value from the last time we fetched a folder
24232437
/// See <https://tools.ietf.org/html/rfc3501#section-2.3.1.1>
24242438
/// This function is used to update our uid_next after fetching messages.
2425-
pub(crate) async fn set_uid_next(context: &Context, folder: &str, uid_next: u32) -> Result<()> {
2426-
let transport_id = 1; // FIXME
2439+
pub(crate) async fn set_uid_next(
2440+
context: &Context,
2441+
transport_id: u32,
2442+
folder: &str,
2443+
uid_next: u32,
2444+
) -> Result<()> {
24272445
context
24282446
.sql
24292447
.execute(
@@ -2440,20 +2458,23 @@ pub(crate) async fn set_uid_next(context: &Context, folder: &str, uid_next: u32)
24402458
/// This method returns the uid_next from the last time we fetched messages.
24412459
/// We can compare this to the current uid_next to find out whether there are new messages
24422460
/// and fetch from this value on to get all new messages.
2443-
async fn get_uid_next(context: &Context, folder: &str) -> Result<u32> {
2461+
async fn get_uid_next(context: &Context, transport_id: u32, folder: &str) -> Result<u32> {
24442462
Ok(context
24452463
.sql
2446-
.query_get_value("SELECT uid_next FROM imap_sync WHERE folder=?;", (folder,))
2464+
.query_get_value(
2465+
"SELECT uid_next FROM imap_sync WHERE transport_id=? AND folder=?",
2466+
(transport_id, folder),
2467+
)
24472468
.await?
24482469
.unwrap_or(0))
24492470
}
24502471

24512472
pub(crate) async fn set_uidvalidity(
24522473
context: &Context,
2474+
transport_id: u32,
24532475
folder: &str,
24542476
uidvalidity: u32,
24552477
) -> Result<()> {
2456-
let transport_id = 1;
24572478
context
24582479
.sql
24592480
.execute(
@@ -2465,19 +2486,23 @@ pub(crate) async fn set_uidvalidity(
24652486
Ok(())
24662487
}
24672488

2468-
async fn get_uidvalidity(context: &Context, folder: &str) -> Result<u32> {
2489+
async fn get_uidvalidity(context: &Context, transport_id: u32, folder: &str) -> Result<u32> {
24692490
Ok(context
24702491
.sql
24712492
.query_get_value(
2472-
"SELECT uidvalidity FROM imap_sync WHERE folder=?;",
2473-
(folder,),
2493+
"SELECT uidvalidity FROM imap_sync WHERE transport_id=? AND folder=?",
2494+
(transport_id, folder),
24742495
)
24752496
.await?
24762497
.unwrap_or(0))
24772498
}
24782499

2479-
pub(crate) async fn set_modseq(context: &Context, folder: &str, modseq: u64) -> Result<()> {
2480-
let transport_id = 1; // FIXME
2500+
pub(crate) async fn set_modseq(
2501+
context: &Context,
2502+
transport_id: u32,
2503+
folder: &str,
2504+
modseq: u64,
2505+
) -> Result<()> {
24812506
context
24822507
.sql
24832508
.execute(
@@ -2489,10 +2514,13 @@ pub(crate) async fn set_modseq(context: &Context, folder: &str, modseq: u64) ->
24892514
Ok(())
24902515
}
24912516

2492-
async fn get_modseq(context: &Context, folder: &str) -> Result<u64> {
2517+
async fn get_modseq(context: &Context, transport_id: u32, folder: &str) -> Result<u64> {
24932518
Ok(context
24942519
.sql
2495-
.query_get_value("SELECT modseq FROM imap_sync WHERE folder=?;", (folder,))
2520+
.query_get_value(
2521+
"SELECT modseq FROM imap_sync WHERE transport_id=? AND folder=?",
2522+
(transport_id, folder),
2523+
)
24962524
.await?
24972525
.unwrap_or(0))
24982526
}

src/imap/imap_tests.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,23 @@ fn test_get_folder_meaning_by_name() {
1111
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
1212
async fn test_set_uid_next_validity() {
1313
let t = TestContext::new_alice().await;
14-
assert_eq!(get_uid_next(&t.ctx, "Inbox").await.unwrap(), 0);
15-
assert_eq!(get_uidvalidity(&t.ctx, "Inbox").await.unwrap(), 0);
14+
assert_eq!(get_uid_next(&t.ctx, 1, "Inbox").await.unwrap(), 0);
15+
assert_eq!(get_uidvalidity(&t.ctx, 1, "Inbox").await.unwrap(), 0);
1616

17-
set_uidvalidity(&t.ctx, "Inbox", 7).await.unwrap();
18-
assert_eq!(get_uidvalidity(&t.ctx, "Inbox").await.unwrap(), 7);
19-
assert_eq!(get_uid_next(&t.ctx, "Inbox").await.unwrap(), 0);
17+
set_uidvalidity(&t.ctx, 1, "Inbox", 7).await.unwrap();
18+
assert_eq!(get_uidvalidity(&t.ctx, 1, "Inbox").await.unwrap(), 7);
19+
assert_eq!(get_uid_next(&t.ctx, 1, "Inbox").await.unwrap(), 0);
2020

21-
set_uid_next(&t.ctx, "Inbox", 5).await.unwrap();
22-
set_uidvalidity(&t.ctx, "Inbox", 6).await.unwrap();
23-
assert_eq!(get_uid_next(&t.ctx, "Inbox").await.unwrap(), 5);
24-
assert_eq!(get_uidvalidity(&t.ctx, "Inbox").await.unwrap(), 6);
21+
// For another transport there is still no UIDVALIDITY set.
22+
assert_eq!(get_uidvalidity(&t.ctx, 2, "Inbox").await.unwrap(), 0);
23+
24+
set_uid_next(&t.ctx, 1, "Inbox", 5).await.unwrap();
25+
set_uidvalidity(&t.ctx, 1, "Inbox", 6).await.unwrap();
26+
assert_eq!(get_uid_next(&t.ctx, 1, "Inbox").await.unwrap(), 5);
27+
assert_eq!(get_uidvalidity(&t.ctx, 1, "Inbox").await.unwrap(), 6);
28+
29+
assert_eq!(get_uid_next(&t.ctx, 2, "Inbox").await.unwrap(), 0);
30+
assert_eq!(get_uidvalidity(&t.ctx, 2, "Inbox").await.unwrap(), 0);
2531
}
2632

2733
#[test]

src/imap/select_folder.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,16 @@ impl ImapSession {
146146
},
147147
}
148148
};
149+
let transport_id = self.transport_id();
149150
let mailbox = self
150151
.selected_mailbox
151152
.as_mut()
152153
.with_context(|| format!("No mailbox selected, folder: {folder:?}"))?;
153154

154-
let old_uid_validity = get_uidvalidity(context, folder)
155+
let old_uid_validity = get_uidvalidity(context, transport_id, folder)
155156
.await
156157
.with_context(|| format!("Failed to get old UID validity for folder {folder:?}"))?;
157-
let old_uid_next = get_uid_next(context, folder)
158+
let old_uid_next = get_uid_next(context, transport_id, folder)
158159
.await
159160
.with_context(|| format!("Failed to get old UID NEXT for folder {folder:?}"))?;
160161

@@ -205,8 +206,8 @@ impl ImapSession {
205206
context,
206207
"The server illegally decreased the uid_next of folder {folder:?} from {old_uid_next} to {new_uid_next} without changing validity ({new_uid_validity}), resyncing UIDs...",
207208
);
208-
set_uid_next(context, folder, new_uid_next).await?;
209209
self.resync_request_sender.try_send(()).ok();
210+
set_uid_next(context, transport_id, folder, new_uid_next).await?;
210211
}
211212

212213
// If UIDNEXT changed, there are new emails.
@@ -223,22 +224,23 @@ impl ImapSession {
223224
return Ok(true);
224225
}
225226

227+
let transport_id = self.transport_id();
226228
// UIDVALIDITY is modified, reset highest seen MODSEQ.
227-
set_modseq(context, folder, 0).await?;
229+
set_modseq(context, transport_id, folder, 0).await?;
228230

229231
// ============== uid_validity has changed or is being set the first time. ==============
230232

231233
let new_uid_next = new_uid_next.unwrap_or_default();
232-
set_uid_next(context, folder, new_uid_next).await?;
233-
set_uidvalidity(context, folder, new_uid_validity).await?;
234+
set_uid_next(context, transport_id, folder, new_uid_next).await?;
235+
set_uidvalidity(context, transport_id, folder, new_uid_validity).await?;
234236
self.new_mail = true;
235237

236238
// Collect garbage entries in `imap` table.
237239
context
238240
.sql
239241
.execute(
240-
"DELETE FROM imap WHERE folder=? AND uidvalidity!=?",
241-
(&folder, new_uid_validity),
242+
"DELETE FROM imap WHERE transport_id=? AND folder=? AND uidvalidity!=?",
243+
(transport_id, &folder, new_uid_validity),
242244
)
243245
.await?;
244246

src/imap/session.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ const PREFETCH_FLAGS: &str = "(UID INTERNALDATE RFC822.SIZE BODY.PEEK[HEADER.FIE
3030

3131
#[derive(Debug)]
3232
pub(crate) struct Session {
33+
transport_id: u32,
34+
3335
pub(super) inner: ImapSession<Box<dyn SessionStream>>,
3436

3537
pub capabilities: Capabilities,
@@ -71,8 +73,10 @@ impl Session {
7173
inner: ImapSession<Box<dyn SessionStream>>,
7274
capabilities: Capabilities,
7375
resync_request_sender: async_channel::Sender<()>,
76+
transport_id: u32,
7477
) -> Self {
7578
Self {
79+
transport_id,
7680
inner,
7781
capabilities,
7882
selected_folder: None,
@@ -84,6 +88,11 @@ impl Session {
8488
}
8589
}
8690

91+
/// Returns ID of the transport for which this session was created.
92+
pub(crate) fn transport_id(&self) -> u32 {
93+
self.transport_id
94+
}
95+
8796
pub fn can_idle(&self) -> bool {
8897
self.capabilities.can_idle
8998
}

0 commit comments

Comments
 (0)