Last Updated on August 2, 2026 by ian
Sending transactional email from Python is something every developer needs to do — welcome emails, password resets, order confirmations, OTP codes. This guide shows you exactly how to do it using the ConvertNow Email API and Python’s built-in requests library.
No extra packages. No complex setup. A working email in under 5 minutes.
What you need
• Python 3.8 or above
• A free ConvertNow account — convertnow.co
• 5 minutes
Step 1: Get your API key
Sign up at convertnow.co, go to Email API in the left sidebar, click + New Key, give it a name, and copy the key. It looks like this:
cn_live_gb8Hdp7uXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Store it as an environment variable — never hardcode it:
export CONVERTNOW_API_KEY=cn_live_YOUR_KEY
Step 2: Send your first email
Python’s requests library handles the HTTP call. No SDK installation required.
import os
import requests
response = requests.post(
'https://api.convertnow.co/v1/email/send',
headers={
'Authorization': f'Bearer {os.environ["CONVERTNOW_API_KEY"]}',
'Content-Type': 'application/json',
},
json={
'to': '[email protected]',
'from': '[email protected]',
'subject': 'Hello from Python',
'html': '<h1>It works!</h1><p>Your first email from Python.</p>',
'text': 'It works! Your first email from Python.',
}
)
print(response.json())
# {'id': 'msg_abc123', 'status': 'sent', 'message': 'Email queued for delivery'}
Step 3: Build a reusable send function
For production use, wrap the call in a function with proper error handling:
import os
import requests
API_KEY = os.environ['CONVERTNOW_API_KEY']
BASE_URL = 'https://api.convertnow.co/v1/email/send'
def send_email(to, subject, html=None, text=None,
from_=None, cc=None, bcc=None,
reply_to=None, attachments=None, tags=None):
"""
Send a transactional email via ConvertNow.
:param to: str or list of str
:param subject: str
:param html: str (HTML body)
:param text: str (plain text fallback)
:param from_: str (optional, defaults to account sender)
:param tags: list of str (max 10, for analytics)
"""
payload = {'to': to, 'subject': subject}
if html: payload['html'] = html
if text: payload['text'] = text
if from_: payload['from'] = from_
if cc: payload['cc'] = cc
if bcc: payload['bcc'] = bcc
if reply_to: payload['reply_to'] = reply_to
if attachments: payload['attachments'] = attachments
if tags: payload['tags'] = tags
response = requests.post(
BASE_URL,
headers={'Authorization': f'Bearer {API_KEY}'},
json=payload
)
response.raise_for_status()
return response.json()
Step 4: Common transactional email patterns
Welcome email
send_email(
to=user_email,
subject=f'Welcome to MyApp, {user_name}!',
html=f'<h1>Hi {user_name}!</h1><p>Your account is ready.',
tags=['welcome', 'onboarding']
)
Password reset
send_email(
to=user_email,
subject='Reset your password',
html=f'<p>Click <a href="{reset_url}">here</a> to reset your password. Link expires in 1 hour.</p>',
tags=['password-reset']
)
Send to multiple recipients
send_email(
to=['[email protected]', '[email protected]'],
subject='Team update',
html='<p>Here is this week's update.</p>'
)
Send with an attachment
import base64
with open('invoice.pdf', 'rb') as f:
encoded = base64.b64encode(f.read()).decode()
send_email(
to='[email protected]',
subject='Your invoice',
html='<p>Please find your invoice attached.</p>',
attachments=[{
'filename': 'invoice.pdf',
'content': encoded,
'content_type': 'application/pdf',
}]
)
Step 5: Send via SMTP with smtplib
If you prefer SMTP over the HTTP API, ConvertNow works as a drop-in SMTP relay on port 465 with implicit SSL:
import smtplib
import ssl
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import os
SMTP_HOST = 'out.convertnow.co'
SMTP_PORT = 465
USERNAME = '[email protected]'
PASSWORD = os.environ['CONVERTNOW_API_KEY']
msg = MIMEMultipart('alternative')
msg['Subject'] = 'Hello via SMTP'
msg['From'] = USERNAME
msg['To'] = '[email protected]'
msg.attach(MIMEText('It works!', 'plain'))
msg.attach(MIMEText('<h1>It works!</h1>', 'html'))
context = ssl.create_default_context()
with smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT, context=context) as server:
server.login(USERNAME, PASSWORD)
server.send_message(msg)
print('Sent via SMTP')
Django: send email in 3 lines
If you’re using Django, configure ConvertNow as your email backend in settings.py and use Django’s built-in send_mail:
# settings.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'out.convertnow.co'
EMAIL_PORT = 465
EMAIL_USE_SSL = True
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = os.environ['CONVERTNOW_API_KEY']
DEFAULT_FROM_EMAIL = '[email protected]'
# views.py or anywhere in your app
from django.core.mail import send_mail
send_mail(
subject='Welcome to MyApp',
message='Thanks for signing up.',
from_email='[email protected]',
recipient_list=['[email protected]'],
html_message='<h1>Welcome!</h1><p>Thanks for signing up.</p>',
)
Flask: send email from a route
For Flask applications, use the HTTP API directly from your route handler:
import os
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/signup', methods=['POST'])
def signup():
data = request.json
email = data['email']
name = data['name']
# Create user in your database here...
# Send welcome email
requests.post(
'https://api.convertnow.co/v1/email/send',
headers={'Authorization': f'Bearer {os.environ["CONVERTNOW_API_KEY"]}'},
json={
'to': email,
'subject': f'Welcome, {name}!',
'html': f'<h1>Hi {name}!</h1><p>Your account is ready.</p>',
'tags': ['welcome']
}
)
return jsonify({'success': True})
Error handling
Always handle the case where email delivery fails:
try:
result = send_email(
to=user_email,
subject='Welcome',
html='<p>Welcome!</p>'
)
print('Sent:', result['id'])
except requests.exceptions.HTTPError as e:
error = e.response.json().get('error', 'Unknown error')
print('Email failed:', error)
# Log to your monitoring system
except requests.exceptions.ConnectionError:
print('Could not reach the email API — check your network')
Why ConvertNow instead of Amazon SES or SendGrid?
• No AWS account, no IAM setup, no sandbox approval process
• $99/year flat for 1 million emails/month – SES costs $1,200/year for the same volume
• Bounce handling, suppression management, and analytics included — no CloudWatch required
• Email marketing campaigns on the same account at no extra cost
Start sending for free — convertnow.co — no credit card required
Next steps
• Authenticate your sending domain (DKIM, SPF, DMARC) for better deliverability
• Set up webhooks to receive delivery and failure events in real time
• Manage your suppression list for GDPR-compliant unsubscribe handling

