Skip to content

Latest commit

Β 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Resend Email Webhook + Inspector for DigitalOcean

A Flask webhook application for receiving and inspecting inbound emails from Resend. Includes a built-in web interface to view and debug incoming emails in real-time. Ready to deploy to DigitalOcean App Platform with one click.

Features

  • πŸ” Email Inspector - Web interface to view and debug incoming emails in real-time
  • πŸ“§ Webhook Receiver - Processes email.received events from Resend
  • πŸ“Š Email Dashboard - View sender, recipients, subject, attachments at a glance
  • πŸ”Œ JSON API - Programmatic access to recent emails via /emails/json
  • πŸ’Ύ In-Memory Storage - Keeps last 20 emails for quick debugging (resets on restart)
  • πŸš€ One-Click Deploy - Deploy to DigitalOcean App Platform instantly
  • πŸ“ Detailed Logging - All webhook events logged for debugging
  • ❀️ Health Monitoring - Built-in health check endpoint

Prerequisites

Before deploying, you'll need:

  1. Resend Account - Sign up at resend.com
  2. Inbound Email Address - Set up in Resend:
    • Go to Resend Dashboard
    • Navigate to Emails β†’ Receiving
    • Follow the instructions to get your inbound email address (e.g., anything@yourdomain.resend.app)
    • Any email sent to this address will trigger your webhook
  3. DigitalOcean Account - Sign up at digitalocean.com (optional for local testing)

Quick Deploy to DigitalOcean

Deploy this app to DigitalOcean App Platform with one click:

Deploy to DO

