-
-
Notifications
You must be signed in to change notification settings - Fork 124
api: add clear_all_relay_storage API #8105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -250,6 +250,16 @@ impl SchedulerState { | |
| } | ||
| } | ||
|
|
||
| pub(crate) async fn clear_all_relay_storage(&self) -> Result<()> { | ||
| let inner = self.inner.read().await; | ||
| if let InnerSchedulerState::Started(ref scheduler) = *inner { | ||
|
iequidoo marked this conversation as resolved.
|
||
| scheduler.clear_all_relay_storage(); | ||
| Ok(()) | ||
| } else { | ||
| bail!("IO is not started"); | ||
| } | ||
| } | ||
|
|
||
| pub(crate) async fn interrupt_smtp(&self) { | ||
| let inner = self.inner.read().await; | ||
| if let InnerSchedulerState::Started(ref scheduler) = *inner { | ||
|
|
@@ -348,6 +358,7 @@ async fn inbox_loop( | |
| let ImapConnectionHandlers { | ||
| mut connection, | ||
| stop_token, | ||
| clear_storage_request_receiver, | ||
| } = inbox_handlers; | ||
|
|
||
| let transport_id = connection.transport_id(); | ||
|
|
@@ -386,7 +397,14 @@ async fn inbox_loop( | |
| } | ||
| }; | ||
|
|
||
| match inbox_fetch_idle(&ctx, &mut connection, session).await { | ||
| match inbox_fetch_idle( | ||
| &ctx, | ||
| &mut connection, | ||
| session, | ||
| &clear_storage_request_receiver, | ||
| ) | ||
| .await | ||
| { | ||
| Err(err) => warn!( | ||
| ctx, | ||
| "Transport {transport_id}: Failed inbox fetch_idle: {err:#}." | ||
|
|
@@ -407,11 +425,29 @@ async fn inbox_loop( | |
| .await; | ||
| } | ||
|
|
||
| async fn inbox_fetch_idle(ctx: &Context, imap: &mut Imap, mut session: Session) -> Result<Session> { | ||
| async fn inbox_fetch_idle( | ||
| ctx: &Context, | ||
| imap: &mut Imap, | ||
| mut session: Session, | ||
| clear_storage_request_receiver: &Receiver<()>, | ||
| ) -> Result<Session> { | ||
| let transport_id = session.transport_id(); | ||
|
|
||
| // Clear IMAP storage on request. | ||
| // | ||
| // Only doing this for chatmail relays to avoid | ||
| // accidentally deleting all emails in a shared mailbox. | ||
| let should_clear_imap_storage = | ||
| clear_storage_request_receiver.try_recv().is_ok() && session.is_chatmail(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice to print an info to the log if the it was requested to clear storage, but
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This |
||
| if should_clear_imap_storage { | ||
| info!(ctx, "Transport {transport_id}: Clearing IMAP storage."); | ||
| session.delete_all_messages(ctx, &imap.folder).await?; | ||
| } | ||
|
|
||
| // Update quota no more than once a minute. | ||
| if ctx.quota_needs_update(session.transport_id(), 60).await | ||
| // | ||
| // Always update if we just cleared IMAP storage. | ||
| if (ctx.quota_needs_update(session.transport_id(), 60).await || should_clear_imap_storage) | ||
| && let Err(err) = ctx.update_recent_quota(&mut session, &imap.folder).await | ||
| { | ||
| warn!( | ||
|
|
@@ -737,6 +773,12 @@ impl Scheduler { | |
| } | ||
| } | ||
|
|
||
| fn clear_all_relay_storage(&self) { | ||
| for b in &self.inboxes { | ||
| b.conn_state.clear_relay_storage(); | ||
| } | ||
| } | ||
|
|
||
| fn interrupt_smtp(&self) { | ||
| self.smtp.interrupt(); | ||
| } | ||
|
|
@@ -870,6 +912,13 @@ struct SmtpConnectionHandlers { | |
| #[derive(Debug)] | ||
| pub(crate) struct ImapConnectionState { | ||
| state: ConnectionState, | ||
|
|
||
| /// Channel to request clearing the folder. | ||
| /// | ||
| /// IMAP loop receiving this should clear the folder | ||
| /// on the next iteration if IMAP server is a chatmail relay | ||
| /// and otherwise ignore the request. | ||
| clear_storage_request_sender: Sender<()>, | ||
| } | ||
|
|
||
| impl ImapConnectionState { | ||
|
|
@@ -881,11 +930,13 @@ impl ImapConnectionState { | |
| ) -> Result<(Self, ImapConnectionHandlers)> { | ||
| let stop_token = CancellationToken::new(); | ||
| let (idle_interrupt_sender, idle_interrupt_receiver) = channel::bounded(1); | ||
| let (clear_storage_request_sender, clear_storage_request_receiver) = channel::bounded(1); | ||
|
|
||
| let handlers = ImapConnectionHandlers { | ||
| connection: Imap::new(context, transport_id, login_param, idle_interrupt_receiver) | ||
| .await?, | ||
| stop_token: stop_token.clone(), | ||
| clear_storage_request_receiver, | ||
| }; | ||
|
|
||
| let state = ConnectionState { | ||
|
|
@@ -894,7 +945,10 @@ impl ImapConnectionState { | |
| connectivity: handlers.connection.connectivity.clone(), | ||
| }; | ||
|
|
||
| let conn = ImapConnectionState { state }; | ||
| let conn = ImapConnectionState { | ||
| state, | ||
| clear_storage_request_sender, | ||
| }; | ||
|
|
||
| Ok((conn, handlers)) | ||
| } | ||
|
|
@@ -908,10 +962,19 @@ impl ImapConnectionState { | |
| fn stop(&self) { | ||
| self.state.stop(); | ||
| } | ||
|
|
||
| /// Requests clearing relay storage and interrupts the inbox. | ||
| fn clear_relay_storage(&self) { | ||
| self.clear_storage_request_sender.try_send(()).ok(); | ||
| self.state.interrupt(); | ||
| } | ||
| } | ||
|
|
||
| #[derive(Debug)] | ||
| struct ImapConnectionHandlers { | ||
| connection: Imap, | ||
| stop_token: CancellationToken, | ||
|
|
||
| /// Channel receiver to get requests to clear IMAP storage. | ||
| pub(crate) clear_storage_request_receiver: Receiver<()>, | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no good way to check if chatmail relay is used currently. There is
is_chatmail, but it gets stuck being true if you add chatmail relay and then remove it. I think it's better to just always offer the option, worst case it will do nothing for non-chatmail users but they are unlikely to want to even click the option. Otherwise we are adding moreis_chatmailchecks and we want to get rid ofis_chatmail.