draft_email from yesterday places emails in your Drafts folder safely. Today you cross the line — GMAIL_SEND_EMAIL delivers immediately. There is no undo. How do you test it without emailing six clients?
Send to myself first. Same function, same arguments, recipient is my own email. Then check Sent and Inbox to confirm it arrived correctly.
That is the safety pattern for every write action in this track. Tests always send to self. The function signature is identical to draft_email — to, subject, body — so once you have confirmed the output looks right on your own address, you swap the recipient to the client list:
result = toolset.execute_action(
Action.GMAIL_SEND_EMAIL,
{"to": "your_own@email.com", "subject": "Invoice — April 2026 — Acme", "body": "Hi Acme, please find April invoice."}
)
print(result.get("id", "sent"))def send_email(to: str, subject: str, body: str) -> dict:
result = toolset.execute_action(
action=Action.GMAIL_SEND_EMAIL,
params={'to': to, 'subject': subject, 'body': body}
)
return resultWhat is different in the response between draft_email and send_email? Both return a dict.
draft_email returns a draft ID in your Drafts folder. send_email returns a message ID in your Sent folder — and the recipient's inbox has the email. The shape is similar; the consequence is different. Check your Sent folder after Day 7 and you will see it there.
I ran draft_email four times before switching to send_email. Then the moment it showed up in my Sent folder I actually had to sit down.
That moment — "it is actually in my Sent folder" — is the point of no return. You have wired Python to your real email.
My six monthly invoice emails are now a for loop. The whole thing takes under a second.
One more rule for production: never call send_email twice with the same arguments without a deduplication check. GMAIL_SEND_EMAIL has no idempotency guard — calling it twice sends two identical emails.
GMAIL_SEND_EMAIL sends immediately — no draft step. Always send to yourself during development:
result = toolset.execute_action(
action=Action.GMAIL_SEND_EMAIL,
params={'to': 'you@example.com', 'subject': 'Test', 'body': 'Hello'}
)During testing, hardcode to='your@email.com' so automated sends go to your inbox, not a real client. Only replace with a dynamic address once the body content and timing have been verified in your own inbox.
draft_email vs send_email: drafts are reversible and reviewable; sends are immediate. Use draft_email for workflows you will review; use send_email for fully automated, scheduled workflows you trust.
draft_email from yesterday places emails in your Drafts folder safely. Today you cross the line — GMAIL_SEND_EMAIL delivers immediately. There is no undo. How do you test it without emailing six clients?
Send to myself first. Same function, same arguments, recipient is my own email. Then check Sent and Inbox to confirm it arrived correctly.
That is the safety pattern for every write action in this track. Tests always send to self. The function signature is identical to draft_email — to, subject, body — so once you have confirmed the output looks right on your own address, you swap the recipient to the client list:
result = toolset.execute_action(
Action.GMAIL_SEND_EMAIL,
{"to": "your_own@email.com", "subject": "Invoice — April 2026 — Acme", "body": "Hi Acme, please find April invoice."}
)
print(result.get("id", "sent"))def send_email(to: str, subject: str, body: str) -> dict:
result = toolset.execute_action(
action=Action.GMAIL_SEND_EMAIL,
params={'to': to, 'subject': subject, 'body': body}
)
return resultWhat is different in the response between draft_email and send_email? Both return a dict.
draft_email returns a draft ID in your Drafts folder. send_email returns a message ID in your Sent folder — and the recipient's inbox has the email. The shape is similar; the consequence is different. Check your Sent folder after Day 7 and you will see it there.
I ran draft_email four times before switching to send_email. Then the moment it showed up in my Sent folder I actually had to sit down.
That moment — "it is actually in my Sent folder" — is the point of no return. You have wired Python to your real email.
My six monthly invoice emails are now a for loop. The whole thing takes under a second.
One more rule for production: never call send_email twice with the same arguments without a deduplication check. GMAIL_SEND_EMAIL has no idempotency guard — calling it twice sends two identical emails.
GMAIL_SEND_EMAIL sends immediately — no draft step. Always send to yourself during development:
result = toolset.execute_action(
action=Action.GMAIL_SEND_EMAIL,
params={'to': 'you@example.com', 'subject': 'Test', 'body': 'Hello'}
)During testing, hardcode to='your@email.com' so automated sends go to your inbox, not a real client. Only replace with a dynamic address once the body content and timing have been verified in your own inbox.
draft_email vs send_email: drafts are reversible and reviewable; sends are immediate. Use draft_email for workflows you will review; use send_email for fully automated, scheduled workflows you trust.
Create a free account to get started. Paid plans unlock all tracks.