♻️ refactor(rule_processor): add TRASH_LABEL, correct Gmail scopes, early returns, and improve idioms
This commit is contained in:
committed by
Jeremiah Russell
parent
ea948eda27
commit
d91b3e3b92
@@ -47,6 +47,17 @@ use google_gmail1::api::{BatchDeleteMessagesRequest, BatchModifyMessagesRequest}
|
||||
|
||||
use crate::{EolAction, Error, GmailClient, Result, message_list::MessageList, rules::EolRule};
|
||||
|
||||
/// Gmail label name for the trash folder.
|
||||
///
|
||||
/// This constant ensures consistent usage of the TRASH label throughout the module.
|
||||
const TRASH_LABEL: &str = "TRASH";
|
||||
|
||||
/// Gmail API scope for modifying messages (recommended scope for most operations).
|
||||
///
|
||||
/// This scope allows adding/removing labels, moving messages to trash, and other
|
||||
/// modification operations. Preferred over broader scopes for security.
|
||||
const GMAIL_MODIFY_SCOPE: &str = "https://www.googleapis.com/auth/gmail.modify";
|
||||
|
||||
/// Trait for processing Gmail messages according to configured end-of-life rules.
|
||||
///
|
||||
/// This trait defines the interface for finding, filtering, and acting upon Gmail messages
|
||||
@@ -221,7 +232,7 @@ impl RuleProcessor for GmailClient {
|
||||
/// The method respects the execute flag - when `false`, it runs in dry-run mode
|
||||
/// and only logs what would be done without making any changes.
|
||||
async fn find_rule_and_messages_for_label(&mut self, label: &str) -> Result<()> {
|
||||
self.add_labels(&[label.to_string()])?;
|
||||
self.add_labels(&[label.to_owned()])?;
|
||||
|
||||
if self.label_ids().is_empty() {
|
||||
return Err(Error::LabelNotFoundInMailbox(label.to_string()));
|
||||
@@ -240,10 +251,10 @@ impl RuleProcessor for GmailClient {
|
||||
log::info!("Ready to run");
|
||||
self.prepare(0).await?;
|
||||
if self.execute {
|
||||
log::info!("***executing final delete messages***");
|
||||
log::info!("Execute mode: applying rule action to messages");
|
||||
self.batch_trash().await
|
||||
} else {
|
||||
log::warn!("Execution stopped for dry run");
|
||||
log::info!("Dry-run mode: no changes made to messages");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -271,12 +282,19 @@ impl RuleProcessor for GmailClient {
|
||||
///
|
||||
/// # API Scope Requirements
|
||||
///
|
||||
/// Uses `https://mail.google.com/` scope for maximum API access. Consider
|
||||
/// using the more restrictive `https://www.googleapis.com/auth/gmail.modify`
|
||||
/// scope if your application security policy allows it.
|
||||
/// Uses `https://www.googleapis.com/auth/gmail.modify` scope for secure,
|
||||
/// minimal privilege access. This scope provides sufficient permissions
|
||||
/// for message deletion while following security best practices.
|
||||
async fn batch_delete(&self) -> Result<()> {
|
||||
let ids = Some(self.message_ids());
|
||||
let message_ids = self.message_ids();
|
||||
|
||||
// Early return if no messages to delete, avoiding unnecessary API calls
|
||||
if message_ids.is_empty() {
|
||||
log::info!("No messages to delete - skipping batch delete operation");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let ids = Some(message_ids);
|
||||
let batch_request = BatchDeleteMessagesRequest { ids };
|
||||
|
||||
log::trace!("{batch_request:#?}");
|
||||
@@ -285,13 +303,13 @@ impl RuleProcessor for GmailClient {
|
||||
.hub()
|
||||
.users()
|
||||
.messages_batch_delete(batch_request, "me")
|
||||
.add_scope("https://mail.google.com/")
|
||||
.add_scope(GMAIL_MODIFY_SCOPE)
|
||||
.doit()
|
||||
.await
|
||||
.map_err(Box::new)?;
|
||||
|
||||
for m in self.messages() {
|
||||
log::info!("Message with subject `{}` deleted.", m.subject());
|
||||
log::info!("Message with subject `{}` permanently deleted", m.subject());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -308,11 +326,19 @@ impl RuleProcessor for GmailClient {
|
||||
///
|
||||
/// # API Scope Requirements
|
||||
///
|
||||
/// Currently uses `https://www.google.com/` scope. Should be updated to use
|
||||
/// `https://www.googleapis.com/auth/gmail.modify` for better security.
|
||||
/// Uses `https://www.googleapis.com/auth/gmail.modify` scope for secure,
|
||||
/// minimal privilege access to Gmail message modification operations.
|
||||
async fn batch_trash(&self) -> Result<()> {
|
||||
let add_label_ids = Some(Vec::from(["TRASH".to_string()]));
|
||||
let ids = Some(self.message_ids());
|
||||
let message_ids = self.message_ids();
|
||||
|
||||
// Early return if no messages to trash, avoiding unnecessary API calls
|
||||
if message_ids.is_empty() {
|
||||
log::info!("No messages to trash - skipping batch trash operation");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let add_label_ids = Some(vec![TRASH_LABEL.to_string()]);
|
||||
let ids = Some(message_ids);
|
||||
let remove_label_ids = Some(self.label_ids());
|
||||
|
||||
let batch_request = BatchModifyMessagesRequest {
|
||||
@@ -327,13 +353,13 @@ impl RuleProcessor for GmailClient {
|
||||
.hub()
|
||||
.users()
|
||||
.messages_batch_modify(batch_request, "me")
|
||||
.add_scope("https://www.google.com/")
|
||||
.add_scope(GMAIL_MODIFY_SCOPE)
|
||||
.doit()
|
||||
.await
|
||||
.map_err(Box::new)?;
|
||||
|
||||
for m in self.messages() {
|
||||
log::info!("Message with subject `{}` moved to trash.", m.subject());
|
||||
log::info!("Message with subject `{}` moved to trash", m.subject());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user