feat(gmail): add +read helper for clean text extraction#502
feat(gmail): add +read helper for clean text extraction#502dumko2001 wants to merge 5 commits intogoogleworkspace:mainfrom
Conversation
🦋 Changeset detectedLatest commit: 4db0c7b The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request enhances the Gmail CLI with a new Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new +read helper for the gmail command, which is a useful addition for extracting email content. The implementation looks good. However, the PR also includes a significant and unexplained downgrade of the ratatui dependency from version 0.30.0 to 0.29.0. This change seems out of scope and should be addressed, either by providing a clear justification or by moving it to a separate pull request.
|
Thanks for the catch! The ratatui downgrade was accidental (likely a rebase/merge artifact). I've restored it to 0.30.0 to match main. I also fixed an unused import warning in setup_tui.rs while I was at it. |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a +read helper for the Gmail CLI, which is a useful addition for extracting email content. The implementation is mostly solid, but I've found a couple of areas for improvement. There's a redundant CLI flag (--body-only) that could be removed to simplify the user interface. Additionally, the logic for handling HTML body content could be made more robust.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a +read helper for the Gmail service, which is a useful addition for extracting email content. The implementation is clean and follows existing patterns. However, a high-severity robustness issue has been identified where the use of println! can lead to a panic if the output pipe is closed. A fix has been recommended to handle I/O errors gracefully, which will improve the robustness of the new helper.
| pub(super) async fn handle_read( | ||
| _doc: &crate::discovery::RestDescription, | ||
| matches: &ArgMatches, | ||
| ) -> Result<(), GwsError> { | ||
| let message_id = matches | ||
| .get_one::<String>("id") | ||
| .unwrap(); | ||
|
|
||
| let dry_run = matches.get_flag("dry-run"); | ||
|
|
||
| let original = if dry_run { | ||
| OriginalMessage::dry_run_placeholder(message_id) | ||
| } else { | ||
| let t = auth::get_token(&[GMAIL_READONLY_SCOPE]) | ||
| .await | ||
| .map_err(|e| GwsError::Auth(format!("Gmail auth failed: {e}")))?; | ||
|
|
||
| let client = crate::client::build_client()?; | ||
| fetch_message_metadata(&client, &t, message_id).await? | ||
| }; | ||
|
|
||
| let format = matches.get_one::<String>("format").unwrap(); | ||
| let show_headers = matches.get_flag("headers"); | ||
| let use_html = matches.get_flag("html"); | ||
|
|
||
| if format == "json" { | ||
| println!( | ||
| "{}", | ||
| serde_json::to_string_pretty(&original) | ||
| .map_err(|e| GwsError::Other(anyhow::anyhow!(e)))? | ||
| ); | ||
| return Ok(()); | ||
| } | ||
|
|
||
| if show_headers { | ||
| println!("From: {}", original.from); | ||
| println!("To: {}", original.to); | ||
| if !original.cc.is_empty() { | ||
| println!("Cc: {}", original.cc); | ||
| } | ||
| println!("Subject: {}", original.subject); | ||
| println!("Date: {}", original.date); | ||
| println!("---"); | ||
| } | ||
|
|
||
| let body = if use_html { | ||
| original | ||
| .body_html | ||
| .as_deref() | ||
| .filter(|s| !s.is_empty()) | ||
| .unwrap_or(&original.body_text) | ||
| } else { | ||
| &original.body_text | ||
| }; | ||
|
|
||
| println!("{}", body); | ||
|
|
||
| Ok(()) | ||
| } |
There was a problem hiding this comment.
This function uses println! multiple times to write to standard output. If the output is piped to another process that closes the pipe early (e.g., | head), println! will panic, causing the program to crash. This is a robustness issue that can affect consumers of this CLI, especially in scripted environments.
To prevent this, you should use writeln! on a handle to stdout and handle the potential io::Error, converting it to a GwsError.
For example:
use std::io::{self, Write};
let mut stdout = io::stdout();
writeln!(stdout, "From: {}", original.from).map_err(|e| GwsError::Other(anyhow::anyhow!(e)))?;This should be applied to all println! calls in this function to make the helper more robust.
Description
Add a Gmail
+readhelper to abstract MIME tree walking and base64 decoding for readable text extraction. This is specifically designed for AI agents to easily consume email content without handling raw MIME structures.Dry Run Output:
{ "thread_id": "thread-123", "message_id_header": "<123@example.com>", "references": "", "from": "sender@example.com", "reply_to": "", "to": "you@example.com", "cc": "", "subject": "Original subject", "date": "Thu, 1 Jan 2026 00:00:00 +0000", "body_text": "Original message body", "body_html": "<p>Original message body</p>" }Checklist:
AGENTS.mdguidelines (no generatedgoogle-*crates).cargo fmt --allto format the code perfectly.cargo clippy -- -D warningsand resolved all warnings.pnpx changeset) to document my changes.