Skip to content

Conversation

@evanhutnik
Copy link
Contributor

@evanhutnik evanhutnik commented Jan 21, 2026

Don't merge until we get gmail approval for elevated oauth scope in prod

Summary

Adds endpoints for blocking and unblocking email senders, as well as listing all currently blocked users.

New Endpoints

Method Endpoint Description
POST /email/contacts/block Block a sender
DELETE /email/contacts/block/:email_address Unblock a sender
GET /email/contacts/blocked List all blocked senders

How It Works

Gmail does not allow external API callers to mark messages as SPAM, so the best we can do is move messages from blocked users directly to trash. This is the same approach Superhuman uses when you block a user.

Blocking is implemented by creating a Gmail filter for the sender's email address, which automatically moves their incoming messages to the trash.

⚠️ OAuth Scope Requirement

This feature requires a new OAuth scope (gmail.settings.basic) to manage Gmail filters. This means:

  1. Existing users won't have this permission until they log out and back in
  2. The endpoints will return 403 Forbidden if the user lacks the required Gmail permissions
  3. Frontend handling: When a 403 is received, the UI should prompt the user to re-authenticate to grant the elevated permission

@claude
Copy link
Contributor

claude bot commented Jan 21, 2026

Code review

Compilation Error: Temporary Value Dropped While Borrowed

Location: rust/cloud-storage/email_service/src/api/email/contacts/block_sender.rs:39-41

The expression self.to_string().as_str() creates a temporary String that is immediately dropped, while the ErrorResponse struct tries to store a borrowed reference to it.

Problem: The ErrorResponse struct expects a &'a str with a lifetime parameter:

pub struct ErrorResponse<'a> {
    pub message: &'a str,
}

When you call self.to_string().as_str():

  1. self.to_string() creates a temporary String
  2. .as_str() borrows from that temporary as &str
  3. The temporary String is dropped at the end of the expression
  4. The &str reference now points to freed memory

This will produce compiler error E0716: temporary value dropped while borrowed.

Solution: Remove the .as_str() call:

Json(ErrorResponse {
    message: &self.to_string(),
}),

Or allocate the String first:

let message = self.to_string();
Json(ErrorResponse { message: &message })

Note: This same issue appears in:

All three files need the same fix.

@JacksonMacro
Copy link

"blocking" does not fit our brand language. what about "remove from runtime memory" ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants