Jun 11 2013

Using Cloudmailin’ with ASP.NET MVC

Category: ASP.NET | Cloud | MVC | PowerShellMatt @ 12:23

I’m building an ASP.NET MVC app that receives E-mail via Cloudmailin.com’s service.   In this post, I’ll show you how to create a handler for Cloudmailin using MVC, and I’ll show you how to test that handler locally.

Receiving Data From Cloudmailin

Cloudmailin is a service that takes E-mail messages and posts them to a URL in your app.  You get a special ‘@cloudmailin.net' address, tell Cloudmailin the URL to send mail to and the format you want it in, and it will automagically route E-mail messages to your app.  While the service is great, the docs on how to get the data flowing in are a bit sparse.  Most everything seems to be written for non-Windows platforms.   It took a little trial-and-error to get it working.

First, set up your target, and set the format to JSON, like so:

image

Cloudmailin will now POST to your app using JSON as the message format.  Your app will receive something that looks like this:

{
  "headers": {
    "Received": [
      "by mail-pa0-f44.google.com with SMTP id lj1so2917442pab.31 for <__________@cloudmailin.net>; Tue, 11 Jun 2013 17:40:31 -0700",
      "by 10.70.84.135 with HTTP; Tue, 11 Jun 2013 17:40:11 -0700"
    ],
    "Date": "Tue, 11 Jun 2013 19:40:11 -0500",
    "From": "Matt Honeycutt <__________@gmail.com>",
    "To": "__________@cloudmailin.net",
    "Message-ID": "<__________@mail.gmail.com>",
    "Subject": "Yet Another Test",
    "Mime-Version": "1.0",
    "Content-Type": "multipart/alternative; boundary=047d7b2e4bc4cafcba04deea4258",
    "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to:content-type; bh=cA+qrBZn8gz9uh92/Xj0GNGYDtszswE7aduxu9S51lk=; b=NyBrEPQYN9EMOkz55i7sx7cMT48IcrSX6p4vAkBNSi+sfDPhDO2tsUD6ngnLSUNc7a Qy0qhETa/SSlZtkUtkkfazr/hmPgv6Gg9IQe3/mfdhqxpotO6mE5LFx3dJ4/ZqmtAWvf B94m+LFs2NEsDcKYjsFqnqXdVhVsipmQEqjzfur+UpcWtvmte6Cnt4v3WjLVUBIAwVGI knc0Xd7NT8O9Oh3aecLgvS9gDiRSuWMJiLdXNLA5h54O8PR5X7oTVfIEkBi4Jkdjkc62 w9ysjXkbIeHOOtJ/KWwNjBrSOKjqyosv9cvRhUiy3Gpblo4UHOiwKtvUidX090NynhKq rGNQ==",
    "X-Received": "by 10.66.122.68 with SMTP id lq4mr21095787pab.78.1370997631152; Tue, 11 Jun 2013 17:40:31 -0700 (PDT)"
  },
  "envelope": {
    "to": "__________@cloudmailin.net",
    "recipients": [
      "__________@cloudmailin.net"
    ],
    "from": "__________@gmail.com",
    "helo_domain": "mail-pa0-f44.google.com",
    "remote_ip": "__________",
    "spf": {
      "result": "neutral",
      "domain": "gmail.com"
    }
  },
  "plain": "Testing!\nAgain!\n",
  "html": "<div dir=\"ltr\">Testing!<div>Again!</div></div>\n",
  "reply_plain": null,
  "attachments": [

  ]
}

You’ll need a model in your MVC app that can deserialize this data.  Here’s what I came up with. 

public class MailinData
{
    public class MailHeaders
    {
        public string From { get; set; }

        public string Subject { get; set; }
    }

    public class MailEnvelope
    {
        public string From { get; set; }
    }

    public MailEnvelope Envelope { get; set; }

    public MailHeaders Headers { get; set; }

    public string Plain { get; set; }

    public string Html { get; set; }

    public string Reply_Plain { get; set; }
}

It only handles the properties I care about.  You can add additional properties to the model if you wish to capture them from the incoming data.

Finally, just create an action method to handle the incoming data.  Remember to decorate it accordingly so that HTML mail can come in, and be sure to allow anonymous requests:

public class YourController : Controller
{
    [HttpPost, AllowAnonymous, ValidateInput(false)]
    public ActionResult FromMail(MailinData data)
    {
        return Content("Hi!, " + data.Headers.From);
    }
}

Now you can send an E-mail through Cloudmailin and receive it in your ASP.NET MVC app!

Testing Cloudmailin Locally with Powershell 3.0

Cloudmailin has some documentation about testing locally, but it was clearly not written with a Windows developer in mind.  You can use their WebHook approach for capturing the body of a message for testing, but good luck getting the CURL command it gives you to work.  CURL does work on Windows, but I prefer the new Invoke-RestMethod cmdlet that ships with Powershell 3.0.

Here’s a simple script you can use to test locally.

#1) Set this to the URL to your app running locally
$url = "http://localhost:57372/mailticket"

#2) Populuate this variable with the JSON body you captured using Webhook
$data = @"
{
  "headers": {
    "Received": [
      "by mail-pa0-f44.google.com with SMTP id lj1so2917442pab.31 for <__________@cloudmailin.net>; Tue, 11 Jun 2013 17:40:31 -0700",
      "by 10.70.84.135 with HTTP; Tue, 11 Jun 2013 17:40:11 -0700"
    ],
    "Date": "Tue, 11 Jun 2013 19:40:11 -0500",
    "From": "Matt Honeycutt <__________@gmail.com>",
    "To": "__________@cloudmailin.net",
    "Message-ID": "<__________@mail.gmail.com>",
    "Subject": "Yet Another Test",
    "Mime-Version": "1.0",
    "Content-Type": "multipart/alternative; boundary=047d7b2e4bc4cafcba04deea4258",
    "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to:content-type; bh=cA+qrBZn8gz9uh92/Xj0GNGYDtszswE7aduxu9S51lk=; b=NyBrEPQYN9EMOkz55i7sx7cMT48IcrSX6p4vAkBNSi+sfDPhDO2tsUD6ngnLSUNc7a Qy0qhETa/SSlZtkUtkkfazr/hmPgv6Gg9IQe3/mfdhqxpotO6mE5LFx3dJ4/ZqmtAWvf B94m+LFs2NEsDcKYjsFqnqXdVhVsipmQEqjzfur+UpcWtvmte6Cnt4v3WjLVUBIAwVGI knc0Xd7NT8O9Oh3aecLgvS9gDiRSuWMJiLdXNLA5h54O8PR5X7oTVfIEkBi4Jkdjkc62 w9ysjXkbIeHOOtJ/KWwNjBrSOKjqyosv9cvRhUiy3Gpblo4UHOiwKtvUidX090NynhKq rGNQ==",
    "X-Received": "by 10.66.122.68 with SMTP id lq4mr21095787pab.78.1370997631152; Tue, 11 Jun 2013 17:40:31 -0700 (PDT)"
  },
  "envelope": {
    "to": "__________@cloudmailin.net",
    "recipients": [
      "__________@cloudmailin.net"
    ],
    "from": "__________@gmail.com",
    "helo_domain": "mail-pa0-f44.google.com",
    "remote_ip": "__________",
    "spf": {
      "result": "neutral",
      "domain": "gmail.com"
    }
  },
  "plain": "Testing!\nAgain!\n",
  "html": "<div dir=\"ltr\">Testing!<div>Again!</div></div>\n",
  "reply_plain": null,
  "attachments": [

  ]
}
"@

#3) Run this to send the message to your app!
Invoke-RestMethod -Body $data -Uri $url -Method POST -ContentType "application/json"

Plug in values for the variables at the top of the script, run it, and you should be all set!

Tags: , , , ,

blog comments powered by Disqus