Özellik kılavuzları
Webhook'lar
Posta ve hesap olayları için imzalı, yeniden denenen HTTP geri çağrıları alın, eşleşmeyen adreslere gelen postayı karşılayın ve her isteği doğrulayın.
Webhook'lar nedir
Webhook uç noktası, kuruluşunuzda bir şey olduğunda mila'nın çağırdığı HTTPS
URL'nizdir: bir posta kutusu oluşturulur, gönderdiğiniz bir mesaj teslim edilir
ya da geri döner, kodunuza yönlendirdiğiniz bir adrese mesaj gelir. Her olay
önce kalıcı olarak kaydedilir, sonra eşleşen her uç noktaya imzalı bir
POST olarak iletilir. Başarısız bir teslim kaybolmaz: mila beş gün boyunca
yeniden dener, 30 gün saklar ve elle yeniden göndermenize izin verir.
- Webhook'ları kim yönetebilir. Organizasyonun sahibi ya da tüm alan adlarına erişimi olan bir yönetici. Yalnızca bazı alan adlarıyla sınırlı üyeler webhook'ları hiç göremez; çünkü bir uç nokta, abone olduğu her alan adının olaylarını (gelen posta için ise mesaj içeriğini) alır.
- Kaç tane. Organizasyon başına en çok 10 uç nokta.
- Nereden. Panelde Webhook'lar bölümünden; herkese açık API'den
/api/v1/webhooksaltından (aşağıya bakın); ve aynı işlemler için webhook araçları bulunan mila'nın MCP sunucusundan (mila'nın API'si ve MCP sunucusuyla entegrasyon rehberine bakın).
Her uç noktanın bir URL'si, isteğe bağlı bir açıklaması, istediği olay türleri
(ya da hepsi), isteğe bağlı olarak sınırlandığı alan adları (boş = her alan
adı), bir gelen posta biçimi (raw ya da json, bkz. "Posta almak") ve bir
etkin/pasif anahtarı vardır. Oluşturduğunuzda mila imza sırrını yalnızca bir
kez gösterir -- o an kopyalayın; bkz. "İmzaları doğrulamak".
API
API anahtarlarının webhooks:read ve/veya webhooks:write yetkisi olmalı ve
anahtarın sahibi organizasyonun sahibi ya da tüm alan adlarına erişen bir
yöneticisi olmalıdır. Yetkilerden önce oluşturulmuş anahtarlarda bu yetkiler
yoktur -- yeni bir anahtar oluşturun.
| Çağrı | Yetki | Ne yapar |
|---|---|---|
GET /api/v1/webhook-event-types | webhooks:read | Olay türleri ve gruplarının kataloğu |
GET /api/v1/webhooks, GET /api/v1/webhooks/{id} | webhooks:read | Uç noktaları (24 saatlik sağlıkla) listeler ya da birini okur |
POST /api/v1/webhooks | webhooks:write | Oluşturur; yanıtta secret bir kez gelir |
PATCH /api/v1/webhooks/{id}, DELETE /api/v1/webhooks/{id} | webhooks:write | Değiştirir ya da siler (silmek bekleyen teslimleri de düşürür) |
POST /api/v1/webhooks/{id}/rotate-secret | webhooks:write | Yeni sır; eski sır 24 saat daha imzalamaya devam eder |
POST /api/v1/webhooks/{id}/test | webhooks:write | Hemen bir webhook.test olayı gönderir ve sonucu bildirir |
GET /api/v1/webhooks/{id}/deliveries, .../deliveries/{deliveryId} | webhooks:read | Teslim kaydı; status, eventType, createdAfter, createdBefore ile süzülür |
POST /api/v1/webhooks/{id}/deliveries/{deliveryId}/retry | webhooks:write | Tek bir teslimi yeniden gönderir |
POST /api/v1/webhooks/{id}/deliveries/retry | webhooks:write | Süzgeçle toplu yeniden gönderim (çağrı başına en çok 1000; hasMore yeniden çağırmanızı söyler) |
GET /api/v1/domains/{domainId}/inbound-webhook | domains:read | "Eşleşmeyen adresleri webhook'a ilet" ayarının açık olup olmadığı ({ "enabled": true }) |
PUT /api/v1/domains/{domainId}/inbound-webhook | domains:write (yönetici) | "Eşleşmeyen adresleri webhook'a ilet" ayarını açar ya da kapatır ({ "enabled": true }). 409 CATCHALL_ACTIVE / DOMAIN_ALIAS_ACTIVE; posta sunucusu + alt adresleme değişikliğini uygulayamazsa 503 MAIL_SERVER_UNAVAILABLE (açarken hiçbir şey değişmemiştir, tekrarlayın; kapatırken ayar zaten kapalıdır ve + birkaç dakika içinde kendiliğinden geri gelir) |
Uç nokta oluşturmak:
curl -X POST "https://api.mila.cx/api/v1/webhooks" \
-H "Authorization: Bearer $MILA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/mila",
"description": "Canlı olaylar",
"eventTypes": ["email.sent", "email.delivered", "email.bounced", "mailbox.created"]
}'
eventTypes, aşağıdaki katalogdan boş olmayan bir tür listesidir ya da tümü
için tam olarak ["*"] ("*" başka türlerle birleştirilemez).
webhook.test yalnızca test eylemiyle gönderilir ve abone olunamaz.
Sınırlar: url en çok 2048 karakter, description en çok 500, domainIds en
çok 500 öğe.
Olaylar
Her olay aynı zarfta bir JSON belgesidir:
{
"id": "evt_01JBQ6Z9X4M2K7R8T5V3N1W0YC",
"type": "mailbox.created",
"createdAt": "2026-10-30T09:15:42.118Z",
"organizationId": "<organizasyon kimliği>",
"data": { "mailboxId": "...", "domainId": "...", "address": "sales@example.com" }
}
id, olayın uç noktalarınıza yapılan tüm teslimlerinde aynıdır.
(JSON zarfının tek istisnası raw biçimindeki email.received'dir; bkz.
"Posta almak".)
| Olay | Ne zaman tetiklenir | data alanları |
|---|---|---|
email.received | Bir mesaj gelir. Alan adındaki bir posta kutusu adresi için: yalnızca üst veri. "Eşleşmeyen adresleri webhook'a ilet" açık bir alan adında eşleşmeyen bir adres için: mesajın tamamı, bkz. "Posta almak" | Üst veri: messageId, from, to, subject, size, format: "metadata". Eşleşmeyen, raw biçimi: JSON gövde yok (gövde mesajın kendisidir). Eşleşmeyen, json biçimi: messageId, from, subject, size, format: "raw", ayrıca raw (base64) ya da rawOmitted |
email.sent | Alan adlarınızdan birinin kimliği doğrulanmış bir gönderici (SMTP girişi, webmail, REST API, MCP) bir mesaj gönderdi. Mesaj başına bir olay, tüm alıcıları listeler | queueId, messageId, from, recipients[], subject (mila'nın kendisinin kaydetmesi gereken bir API gönderiminde queueId yerine submissionId bulunur) |
email.delivered | Uzak sunucu mesajı bir alıcı için kabul etti. Kendi yönlendirmenizin aldığı bir alıcı (takma ad, yeniden yazma, yönlendirme ya da "eşleşmeyen adresleri webhook'a ilet" açık bir alan adında eşleşmeyen bir adres) hemen 250 2.1.5 Accepted for local routing yanıtıyla teslim edildi sayılır | queueId, submissionId (API gönderimleri), messageId, recipient, smtpReply |
email.delivery_delayed | Geçici bir hata; mila hâlâ deniyor. Alıcı başına 6 saatte en çok bir kez | email.delivered ile aynı |
email.bounced | Bir alıcı için kalıcı hata | email.delivered ile aynı |
email.delivery_unknown | mila bir alıcıya ne olduğunu öğrenemedi: aşağıdaki garantilere bakın | email.delivered ile aynı |
domain.created | Organizasyona bir alan adı eklendi | domainId, name |
domain.verified | Bir alan adı etkin oldu. Alan adı etkin değilken etkin olduğu her seferinde tetiklenir; yalnızca ilk doğrulamada değil, devre dışı bırakılmış bir alan adının yeniden etkinleştirilmesinde de | domainId, name |
domain.dns_issue | MX, SPF ve DKIM'in üçü de sağlıklı olan etkin bir alan adı sağlıksız hale geldi. Bozulma başına bir kez tetiklenir; bozuk kaldığı sürece her kontrolde tetiklenmez | domainId, name, issues[] (record, expected, found) |
domain.deleted | Bir alan adı organizasyondan kaldırıldı | domainId, name |
mailbox.created | Bir posta kutusu oluşturuldu (gizli sistem posta kutuları hiç olay üretmez) | mailboxId, domainId, address |
mailbox.updated | Bir posta kutusu ayarı değişti; parola değişikliği ya da süre dolumunun kutuyu devre dışı bırakması dahil | mailboxId, domainId, address, changes[] -- değişen alanların adları (may_send, active, password gibi), değerleri asla |
mailbox.deleted | Bir posta kutusu silindi (özgün adresiyle) | mailboxId, domainId, address |
alias.created, alias.deleted | Bir takma ad eklendi ya da kaldırıldı | aliasId, domainId, address, destinations[] |
forwarding.created, forwarding.deleted | Bir yönlendirme kuralı eklendi ya da kaldırıldı | forwardingId, mailboxAddress, destination |
webhook.test | "Test gönder"e bastınız (panel ya da API) | message, endpointId |
Bilmeye değer noktalar:
- Alan adı devri. Bir alan adını başka bir organizasyona taşımak, kaynak
organizasyonda
domain.deleted, hedef organizasyondadomain.createdüretir; ikisinde dedataiçinde"transferred": truebulunur, böylece bir taşımayı gerçek bir silme ya da oluşturmadan ayırt edebilirsiniz. - Satır bazında zincirleme olay yok. Bir alan adı ya da posta kutusu
silindiğinde onunla giden satırlar (takma adlar, yönlendirmeler vb.) kendi
alias.deleted/forwarding.deletedolaylarını üretmez.domain.deletedvemailbox.deleted'ı altındaki her şeyi kapsıyor sayın. - Olay olmayanlar. Bir takma adı güncellemek, bir yönlendirme kuralını güncellemek ve yönlendirme onayı olay üretmez.
- Sıra garantisi yok. Olaylar sırasız gelebilir. Sıra sizin için önemliyse
createdAt'i kullanın.
Neler garanti
"Kalıcı"nın burada ne demek olduğunu net söyleyelim:
| Olay | Garanti |
|---|---|
email.received | Garantili. mila mesajı kabul etmeden önce kaydedilir. mila kaydı yazamazsa gönderen sunucuya geçici bir SMTP hatası (4xx) döner ve gönderen yeniden dener. (Posta kutusu adresleri için üst veri olayları yalnızca uç noktalarınızdan biri o alan adı için email.received'e abone olduğu sürece kaydedilir; yeni oluşturulan ya da süzgeci değişen bir uç nokta bunların yaklaşık 30 saniyesini kaçırabilir. Eşleşmeyen adres postası her zaman kaydedilir.) |
email.sent | Kimliği doğrulanmış gönderimler (587'de SMTP girişi, webmail, REST API, MCP) için, uç noktalarınızdan biri gönderenin alan adı için bir giden posta olayına (email.sent, email.delivered, email.delivery_delayed, email.bounced, email.delivery_unknown ya da tüm olaylar) abone olduğu sürece garantili. Mesaj kabul edilmeden önce kaydedilir; kaydedilemezse gönderime, kabul edilmiş ama kaydedilmemiş bir mesaj yerine geçici bir SMTP hatası döner. Hiçbir uç noktanın abone olmadığı sırada gönderilen mesajlar hiç izlenmez -- ne email.sent ne de sonradan sonuç olayları gelir -- ve bir uç nokta eklediğinizde geriye dönük doldurma yapılmaz; yeni oluşturulan ya da süzgeci değişen bir uç nokta gönderimlerin yaklaşık 30 saniyesini kaçırabilir. |
email.delivered, email.delivery_delayed, email.bounced | Neredeyse garantili. Sonuç, bellekte tutulan posta sunucusu telemetrisinden gelir: yalnızca posta sunucusu yanlış anda yeniden başlarsa kaybolabilir. Bunun üzerine 5 dakikada bir çalışan bir süpürme, 10 dakikadan eski her mesaj için posta kuyruğuna bakar ve mümkünse sonucu kurtarır. |
email.delivery_unknown | Garantili ve açık. Bir alıcının mesajı kuyruktan çıkmış ve hiçbir sonuç görülmemişse mila yaklaşık 15 dakikalık bir bekleme süresinden sonra sessiz kalmak yerine size "bilinmiyor" der. Bu "başarısız oldu" demek değil, "bilmiyoruz" demektir: alıcı tarafına bakın. |
domain.*, mailbox.*, alias.*, forwarding.* | Garantili. Olay, değişikliğin kendisiyle aynı veritabanı işleminde yazılır: ya ikisi birden olur ya hiçbiri. |
Teslim
mila en az bir kez teslim eder. Bir alıcı aynı teslimi birden fazla görebilir (yanıtınızı gönderdiğiniz hâlde zaman aşımına uğrayan bir yeniden deneme, teslim sırasında bir çökme) ve idempotent olmalıdır. Olaylar arasında sıra garantisi yoktur.
Her istek şu başlıklarla bir POST'tur:
| Başlık | Anlamı |
|---|---|
X-Mila-Event | Olay türü, örneğin mailbox.created |
X-Mila-Event-Id | Olayın kimliği (evt_...); onu alan tüm uç noktalarda aynı |
X-Mila-Delivery-Id | Bu teslimin kimliği. Her yeniden denemede sabittir -- tekrarları bununla ayıklayın |
X-Mila-Attempt | İlk deneme için 1, sonra 2, 3, ... (elle yeniden gönderim saymaya devam eder) |
X-Mila-Timestamp | Bu denemenin imzalandığı Unix saniyesi |
X-Mila-Signature | v1=<hex>; sır döndürme sırasında virgülle ayrılmış iki değer |
X-Mila-Recipient | Yalnızca email.received'de: zarf alıcısı; düz ASCII ise geldiği gibi (rsvp+<token>@... gibi adresler için her zaman böyledir). ASCII olmayan karakterler içeren bir adres (örneğin şükrü@...) yüzde kodlanmış UTF-8 olarak gönderilir (%C5%9F%C3%BCkr%C3%BC%40..., JavaScript'in encodeURIComponent'inin ürettiği biçimde): böyle bir değer hiçbir zaman düz bir @ içermez, yani @ içermeyen bir başlık decodeURIComponent / urllib.parse.unquote ile çözülür |
User-Agent | Mila-Webhooks/1.0 |
Gövde JSON zarfıdır (Content-Type: application/json); raw biçimindeki
email.received için ise ham mesajdır.
Yanıtınız nasıl okunur
- Sunucunuzun yanıt vermesi için 10 saniyesi vardır. mila yönlendirmeleri izlemez.
- 2xx -- teslim edildi. Gövdedeki hiçbir şey dikkate alınmaz.
- 408 ve 429 dışındaki 4xx (ve her 3xx) -- rejected: hayır dediniz, bu yüzden mila yeniden denemez. Teslim saklanır; kendi tarafınızı düzeltip yeniden gönderebilirsiniz.
- 408, 429, 5xx, zaman aşımı, ağ ve TLS hataları -- yeniden denenir.
429yanıtındakiRetry-After, en çok 6 saate kadar asgari bekleme olarak dikkate alınır. - DNS hataları ve mila'nın bağlanmayı reddettiği hedefler ("Güvenlik"e bakın) aynı şekilde yeniden denenir.
Yeniden denemeler bir önceki denemeden 1 dakika, 5 dakika, 15 dakika, 1 saat ve 3 saat sonra, ardından 6 saatte bir olur; her birinde %10 sapma (jitter) vardır ve ilk denemeden 5 gün sonrasına kadar sürer. Sonraki deneme bu pencerenin dışına düşecekse teslim failed olur ve mila operatörlerine uyarı gider (uyarı yalnızca kimlik ve sayı taşır; mesaj içeriği ya da alıcı asla).
Bir teslim şu durumlardan birinde biter:
| Durum | Anlamı |
|---|---|
pending, delivering | Sırada ya da şu an gönderiliyor |
delivered | 2xx yanıtladınız |
rejected | 4xx yanıtladınız (408/429 hariç) |
failed | Beş günlük yeniden deneme bitti (ya da duraklatılmış bir uç noktada 30 günden uzun tutuldu, ya da -- hata raw_message_purged -- bir email.received'in ham iletisi zaten silinmişti, aşağıya bakın) |
too_large | Gövde 1 MiB'ı aşacaktı; bkz. "Posta almak" |
cancelled | Uç nokta, gönderilmeden önce olayla artık eşleşmeyecek şekilde düzenlendi |
Biten teslimler, denemeleri ve olay gövdeleri 30 gün saklanır. Bu sürede
herhangi birini (teslim edilmiş olanı bile) panelde teslim kaydından tek tek
ya da süzgeçle toplu olarak yeniden gönderebilirsiniz (durum belirtmeyen
bir toplu yeniden gönderim failed, rejected ve too_large olanları alır).
Yeniden gönderim aynı X-Mila-Delivery-Id ile, yeni bir 5 günlük deneme
penceresiyle ve devam eden deneme sayısıyla çıkar. webhook.test teslimleri
yeniden gönderilemez -- yeni bir test gönderin. Ham email.received
teslimleri yalnızca mila iletiyi hâlâ saklarken yeniden gönderilebilir:
saklanan kopya, iletinin tüm teslimleri başarılı olur olmaz silinir (aksi
hâlde sonuncusu bittikten 30 gün sonra ya da alan adıyla birlikte). Ondan sonra
yeniden gönderim 409 RAW_MESSAGE_PURGED ile reddedilir; yine de gönderime
ulaşan bir teslim (toplu yeniden gönderim) yeniden denenmeden hemen failed
olarak, raw_message_purged hatasıyla biter.
Bir uç noktayı duraklatmak
Bir uç noktayı kapatmak onu duraklatır; olayları düşürmez. Eşleşen olaylar
kaydedilmeye devam eder ve pending olarak bekler. Uç noktayı yeniden
açtığınızda her biri yeni bir 5 günlük deneme penceresiyle gönderilir.
Duraklatılmış bir uç noktada 30 günden uzun tutulan teslim failed olur (hata
endpoint_paused_too_long) ve diğer başarısızlıklar gibi 30 gün daha saklanır.
Bir uç noktayı silmek farklıdır: uç noktayı ve tüm teslimlerini, bekleyenler
dahil, düşürür; bunlar bir daha gönderilmez. Olayları sonra isteyebilecekseniz
silmek yerine duraklatın.
İmzaları doğrulamak
URL'nizi öğrenen herkes ona sahte bir istek gönderebilir; bu yüzden her isteği doğrulayın.
İmza, üç şeyden oluşan bir dizge üzerinde HMAC-SHA256'dır:
imzalanan dizge = X-Mila-Timestamp + "\n" + X-Mila-Recipient + "\n" + hex(sha256(ham gövde))
X-Mila-Signature = "v1=" + küçük harfli hex( HMAC-SHA256(anahtar, imzalanan dizge) )
X-Mila-Recipientbaşlığı yoksa (email.receiveddışındaki her olay) boş dizge kullanılır. Başlık değerini geldiği gibi kullanın -- ASCII olmayan bir adres için bu yüzde kodlanmış biçimdir; çözmeyi doğrulamadan sonra yapın.- Anahtar, 64 karakterlik hex sırrın 32 bayta çözülmüş halidir; hex metnini anahtar olarak kullanmayın.
- Aldığınız tam baytları özetleyin. JSON'u önce ayrıştırıp yeniden serileştirmeyin.
- Sır döndürme sırasında başlıkta iki değer bulunur, yeni sırrınki ve eskisininki:
v1=<yeni>,v1=<eski>. Herhangi birv1değeri eşleşirse isteği kabul edin. - Tekrar saldırılarını (replay) engellemek için
X-Mila-Timestamp'i saatinizden yaklaşık 5 dakikadan fazla sapan istekleri reddedin ve imzaları sabit zamanlı karşılaştırın.
Node.js:
import { createHash, createHmac, timingSafeEqual } from 'node:crypto';
const TOLERANCE_SECONDS = 300;
export function verifyMilaWebhook({ secretHex, headers, rawBody, now = Date.now() / 1000 }) {
const timestamp = headers['x-mila-timestamp'];
const recipient = headers['x-mila-recipient'] ?? '';
const signature = headers['x-mila-signature'] ?? '';
// Eski ya da çok ileri tarihli zaman damgalarını reddet (tekrar koruması).
if (!/^\d+$/.test(timestamp ?? '') || Math.abs(now - Number(timestamp)) > TOLERANCE_SECONDS) return false;
const bodyHash = createHash('sha256').update(rawBody).digest('hex');
const expected = createHmac('sha256', Buffer.from(secretHex, 'hex'))
.update(`${timestamp}\n${recipient}\n${bodyHash}`)
.digest('hex');
// Sır döndürme sırasında başlıkta iki değer olabilir: "v1=<yeni>,v1=<eski>".
let ok = false;
for (const part of signature.split(',')) {
const candidate = part.trim();
if (!candidate.startsWith('v1=')) continue;
const got = Buffer.from(candidate.slice(3), 'utf8');
const want = Buffer.from(expected, 'utf8');
if (got.length === want.length && timingSafeEqual(got, want)) ok = true;
}
return ok;
}
Python:
import hashlib
import hmac
import time
TOLERANCE_SECONDS = 300
def verify_mila_webhook(secret_hex: str, headers: dict, raw_body: bytes, now: float | None = None) -> bool:
now = time.time() if now is None else now
timestamp = headers.get("x-mila-timestamp", "")
recipient = headers.get("x-mila-recipient", "")
signature = headers.get("x-mila-signature", "")
# Eski ya da çok ileri tarihli zaman damgalarını reddet (tekrar koruması).
if not timestamp.isdigit() or abs(now - int(timestamp)) > TOLERANCE_SECONDS:
return False
body_hash = hashlib.sha256(raw_body).hexdigest()
expected = hmac.new(
bytes.fromhex(secret_hex),
f"{timestamp}\n{recipient}\n{body_hash}".encode(),
hashlib.sha256,
).hexdigest()
# Sır döndürme sırasında başlıkta iki değer olabilir: "v1=<yeni>,v1=<eski>".
ok = False
for part in signature.split(","):
part = part.strip()
if part.startswith("v1=") and hmac.compare_digest(part[3:], expected):
ok = True
return ok
Uygulamanızı bu test vektörüyle sınayın. Sır
0000000000000000000000000000000000000000000000000000000000000000 (64 sıfır,
yani 32 sıfır bayt), zaman damgası 1761800000, alıcı
rsvp+abc.def@reply.vnnx.app ve gövde hello iken başlık şu olmalıdır:
X-Mila-Signature: v1=025d4e1d55076d9a8c7322e8ab58c2f80bebe174300ab0604b305dd071f31f9c
(Yukarıdaki iki örnek de bu girdiler için tam olarak bu değeri üretir.)
Sırrı döndürmek
Panelden ya da POST /api/v1/webhooks/{id}/rotate-secret ile döndürün. Yeni sır
bir kez gösterilir. Sonraki 24 saat boyunca her teslim -- süren yeniden
denemeler dahil -- ikisiyle birden imzalanır; böylece olay kaçırmadan yeni sırra
geçebilirsiniz. Bu pencere içinde ikinci bir döndürme 409 ROTATION_IN_PROGRESS
ile reddedilir, çünkü hâlâ geçiş yapmakta olduğunuz bir sırrı emekliye ayırırdı;
geçersiz kılmak için { "force": true } gönderin -- bu, eski sırrın imzalamasını
hemen durdurur.
Posta almak (email.received)
İki tür email.received vardır.
Posta kutusu teslimleri -- yalnızca üst veri. Uç noktanızın kapsadığı bir
alan adındaki gerçek bir posta kutusuna mesaj gönderildiğinde gönderen, To,
konu, Message-ID ve boyutu içeren bir JSON olayı alırsınız -- gövde yok, ek
yok. Bu bir bildirimdir, postanın kopyası değil.
Eşleşmeyen adresler -- mesajın tamamı. Bir alan adında Eşleşmeyen adresleri
webhook'a ilet ayarını açabilirsiniz (panel: alan adının ayarları; API:
PUT /api/v1/domains/{domainId}/inbound-webhook, gövde
{ "enabled": true }). O alan adındaki posta kutusu, takma adı ya da kimliği
olmayan her adrese gelen posta reddedilmek yerine kabul edilir ve eksiksiz mesajla
email.received uç noktalarınıza iletilir. rsvp+<jeton>@reply.example.com
gibi "e-postayla yanıtla" özellikleri böyle kurulur.
Uç noktanın inboundFormat değeri biçimi belirler:
raw(varsayılan): gövde mesajın kendisidir (Content-Type: message/rfc822), aşağıda sıralanan başlık değişiklikleri dışında olduğu gibi, zarf alıcısı başına birPOSTile: eşleşmeyen iki adrese gönderilmiş bir mesaj ikiPOSTüretir; her birininX-Mila-Recipientbaşlığında, varsa+etiketdahil, o tam adres bulunur. 1 MiB'ı aşan bir mesaj gönderilemez: o teslimtoo_largeolarak biter.json: her zamanki JSON zarfı; mesajdata.rawiçinde base64 olarak bulunur. Zarfın tamamı 1 MiB'ı aşacaksadata.rawçıkarılır ve yerinedata.rawOmitteddeğeri"too_large"olur; üst veri yine de iletilir.
Açarken bilmeniz gerekenler:
- mila bu postayı geri çevirmez (bounce). Kabul edilir ve uç noktanıza verilir; diğer her şeyle aynı yeniden deneme kuralları geçerlidir. Uç noktanız kapalıysa mila mesajı saklar ve yeniden dener; gönderene bir şey söylenmez. (Kabul sırasında gerçek bir veritabanı hatası olursa mila geçici bir 4xx döner ve gönderen yeniden dener.) Tek istisna: posta sunucusunun kendisinin üretip mila'nın yönlendirmesinden geçirmeden gönderdiği posta -- bir mila posta kutusundan Sieve yönlendirmesi, tatil yanıtı ya da bildirim, veya bir teslim durumu bildirimi (DSN) -- eşleşmeyen bir adres için reddedilir ve göndericisine geri döner.
Delivered-Todeğil,X-Mila-Recipientkullanın. mila bu postayı iç bir hesap üzerinden yönlendirir; bu yüzden ham mesajınDelivered-Tobaşlığı postanın gönderildiği adresi değil, o hesabı (#inbound@<alan adınız>) gösterir. Postanın gönderildiği adresX-Mila-Recipient'tadır (ve gönderenin yazdığı, gönderenin denetiminde olanTo/Ccbaşlıklarında).- Catch-all (tümünü yakala) ile birlikte kullanılamaz ve başka bir alan
adının takma alan adı olan bir alan adında açılamaz:
409alırsınız (CATCHALL_ACTIVEya daDOMAIN_ALIAS_ACTIVE). - O alan adında
+alt adreslemeyi kapatır. Aksi haldersvp+abc@alanadi,rsvp@alanadigibi ele alınırdı. Açtıktan sonraad+etiket@alanadiartıkadposta kutusuna ulaşmaz: sıradan bir eşleşmeyen adrestir ve webhook'a gider. Ayarı kapatmak+adreslemeyi geri getirir. - Saklanan mesaj, tüm teslimleri
deliveredolunca silinir; aksi halde son teslimin bitmesinden 30 gün sonra.
Ham postada Authentication-Results'a güvenmek
Kodunuz kimlik doğrulama sonuçlarına bakarak karar veriyorsa ("bu gerçekten o
göndericiden mi geldi?") bu bölümü dikkatle okuyun. Bir gönderen, sahte bir
Authentication-Results (A-R) başlığı dahil, istediği başlığı yazabilir. mila
size dayanabileceğiniz tek bir kural verir:
mila'nın ilettiği her ham mesajda mila'nın yazdığı tam olarak bir
Authentication-Resultsbaşlığı bulunur; authserv-id'simx1.mila.cx'tir ve mesajdaki ilkAuthentication-Resultsbaşlığı mila'nındır. Yalnızca bu ilk başlığa güvenin.
mila bunu her mesaj için uygular:
- Olağan gelen SMTP ile (kimliği doğrulanmamış gönderen) gelen bir mesaj,
mila'nın kendi posta sunucusunun en üste yazdığı sonucu (SPF, DKIM ve DMARC
sonuçları) korur. Herhangi bir nedenle göndericinin kendi başlıklarının üstünde
böyle bir sonuç yoksa, aşağıda anlatılan
nonebaşlığını alır. - mila'da kimliği doğrulanmış bir göndericiden (mila SMTP'sine, webmail'e
ya da API'ye giriş yapıp gelen alan adınıza yazan biri) ya da başka bir iç
yoldan gelen mesajın bildirilecek dış bir sonucu yoktur. Bu mesajların en
üstüne
Authentication-Results: mx1.mila.cx; noneyazılır.nonetam olarak dediğini söyler: hiçbir şey doğrulanmadı, göndericiyi kanıtlanmış saymayın. - Authserv-id'si
mx1.mila.cxya damx2.mila.cxolan diğer herAuthentication-Resultsbaşlığı -- ki bunu ancak bir gönderen koymuş ya da önceki bir atlama bırakmış olabilir --X-Mila-Neutralized-Authentication-Resultsolarak yeniden adlandırılır; böylece bir sonuçla karıştırılamaz. - mila ayrıca iç
X-Mila-Inbound-Idbaşlığını ve kendiResent-Message-IDişaretini teslimden önce kaldırır ve başlık bloğundaki yalnız (satır başı olmayan) CR karakterlerini boşlukla değiştirir. Başlık bloğundan sonraki her şey olduğu gibi iletilir ve imza mesajı tam olarak gönderildiği haliyle kapsar.
Yani: mesajdaki ilk Authentication-Results başlığını alın, authserv-id'sinin
mx1.mila.cx olduğunu doğrulayın ve sonucu ondan okuyun; diğerlerini yok sayın.
MCP sunucusundan
mila'nın MCP sunucusunda on iki webhook aracı vardır: list_webhook_event_types,
list_webhooks, get_webhook, create_webhook, update_webhook,
delete_webhook, rotate_webhook_secret, send_webhook_test,
list_webhook_deliveries, retry_webhook_delivery,
retry_webhook_deliveries ve set_domain_inbound_webhook. Panel ve API ile
aynı yönetim kuralı geçerlidir: yalnızca sahip ya da tüm alan adlarına erişimi
olan bir yönetici, ve yalnızca tüm alan adları için verilmiş bir yetkilendirme
ile.
- Yetkiler. Okuma araçları için
webhooks:read, diğerleri içinwebhooks:write(set_domain_inbound_webhookayrıcadomains:writeister), imza sırları için ise hassaswebhooks:secrets. - Sırlar.
create_webhookverotate_webhook_secretimza sırrını yalnızcawebhooks:secretsiçeren bir yetkilendirmeye döndürür. Bu yetki yoksacreate_webhookuç noktayı yine oluşturur amasecret: nulldöndürür (sırrı görmek için panelde döndürün);rotate_webhook_secretise reddedilir, çünkü alıcınızın mevcut sırrı 24 saat sonra geçersiz olur ve istemci yeni sırrı hiç göremez. - Posta webhook'ları
mail:readister.email.*olaylarını (ya da*) alan bir uç nokta mesaj meta verilerini, gelen posta yönlendirilen alan adlarında ise ham postayı taşır. Bu yüzden posta olaylarına abone bir webhook'u (duraklatılmış olsa bile) oluşturmak ya da değiştirmek -- URL'sini, olaylarını, alan adlarını veya biçimini değiştirmek ya da etkinleştirmek -- veset_domain_inbound_webhookile gelen posta yönlendirmesini açmak, tüm adreslere erişimi olan bir yetkilendirmede ayrıcamail:readgerektirir. Biremail.*teslimatını yeniden denemek için de aynısı gerekir (bu yetki olmadan toplu yeniden denemeemail.*teslimatlarını atlar). Yalnızca uç noktayı duraklatmak ya da açıklamasını düzenlemek muaftır.
Güvenlik
- Oluşturma sırasındaki URL kuralları. URL
https://olmalı, en çok 2048 karakter olmalı vekullanıcı:parola@biçiminde kimlik bilgisi içermemelidir. Özel ya da iç aralıklardaki bir IP adresi (https://10.0.0.1/,https://[::1]/ya dahttps://2130706433/gibi) uç nokta oluşturulurken reddedilir. - İç adresler yok. mila her denemede ana makine adınızı çözer; özel,
loopback, link-local, operatör düzeyinde NAT, multicast ve bulut metadata
adreslerini (IPv4-eşlemeli IPv6 olanlar dahil) reddeder ve kontrol ettiği
adrese bağlanır; dolayısıyla kontrolden sonra adı başka yere çevirmek işe
yaramaz. Ana makine adları uç nokta oluşturulurken çözülmez, çünkü DNS
değişebilir: özel bir adrese çözülen bir ad, o denemeyi yeniden denenebilir
bir
blocked_destinationhatasıyla başarısız kılar. - Posta içeriği.
email.*olaylarına abone bir uç nokta mesaj meta verilerini (gelen posta yönlendirilen alan adlarında ham mesajı da) alır. Bu yüzden webhook'ları yalnızca sahipler ve tüm alan adlarına erişimi olan yöneticiler yönetebilir; webhook yönetebilen API anahtarlarını da posta erişimi gibi ele alın. - Sır yalnızca bir kez gösterilir: oluştururken ve her döndürmede. mila onu şifreli saklar ve size tekrar gösteremez; panel yalnızca son dört karakterini gösterir. Sızarsa döndürün.
- Yanıtınıza hiçbir konuda güvenilmez: mila teslim kaydı için yanıt gövdenizin yalnızca ilk 1 KiB'ını saklar ve yönlendirmeleri izlemez.