آموزش
ارسال ایمیل در Python
ارسال با requests (API) یا smtplib (SMTP)، با مهلت و تلاش دوباره.
آخرین ویرایش: ۲۱ آبان ۱۴۰۵
پیش از شروع، دامنهتان را تأیید و یک کلید بسازید. کلید را در متغیر محیطی بگذارید، نه در کد:
export SENDAK_USER="شناسه_کلید"
export SENDAK_KEY="sd_live_…"با API (requests)
import os
import time
import requests
API = "https://api.sendak.ir/v1/emails"
def send_email(idempotency_key: str, to: list[str], subject: str, text: str, tags: list[str] | None = None) -> list[dict]:
body = {"from": "hello@shop.ir", "to": to, "subject": subject, "text": text, "tags": tags or []}
headers = {
"Authorization": f"Bearer {os.environ['SENDAK_KEY']}",
"Idempotency-Key": idempotency_key,
}
for attempt in range(4):
try:
response = requests.post(API, json=body, headers=headers, timeout=10)
except requests.RequestException:
# Network error or timeout: the key makes a second try safe.
time.sleep(2**attempt)
continue
if response.ok:
return response.json()["data"]
if response.status_code != 429 and response.status_code < 500:
raise RuntimeError(f"Sendak refused the message: {response.text}")
time.sleep(float(response.headers.get("Retry-After", 2**attempt)))
raise RuntimeError("Sendak did not accept the message after 4 tries")result = send_email("receipt-1201", ["ali@gmail.com"], "رسید سفارش ۱۲۰۱", "سفارش شما ثبت شد.")
print(result[0]["id"], result[0]["status"]) # ... queuedidempotency_key را برای هر ایمیل منطقی ثابت بگیرید؛ نه برای هر تلاش. توضیح بیشتر.
هشدار: فقط
429و5xxرا دوباره امتحان کنید.422و دیگر4xxها با تکرار درست نمیشوند. کدها: خطاها و سقفها.
با SMTP (smtplib)
import os
import smtplib
from email.message import EmailMessage
message = EmailMessage()
message["From"] = "hello@shop.ir"
message["To"] = "ali@gmail.com"
message["Subject"] = "اولین ایمیل"
message.set_content("سلام از سندک")
with smtplib.SMTP("smtp.sendak.ir", 587, timeout=20) as server:
server.starttls() # login is refused before this
server.login(os.environ["SENDAK_USER"], os.environ["SENDAK_KEY"])
server.send_message(message)starttls()را پیش ازlogin()بزنید؛ ورود بدون TLS رد میشود.SMTP_SSL(پورت ۴۶۵) پشتیبانی نمیشود.EmailMessageنویسههای فارسی در موضوع و متن را خودش درست رمزگذاری میکند.
بررسی وبهوک (Flask)
import hashlib
import hmac
import os
import time
from flask import Flask, abort, request
app = Flask(__name__)
@app.post("/webhooks/sendak")
def webhook():
raw = request.get_data() # the raw body, before any JSON parsing
parts = dict(p.split("=", 1) for p in request.headers.get("X-Sendak-Signature", "").split(",") if "=" in p)
t = int(parts.get("t", "0") or 0)
expected = hmac.new(os.environ["SENDAK_WEBHOOK_SECRET"].encode(), f"{t}.".encode() + raw, hashlib.sha256).hexdigest()
if t == 0 or abs(time.time() - t) > 300 or not hmac.compare_digest(expected, parts.get("v1", "")):
abort(401)
event = request.get_json()
# Put the event on your own queue and answer fast.
return "", 200جزئیات رویدادها: وبهوک.