Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

In this cookbook recipe, we're going to show how you can raise events to a pico using an external mail service, like mainIn. Transforming a mail message into an event isn't too difficult. The fun part is in parsing the body of the email to take further action. This recipe shows how to do that too. 

Making a localhost engine available to the outside world

You'll need to have access to an email address that can be used. This implies also having access to a domain name. This can be challenging if you are running a node pico engine locally.

Making a localhost engine available to the outside world

Here at Pico Labs, we have a pico engine running on a Rapberry Raspberry Pi 3, and make it available to the outside world by using ngrok which supplies "secure introspectable tunnels to localhost". This means that our engine can be accessed at https://assigned_id_1.ngrok.io etc. where "assigned_id_1" is a pseudo-random identifier given to us by ngrok. (The actual ID is redacted here, to avoid denial of service attacks, because ngrok only allows us 20 uses per minute.) Another alternative is PageKite, but we'll use ngrok in this cookbook.

Obtaining an email address that forwards to a webhook

Here we will show how to use CloudMailin which is a cloud service that assigns us an email address, which we can configure so that it does an HTTP POST to a webhook that we supply. We redact the actual address as "assigned_id_2" because CloudMailin only allows us 200 incoming email messages per month. The address we are using is assigned_id_2@cloudmailin.net

We have configured it to use https://assigned_id_1.ngrok.io/sky/event/assigned_id_3<eci>/eid/mail/received where "assigned_id_3<eci>" is an ECI (event channel identifier) which we created for the pico which we will be using to respond to mail:received events.  We'll call that assigned_id_3. 

It should also be possible to install, configure, and run your own mailin server, but here we will use the CloudMailin service.

A ruleset that handles the mail:received event

We created a pico, named Mail, and added a new channel with type "secret" and name "incoming mail", whose id is known here as assigned_id_3<eci>, and added a ruleset containing this rule

...

This rule logs many things (and these log messages could be removed in a production application), extracts a few simple items from the incoming message and headers, and raises a new mail:parsed event supplying those items as event attributes. You may wish to add rules in this or another ruleset for use within the Mail pico to respond to the mail:parsed event. In our case, we wanted to pass the event on to another pico.

Forwarding to another pico

For this purpose, the same ruleset also contains a rule which is triggered by this mail:parsed event, which parses out the ECI of the other pico from the "To" email address.

Code Block
linenumberstrue
  rule mail_reactionrouter {
    select when mail parsed to re#assigned_id_2[+]([^@]*)@cloudmailin.net# setting(eci)
    event:send({"eci":eci, "domain":"test", "type":"test", "attrs":event:attrs()})
  }

...

The redacted "assigned_id_4" is an ECI of another pico to which the rule (in line 3) sends the test:test event with parsed fields from the email message as attributes. We created a new channel for this purpose, with name "email tests" and type "secret" whose id is known herein as "assigned_id_4". This is easily done in the "Channels" tab of the developer UI.

...

Code Block
linenumberstrue
  global {
    newline = (13.chr() + "?" + 10.chr()).as("RegExp")
  }
  rule test_test {
    select when test test
    foreach event:attr("text").split(newline) setting(request)
    pre {
      parts = request.klog("REQUESTED_EVENT").split(re#/#)
      aurora = parts.length() == 2 && parts[0] == "aurora"
    }
    if aurora then noop()
    fired {
      raise aurora event parts[1]
    }
  }

...

Each line is split into parts using a forward slash as a separator. We ignore any lines which do not begin "aurora/" followed by just one slash-separated string of characters. They are ignored because the rule won't fire for such lines. For lines which match our expectation, in line 13 we raise an aurora event whose type is parts[1] (the second slash-separated string of characters).

Sample email message

A sample email message might look like this:

...

The person composing the email message needs some knowledge of the events understood by the Aurora pico, but doesn't need to know where its pico is hosted, just the email address to which the message must be sent.

Caveats

In general, the most difficult part of turning an incoming email message into an event is parsing the message body to determine what further events need to be raised.

...

You will want to thoroughly test your rules before putting this cookbook into production.

Extended parsing

This modification to the rule in the Aurora pico which parses the incoming email message shows how we can extend the mini-language to include event attributes. Basically, lines in the message follow the syntax of standard event URL's starting with the domain portion, so that a line like

...