Aby przetestować Mailgun haki na localhost, zdemaskować lokalnego opiekuna npx portpreview PORT, skonfigurować otrzymany punkt końcowy HTTPS dla wymaganych typów zdarzeń Mailgun i zweryfikować znacznik czasu, token i HMAC-SHA256 przed zaakceptowaniem zdarzenia.
Co Mailgun webhacks report
Mailgun wysyła HTTP lub HTTPS POST z ładunkiem JSON w przypadku wystąpienia skonfigurowanego zdarzenia. Bieżące typy zdarzeń obejmują accepted, delivered, temporary_fail, permanent_fail, opened, clicked, skargi spamu i niesubskrybowane. Zdarzenia zależne od śledzenia pojawiają się tylko po włączeniu odpowiedniego śledzenia.
Bieżący Mailgun Send korpus haka ma signature obiekt obok event-data. Dane zdarzenia zawierają pola takie jak event, id, timestamp, nagłówki wiadomości, informacje odbiorcy, znaczniki i szczegóły dostawy, w zależności od typu zdarzenia. Kod przeciw udokumentowanym polom i tolerować brak właściwości opcjonalnych. Mailgun s official Przykłady ładunku są najlepszymi urządzeniami do testów kontraktowych.
Nie mylić haka Mailgun Send z Mailgun Alarmy. Wpisy używają innego klucza podpisu i podpisują całe ciało POST w X-Sign nagłówek. Niniejszy przewodnik obejmuje Haki internetowe Wyślij: pola podpisu w ładunku i konta Webhook Signing Key.
1. Zbuduj lokalny punkt końcowy Mailgun
W przeciwieństwie do schematów, które podpisują surowe ciało JSON, udokumentowane obliczenia Mailgun Send używają znacznika czasu i symbolu podpisu obiektu. Dlatego też właściwe jest standardowe parsowanie JSON. Następujący Express handler weryfikuje HMAC, przeprowadza kontrolę wieku odtwarzania i stale akceptuje zdarzenie.
import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.use(express.json({ limit: '1mb' }));
function verifyMailgunSignature({ timestamp, token, signature }) {
if (!timestamp || !token || !signature) return false;
const expected = crypto
.createHmac('sha256', process.env.MAILGUN_WEBHOOK_SIGNING_KEY)
.update(String(timestamp) + String(token))
.digest('hex');
const expectedBytes = Buffer.from(expected, 'hex');
const actualBytes = Buffer.from(String(signature), 'hex');
return expectedBytes.length === actualBytes.length &&
crypto.timingSafeEqual(expectedBytes, actualBytes);
}
app.post('/webhooks/mailgun', async (req, res) => {
const signing = req.body?.signature;
const event = req.body?.['event-data'];
if (!signing || !event || !verifyMailgunSignature(signing)) {
return res.status(406).send('invalid webhook');
}
const ageSeconds = Math.abs(Date.now() / 1000 - Number(signing.timestamp));
if (!Number.isFinite(ageSeconds) || ageSeconds > 15 * 60) {
return res.status(406).send('stale webhook');
}
await acceptOnce({
eventId: event.id,
replayToken: signing.token,
payload: event,
});
return res.sendStatus(200);
});
app.listen(3000);
15-minutowe okno jest polityką aplikacji, a nie wartością Mailgun. Mailgun zaleca sprawdzenie, czy znacznik czasu nie jest zbyt daleko od obecnego czasu, ale ostrzega przed nadmierną agresywnością, ponieważ dostawa może być opóźniona. Wybierz okno, które pasuje do Twoich wymagań kolejki i event- recovery, monitoruj uzasadnione odrzucenie i dostosowuj go celowo.
Przechowywać Webhook Signing Key w tajnym menedżerze lub zmiennej środowiskowej, nigdy w kontroli źródła. Mailgun zabezpieczenie prowadnicy haczyków definiuje dokładne obliczenie: podłączyć znacznik czasu i token bez separatora, obliczyć HMAC-SHA256 przy użyciu Webhook Signing Key i porównać sexadecimal digest z signature.
2. Wyświetlanie lokalizacji hosta nad HTTPS
Z aplikacji słuchania na porcie 3000, uruchomić:
npx portpreview 3000
Dołącz trasę lokalną do publicznego pochodzenia HTTPS. Na przykład:
https://example.portpreview.dev/webhooks/mailgun
Mailgun potrzebuje publicznie dostępnego adresu URL; localhost, prywatny adres sieci LAN i autodestrukcyjny certyfikat rozwoju nie są odpowiednimi zdalnymi miejscami. PortPreview zamyka publiczne HTTPS i przekazuje wniosek do lokalnego portu.
3. Konfiguracja Mailgun adresów zdarzeń
Mailgun obsługuje konfigurację haka internetowego na poziomie konta i domain- level. Punkty końcowe poziomu Account- level mogą odbierać zdarzenia w różnych domenach i odziedziczonych subkontach; punkty końcowe poziomu domain- level dotyczą tylko tej domeny. Każdy typ zdarzenia jest skonfigurowany indywidualnie i może mieć maksymalnie trzy adresy URL. Wybierz najwęższy zakres pasujący do aplikacji.
- Otwórz obszar Webhacks dla zamierzonego konta lub domeny wysyłania.
- Wybierz typ zdarzenia, taki jak
deliveredlubpermanent_fail. - Dodać pełny PortPreview punkt końcowy HTTPS.
- Powtórz dla każdego typu zdarzenia, który obsługuje Twój opiekun.
- Wyślij testową lub rzeczywistą wiadomość i sprawdź lokalne dzienniki zapytań i aplikacji.
Mailgun odduplikuje ten sam adres URL dla tego samego zdarzenia, gdy jest skonfigurowany zarówno na poziomie konta, jak i domeny, ale różne adresy URL mogą otrzymać kopię. Dziedziczenie konta Parent- może również powodować dostawy do wielu różnych punktów końcowych. Przegląd urzędnika zasady konfiguracji przed przydzieleniem każdej dodatkowej dostawy do powtórzenia.
Jak działa weryfikacja podpisu Mailgun
W signature obiekt zawiera:
timestampCzas Uniksa w kilka sekund.token: losowo wygenerowany ciąg 50- znaków.signature: sexodecimal HMAC digest.parent-signature: opcjonalnie obecny dla zdarzenia z subkonta, pozwalający na walidację stosunku pierwotnego rachunku opisanego przez Mailgun.
Dla zwykłego podpisu rachunku, obliczyć HMAC-SHA256(signingKey, timestamp + token). Nie ma separatora i event-data JSON nie jest częścią tego udokumentowanego obliczenia Mailgun Send. Porównaj dekodowane bajty z funkcją timing- safe po sprawdzeniu równych długości. A plain === porównanie jest prostsze, ale porównanie w bezpiecznym czasie jest bezpieczniejszym standardem produkcji.
Autentyczny HMAC dowodzi, że strona posiadająca klucz do podpisu złożyła podpis. Nie dowodzi to, że dostawa ta nie została ponownie rozegrana. Mailgun szczególnie zaleca buforowanie symbolu i odrzucenie kolejnego wniosku z tym samym symbolem. Sprawdzanie wieku i czasu ogranicza czas trwania przechwyconego ważnego żądania. Użyj obu urządzeń sterujących: unikalne ograniczenie symbolu dla powtórki i rozsądne okno czasowe dla świeżości.
Kopie zarówno dostaw, jak i skutków
Zachować dwa trwałe ograniczenia wyjątkowości: jeden dla symbolu podpisu i jeden dla Mailgun event-data.id. Symbol łapie identyczną podaną powtórkę dostawy. Identyfikator zdarzenia chroni logikę biznesową, jeśli to samo zdarzenie pojawia się w innym ważnym kontekście dostawy. Przestrzeń nazw zarówno przez dostawcę, jak i konta lub środowiska.
async function acceptOnce({ eventId, replayToken, payload }) {
await db.transaction(async (tx) => {
const tokenWasNew = await tx.webhookTokens.insertIfAbsent({
provider: 'mailgun',
token: replayToken,
});
if (!tokenWasNew) return;
const eventWasNew = await tx.webhookEvents.insertIfAbsent({
provider: 'mailgun',
eventId,
receivedAt: new Date(),
});
if (!eventWasNew) return;
await tx.jobs.enqueue({
type: 'process-mailgun-event',
payload,
});
});
}
Back the insert- if- unposit operations with database unique indicles; a read followed by an insert is race- provided under adjusting. Wydaj dane i kolejkę pracy atomicznie. Następnie szybko potwierdzić i niech pracownik uaktualnić stan wiadomości, uruchomić alarmy lub synchronizacji CRM. Patrz powtórne i idepotencja przewodnik dla alternatyw, gdy kolejka i baza danych biznesu nie mogą dzielić się transakcją.
Mailgun Kody odpowiedzi i powtórne zachowanie
Aktualna dokumentacja Send webhook Mailgun daje trzy ważne wyniki:
- Sukces: Mailgun traktuje webhook POST jako udany i nie próbuje ponownie.
- 406 Nie do przyjęcia: Mailgun traktuje POST jako odrzucony i nie próbuje ponownie.
- Każdy inny kod: w przypadku haków webowych innych niż powiadomienia o dostawie Mailgun powtarza się w ciągu ośmiu godzin w 5 minut, 10 minut, 15 minut, 1 godzinę, 2 godziny i 4 godziny.
Wyjątek od powiadomienia o dostawie ma znaczenie: nie obiecuj, że każdy typ zdarzenia jest zgodny z ogólnym harmonogramem ponownego próby. Sprawdź najnowsze automatyczne ponowne próby dokumentacji gdy gwarancja dostawy wpływa na projekt.
Używać 406 tylko dla prośby celowo odrzucić na stałe, takich jak nieprawidłowy podpis lub powtórka poza polityką. Użyj 500 lub 503 dla przejściowej bazy danych i awarii kolejki, aby kwalifikujące się typy haków webowych mogły ponownie spróbować. Powrót 200 tylko po trwałej akceptacji. Zwracanie 200 podczas rozpoczynania nieśledzonych prac w tle może stracić zdarzenie, jeśli proces się zakończy.
Rozwiązywanie problemów Mailgun
Obliczony HMAC nigdy nie pasuje
Potwierdź, że używasz Webhook Signing Key, nie klucz API, hasło SMTP, lub Wpisy podpisanie klucza. Konfiguracja znacznika czasu i symbolu sygnatury obiektu bez ogranicznika. Wyprodukuj niską sexadecimal SHA-256 digest. Sprawdź również, że Twoje ramy nie zmienił nazwę hifenatu event-data właściwość; notacja wspornika unika tego błędu.
Opiekun otrzymuje pola formularza zamiast obecnego JSON
Sprawdź, która wersja Mailgun funkcji i punktu końcowego wygenerowała żądanie. Nie należy stosować legalistycznego tutorial ładunku ślepo do bieżącego Send webhook. Typ zawartości dziennika, nazwy pól na najwyższym poziomie i długość ciała w rozwoju bez logowania treści wiadomości lub tajemnic, a następnie wdrożyć udokumentowaną umowę dla Twojego konta i integracji.
Mailgun próbuje ponownie
Sprawdź faktyczny status wysłany przez przewód. Wyjątek po włączeniu bazy danych może zmienić odpowiedź na 500, powodując kolejną próbę. Dlatego identyfikator zdarzenia i wkładki tokena muszą być unikalne i trwałe. Jeżeli żądanie jest trwale nieważne, zwróć 406; jeśli awaria jest przejściowa, napraw usługę i pozwól ponownie spróbować zachowania do pracy.
Żadne zdarzenie nie dociera do localhosta
Potwierdź, że adres URL jest dołączony do właściwego konta lub domeny oraz do produkowanego typu zdarzenia. A delivered URL nie otrzyma opened zdarzeń. Sprawdź, czy lokalny proces i tunel są nadal aktywne i czy skonfigurowana ścieżka jest /webhooks/mailgunPodążaj za lokalny poradnik debugowania haka oddzielenie konfiguracji dostawcy od błędów routingu i aplikacji.
Lista kontrolna bezpieczeństwa
- Sprawdzić HMAC przed zaufaniem lub logowaniem
event-data. - Keep the signing key in a secret store and turn it through a controlled implementation; never display it in client- side code.
- Użyj timing- bezpieczne porównanie trawienie, polityka znacznika czasu i trwałe unikalne ograniczenie na tokenie.
- Weryfikacja typu zdarzenia i wymaganych pól przed włączeniem. Traktuj adresy odbiorców, tematy, adresy URL do przechowywania i zmienne użytkownika jako dane wrażliwe.
- Akceptuj tylko POST, rozmiar cap body, użyj HTTPS i rate- limit błędów bez blokowania uzasadnionych Mailgun powtórzeń.
- Nie narażać niepowiązanych lokalnych admin lub debug punktów końcowych poprzez tymczasowe pochodzenie publiczne.
- Po zakończeniu badania usunąć tymczasowy adres URL i skonfigurować stabilny punkt końcowy produkcji.
Mailgun również dokumentuje opcjonalny certyfikat klienta TLS na żądanie haka WWW, gdy serwer odbiorczy posiada ważny TLS. Może to zapewnić walidację poziomu transportowego, ale nie zastępuje weryfikacji HMAC ładunku, kontroli powtórnej i autoryzacji aplikacji. Warstwa kontroluje według twojego modelu zagrożenia.
Badania akceptacji produkcji
- Dostarcz ważne podpisane urządzenie i potwierdź jedno trwałe zdarzenie plus odpowiedź 200.
- Zmień token bez zmiany podpisu i potwierdzić 406 bez zapisu zdarzenia.
- Ponownie odtworzyć poprawny organ i potwierdzić brak drugiej pracy lub efekt uboczny.
- Wyślij prawidłową sygnaturę z znacznikiem czasu na zewnątrz skonfigurowanego okna i zweryfikuj zamierzone odrzucenie.
- Wymusić tymczasowy błąd bazy danych, potwierdzić odpowiedź non-200 / non-406, a następnie przywrócić bazę danych i zweryfikować jedną pozytywną akceptację.
- Ćwicz każdy skonfigurowany typ zdarzenia Mailgun, ponieważ pola obciążenia i oczekiwania ponownego próby są różne.
Po przejściu tych testów należy zastosować tę samą ścieżkę weryfikacji i odtworzenia produkcji. W celu uzyskania niezależnego od dostawcy wyjaśnienia porównania HMAC i tajnej obsługi, przeczytaj Przewodnik weryfikacji podpisu haka webowego.
