Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: added a strategy section and diagram

In this cookbook recipe, we're going to show how you can raise events to a pico using an external mail service, like mailin. 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. 

Strategy overview

An incoming email message (1) will be transformed into a webhook. The webhook will be received (2) by the pico engine as an event for a mail routing pico. This pico will select some fields from the email message and pass these on to another rule (3). This rule will identify the target pico--the logical final recipient of the original email message--and send it an event which includes the body of the email message (4). The target pico will use functions provided (5) by the mail pico to parse the message body and will then raise (i.e. send to itself) the events (6) represented therein. We will define a simple language which will allow Alice to specify a list of events in the body of her email message.

Image Added

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.

Here at Pico Labs, we have a pico engine running on a 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/<eci>/eid/mail/received where "<eci>" is an ECI (event channel identifier) which we created for the mail pico which we will be using to respond to mail:received events.  We'll call that 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.

...

We created a pico, named Mail, and added a new channel with type "secret" and name "incoming mail", whose id is known here as <eci>, and added is "assigned_id_3". It has 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, the target 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 target pico from the "To" email address.

...

This rule is only selected when the "to" address matches the regular expression in line 2. The construct [+] matches a literal plus sign, and the capture group ([^@]*) matches all characters up to the next at sign. The setting clause binds the captured characters as the value of the eci identifier. This ECI is how we refer to the target pico which is to handle the incoming email message.

...

The redacted "assigned_id_4" is an ECI of another the target pico to which the mail_router rule (in line 3) sends the mail:events event with parsed selected 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.

Further processing of an incoming email message

In this example, the other target pico has a ruleset which handles numerous events with domain "aurora" and controls a set of 12 Nanoleaf Aurora units. Rather than modify the existing ruleset, we make made a new ruleset and add it to the same pico. Shown here is a global definition and a rule that reacts to the mail:events event.

...

Update

The complete ruleset for the Mail Pico that first receives email, and reacts to the mail:received event, can be found at https://github.com/Picolab/pico_lessons/blob/master/mailin/io.picolabs.mail.krl and nearby is the ruleset to test this with Aurora, the target pico, at https://github.com/Picolab/pico_lessons/blob/master/mailin/aurora_test.krl

We moved the parsing functions into the io.picolabs.mail ruleset, which provides them to rulesets which might want to react to the mail:events event. Such rulesets can would include a clause in their meta block like

...