Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion python-send-email/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ description = "Source files supporting 'Sending Emails With Python' tutorial on
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"aiosmtpd>=1.4.6",
"aiosmtpd==1.4.6",
"proton-mail-bridge-client==1.0.1",
"ruff>=0.15.9",
"sendgrid==6.12.5",
"yagmail[all]==0.16.0",
]

[dependency-groups]
Expand Down
158 changes: 156 additions & 2 deletions python-send-email/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,164 @@
# This file was autogenerated by uv via the following command:
# uv pip compile pyproject.toml -o requirements.txt
# uv pip compile pyproject.toml -o requirements.txt --python-version 3.12
aiosmtpd==1.4.6
# via python-send-email (pyproject.toml)
annotated-types==0.8.0
# via pydantic
anyio==4.15.1
# via
# httpx2
# mcp
# sse-starlette
# starlette
atpublic==7.0.0
# via aiosmtpd
attrs==26.1.0
# via aiosmtpd
# via
# aiosmtpd
# jsonschema
# referencing
cachetools==7.2.0
# via premailer
certifi==2026.7.22
# via requests
cffi==2.1.1
# via cryptography
chardet==7.6.0
# via encutils
charset-normalizer==3.5.2
# via requests
click==8.5.0
# via uvicorn
cryptography==50.0.2
# via
# pyjwt
# secretstorage
# sendgrid
cssselect==1.5.0
# via premailer
cssutils==2.15.0
# via premailer
dkimpy==1.1.8
# via yagmail
dnspython==2.8.0
# via dkimpy
encutils==1.0.0
# via cssutils
h11==0.16.0
# via
# httpcore2
# uvicorn
httpcore2==2.13.1
# via httpx2
httpx2==2.13.1
# via mcp
idna==3.20
# via
# anyio
# httpx2
# requests
inscriptis==2.7.5
# via proton-mail-bridge-client
jaraco-classes==3.4.0
# via keyring
jaraco-context==6.1.2
# via keyring
jaraco-functools==4.6.0
# via keyring
jeepney==0.9.0
# via
# keyring
# secretstorage
jsonschema==4.26.0
# via mcp
jsonschema-specifications==2025.9.1
# via jsonschema
keyring==25.7.0
# via yagmail
lxml==6.1.3
# via
# inscriptis
# premailer
markupsafe==3.0.4
# via werkzeug
mcp==2.3.0
# via proton-mail-bridge-client
mcp-types==2.3.0
# via mcp
more-itertools==11.1.0
# via
# cssutils
# jaraco-classes
# jaraco-functools
opentelemetry-api==1.45.0
# via mcp
premailer==3.10.0
# via yagmail
proton-mail-bridge-client==1.0.1
# via python-send-email (pyproject.toml)
pycparser==3.0
# via cffi
pydantic==2.13.5
# via
# mcp
# mcp-types
pydantic-core==2.46.5
# via pydantic
pyjwt==2.15.1
# via mcp
python-http-client==3.3.7
# via sendgrid
python-multipart==0.0.32
# via mcp
referencing==0.37.0
# via
# jsonschema
# jsonschema-specifications
requests==2.34.2
# via
# inscriptis
# premailer
rpds-py==2026.6.3
# via
# jsonschema
# referencing
ruff==0.15.9
# via python-send-email (pyproject.toml)
secretstorage==3.5.0
# via keyring
sendgrid==6.12.5
# via python-send-email (pyproject.toml)
sse-starlette==3.5.0
# via mcp
starlette==1.7.0
# via
# mcp
# sse-starlette
truststore==0.10.4
# via
# httpcore2
# httpx2
typing-extensions==4.16.0
# via
# anyio
# httpx2
# mcp
# mcp-types
# opentelemetry-api
# pydantic
# pydantic-core
# referencing
# starlette
# typing-inspection
typing-inspection==0.4.4
# via
# mcp
# pydantic
urllib3==2.8.0
# via requests
uvicorn==0.54.0
# via mcp
werkzeug==3.1.9
# via sendgrid
yagmail==0.16.0
# via python-send-email (pyproject.toml)
18 changes: 18 additions & 0 deletions python-send-email/sendgrid_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import os
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail

message = Mail(
from_email="from_email@example.com",
to_emails="to@example.com",
subject="Sending with Twilio SendGrid is Fun",
html_content="<strong>and easy to do anywhere, even with Python</strong>",
)
try:
sg = SendGridAPIClient(os.environ.get("SENDGRID_API_KEY"))
response = sg.send(message)
print(response.status_code)
print(response.body)
print(response.headers)
except Exception as e:
print(str(e))
Loading
Loading