Implemented a production-ready TypeScript/Express.js service to receive and log MailGun webhook events (delivered, failed, opened, clicked, etc.). Key features: - Webhook endpoint (POST /webhook) with comprehensive event logging - Full TypeScript type definitions for all MailGun event types - Prometheus metrics integration for monitoring - Health check endpoint (GET /ping) - Comprehensive Jest test suite with 87.76% coverage - Docker containerization with build scripts Removed template/example code: - All SQL/MSSQL dependencies and related code - Example auth router and middleware - PRTG metrics support (simplified to Prometheus only) - Unused middleware (CORS, IP whitelist, request parsing/validation) - Template documentation (kept only MailGun webhook API spec) The service is clean, minimal, and focused solely on receiving and logging MailGun webhook events to the console. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
177 lines
5.0 KiB
Markdown
177 lines
5.0 KiB
Markdown
# MailGun Webhook API Specification
|
|
|
|
## Overview
|
|
|
|
This document specifies the API for receiving webhook events from MailGun. The service logs all received event data to the console for monitoring and debugging purposes.
|
|
|
|
## API Endpoints
|
|
|
|
### POST /webhook
|
|
|
|
Receives webhook events from MailGun when email events occur.
|
|
|
|
#### Request Format
|
|
|
|
- **Method**: POST
|
|
- **Content-Type**: `application/x-www-form-urlencoded` or `multipart/form-data`
|
|
- **Headers**:
|
|
- No custom headers required for initial implementation
|
|
|
|
#### Request Parameters
|
|
|
|
MailGun sends various parameters depending on the event type. Common parameters include:
|
|
|
|
**Event Identification:**
|
|
- `event` (string) - Type of event (delivered, failed, opened, clicked, bounced, complained, unsubscribed)
|
|
- `timestamp` (number) - Unix timestamp when the event occurred
|
|
- `token` (string) - Randomly generated string for message signature verification
|
|
- `signature` (string) - String with hexadecimal digits for signature verification
|
|
|
|
**Message Information:**
|
|
- `message-id` (string) - MailGun message ID
|
|
- `recipient` (string) - Email address of the recipient
|
|
- `domain` (string) - Domain from which the email was sent
|
|
- `Message-Id` (string) - SMTP Message-ID header
|
|
|
|
**Event-Specific Parameters:**
|
|
|
|
For **delivered** events:
|
|
- `message-headers` (string) - JSON string of message headers
|
|
|
|
For **failed** events:
|
|
- `severity` (string) - Severity level (temporary/permanent)
|
|
- `reason` (string) - Reason for failure
|
|
- `notification` (string) - Detailed notification message
|
|
|
|
For **opened** events:
|
|
- `city` (string) - City where email was opened
|
|
- `country` (string) - Country code
|
|
- `device-type` (string) - Device type (desktop/mobile/tablet)
|
|
- `client-os` (string) - Operating system
|
|
- `client-name` (string) - Email client name
|
|
- `ip` (string) - IP address
|
|
|
|
For **clicked** events:
|
|
- `url` (string) - URL that was clicked
|
|
- `city`, `country`, `device-type`, `client-os`, `client-name`, `ip` - Same as opened events
|
|
|
|
For **bounced** events:
|
|
- `code` (string) - SMTP error code
|
|
- `error` (string) - Detailed error message
|
|
- `notification` (string) - Bounce notification
|
|
|
|
For **complained** events:
|
|
- No additional parameters
|
|
|
|
For **unsubscribed** events:
|
|
- No additional parameters
|
|
|
|
#### Success Response
|
|
|
|
- **HTTP Status**: 200 OK
|
|
- **Content-Type**: `application/json`
|
|
- **Response Body**:
|
|
```json
|
|
{
|
|
"status": "received",
|
|
"message": "Webhook event logged successfully"
|
|
}
|
|
```
|
|
|
|
#### Error Responses
|
|
|
|
**Invalid Request (400 Bad Request)**:
|
|
- **Content-Type**: `application/json`
|
|
- **Response Body**:
|
|
```json
|
|
{
|
|
"error": "Invalid request format"
|
|
}
|
|
```
|
|
|
|
**Server Error (500 Internal Server Error)**:
|
|
- **Content-Type**: `application/json`
|
|
- **Response Body**:
|
|
```json
|
|
{
|
|
"error": "Internal server error"
|
|
}
|
|
```
|
|
|
|
## Execution Flow
|
|
|
|
1. **Receive webhook POST request** from MailGun
|
|
2. **Parse request body** (form-urlencoded or multipart data)
|
|
3. **Extract event data** from request parameters
|
|
4. **Log event data to console** with structured formatting:
|
|
- Event type
|
|
- Timestamp (both Unix and human-readable)
|
|
- Recipient
|
|
- All additional event-specific parameters
|
|
5. **Return success response** to MailGun
|
|
|
|
## Edge Cases
|
|
|
|
### Missing Event Type
|
|
- **Detection**: Check if `event` parameter is present
|
|
- **Handling**: Log warning and return 400 Bad Request
|
|
|
|
### Malformed Timestamp
|
|
- **Detection**: Check if `timestamp` can be parsed as number
|
|
- **Handling**: Log with current timestamp instead, continue processing
|
|
|
|
### Large Payload
|
|
- **Detection**: Monitor request body size
|
|
- **Handling**: Log truncated data if exceeds reasonable size
|
|
|
|
### Duplicate Events
|
|
- **Detection**: MailGun may send duplicate webhooks
|
|
- **Handling**: Log all events (no deduplication in initial implementation)
|
|
|
|
## Security Considerations
|
|
|
|
### Future Enhancements
|
|
For production deployment, consider:
|
|
- **Signature Verification**: Verify webhook authenticity using `timestamp`, `token`, and `signature`
|
|
- **IP Whitelisting**: Restrict to MailGun's IP ranges
|
|
- **Rate Limiting**: Prevent abuse
|
|
|
|
## Database Integration
|
|
|
|
- **Current Implementation**: No database operations required
|
|
- **Future Enhancement**: Store events in database for analysis
|
|
|
|
## Third-Party API Calls
|
|
|
|
- **Current Implementation**: No third-party API calls
|
|
- **Future Enhancement**: Could integrate with notification services
|
|
|
|
## Logging Format
|
|
|
|
Console output format:
|
|
```
|
|
========================================
|
|
MailGun Webhook Event Received
|
|
========================================
|
|
Event Type: delivered
|
|
Timestamp: 1234567890 (2024-01-01 12:00:00 UTC)
|
|
Recipient: user@example.com
|
|
Domain: mail.example.com
|
|
Message ID: <20240101120000.1.ABC123@mail.example.com>
|
|
----------------------------------------
|
|
Additional Parameters:
|
|
{
|
|
"message-headers": "[...]",
|
|
"token": "...",
|
|
"signature": "..."
|
|
}
|
|
========================================
|
|
```
|
|
|
|
## Implementation Notes
|
|
|
|
- Use Express body-parser middleware for form data parsing
|
|
- All logging should use structured logger (debug package)
|
|
- Maintain type safety with TypeScript interfaces for event data
|
|
- Follow template's error handling patterns
|