After deployment:

  1. Get your app URL from DigitalOcean (e.g., https://resend-webhook-xxxxx.ondigitalocean.app)
  2. Configure webhook in Resend:
  3. Test it:
    • Send an email to your Resend inbound address
    • Visit https://your-app-url.ondigitalocean.app/emails to see it in the inspector!

Or fork and deploy manually - See detailed deployment instructions below.


Setup

1. Install Dependencies

# Create a virtual environment (recommended)
python3 -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

2. Configure Resend Webhook

  1. Go to your Resend Dashboard
  2. Navigate to Webhooks section
  3. Click Add Webhook
  4. Enter your webhook URL (e.g., https://yourdomain.com/webhook)
  5. Select the event type: email.received
  6. Click Add

3. Set Up Inbound Email Address

  1. In Resend dashboard, go to Emails β†’ Receiving
  2. View your inbound address (e.g., anything@your-domain.resend.app)
  3. Any email sent to this address will trigger the webhook

Running the Application

Local Development

# Run the Flask app
python app.py

The app will run on http://localhost:8080 by default.

View received emails:

  • Open http://localhost:8080/emails in your browser to see the email viewer
  • Send a test email to your Resend inbound address
  • Refresh the page to see new emails appear

Testing Locally with ngrok

To test webhooks locally, use ngrok:

# Install ngrok (if not already installed)
# Then expose your local server
ngrok http 8080

# Use the ngrok URL (e.g., https://abc123.ngrok.io/webhook) 
# as your webhook endpoint in Resend

Production Deployment

For production, use gunicorn:

gunicorn -w 4 -b 0.0.0.0:8080 app:app

Manual Deployment to DigitalOcean

If you want to customize the app before deploying, follow these steps:

Method 1: Fork and Deploy

  1. Fork this repository on GitHub
  2. Click the deploy button above (it will use your forked repo)
  3. Or manually deploy:
    • Go to DigitalOcean App Platform
    • Click Create App
    • Choose GitHub and select your forked repository
    • DigitalOcean will auto-detect settings from the Procfile
    • Click Deploy

Method 2: Deploy Your Own Repo

  1. Clone and customize:

    git clone https://github.com/ajot/resend-webhook.git
    cd resend-webhook
    # Make your changes
  2. Create your own GitHub repo:

    gh repo create your-resend-webhook --public --source=. --remote=origin
    git push -u origin main
  3. Deploy to DigitalOcean:

    • Go to DigitalOcean App Platform
    • Click Create App
    • Choose GitHub as your source
    • Select your repository
    • DigitalOcean will auto-detect Python and use the Procfile
    • Important: Leave "Run Command" empty (let the Procfile handle it)
    • Choose your plan (Basic $5/month is sufficient)
    • Click Create Resources
  4. Configure Resend Webhook:

    • Once deployed, get your app URL (e.g., https://your-app-xxxxx.ondigitalocean.app)
    • Go to Resend Dashboard β†’ Webhooks
    • Add webhook: https://your-app-xxxxx.ondigitalocean.app/webhook
    • Select event: email.received

Files for DigitalOcean Deployment

  • βœ… Procfile - Specifies how to run the app (gunicorn command)
  • βœ… requirements.txt - Python dependencies (includes gunicorn)
  • βœ… app.py - Main Flask application (configured for port 8080)
  • βœ… .do/deploy.template.yaml - One-click deployment configuration

Troubleshooting Deployment

Error: "No application module specified"

  • This happens when the Run Command is incomplete or incorrect
  • Solution: Go to Settings β†’ Components β†’ web β†’ Run Command
  • Either leave it empty (recommended - uses Procfile) or set it to gunicorn app:app
  • Never use a partial command like gunicorn --worker-tmp-dir /dev/shm without app:app

Build fails with "invalid Procfile entry"

  • Check for extra blank lines in your Procfile
  • Procfile should contain only: web: gunicorn app:app

App deployed but webhook not working

  • Check your Resend webhook URL includes /webhook at the end
  • Verify event type is set to email.received (not email.delivered)
  • Check the app logs in DigitalOcean for error messages

Custom Domain (Optional)

  1. In App Platform, go to Settings β†’ Domains
  2. Add your custom domain
  3. Follow DNS configuration instructions
  4. Update your Resend webhook URL to use the custom domain

API Endpoints

POST /webhook

Receives inbound email webhook events from Resend.

Expected Payload:

{
  "type": "email.received",
  "created_at": "2024-02-22T23:41:12.126Z",
  "data": {
    "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
    "created_at": "2024-02-22T23:41:11.894719+00:00",
    "from": "Acme <onboarding@resend.dev>",
    "to": ["delivered@resend.dev"],
    "bcc": [],
    "cc": [],
    "message_id": "<example+123>",
    "subject": "Sending this example",
    "attachments": [
      {
        "id": "2a0c9ce0-3112-4728-976e-47ddcd16a318",
        "filename": "avatar.png",
        "content_type": "image/png",
        "content_disposition": "inline",
        "content_id": "img001"
      }
    ]
  }
}

Response:

{
  "status": "success",
  "message": "Email processed successfully",
  "result": {
    "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
    "processed_at": "2024-02-22T23:41:12.126Z",
    "status": "processed"
  }
}

GET /emails

Web interface to view recent received emails.

Features:

  • Displays last 20 emails in a responsive table
  • Shows: timestamp, from, to, subject, attachment count
  • Click "View Details" to see full email payload
  • Empty state when no emails received yet
  • Styled with Tailwind CSS

Access: Visit https://your-app-url.ondigitalocean.app/emails in your browser

GET /emails/json

Returns recent emails as JSON for programmatic access.

Response:

{
  "emails": [
    {
      "email_id": "56761188-7520-42d8-8898-ff6fc54ce618",
      "from": "sender@example.com",
      "to": ["recipient@example.com"],
      "cc": [],
      "bcc": [],
      "subject": "Test email",
      "message_id": "<message@example.com>",
      "attachments": [],
      "created_at": "2024-02-22T23:41:11.894719+00:00",
      "processed_at": "2024-02-22T23:41:12.126Z"
    }
  ],
  "count": 1
}

GET /health

Health check endpoint.

Response:

{
  "status": "healthy"
}

Customization

Edit the process_inbound_email() function in app.py to add your custom logic:

  • Store emails in a database
  • Forward emails to another service
  • Parse email content
  • Download and process attachments
  • Send notifications
  • etc.

Environment Variables

  • PORT - Port to run the application on (default: 8080)

Notes

  • Email storage: Emails are stored in-memory (last 20 emails). Data resets when the app restarts. For production, consider using a database.
  • The webhook currently logs all email data. Adjust logging levels in production.
  • Attachment metadata is included, but actual attachment content would need to be fetched separately if needed.
  • Consider adding webhook signature verification for production use.
  • The /emails viewer is great for demos and testing. For production dashboards, build a proper frontend with persistent storage.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages