Tutorial•3 min read

Sending Transactional Email from Python with httpx and Piisend

Learn how to send transactional emails efficiently from your Python applications using the httpx library and Piisend's robust email API. This guide covers basic sends, error handling, idempotency, and leveraging email templates for developers.

Sending Transactional Email from Python with httpx and Piisend

Section 1

Getting Started: Sending Your First Email with httpx and Piisend

Sending transactional emails from Python is straightforward with Piisend's REST API and the httpx library. httpx is a modern, async-first HTTP client for Python, offering a familiar API similar to requests but with added async capabilities. To begin, ensure you have httpx installed (pip install httpx) and your Piisend API key ready. This example demonstrates a basic email send.

python
1import httpx
2import os
3
4PIISEND_API_KEY = os.getenv("PIISEND_API_KEY")
5API_URL = "https://api.piisend.com/api/v1/emails"
6
7def send_simple_email():
8 headers = {
9 "Authorization": f"Bearer {PIISEND_API_KEY}",
10 "Content-Type": "application/json"
11 }
12 payload = {
13 "to": ["recipient@example.com"],
14 "subject": "Your First Piisend Email",
15 "html": "<p>Hello from <strong>Piisend</strong> and <i>httpx</i>!</p>",
16 "text": "Hello from Piisend and httpx!"
17 }
18
19 try:
20 response = httpx.post(API_URL, headers=headers, json=payload)
21 response.raise_for_status() # Raises HTTPStatusError for bad responses (4xx or 5xx)
22 print(f"Email sent successfully: {response.json()}")
23 except httpx.HTTPStatusError as e:
24 print(f"HTTP error occurred: {e.response.status_code} - {e.response.text}")
25 except httpx.RequestError as e:
26 print(f"An error occurred while requesting: {e}")
27
28if __name__ == "__main__":
29 send_simple_email()

Section 2

Handling API Responses and Errors Gracefully

Robust applications must handle API responses and potential errors effectively. Piisend's API returns clear JSON responses for both success and failure. When an email is successfully queued, you'll receive a 200 OK status with a message and a unique email_id. In case of errors, such as invalid API keys or malformed requests, Piisend will return an appropriate HTTP status code (e.g., 400 Bad Request, 401 Unauthorized) along with a JSON body detailing the error. Always check the response status and parse the JSON body for detailed feedback.

json
1{
2 "message": "Email queued successfully",
3 "email_id": "eml_xxxxxxxxxxxxxxxx"
4}

Section 3

Ensuring Idempotency for Reliable Email Sends

Idempotency is crucial for transactional systems, preventing duplicate actions if an API request is retried due to network issues or client-side errors. Piisend supports idempotency using the Idempotency-Key header. By providing a unique, client-generated key with each request, you ensure that even if the same request is sent multiple times, the email is only processed and sent once. This is particularly useful for critical emails like order confirmations or password resets.

python
1import httpx
2import os
3import uuid
4
5PIISEND_API_KEY = os.getenv("PIISEND_API_KEY")
6API_URL = "https://api.piisend.com/api/v1/emails"
7
8def send_idempotent_email(recipient_email, order_id):
9 idempotency_key = f"order-confirmation-{order_id}"
10
11 headers = {
12 "Authorization": f"Bearer {PIISEND_API_KEY}",
13 "Content-Type": "application/json",
14 "Idempotency-Key": idempotency_key
15 }
16 payload = {
17 "to": [recipient_email],
18 "subject": f"Order {order_id} Confirmation",
19 "html": f"<p>Thank you for your order <b>#{order_id}</b>!</p>",
20 "text": f"Thank you for your order #{order_id}!"
21 }
22
23 try:
24 response = httpx.post(API_URL, headers=headers, json=payload)
25 response.raise_for_status()
26 print(f"Idempotent email sent/processed: {response.json()}")
27 except httpx.HTTPStatusError as e:
28 print(f"HTTP error occurred: {e.response.status_code} - {e.response.text}")
29 except httpx.RequestError as e:
30 print(f"An error occurred while requesting: {e}")
31
32if __name__ == "__main__":
33 # Example usage with a unique order ID
34 send_idempotent_email("customer@example.com", "ORD-" + str(uuid.uuid4())[:8])

Section 4

Leveraging Email Templates with Merge Variables

For consistent branding and dynamic content, Piisend's email templates are invaluable. You can design your email layouts within the Piisend dashboard and then populate them with personalized data using template_vars. This approach separates content from presentation, making your email sending logic cleaner and easier to manage. Simply provide the template_id and a dictionary of template_vars in your API request, and Piisend will handle the merging.

python
1import httpx
2import os
3
4PIISEND_API_KEY = os.getenv("PIISEND_API_KEY")
5API_URL = "https://api.piisend.com/api/v1/emails"
6
7def send_templated_email(recipient_email, user_name, product_name):
8 # Replace 'YOUR_TEMPLATE_ID' with an actual template ID from your Piisend account
9 template_id = "tpl_xxxxxxxxxxxxxxxx"
10
11 headers = {
12 "Authorization": f"Bearer {PIISEND_API_KEY}",
13 "Content-Type": "application/json"
14 }
15 payload = {
16 "to": [recipient_email],
17 "template_id": template_id,
18 "template_vars": {
19 "user_name": user_name,
20 "product_name": product_name,
21 "support_email": "support@yourcompany.com"
22 }
23 }
24
25 try:
26 response = httpx.post(API_URL, headers=headers, json=payload)
27 response.raise_for_status()
28 print(f"Templated email queued successfully: {response.json()}")
29 except httpx.HTTPStatusError as e:
30 print(f"HTTP error occurred: {e.response.status_code} - {e.response.text}")
31 except httpx.RequestError as e:
32 print(f"An error occurred while requesting: {e}")
33
34if __name__ == "__main__":
35 send_templated_email("jane.doe@example.com", "Jane Doe", "Premium Widget")

Start sending

Ship transactional email in minutes

Create an API key, verify a domain, and send your first message with Piisend.