Python Email SDK Reference
Complete reference for the wraps-email Python SDK — send email via AWS SES from Python.
Send email through your Wraps-deployed AWS SES infrastructure from Python. Typed, lightweight (built on httpx and botocore signing — no boto3), with a simple synchronous API.
pip install wraps-email
Requires Python 3.10+
The distribution is wraps-email; import it as wraps.email. Use from_ for the sender — from is a Python keyword.
from wraps.email import WrapsEmailemail = WrapsEmail()result = email.send( from_="hello@yourdomain.com", to="user@example.com", subject="Welcome!", html="<h1>Hello!</h1>",)print("Message ID:", result.message_id)from wraps.email import WrapsEmail# Default AWS credential chain (env vars, shared config, SSO, OIDC, IMDS)email = WrapsEmail()# Explicit region + static credentialsemail = WrapsEmail( region="us-west-2", credentials={ "access_key_id": "...", "secret_access_key": "...", "session_token": "...", # optional },)# Named AWS profileemail = WrapsEmail(profile="my-profile")# Assume an IAM role (OIDC / cross-account)email = WrapsEmail(role_arn="arn:aws:iam::123456789012:role/MyRole")Credentials resolve in this order: explicit credentials → role_arn → profile → the default AWS chain (env vars, shared config, SSO, OIDC, IMDS).
result = email.send( from_="hello@yourdomain.com", to="user@example.com", subject="Welcome to our app", html="<h1>Welcome!</h1><p>Thanks for signing up.</p>", text="Welcome! Thanks for signing up.",)print("Message ID:", result.message_id)print("Request ID:", result.request_id)result = email.send( from_="newsletter@yourdomain.com", to=["user1@example.com", "user2@example.com"], cc="manager@yourdomain.com", bcc=["archive@yourdomain.com"], reply_to="support@yourdomain.com", subject="Weekly Newsletter", html="<h1>This week's updates</h1>",)# Add SES tags for tracking and analyticsemail.send( from_="you@yourdomain.com", to="user@example.com", subject="Newsletter", html="<p>Content</p>", tags={"campaign": "newsletter-2026-07", "type": "marketing"}, configuration_set_name="wraps-email-tracking", # optional)from wraps.email import Attachmentresult = email.send( from_="hello@yourdomain.com", to="user@example.com", subject="Your report", html="<p>See attached.</p>", attachments=[ Attachment( filename="report.csv", content="date,sends\n2026-07-13,42\n", content_type="text/csv", ), # Binary content works too — pass raw bytes: Attachment(filename="logo.png", content=open("logo.png", "rb").read()), ],)result = email.send_batch( [ {"from_": "you@x.com", "to": "a@y.com", "subject": "Hi", "text": "1"}, {"from_": "you@x.com", "to": "b@y.com", "subject": "Hi", "text": "2"}, ], max_concurrency=10,)print(result.success_count, result.failure_count)# Results are aligned to input orderfor entry in result.results: if not entry.success: print(entry.index, entry.error_code, entry.error)# Create a stored template — rendered server-side by SES at send timeemail.templates.create( name="welcome", subject="Hi {{name}}", html="<h1>Welcome, {{name}}!</h1>", text="Welcome, {{name}}!",)email.templates.get("welcome") # -> Templateemail.templates.list(page_size=20) # -> .templates, .next_tokenemail.templates.update( name="welcome", subject="Hey {{name}}", html="<h1>{{name}}</h1>")email.templates.delete("welcome")result = email.send_template( template="welcome", from_="hello@yourdomain.com", to="user@example.com", data={"name": "Sam"},)# Account-level SES suppression list (bounces + complaints)email.suppression.add("bad@example.com", "COMPLAINT")email.suppression.get("bad@example.com") # -> SuppressionEntry | Noneemail.suppression.list(reason="BOUNCE") # -> .entries, .next_tokenemail.suppression.remove("bad@example.com")from wraps.email import CredentialsError, SESError, ValidationErrortry: email.send( from_="you@x.com", to="user@y.com", subject="Hi", html="<p>Hi</p>" )except ValidationError as err: print("Invalid input:", err, err.field) # caught before any AWS callexcept CredentialsError: print("No AWS credentials found")except SESError as err: print(err.code, err.request_id, err.retryable, err.status)from wraps.email import SendEmailResult, WrapsEmailemail = WrapsEmail()# Explicit signatures + a PEP 561 py.typed marker mean mypy / ty / Pyright# check your calls, and editors autocomplete every argument.result: SendEmailResult = email.send( from_="you@yourdomain.com", to="user@example.com", subject="Typed", html="<p>Autocomplete + static checks</p>",)The Node/TypeScript email SDK, with React Email, inbound, and event tracking.
Email SDK ReferenceVerify your sending domain with DKIM so mail authenticates at Gmail and Yahoo.
Verify a Domain