رفتن به محتوای اصلی
سندک

آموزش

ارسال ایمیل در Python

ارسال با requests (API) یا smtplib (SMTP)، با مهلت و تلاش دوباره.

آخرین ویرایش: ۲۱ آبان ۱۴۰۵

پیش از شروع، دامنه‌تان را تأیید و یک کلید بسازید. کلید را در متغیر محیطی بگذارید، نه در کد:

shell
export SENDAK_USER="شناسه_کلید"
export SENDAK_KEY="sd_live_…"

با API (requests)

sendak.py
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"])  # ... queued

idempotency_key را برای هر ایمیل منطقی ثابت بگیرید؛ نه برای هر تلاش. توضیح بیشتر.

هشدار: فقط 429 و 5xx را دوباره امتحان کنید. 422 و دیگر 4xxها با تکرار درست نمی‌شوند. کدها: خطاها و سقف‌ها.

با SMTP (smtplib)

smtp.py
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)

webhook.py
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

جزئیات رویدادها: وب‌هوک.

کلید ندارید؟

با پلن رایگان، ۱٬۰۰۰ ایمیل در ماه می‌فرستید.