# Python Email SDK Reference

Source: https://wraps.dev/docs/python-sdk-reference

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.

## Installation

Copy for AI

pipuvpoetry

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.

## Quick Start

Copy for AI

example.py

```
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)
```

## Configuration

Copy for AI

client.py

```
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).

## Sending Emails

Copy for AI

send.py

```
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)
```

recipients.py

```
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>",)
```

tags.py

```
# 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)
```

## Attachments

Copy for AI

attachments.py

```
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()),    ],)
```

## Batch Sending

Copy for AI

batch.py

```
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)
```

## Templates

Copy for AI

templates.py

```
# 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")
```

send\_template.py

```
result = email.send_template(    template="welcome",    from_="hello@yourdomain.com",    to="user@example.com",    data={"name": "Sam"},)
```

## Suppression

Copy for AI

suppression.py

```
# 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")
```

## Error Handling

Copy for AI

errors.py

```
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)
```

## Fully Typed

Copy for AI

typed.py

```
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>",)
```

## Next Steps

TypeScript SDK

The Node/TypeScript email SDK, with React Email, inbound, and event tracking.

[Email SDK Reference](https://wraps.dev/docs/sdk-reference)

Domain Verification

Verify your sending domain with DKIM so mail authenticates at Gmail and Yahoo.

[Verify a Domain](https://wraps.dev/docs/guides/domain-verification)

### Need Help?

Found a bug or have a feature request? Open an issue on GitHub.

[Open an Issue](https://github.com/wraps-team/wraps-py/issues)
