Projects · · 4 min read
Adding Email Notifications to My Python Chatbot
I walk through how I added email notifications to a Python chatbot using Supabase Edge Functions, Gemini, and a few simple libraries.
When I searched for "how to add email notifications python chatbot" I realized that many small‑scale bots I build never tell users about important events unless they check the chat manually. Adding email alerts seemed like a practical next step, especially for reminders or status updates. In this post I describe the exact steps I took, the tools I used, and a few hiccups I ran into. If you’ve read my Supabase auth walkthrough you’ll already be familiar with the database layer, and the same patterns apply here. I also link to my JARVIS voice assistant for a quick look at how I handle external APIs.
how to add email notifications python chatbot
First I chose an email delivery service that offers a free tier and a simple HTTP API. I went with SendGrid because their Python SDK is lightweight and their free plan covers a few hundred emails per month – more than enough for my personal projects. I created a SendGrid API key, stored it securely in Supabase's secret manager, and made sure the key never appears in my repo.
Next I needed a place where the chatbot could trigger the email without exposing the API key to the client. Supabase Edge Functions are perfect for this: they run server‑side, can read secrets, and are deployed with a single command from VS Code. I added a new function called `send_email` and gave it the following responsibilities:
- Accept a JSON payload with `to`, `subject`, and `body` fields.
- Validate the payload to avoid spam or malformed requests.
- Call the SendGrid API using the stored secret.
- Return a success or error message back to the chatbot.
import os
import json
import httpx
SENDGRID_API_KEY = os.getenv('SENDGRID_API_KEY')
async def handler(request):
payload = await request.json()
to = payload.get('to')
subject = payload.get('subject')
body = payload.get('body')
if not all([to, subject, body]):
return json.dumps({'error': 'missing fields'}), 400
data = {
'personalizations': [{'to': [{'email': to}]}],
'from': {'email': 'no-reply@mychatbot.com'},
'subject': subject,
'content': [{'type': 'text/plain', 'value': body}]
}
headers = {'Authorization': f'Bearer {SENDGRID_API_KEY}', 'Content-Type': 'application/json'}
async with httpx.AsyncClient() as client:
resp = await client.post('https://api.sendgrid.com/v3/mail/send', json=data, headers=headers)
if resp.status_code == 202:
return json.dumps({'status': 'queued'}), 200
return json.dumps({'error': resp.text}), 500
Deploying the function is a one‑liner: `supabase functions deploy send_email`. Once live, the function URL looks like `https://<project>.supabase.co/functions/v1/send_email`. I added this URL to my chatbot’s config file so the bot can call it whenever it needs to notify a user.
Inside the chatbot code, I created a small helper that builds the payload and makes a POST request. I used the `httpx` library because it works well with async code and fits nicely with the Gemini‑powered response generation I already have.
import httpx
async def email_user(to_email, subject, body):
payload = {'to': to_email, 'subject': subject, 'body': body}
async with httpx.AsyncClient() as client:
resp = await client.post('https://<project>.supabase.co/functions/v1/send_email', json=payload)
if resp.status_code == 200:
print('Email queued')
else:
print('Failed to send email:', resp.text)
Now the bot can send an email after any meaningful interaction. For example, after a user asks the bot to remind them of a deadline, the bot stores the reminder in Supabase, and simultaneously calls `email_user` with a friendly message. The user receives an email even if they close the chat window.
Why email notifications matter for small bots
Most of my projects live in a single‑page UI, and users often forget to come back. Adding email gives a gentle nudge without forcing me to build a full‑blown notification system. It also lets me experiment with asynchronous workflows: the bot can fire‑and‑forget the email request, while the rest of the conversation continues unhindered. This pattern scales well when you later add SMS or push notifications – the same Edge Function can be extended to call other providers.
From a learning perspective, I got hands‑on experience with three new concepts: secure secret handling in Supabase, writing stateless Edge Functions, and integrating third‑party REST APIs from Python. All of these are skills I can reuse in future projects, such as building a newsletter service for my video‑editing tutorials.
What I struggled with (and how I fixed it)
The biggest hiccup was the CORS error when the chatbot tried to call the Edge Function directly from the browser. Supabase Edge Functions block cross‑origin requests by default. I solved it by adding the `Access-Control-Allow-Origin: *` header in the function response. In production you’d restrict the origin to your domain, but for a personal project a wildcard is fine.
Another minor issue was rate‑limiting on the free SendGrid tier. During testing I hit the limit because the bot was sending an email for every debug message. I added a simple flag `DEBUG_MODE` that disables the email call when I’m running unit tests. This kept my quota intact and reminded me to separate development and production settings.
Takeaway
Adding email notifications to a Python chatbot is surprisingly straightforward when you leverage Supabase Edge Functions and a free email API like SendGrid. You keep secrets safe, avoid exposing keys to the front end, and get a reusable serverless endpoint that can grow with your app. If you’re already using Supabase for storage or auth, adding an email function is the next natural step in making your bots more helpful and user‑friendly.
Feel free to explore the code on my GitHub, or check out more of my projects for inspiration. You can also browse my projects to see how I combine AI and simple web tools in other creations.
Frequently asked questions
Can I use a free email service with Supabase Edge Functions?
Yes. Services like SendGrid, Mailgun, or Amazon SES offer free tiers that work well with Supabase Edge Functions. Store the API key in Supabase secrets and call the provider’s HTTP endpoint from your function.
Do I need to expose my email API key to the client?
No. Keep the key in Supabase's secret manager and only access it inside an Edge Function. The client calls the function URL, which then forwards the request to the email provider securely.
What should I do if I get CORS errors when calling the function?
Add the appropriate CORS headers (`Access-Control-Allow-Origin`) to the response in your Edge Function. For production, limit the origin to your domain rather than using a wildcard.
Is it possible to send other types of notifications besides email?
Absolutely. Once you have an Edge Function that can call an external API, you can extend it to send SMS via Twilio, push notifications via Firebase, or even Slack messages. The same pattern of secret handling and async calls applies.