feat(n8n-webhook): add gmail draft list/delete/send approval flows

This commit is contained in:
zap
2026-03-12 20:58:02 +00:00
parent e45949d496
commit 111dda91b8
10 changed files with 321 additions and 17 deletions
@@ -103,7 +103,7 @@ def attach_execution(item_id: str, execution: dict, *, base_url: str, path: str,
)
def build_email_command(item: dict, account: str, dry_run: bool):
def build_email_draft_create_command(item: dict, account: str, dry_run: bool):
payload = item.get('payload') or {}
body_text = payload.get('body_text') or ''
body_html = payload.get('body_html') or ''
@@ -137,6 +137,68 @@ def build_email_command(item: dict, account: str, dry_run: bool):
return cmd, tmp.name if tmp else None
def build_email_draft_delete_command(item: dict, account: str, dry_run: bool):
payload = item.get('payload') or {}
draft_id = (payload.get('draft_id') or payload.get('id') or '').strip()
if not draft_id:
fail('email_draft_delete payload missing draft_id')
cmd = [
'gog', 'gmail', 'drafts', 'delete', draft_id,
'--account', account,
'--json',
'--no-input',
'--force',
]
if dry_run:
cmd.append('--dry-run')
return cmd
def build_email_draft_send_command(item: dict, account: str, dry_run: bool):
payload = item.get('payload') or {}
draft_id = (payload.get('draft_id') or payload.get('id') or '').strip()
if not draft_id:
fail('email_draft_send payload missing draft_id')
cmd = [
'gog', 'gmail', 'drafts', 'send', draft_id,
'--account', account,
'--json',
'--no-input',
]
if dry_run:
cmd.append('--dry-run')
return cmd
def build_email_drafts_list_command(item: dict, account: str, dry_run: bool):
payload = item.get('payload') or {}
max_results = payload.get('max')
if max_results is None:
max_results = 20
try:
max_results = max(1, min(100, int(max_results)))
except Exception:
max_results = 20
cmd = [
'gog', 'gmail', 'drafts', 'list',
'--account', account,
'--json',
'--no-input',
'--max', str(max_results),
]
page = (payload.get('page') or '').strip()
if page:
cmd.extend(['--page', page])
if payload.get('all') is True:
cmd.append('--all')
if payload.get('fail_empty') is True:
cmd.append('--fail-empty')
if dry_run:
cmd.append('--dry-run')
return cmd
def build_calendar_command(item: dict, account: str, dry_run: bool):
payload = item.get('payload') or {}
calendar = payload.get('calendar') or 'primary'
@@ -211,7 +273,41 @@ def main():
print(json.dumps({'resolved': resolved, 'executed': True, 'driver': 'n8n'}, indent=2))
return
if kind not in {'email_draft', 'calendar_event'}:
executors = {
'email_draft': {
'builder': build_email_draft_create_command,
'op': 'gmail.drafts.create',
'success_status': 'draft_created',
'uses_tmpfile': True,
},
'email_list_drafts': {
'builder': build_email_drafts_list_command,
'op': 'gmail.drafts.list',
'success_status': 'drafts_listed',
'uses_tmpfile': False,
},
'email_draft_delete': {
'builder': build_email_draft_delete_command,
'op': 'gmail.drafts.delete',
'success_status': 'draft_deleted',
'uses_tmpfile': False,
},
'email_draft_send': {
'builder': build_email_draft_send_command,
'op': 'gmail.drafts.send',
'success_status': 'draft_sent',
'uses_tmpfile': False,
},
'calendar_event': {
'builder': build_calendar_command,
'op': 'calendar.create',
'success_status': 'event_created',
'uses_tmpfile': False,
},
}
spec = executors.get(kind)
if not spec:
print(json.dumps({'resolved': resolved, 'executed': False, 'reason': f'no host executor for kind {kind}'}, indent=2))
return
@@ -219,15 +315,14 @@ def main():
env = os.environ.copy()
env['GOG_ACCOUNT'] = account
if kind == 'email_draft':
cmd, tmpfile = build_email_command(item, account, args.dry_run)
op = 'gmail.drafts.create'
success_status = 'draft_created' if not args.dry_run else 'dry_run'
tmpfile = None
if spec['uses_tmpfile']:
cmd, tmpfile = spec['builder'](item, account, args.dry_run)
else:
cmd = build_calendar_command(item, account, args.dry_run)
tmpfile = None
op = 'calendar.create'
success_status = 'event_created' if not args.dry_run else 'dry_run'
cmd = spec['builder'](item, account, args.dry_run)
op = spec['op']
success_status = spec['success_status'] if not args.dry_run else 'dry_run'
try:
code, stdout, stderr = run(cmd, env=env)
@@ -26,6 +26,10 @@ SAMPLE_FILES = [
'test-notify.json',
'test-send-notification-draft.json',
'test-send-email-draft.json',
'test-list-email-drafts.json',
'test-delete-email-draft.json',
'test-send-gmail-draft.json',
'test-send-approved-email.json',
'test-create-calendar-event.json',
'test-fetch-and-normalize-url.json',
'test-approval-queue-list.json',
@@ -38,6 +42,10 @@ ROUTER_SNIPPETS = [
'notify',
'send_notification_draft',
'send_email_draft',
'list_email_drafts',
'delete_email_draft',
'send_gmail_draft',
'send_approved_email',
'create_calendar_event',
'approval_queue_add',
'approval_queue_list',
@@ -50,6 +58,10 @@ ROUTER_SNIPPETS = [
'$getWorkflowStaticData',
'approvalQueue',
'approvalHistory',
'email_draft_send',
'email_draft_delete',
'email_list_drafts',
'makeApprovalPolicy',
'inboundEvents',
'eventDedup',
'notify_text',