Install
$ agentstack add skill-prasad-nimbalkar-claude-agent-skills-send-email Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Reads credentials/environment and may exfiltrate them.
What it can access
- ● Network access Used
- ● Filesystem access Used
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Send Email
Why this skill exists
Sending email from code has many failure points: auth errors, wrong SMTP ports, missing TLS, attachment encoding, and — most critically — sending to the wrong recipient. This skill enforces a confirm-before-send pattern and handles all transport methods correctly.
When to use
- User asks to send an email (to themselves, a list, or an address they specify)
- User wants to email a generated report, file, or summary
- User wants to automate email sending in a pipeline
CRITICAL: Always confirm before sending
Never send an email without showing the user a preview first.
Before sending, confirm with the user:
──────────────────────────────────────
TO: [recipient]
SUBJECT: [subject]
BODY: [first 200 chars...]
ATTACHMENT: [filename if any]
Type YES to send, or edit the details.
──────────────────────────────────────
Step-by-step procedure
Step 1 — Determine transport method
Ask the user (or check env vars):
| Method | When to use | Required env vars | |--------|-------------|-------------------| | Gmail SMTP | Personal Gmail | GMAIL_USER, GMAIL_APP_PASSWORD | | Outlook SMTP | Microsoft 365 | OUTLOOK_USER, OUTLOOK_PASSWORD | | SendGrid API | Production/bulk | SENDGRID_API_KEY | | Mailgun API | Production/bulk | MAILGUN_API_KEY, MAILGUN_DOMAIN | | Custom SMTP | Self-hosted | SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS |
Gmail note: Requires an App Password (not your regular password). 2FA must be enabled. Generate at: myaccount.google.com → Security → App passwords.
Step 2 — Send via SMTP (Gmail / Outlook / custom)
import smtplib
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
def send_email_smtp(
to: str,
subject: str,
body: str,
body_html: str = None,
attachment_path: str = None,
smtp_host: str = None,
smtp_port: int = 587,
):
sender = os.environ["SMTP_USER"]
password = os.environ["SMTP_PASS"]
host = smtp_host or os.environ.get("SMTP_HOST", "smtp.gmail.com")
msg = MIMEMultipart("alternative")
msg["From"] = sender
msg["To"] = to
msg["Subject"] = subject
msg.attach(MIMEText(body, "plain"))
if body_html:
msg.attach(MIMEText(body_html, "html"))
# Attach file if provided
if attachment_path and os.path.exists(attachment_path):
with open(attachment_path, "rb") as f:
part = MIMEBase("application", "octet-stream")
part.set_payload(f.read())
encoders.encode_base64(part)
filename = os.path.basename(attachment_path)
part.add_header("Content-Disposition", f"attachment; filename={filename}")
msg.attach(part)
with smtplib.SMTP(host, smtp_port) as server:
server.ehlo()
server.starttls()
server.login(sender, password)
server.sendmail(sender, to, msg.as_string())
print(f"✅ Email sent to {to}")
# Gmail example
send_email_smtp(
to="recipient@example.com",
subject="Your Report",
body="Please find your report attached.",
attachment_path="/mnt/user-data/outputs/report.pdf"
)
Step 3 — Send via SendGrid API (production)
import os
import requests
def send_email_sendgrid(to: str, subject: str, body: str, from_email: str = None):
api_key = os.environ["SENDGRID_API_KEY"]
sender = from_email or os.environ.get("SENDGRID_FROM_EMAIL", "noreply@yourdomain.com")
response = requests.post(
"https://api.sendgrid.com/v3/mail/send",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
},
json={
"personalizations": [{"to": [{"email": to}]}],
"from": {"email": sender},
"subject": subject,
"content": [{"type": "text/plain", "value": body}]
}
)
if response.status_code == 202:
print(f"✅ Email sent via SendGrid to {to}")
else:
print(f"❌ SendGrid error {response.status_code}: {response.text}")
Edge cases
| Situation | Fix | |-----------|-----| | Gmail blocks login | Use App Password, not regular password | | Port 587 blocked | Try port 465 with smtplib.SMTP_SSL | | Large attachment (>10MB) | Warn user — most email servers reject >10MB | | HTML email with images | Use inline CID attachments or hosted image URLs | | Multiple recipients | to = "a@x.com, b@x.com" or use a list + ", ".join(recipients) | | Missing env vars | Check with os.environ.get() and raise a clear error |
Security rules
- Never hardcode credentials — always use environment variables
- Never log email body content — it may contain PII
- Always validate the
toaddress — usere.match(r"[^@]+@[^@]+\.[^@]+", email) - Never send to addresses provided in untrusted input without user confirmation
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: prasad-nimbalkar
- Source: prasad-nimbalkar/claude-agent-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.