Wie man E-Mail über API senden in Python (Schnell-Tutorial)
Überspringen Sie den SMTP-Boilerplate-Code. Diese Anleitung zeigt Ihnen, wie Sie Unipile einheitliche E-Mail-API E-Mails in Python senden - mit Copy-Paste-Beispielen für Gmail, Outlook und IMAP mit dem Anfragen Bibliothek.
import Anfragen, Betriebssystem
API-Schlüssel = os.environ['UNIPILE_API_SCHLÜSSEL']
DSN = os.environ['UNIPILE_DSN']
KONTO_ID = os.environ['UNIPILE_KONTO_ID']
response = requests.Beitrag(
f'{DSN}/api/v1/emails',
Kopfzeilen={'X-API-KEY': API-Schlüssel},
daten={
'Konto-ID': KONTO_ID,
'zu': '[{"display_name":"Alice","identifier":"alice@acme.com"}]',
'Betreff': 'Hallo von Python',
'Körper': 'Gesendet über Unipile!
'
}
)
print(Antwort.json())5-Zeilen-Python-Beispiel
Wenn du es bereits weißt Was ist eine E-Mail-Send-API und möchte nur den Python-Code für die E-Mail-API, der tatsächlich funktioniert, hier ist er. Das vollständige Tutorial folgt unten.
pip install requests python-dotenvUNIPILE_DSN, UNIPILE_API_KEYund UNIPILE_KONTO_ID zu dir .env Datei./api/v1/emailsaccount_id, zu, Themaund Körper. Erledigt.import Anfragen, Betriebssystem
from dotenv import laden_dotenv
laden_dotenv()
API-Schlüssel = os.environ['UNIPILE_API_SCHLÜSSEL']
DSN = os.environ['UNIPILE_DSN']
KONTO_ID = os.environ['UNIPILE_KONTO_ID']
resp = Anfragen.Beitrag(
f'{DSN}/api/v1/emails',
Kopfzeilen={'X-API-KEY': API-Schlüssel},
daten={
'Konto-ID': KONTO_ID,
'zu': '[{"display_name":"Alice","identifier":"alice@acme.com"}]',
'Betreff': 'Hallo von Python',
'Körper': 'Gesendet über Unipile!
'
}
)
printbzw.json()) # {'tracking_id': 'msg_...'}Voraussetzungen & Einrichtung
Bevor Sie den Python-Workflow der E-Mail-API in der Produktion verwenden können, benötigen Sie vier Dinge: Python 3.9+, die Anfragen Bibliothek, ein API-Schlüssel mit DSN und ein verknüpftes E-Mail-Konto.
| Union-Typen und Standardbibliothek-Funktionen ab 3.9+. Python 3.11 LTS wird für die Produktion empfohlen. Überprüfen Sie Ihre Version mit python --version.api4.unipile.com:13444). Beide sind in jedem Anfrage-Header erforderlich.python -m venv .venv && source .venv/bin/activate. Installieren Sie niemals Pakete in der System-Python – dies ist besonders wichtig für die Handhabung von Anmeldedaten.pip install requests python-dotenv
# Optional: Asynchroner Support
pip install aiohttp httpx
# Optionale: Wiederholungslogik
pip install tenacitypipenv install requests python-dotenv tenacitypoetry add requests python-dotenv tenacity# Unipile-Anmeldeinformationen – diese Datei niemals einchecken
UNIPILE_DSN=https://api4.unipile.com:13444
UNIPILE_API_KEY=dein_zugangstoken_hier
# Die Konto-ID des verknüpften E-Mail-Kontos
UNIPILE_KONTO_ID=acc_xxxxxxxxxxxxxxxxHinzufügen .env zu dir .gitignore. Laden mit python-dotenv über load_dotenv() Am Anfang Ihres Skripts. In der Produktion sollten Sie bevorzugt tatsächliche Umgebungsvariablen verwenden, die von Ihrer Bereitstellungsplattform (Heroku, Railway, Docker Compose) injiziert werden.
Einrichten Ihres ersten E-Mail-Kontos
Bevor Sie senden können, müssen Sie ein E-Mail-Konto mit Unipile verknüpfen. Dies ist ein einmaliger Schritt pro Konto. Sehen Sie sich die vollständige einheitlicher E-Mail-API-Integrationsleitfaden für weitere Informationen zu Mehrkonten-Flüssen.
Unipile verwendet einen gehosteten Auth-Assistenten – Ihr Python-Skript generiert einen Auth-Link, der Benutzer klickt darauf und schließt OAuth im Browser ab, dann ruft Unipile Ihren Webhook mit dem neuen account_id. Keine SMTP-Anmeldeinformationen für Gmail oder Outlook werden in Ihrem Code gespeichert.
import Anfragen, Betriebssystem
from dotenv import laden_dotenv
laden_dotenv()
API-Schlüssel = os.environ['UNIPILE_API_SCHLÜSSEL']
DSN = os.environ['UNIPILE_DSN']
# Schritt 1: Erstellen Sie einen gehosteten Authentifizierungslink für Gmail OAuth
resp = Anfragen.Beitrag(
f'{DSN}/api/v1/hosted/accounts/link',
Kopfzeilen={'X-API-KEY': API-Schlüssel},
daten={
'Typ': 'GOOGLE',
'Name': 'Alice Gmail',
'erfolgreicher_pfad': '`https://yourapp.com/oauth/success`',
'Fehlgeschlagene_URL': 'https://yourapp.com/oauth/fehler'
}
)
# Schritt 2: Senden Sie diese URL an Ihren Benutzer
auth_url = resp.json()['URL']
print(Leiten Sie den Benutzer weiter an: {auth_url}')
# Schritt 3: Unipile POSTet {account_id} nach OAuth an Ihren Webhook
# Siehe /gmail-api-send-email-a-comprehensive-guide-for-developers/ für Gmail-Detailsimport Anfragen, Betriebssystem
from dotenv import laden_dotenv
laden_dotenv()
# Outlook OAuth - deckt privates Outlook + Microsoft 365 ab
# Siehe /microsoft-graph-api-email-integration-guide/
resp = Anfragen.Beitrag(
f'{os.environ["UNIPILE_DSN"]}/api/v1/hosted/accounts/link',
Kopfzeilen={'X-API-KEY'os.environ['UNIPILE_API_SCHLÜSSEL']},
daten={
'Typ': 'MICROSOFT',
'Name': 'Bob Outlook',
'erfolgreicher_pfad': '`https://yourapp.com/oauth/success`',
'Fehlgeschlagene_URL': 'https://yourapp.com/oauth/fehler'
}
)
printbzw.json()['URL'])import requests, os, json
# IMAP: IMAP-Anmeldedaten direkt übergeben (keine OAuth-Weiterleitung erforderlich)
# Siehe /the-developers-guide-to-imap-api-solution/ für vollständige IMAP-Details
resp = Anfragen.Beitrag(
f'{os.environ["UNIPILE_DSN"]}/api/v1/konten',
Kopfzeilen={'X-API-KEY'os.environ['UNIPILE_API_SCHLÜSSEL']},
json={
'Anbieter': 'IMAP',
'Benutzername': 'alice@company.com',
'Passwort': 'app_password_hier',
'imap_host': 'imap.company.com',
'smtp_host': 'smtp.company.com'
}
)
account_id = resp.json()['Konto-ID']
print(Verknüpfter Account: {account_id}')Ihre erste E-Mail von Python senden
Der Send-Endpunkt akzeptiert multipart/form-data. Benutzen Daten= nicht json=) in requests.post(). Der zu, ccund BCC Die Felder sind als JSON kodierte Strings im Formulardaten.
import requests, os, json
Anfragen.Beitrag(
f'{os.environ["UNIPILE_DSN"]}/api/v1/emails',
Kopfzeilen={'X-API-KEY'os.environ['UNIPILE_API_SCHLÜSSEL']},
daten={
'Konto-ID'os.environ['UNIPILE_KONTO_ID'],
'zu': json.Müll([{'Anzeigename': 'Alice', 'Bezeichner': 'alice@acme.com'}]),
'Betreff': 'Kurzes Update',
'Körper': 'Hallo Alice, ich melde mich nur kurz.'
}
)Körper Feld akzeptiert sowohl reinen Text als auch HTML. Verwenden Sie Tags für HTML-Formatierung.import requests, os, json
response = requests.Beitrag(
f'{os.environ["UNIPILE_DSN"]}/api/v1/emails',
Kopfzeilen={'X-API-KEY'os.environ['UNIPILE_API_SCHLÜSSEL']},
daten={
'Konto-ID'os.environ['UNIPILE_KONTO_ID'],
'zu'json.Müll([{'Bezeichner': 'alice@acme.com'}]),
'cc'json.Müll([{'Bezeichner': 'manager@acme.com'}]),
'BCC': json.Müll([{'Bezeichner': 'crm@yourapp.com'}]),
'Betreff': 'Ihre Rechnung ist fertig',
'Körper': 'Rechnung #1042
Bitte finden Sie Ihre Rechnung beigefügt.
'
}
)
# 202 Akzeptiert = in Zustellung
print(response.status_code, response.json())import requests, os, json
def E-Mail sendenan_email: Str, Betreff: Str, Körper: Str) -> Wörterbuch:
"E-Mail über die Python-Wrapper der Unipile E-Mail-API senden."
response = requests.Beitrag(
f'{os.environ["UNIPILE_DSN"]}/api/v1/emails',
Kopfzeilen={'X-API-KEY'os.environ['UNIPILE_API_SCHLÜSSEL']},
daten={
'Konto-ID'os.environ['UNIPILE_KONTO_ID'],
'zu'JSON.Müll([{'Bezeichner': to_email}]),
'Betreff'Betreff:,
'Körper': Körper,
},
timeout=30
)
Antwort.raise_for_status() # löst HTTPError bei 4xx/5xx aus
return Antwort.json() # {'tracking_id': 'msg_...'}timeout=30 um endlose Wartezeiten bei Netzwerkproblemen zu vermeiden. Verwenden Sie raise_for_status() HTTP-Fehler als Python-Exceptions weitergeben.Holen Sie sich Ihren API-Schlüssel, verknüpfen Sie in wenigen Minuten ein Gmail- oder Outlook-Konto und führen Sie die Python-Beispiele aus diesem Leitfaden anhand echter Postfächer aus.
Anhänge senden in Python
Anhänge werden im Rahmen von Multipart-Formulardaten mit Pythons gesendet Dateien= Parameter. Öffne die Datei im Binärmodus ('RB') - Bytes, keine Zeichenketten.
import requests, os, json
# Einzelne Dateianlage
mit öffnen('Rechnung.pdf', 'RB') als w
resp = Anfragen.Beitrag(
f'{os.environ["UNIPILE_DSN"]}/api/v1/emails',
Kopfzeilen={'X-API-KEY'os.environ['UNIPILE_API_SCHLÜSSEL']},
daten={
'Konto-ID'os.environ['UNIPILE_KONTO_ID'],
'zu': json.Müll([{'Bezeichner': 'client@example.com'}]),
'Betreff': 'Rechnung angehängt',
'Körper': 'Bitte sehen Sie sich die angehängte Rechnung an.
'
},
Dateien={'Anhänge': ('Rechnung.pdf', w, 'Anwendung/pdf')}
)
# Mehrere Anhänge: eine Liste von Tupeln übergeben
# Dateien=[('Anhänge', ('a.pdf', f1, 'application/pdf')),
# ('Anhänge', ('b.png', f2, 'image/png'))]open('file.pdf', 'rb'), nicht 'r'. Übergabe eines Textdateiobjekts an Dateien= hebt sich TypeError. Dies ist eine häufige Besonderheit, die nur Python-spezifisch ist, wenn man von smtplib migriert.Dateien=jedes Tupel ist ('Anhänge', (Dateiname, Dateiobjekt, Inhaltstyp)). Requests behandelt die Multipart-Grenze automatisch.BytesIO Objekt direkt: from io import BytesIO; buf = BytesIO(pdf_bytes) dann ('Bericht.pdf', buf, 'application/pdf').Antworten, Threads & Nachverfolgung
Für E-Mails im Namen eines Benutzers senden, Threading, und Webhook-basierte Zustellverfolgung, hier sind die Python-Muster, die Sie benötigen.
01Threading mit in_reply_to
Um innerhalb eines bestehenden Threads zu antworten, übergeben Sie antworten_an Feld mit dem Sendungs-ID der E-Mail, auf die Sie antworten möchten. Unipile kümmert sich um die Referenzen und Antwort auf Kopfzeilen automatisch.
Anfragen.Beitrag(
f'{DSN}/api/v1/emails',
Kopfzeilen={'X-API-KEY': API-Schlüssel},
daten={
'Konto-ID': KONTO_ID,
'zu': json.Müll([{'Bezeichner': 'alice@acme.com'}]),
'Betreff': 'Betreff: Ihre Frage',
'Körper': 'Als Nachfassung zu Ihrer Nachricht.
',
'antwort_auf': 'ursprüngliche_Sendungsverfolgungs_ID'
}
)02Webhooks in Python (Flask Beispiel)
Registrieren Sie eine Webhook-URL in Ihrem Unipile-Dashboard, um Zustellungsereignisse (gesendet, zurückgewiesen, geöffnet) zu empfangen. Hier ist ein minimaler Flask-Empfänger:
from Flasche import Flask, Anfrage, jsonify
import Protokollierung
app Flasche(__name__)
Protokollierung.Grundkonfiguration(level=logging.INFO)
@app.Route('/webhook/email', Methoden=['POST'])
def E-Mail-Webhook():
Ereignis = Anfrage.get_json()
event_typ = ereignis.bekommen.('Typ')
tracking_id = event.bekommen.('tracking_id')
Protokollierung.Informationen(f'E-Mail-Ereignis: {event_type} für {tracking_id}')
return in JSON umwandelnOK=Wahr), 20003Idempotenzschlüssel
Um doppelte Übertragungen bei Netzwerk-Wiederholungen zu verhindern, übergeben Sie eine eindeutige Idempotenzschlüssel Header. Wenn derselbe Schlüssel zweimal gesendet wird, gibt Unipile die ursprüngliche Antwort zurück, ohne eine zweite E-Mail zu senden.
import uuid, anfragen, os, json
Schlüssel = Str(uuid.uuid4()) # einmal generieren, in DB speichern
Anfragen.Beitrag(
f'{os.environ["UNIPILE_DSN"]}/api/v1/emails',
Kopfzeilen={
'X-API-KEY'os.environ['UNIPILE_API_SCHLÜSSEL'],
'Idempotenz-Schlüssel'Schlüssel
},
daten={'Konto-ID'os.environ['UNIPILE_KONTO_ID'],
'zu': json.Müll([{'Bezeichner': 'alice@acme.com'}]),
'Betreff': 'Willkommen!', 'Körper': 'Hallo!'}
)Fehlerbehandlung & Wiederholungsversuche
Produktions-Python-Code für die E-Mail-API benötigt eine ordnungsgemäße Fehlerbehandlung, strukturiertes Logging und automatische Wiederholungsversuche mit exponentiellem Backoff unter Verwendung des Hartnäckigkeit Bibliothek.
| HTTP-Code | Bedeutung | Aktion |
|---|---|---|
| 202 | Akzeptiert - in der Warteschlange für die Lieferung | tracking_id speichern |
| 400 | Ungültige Anfrage (ungültige Felder) | Payload reparieren, nicht erneut versuchen |
| 401 | Ungültiger API-Schlüssel | Überprüfen Sie UNIPILE_API_KEY |
| 403 | Konto nicht autorisiert | Konto neu verknüpfen |
| 404 | Konto-ID nicht gefunden | UNIPILE_ACCOUNT_ID prüfen |
| 429 | Rate begrenzt | Backoff + Wiederholung (siehe Code) |
| 500 | Serverfehler | Wiederholen Sie den Vorgang nach 5 Sekunden Verzögerung |
import requests, os, json, logging
from Hartnäckigkeit import (
wiederholen, stoppen_nach_versuch,
warte_exponentiell, wiederhole_bei_Ausnahmetyp
)
Protokollierung.Grundkonfiguration(level=logging.INFO)
logger = logging.getLogger(__name__)
Klasse RateLimitError(Ausnahme):
Pass
@Erneut versuchen(
stoppen=nach_dem_versuch_stoppen(4),
warteexponential_warten(Multiplikator=1, Minimum=2, Maximum=30),
Erneut versuchen=wiederholen_bei_Ausnahmeart(RateLimitError)
)
def mit_wiederholung_senden(an: Str, Betreff: Str, Körper: Str) -> Wörterbuch:
resp = Anfragen.Beitrag(
f'{os.environ["UNIPILE_DSN"]}/api/v1/emails',
Kopfzeilen={'X-API-KEY'os.environ['UNIPILE_API_SCHLÜSSEL']},
daten={
'Konto-ID'os.environ['UNIPILE_KONTO_ID'],
'zu'JSON.Müll([{'Bezeichner': zu}]),
'Betreff'Betreff:, 'Körper'Körper
},
timeout=30
)
wenn resp.status_code == 429:
Protokollierer.Warnung('Limit erreicht, verlangsame...')
erhöhen RateLimitError()
bzw.raise_for_status()
return bzw.json()Sicherheitspraktiken in Python
Für eine vollständige Anleitung zum Schutz Ihrer E-Mail-API-Integration siehe E-Mail-API-Sicherheitsleitfaden. Hier sind die Python-spezifischen Grundlagen.
os.environ oder python-dotenv. Niemals legen UNIPILE_API_KEY als Zeichenkette in Ihrem Quellcode. Wenn der Schlüssel versehentlich in Git hochgeladen wird, drehen Sie ihn sofort über Ihr Dashboard.venv oder conda. Dies verhindert Abhängigkeitsverwirrungsangriffe und macht Ihr Anforderungen.txt prüfbar. Versionen in der Produktion fixieren.UNIPILE_API_KEY gültig.Sendungs-ID für jede gesendete E-Mail, um Zustellungsprüfungen zu ermöglichen. Verwenden Sie den Standard von Python Protokollierung Modul - nie drucken() in Produktion. Senden Sie Protokolle an ein SIEM für stark regulierte Anwendungsfälle.Gängige Python-spezifische Fallstricke
Das sind die häufigsten Fehler, die Python-Entwickler bei der Integration der E-Mail-API machen. Wenn Sie stattdessen Node.js verwenden, sehen Sie unsere JavaScript E-Mail-Senden API-Tutorial.
json= anstatt Daten=multipart/form-data, nicht JSON. Immer benützen requests.post(..., data={...}). Verwendung von JSON={...} wird einen 400er-Fehler zurückgeben. Die zu, ccund BCC Felder sind JSON-Zeichenketten innerhalb der Formulardaten - verwenden json.dumps() zum Kodieren des Empfängerarrays.open('file.pdf', 'rb') - Binärmodus. Textmodus ('r') wirft eine TypeError wenn übergeben an die Dateien= Parameter. Verwenden Sie für In-Memory-Inhalte io.BytesIO.Anfragen Die Bibliothek ist synchron. Wenn sie in einem async def blockiert die Ereignisschleife. Verwende httpx.AsyncClient oder aiohttp.ClientSession für asynchrone Python-Kontexte (FastAPI, asynchrone Django-Views, asyncio-Skripte).requests.post() wartet ewig. Eine hängende Verbindung blockiert Ihren Thread (oder Celery-Worker) unbegrenzt. Übergeben Sie immer timeout=30 (Verbindungszeitüberschreitung, Lesezeitüberschreitung in Sekunden).from datetime import datetime, timezone; datetime.now(timezone.utc). Naive Datumsangaben führen in Multi-Region-Bereitstellungen zu stillschweigenden Fehlern um Stunden.concurrent.futures.ThreadPoolExecutor) oder in eine Celery-Warteschlange auslagern.Häufig gestellte Fragen
Häufige Fragen zur Verwendung der E-Mail-API in Python mit der Unipile Unified Email API.
Verwenden Sie die Unipile Unified Email API anstelle von smtplib oder einer direkten SMTP-Verbindung. Installieren Sie Anfragen, holen Sie sich Ihren API-Schlüssel und DSN vom Unipile Dashboard, verknüpfen Sie ein Gmail- oder Outlook-Konto über OAuth und senden Sie dann eine POST-Anfrage an /api/v1/emails mit Ihrem account_id, zu, Themaund Körper. Kein SMTP-Server, kein Port 587, keine TLS-Konfiguration in Ihrem Python-Code erforderlich.
Django: rufe die API in einer Ansicht oder einem Management-Befehl auf. Für asynchrone Django-Versionen (3.1+) verwende httpx.AsyncClient in asynchronen Ansichten.
Flasche Rufe die API in einem Routenhandler serverseitig auf. Rufe sie niemals aus einer Jinja-Vorlage oder clientseitigem JavaScript auf. Verwende Flask-Celery, um Sends mit hohem Volumen an Hintergrund-Worker auszulagern.
FastAPI: verwenden httpx.AsyncClient innen async def Endpunkte. Die synchronen Anfragen Bibliotheken blockieren die asynchrone Ereignisschleife – verwenden Sie immer einen asynchronen HTTP-Client in FastAPI.
smtplib verbindet sich direkt mit einem SMTP-Server aus Ihrem Python-Prozess. Sie verwalten SMTP-Anmeldedaten, TLS-Einrichtung und anbieterspezifische Eigenheiten (Gmail App-Passwörter, Outlook Modern Authentication). Es ist auch nur synchron.
Die Unipile-E-Mail-API ist eine Cloud-Abstraktion: Verknüpfen Sie Konten über OAuth (keine SMTP-Anmeldeinformationen in Ihrem Code für Gmail/Outlook), erhalten Sie eine einzige konsistente HTTP-API für alle Anbieter, und Unipile kümmert sich um Transport, Token-Aktualisierung und Wiederholungsversuche. Der Kompromiss besteht darin, dass die Sendungen über die Infrastruktur von Unipile und nicht über eine direkte SMTP-Verbindung laufen.
Ja, aber Sie benötigen einen asynchronen HTTP-Client – den Standard Anfragen Die Bibliothek ist synchron und blockiert Ihre Ereignisschleife. Verwenden Sie httpx (empfohlen, asynchrone Drop-in-Alternative) oder aiohttp.
import httpx, os, json
async def send_email_async(an: Str, Betreff: Str, Körper: Str):
asynchron mit httpx.AsyncClient() als Kunde
resp = await Klient.Beitrag(
f'{os.environ["UNIPILE_DSN"]}/api/v1/emails',
Kopfzeilen={'X-API-KEY'os.environ['UNIPILE_API_SCHLÜSSEL']},
daten={'Konto-ID'os.environ['UNIPILE_KONTO_ID'],
'zu': json.Müll([{'Bezeichner': zu}]),
'Betreff'Betreff:, 'Körper': Body}
)
bzw.raise_for_status()
return bzw.json()Verwenden Sie eine Celery-Aufgabenwarteschlange mit einem Redis- oder RabbitMQ-Broker. Jede E-Mail wird zu einer Aufgabe - Celery verwaltet die Gleichzeitigkeit und Wiederholungen automatisch. Begrenzen Sie die Gleichzeitigkeit pro Worker, um Ratenbeschränkungen zu vermeiden (typischerweise 5-10 gleichzeitige Sendungen pro verbundenem Konto). Kombinieren Sie Unipile für den OAuth-basierten Transaktionsversand mit einem dedizierten ESP für Massenkampagnen, wenn Sie wirklich große Mengen an Marketing-E-Mails versenden möchten (Millionen pro Tag).
Für leichtere Anwendungsfälle, concurrent.futures.ThreadPoolExecutor(max_workers=5) mit dem Anfragen Die Bibliothek ist ein einfacherer Ansatz, der den Celery-Overhead vermeidet.
Ja. Erstellen Sie eine Celery-Aufgabe, die aufruft requests.post() an den Unipile-Endpunkt. Celery-Arbeiter sind standardmäßige synchrone Python-Prozesse, so dass Anfragen funktioniert perfekt. Verwenden Sie das integrierte Celery autoretry_for=(requests.exceptions.HTTPError,) mit max_versuche=3 und Standard-Wiederholung-Verzögerung=5 für automatisierte Wiederholungen bei transienten Fehlern. Kombinieren Sie mit Idempotenzschlüssel Headerdateien zur Verhinderung von Mehrfachsendungen bei Neustarts von Workern.
Haben Sie noch Fragen? Unser Team ist für Sie da.