How to handle incoming emails with Mailgun in C# MVC

I’m working on a C# MVC project and need to build an endpoint that processes incoming emails sent through Mailgun’s forwarding service. I found their documentation but the example is written in Python which I’m not comfortable with.

Here’s their Python sample:

def handle_email_webhook(request):
    if request.method == 'POST':
        from_email = request.POST.get('sender')
        to_email = request.POST.get('recipient') 
        email_subject = request.POST.get('subject', '')
        
        plain_content = request.POST.get('body-plain', '')
        clean_text = request.POST.get('stripped-text', '')
        
        # handle file uploads
        for file_key in request.FILES:
            uploaded_file = request.FILES[file_key]
            # process the attachment
            
    # Return 200 status or Mailgun will retry in 5 minutes
    return HttpResponse('OK')

Can someone show me how to create a similar controller action in C# that extracts the email data from the POST request? Any working example would be really helpful.

I’ve been handling Mailgun webhooks in ASP.NET MVC for two years - here’s what actually works. Set up a controller action that takes form data since Mailgun sends everything as form-encoded POST. Use Request.Form to grab the fields directly instead of model binding. The field names have hyphens and they don’t mesh well with C# properties.

[HttpPost]
public ActionResult ProcessInboundEmail()
{
    var sender = Request.Form["sender"];
    var recipient = Request.Form["recipient"];
    var subject = Request.Form["subject"] ?? string.Empty;
    var bodyPlain = Request.Form["body-plain"] ?? string.Empty;
    var strippedText = Request.Form["stripped-text"] ?? string.Empty;
    
    // Handle attachments
    foreach (string fileKey in Request.Files)
    {
        var file = Request.Files[fileKey];
        if (file != null && file.ContentLength > 0)
        {
            // Process your attachment here
        }
    }
    
    return new HttpStatusCodeResult(200, "OK");
}

Add [ValidateInput(false)] if you’re processing HTML content, or ASP.NET will throw validation errors for potentially dangerous input.

The signature verification totally caught me off guard. Mailgun sends security tokens that you need to validate - otherwise spam bots will hammer your endpoint. I’d create a model class to keep things clean, even though the form fields have hyphens. Just map them manually.

public class MailgunInboundModel
{
    public string Sender { get; set; }
    public string Recipient { get; set; }
    public string Subject { get; set; }
    public string BodyPlain { get; set; }
    public string Timestamp { get; set; }
    public string Token { get; set; }
    public string Signature { get; set; }
}

[HttpPost]
public ActionResult HandleInbound()
{
    var model = new MailgunInboundModel
    {
        Sender = Request.Form["sender"],
        Recipient = Request.Form["recipient"],
        Subject = Request.Form["subject"],
        BodyPlain = Request.Form["body-plain"],
        Timestamp = Request.Form["timestamp"],
        Token = Request.Form["token"],
        Signature = Request.Form["signature"]
    };
    
    // Verify webhook authenticity here
    
    return new HttpStatusCodeResult(HttpStatusCode.OK);
}

Also make sure to whitelist your endpoint URL in the Mailgun control panel under Routes configuration.

heads up - disable CSRF protection for that endpoint or you’ll get 500 errors when mailgun posts. Add [ValidateAntiForgeryToken(false)] or exclude the route from antiforgery checks in your config. learned this the hard way when my webhook kept failing