@@ -217,8 +217,7 @@ async fn build_http_request(
217217async fn handle_json_response (
218218 body_text : & str ,
219219 pagination : & PaginationConfig ,
220- sanitize_template : Option < & str > ,
221- sanitize_mode : & crate :: helpers:: modelarmor:: SanitizeMode ,
220+ policy : & crate :: helpers:: modelarmor:: ExecutionPolicy ,
222221 output_format : & crate :: formatter:: OutputFormat ,
223222 pages_fetched : & mut u32 ,
224223 page_token : & mut Option < String > ,
@@ -229,7 +228,7 @@ async fn handle_json_response(
229228 * pages_fetched += 1 ;
230229
231230 // Run Model Armor sanitization if --sanitize is enabled
232- if let Some ( template) = sanitize_template {
231+ if let Some ( ref template) = policy . template {
233232 let text_to_check = serde_json:: to_string ( & json_val) . unwrap_or_default ( ) ;
234233 match crate :: helpers:: modelarmor:: sanitize_text ( template, & text_to_check) . await {
235234 Ok ( result) => {
@@ -238,7 +237,7 @@ async fn handle_json_response(
238237 eprintln ! ( "⚠️ Model Armor: prompt injection detected (filterMatchState: MATCH_FOUND)" ) ;
239238 }
240239
241- if is_match && * sanitize_mode == crate :: helpers:: modelarmor:: SanitizeMode :: Block
240+ if is_match && policy . mode == crate :: helpers:: modelarmor:: SanitizeMode :: Block
242241 {
243242 let blocked = serde_json:: json!( {
244243 "error" : "Content blocked by Model Armor" ,
@@ -377,13 +376,27 @@ pub async fn execute_method(
377376 upload_content_type : Option < & str > ,
378377 dry_run : bool ,
379378 pagination : & PaginationConfig ,
380- sanitize_template : Option < & str > ,
381- sanitize_mode : & crate :: helpers:: modelarmor:: SanitizeMode ,
379+ policy : & crate :: helpers:: modelarmor:: ExecutionPolicy ,
382380 output_format : & crate :: formatter:: OutputFormat ,
383381 capture_output : bool ,
384382) -> Result < Option < Value > , GwsError > {
385383 let input = parse_and_validate_inputs ( doc, method, params_json, body_json, upload_path) ?;
386384
385+ // Gmail-specific safety policy: block sending if draft-only mode is active
386+ if policy. draft_only && !dry_run && doc. name == "gmail" {
387+ let is_send = if let Some ( ref id) = method. id {
388+ id == "gmail.users.messages.send" || id == "gmail.users.drafts.send"
389+ } else {
390+ // Fallback to Discovery path if ID is missing.
391+ // Standard Gmail send path: users/{userId}/messages/send
392+ method. path . contains ( "messages/send" ) || method. path . contains ( "drafts/send" )
393+ } ;
394+
395+ if is_send {
396+ return Err ( GwsError :: Validation ( "Gmail draft-only mode is active. Sending mail is blocked (preparing a draft is still allowed)." . to_string ( ) ) ) ;
397+ }
398+ }
399+
387400 if dry_run {
388401 let dry_run_info = json ! ( {
389402 "dry_run" : true ,
@@ -470,8 +483,7 @@ pub async fn execute_method(
470483 let should_continue = handle_json_response (
471484 & body_text,
472485 pagination,
473- sanitize_template,
474- sanitize_mode,
486+ policy,
475487 output_format,
476488 & mut pages_fetched,
477489 & mut page_token,
0 commit comments