PageSourceSearch

https://sidemail.io/assets/C9U1WlFH.js

js sidemail.io collected 2026-09-25 20:14:00 UTC 9,047 bytes, 216 lines download raw bytes

1import{j as e}from"./DJx4IWN9.js";const t={title:"Send emails with FastAPI"};function s(r){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",...r.components};return e.jsxs(e.Fragment,{children:[e.jsx(n.h1,{children:"Send emails with FastAPI"}),`
2`,e.jsxs(n.p,{children:["In this quickstart, you'll learn how to send transactional emails from your ",e.jsx(n.a,{href:"https://fastapi.tiangolo.com/",children:"FastAPI"})," app with Sidemail. You'll set up the SDK, send your first email, and see examples for common use cases like welcome emails, password resets, and background tasks."]}),`
3`,e.jsx(n.h2,{children:"Before you start"}),`
4`,e.jsxs(n.ol,{children:[`
5`,e.jsxs(n.li,{children:[e.jsx(n.a,{href:"https://sidemail.io",children:"Create a Sidemail account"})," → get your API key"]}),`
6`,e.jsxs(n.li,{children:[e.jsx(n.a,{href:"/docs/sending-identities/",children:"Add a sending domain"})," → set up your domain for sending"]}),`
7`]}),`
8`,e.jsx(n.h2,{children:"1. Install"}),`
9`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-bash",children:`pip install sidemail
10`})}),`
11`,e.jsx(n.h2,{children:"2. Configure API key"}),`
12`,e.jsxs(n.p,{children:["Add your Sidemail API key to ",e.jsx(n.code,{children:".env"}),":"]}),`
13`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-bash",children:`SIDEMAIL_API_KEY=your-api-key
14`})}),`
15`,e.jsx(n.h2,{children:"3. Setup client"}),`
16`,e.jsx(n.p,{children:"Create a shared instance of the Sidemail client."}),`
17`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-python",children:`# services.py\r
18from sidemail import Sidemail\r
19import os\r
20\r
21# The SDK automatically reads SIDEMAIL_API_KEY from environment variables\r
22sidemail = Sidemail()
23`})}),`
24`,e.jsx(n.h2,{children:"4. Send a welcome email"}),`
25`,e.jsxs(n.p,{children:["Send an email when a user registers. We use a standard ",e.jsx(n.code,{children:"def"})," route so FastAPI runs the synchronous Sidemail SDK in a threadpool, preventing it from blocking the event loop."]}),`
26`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-python",children:`# main.py\r
27from fastapi import FastAPI\r
28from pydantic import BaseModel\r
29from .services import sidemail\r
30\r
31app = FastAPI()\r
32\r
33class User(BaseModel):\r
34    email: str\r
35    name: str\r
36\r
37@app.post("/register")\r
38def register(user: User):\r
39    # ... create user in database ...\r
40\r
41    sidemail.send_email(\r
42        toAddress=user.email,\r
43        fromAddress="[email protected]",\r
44        fromName="Your App",\r
45        templateName="Welcome",\r
46        templateProps={"firstName": user.name},\r
47    )\r
48\r
49    return {"message": "User registered"}
50`})}),`
51`,e.jsx(n.h2,{children:"5. Send a password reset email"}),`
52`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-python",children:`# main.py\r
53class PasswordResetRequest(BaseModel):\r
54    email: str\r
55\r
56@app.post("/forgot-password")\r
57def forgot_password(request: PasswordResetRequest):\r
58    token = "secure-reset-token" # Generate this securely\r
59\r
60    sidemail.send_email(\r
61        toAddress=request.email,\r
62        fromAddress="[email protected]",\r
63        fromName="Your App",\r
64        templateName="Password Reset",\r
65        templateProps={\r
66            "actionUrl": f"https://myapp.com/reset/{token}",\r
67        },\r
68    )\r
69\r
70    return {"message": "Reset email sent"}
71`})}),`
72`,e.jsx(n.h2,{children:"6. Send a weekly report"}),`
73`,e.jsx(n.p,{children:"You can create a standalone script for cron jobs."}),`
74`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-python",children:`# scripts/send_weekly_report.py\r
75from myapp.services import sidemail\r
76\r
77def main():\r
78    # In a real app, fetch this from your database\r
79    new_signups = 150\r
80    chart_data = [100, 200, 300, 400, 200, 300, 200, 500]\r
81\r
82    sidemail.send_email(\r
83        toAddress="[email protected]",\r
84        fromAddress="[email protected]",\r
85        fromName="My App",\r
86        templateName="Weekly Report",\r
87        templateProps={\r
88            "signups": new_signups,\r
89            "chart": chart_data,\r
90        },\r
91    )\r
92    print("Weekly report sent")\r
93\r
94if __name__ == "__main__":\r
95    main()
96`})}),`
97`,e.jsx(n.p,{children:"Run it via cron:"}),`
98`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-bash",children:`# Run every Monday at 8:00 AM\r
990 8 * * 1 python -m scripts.send_weekly_report
100`})}),`
101`,e.jsx(n.h2,{children:"7. Send email via Background Tasks"}),`
102`,e.jsxs(n.p,{children:["Decouple email sending from the response using FastAPI's ",e.jsx(n.code,{children:"BackgroundTasks"}),". This allows you to return a response immediately while the email sends in the background."]}),`
103`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-python",children:`# main.py\r
104from fastapi import BackgroundTasks\r
105\r
106def send_welcome_email_task(email: str, name: str):\r
107    sidemail.send_email(\r
108        toAddress=email,\r
109        fromAddress="[email protected]",\r
110        fromName="My App",\r
111        templateName="Welcome",\r
112        templateProps={"firstName": name},\r
113    )\r
114\r
115@app.post("/register-async")\r
116async def register_async(user: User, background_tasks: BackgroundTasks):\r
117    # ... create user in database ...\r
118\r
119    background_tasks.add_task(send_welcome_email_task, user.email, user.name)\r
120\r
121    return {"message": "User registered, email sending in background"}
122`})}),`
123`,e.jsx(n.h2,{children:"8. Send HTML email"}),`
124`,e.jsxs(n.p,{children:["Use ",e.jsx(n.code,{children:"jinja2"})," to generate HTML from templates."]}),`
125`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-python",children:`from fastapi.templating import Jinja2Templates\r
126\r
127templates = Jinja2Templates(directory="templates")\r
128\r
129@app.post("/send-invoice")\r
130def send_invoice(email: str):\r
131    # templates/invoice.html\r
132    template = templates.get_template("invoice.html")\r
133    html_content = template.render(amount=99)\r
134\r
135    sidemail.send_email(\r
136        toAddress=email,\r
137        fromAddress="[email protected]",\r
138        fromName="Your App",\r
139        subject="Your Invoice",\r
140        html=html_content,\r
141    )\r
142\r
143    return {"message": "Invoice sent"}
144`})}),`
145`,e.jsx(n.h2,{children:"9. Send Markdown email"}),`
146`,e.jsxs(n.p,{children:["Store your markdown content in a file and load it (",e.jsx(n.a,{href:"https://sidemail.io/docs/markdown-emails/",children:"learn more"}),")."]}),`
147`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-python",children:`def send_markdown():\r
148    with open("templates/emails/welcome.md", "r") as f:\r
149        markdown_content = f.read()\r
150\r
151    # Subject and sender are defined in the markdown frontmatter\r
152    sidemail.send_email(\r
153        toAddress="[email protected]",\r
154        markdown=markdown_content,\r
155        templateProps={\r
156            "name": "John",\r
157            "link": "https://example.com",\r
158        },\r
159    )
160`})}),`
161`,e.jsx(n.h2,{children:"10. Send plain text email"}),`
162`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-python",children:`sidemail.send_email(\r
163    toAddress="[email protected]",\r
164    fromAddress="[email protected]",\r
165    fromName="Your App",\r
166    subject="Hello",\r
167    text="Hello! 👋",\r
168)
169`})}),`
170`,e.jsx(n.h2,{children:"11. Schedule email"}),`
171`,e.jsxs(n.p,{children:["Send email later. Set ",e.jsx(n.code,{children:"scheduledAt"})," to an ISO date string in the future, no more than 30 days from now."]}),`
172`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-python",children:`import datetime\r
173\r
174# Schedule for 1 hour from now\r
175scheduled_at = (datetime.datetime.utcnow() + datetime.timedelta(hours=1)).isoformat() + "Z"\r
176\r
177sidemail.send_email(\r
178    toAddress="[email protected]",\r
179    fromAddress="[email protected]",\r
180    fromName="Your App",\r
181    templateName="Welcome",\r
182    templateProps={"firstName": "Alex"},\r
183    scheduledAt=scheduled_at,\r
184)
185`})}),`
186`,e.jsx(n.h2,{children:"12. Send with attachment"}),`
187`,e.jsxs(n.p,{children:["Use the ",e.jsx(n.code,{children:"Sidemail.file_to_attachment"})," helper to attach files."]}),`
188`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-python",children:`from sidemail import Sidemail\r
189\r
190with open("invoice.pdf", "rb") as f:\r
191    pdf_data = f.read()\r
192\r
193attachment = Sidemail.file_to_attachment("invoice.pdf", pdf_data)\r
194\r
195sidemail.send_email(\r
196    toAddress="[email protected]",\r
197    fromAddress="[email protected]",\r
198    fromName="Your App",\r
199    subject="Your invoice",\r
200    text="See attached.",\r
201    attachments=[attachment],\r
202)
203`})}),`
204`,e.jsx(n.h2,{children:"13. Handle errors"}),`
205`,e.jsx(n.pre,{children:e.jsx(n.code,{className:"language-python",children:`from sidemail import SidemailError\r
206import logging\r
207\r
208logger = logging.getLogger(__name__)\r
209\r
210try:\r
211    sidemail.send_email(\r
212        # ...\r
213    )\r
214except SidemailError as e:\r
215    logger.error(f"Sidemail error: {e.message}")
216`})})]})}function i(r={}){const{wrapper:n}=r.components||{};return n?e.jsx(n,{...r,children:e.jsx(s,{...r})}):s(r)}export{i as default,t as meta};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.