پایگاه دانش
وبهوکها
بهجای اینکه وادارتان کند مدام سر بزنید، وقتی نامهای رسید به نقطهی پایانی شما خبر میدهد.
جزئیات
- از همین امروز از تنظیمات ← وبهوکها و روی API قابل استفاده است: یک نقطهی پایانی https ثبت کنید، از میان آن بیست رویداد آنهایی را که میخواهد انتخاب کنید، و رمز امضای whsec_ را کپی کنید، که هنگام ساخت و هنگام چرخاندن نشان داده میشود و دیگر هرگز. تحویلها POSTهای امضاشدهی واقعیاند که خودِ صندوق پستی برمیانگیزد نه هیچ فراخوانی APIای، پس روی نامهی ورودی و روی بازشدنها و کلیکها شلیک میکنند، هرچه که پیام را فرستاده باشد. ارسال از هر سطحی شلیک میکند، و پیشتر فقط از بعضی شلیک میکرد: ارسالی از راه API، MCP، یک قالب یا یک قاعده email.sent را برمیانگیخت اما پیامی که از بخش نگارشِ خودِ برنامه فرستاده میشد نه، چون بخش نگارش مستقیم در صندوق پستی مینویسد نه از راه سرویس ارسالی که آن رویداد را منتشر میکرد. حالا رویداد در خودِ صندوق پستی برانگیخته میشود، جایی که همهشان به هم میرسند، پس نوشتن در برنامه، زمانبندی برای سهشنبه و POST به API سه راه برای برانگیختن یک وبهوکاند. ارسال تعویقی دو بار خبر میدهد: email.scheduled یا email.queued وقتی پذیرفته میشود، email.sent وقتی واقعاً میرود، و email.cancelled اگر در این میان پسش بگیرید. ده نقطهی پایانی برای هر صندوق پستی، که هرجا یکی ثبت شود اعمال میشود نه فقط در این صفحه.
- رویدادها در سه خانواده میآیند. پانزدهتا دربارهی یک پیاماند: email.received، email.replied، email.sent، email.delivered، email.failed، email.cancelled، email.scheduled، email.queued (خواهرِ لغو-ارسالِ scheduled)، email.delivery_delayed، email.bounced، email.complained، email.suppressed، email.opened، email.clicked و email.downloaded. email.sent یعنی سرویس ارسال پیام را پذیرفت، email.delivered یعنی سرور گیرنده آن را پذیرفت، و email.delivery_delayed یعنی هنوز نرسیده و همچنان تلاش دوباره میشود. email.replied در کنار email.received شلیک میکند وقتی پیام رسیده پاسخِ پیامی است که از پیش در صندوق پستی هست، پس مصرفکنندهای که هر دو را بخواهد هر دو را میگیرد. email.downloaded وقتی شلیک میکند که کسی فایلی را که بهصورت لینک دانلود بیرون رفته بگیرد، با همان دستهبندیکنندهای که پویشگرها و پیشنمایشگرهای لینک را از شمارش بیرون نگه میدارد، و هیچ گیرندهای را نام نمیبرد، چون آن لینک برای همهی کسانی که پیام به آنها رفته یکی است. سهتا دربارهی یک دامنهاند: domain.verified وقتی شروع به دریافت میکند، domain.sending_changed وقتی حکم ارسالش جابهجا میشود، و domain.deleted وقتی برداشته میشود، چه شما خواسته باشید چه دروکنندهی هفتروزه آن را تأییدنشده انداخته باشد. دوتا دربارهی خودِ فهرست سرکوباند، که چیزی جدا از email.suppressed است: suppression.added وقتی آدرسی روی آن میرود، suppression.removed وقتی دوباره اجازه مییابد. مشترکنشدن در هیچکدام یعنی همهی رویدادهای پیام جز email.replied، که امروز چهاردهتاست، و هرگز خانوادهای که بعداً افزوده شود، و API آن را بهصورت ["*"] بازمیخواند. اگر ترجیح میدهید صریح باشید، رویدادهایی را که میخواهید نام ببرید. هر تحویل X-OpenEmail-Signature را به شکل t=<unix>,v1=<hex> حمل میکند، یک HMAC-SHA-256 روی برچسب زمانی، یک نقطه، و بدنهی خام، بهعلاوهی X-OpenEmail-Event و X-OpenEmail-Delivery. در برابر همان بایتهایی که رسیدهاند راستیآزمایی کنید: تجزیه و دوبارهسریالسازی ترتیب کلیدها را به هم میزند و امضا را میشکند. پنجرهی بازپخش 300 ثانیهای بر عهدهی گیرنده است، و راستیآزمای SDK همان را پیشفرض میگیرد.
- ثبتنام برای هر چیزی که https نباشد یا بهطور عمومی قابل مسیریابی نباشد رد میشود (loopback، RFC1918، link-local، CGNAT و معادلهای IPv6 آنها)، و redirect دنبال نمیشود، پس یک 3xx بهجای اینکه جای دیگری تعقیب شود، بهعنوان تحویل ناموفق ثبت میشود. گیرنده 5 ثانیه وقت دارد، نقطههای پایانی بهموازات تحویل میگیرند پس دهتای آنها هم 5 ثانیه خرج میکنند نه 50، و تلاشهای اخیر در صفحهی همان نقطهی پایانی با کد پاسخ و مدت زمانی که برد فهرست میشوند.
- هر تحویل تا پنج بار تلاش میشود. اولی همان لحظهی رخدادن رویداد بیرون میرود؛ شکستی که بهطور معقول ممکن است خودبهخود رفع شود پس از 1 دقیقه، بعد 5، بعد 25، بعد 2 ساعت دوباره تلاش میشود، که یک رویداد را روی حدود دو ساعتونیم پخش میکند. تلاشهای دوباره بهجای حافظه، بهصورت کار ماندگار نگه داشته میشوند، پس یک deploy وسط آن پنجره آنها را از بین نمیبرد. فقط شکستهایی که ارزش تکرار دارند تکرار میشوند: یک timeout، اتصال ردشده، 408، 425، 429 یا هر 5xx. هر 4xx دیگری یعنی نقطهی پایانی عمداً محموله را رد میکند، و چهار بار دیگر پرسیدن یعنی چهار برابر بار برای همان پاسخ. شناسهی رویداد یکبار ساخته میشود و هر تلاش آن را در X-OpenEmail-Delivery حمل میکند، پس گیرندهای که یک شناسه را دو بار ببیند میتواند دومی را بیندازد نه اینکه دو بار روی آن عمل کند. پس از آنکه 100 رویداد پشتسرهم در همهی تلاشها شکست بخورند، نقطهی پایانی غیرفعال میشود، به فضای کاری ایمیل زده میشود، و دلیلش روی خودِ نقطهی پایانی خواندنی است. نقطهی پایانیای که 410 Gone پاسخ دهد همانجا غیرفعال میشود.
- نقطهی پایانیای که 100 بار پشتسرهم شکست بخورد بهجای اینکه تا ابد شمارهگیری شود خاموش میشود، و به همهی کسانی که دسترسی وبهوک دارند ایمیل زده میشود تا بدانند: کدام یکی، آخرین تلاش چه گزارش کرد، و اینکه در مدتی که شکست میخورد چیزی در صف نمانده است. این شمارش پشتسرهم است و هر تلاش موفق آن را صفر میکند، پس یک بعدازظهر بدِ اسفندِ پارسال نمیتواند امروز جمع بزند و نقطهی پایانی را غیرفعال کند. روشنکردن دوبارهاش شمارش را هم پاک میکند. کنسول این دو وضعیت را از هم جدا نشان میدهد نه با یک کلید واحد: نقطهی پایانیای که شما خاموش کردهاید با آنکه ما خاموش کردهایم فرق دارد.
- مدیریت نقطههای پایانی یک کار با دو درِ ورودی است. روی API این میشود POST /webhooks، آن patch، آن delete، rotate-secret، test و گزارش تحویل، با یک متد برای هرکدام در SDK؛ در برنامه میشود تنظیمات ← وبهوکها، روی همان مخزن ثبت، نه یک مخزن دوم. خواندن پشت webhooks:read است، پس هرکسی که یکپارچهسازی میسازد میتواند نقطههای پایانی و تاریخچهی تحویلشان را ببیند (کدام شلیک کرد، گیرنده چه پاسخ داد، چقدر طول کشید) بدون آنکه مالک باشد. ثبت، ویرایش، آزمایش، چرخاندن و حذف، هم webhooks:write و هم مالکیت صندوق پستی را لازم دارند، روی هر دو سطح، و آن نیمهی دوم عمدی است: یک نقطهی پایانی محور آدرس ندارد، پس هر آدرسی را که فضای کاری دارد با موضوع و گیرندههایش دریافت میکند، و نداشتن مجوز یعنی «ممکن است همهی اینها برایش فرستاده شود». نقشی که یکپارچهسازی میسازد و نامهها را نمیخواند، بهجایش با یک کلید فضای کاری آن را میگرداند.