...
Code Block | ||
---|---|---|
| ||
rule mail_router { select when mail parsed to re#assigned_id_2[+]([^@]*)@cloudmailin.net# setting(eci) event:send({"eci":eci, "domain":"testmail", "type":"testevents", "attrs":event:attrs()}) } |
...
The redacted "assigned_id_4" is an ECI of another pico to which the rule (in line 3) sends the testmail:testevents
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.
...
In this example, the other 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 a new ruleset and add it to the same pico. Shown here is a global definition and a rule that reacts to the testmail:testevents
event.
Code Block | ||
---|---|---|
| ||
global { newline = (13.chr() + "?" + 10.chr()).as("RegExp") } rule testmail_testevents { select when testmail testevents foreach event:attr("text").split(newline) setting(request) pre { parts = request.split(re#/#) aurora = parts.length() == 2 && parts[0] == "aurora" } if aurora then noop() fired { raise aurora event parts[1] } } |
...
Upon receipt of this email message, our Mail pico will extract the "To" field and the "text" of the message body, and begin a cascade of events. Next, the same pico will parse out the ECI ("assigned_id_4") of the Aurora pico and send it the testmail:testevents
event. This will trigger its new rule which will loop over the lines of the message body, ignoring comment lines, and raise a series of three events, which the existing ruleset will handle to turn the NanoLeaf display on and move through to the second-next theme.
...
Code Block | ||
---|---|---|
| ||
global { newline = (13.chr() + "?" + 10.chr()).as("RegExp") var = function(s) { p = s.split(re#=#); {}.put(p[0],p[1]) } vars = function(s) { p = s=>s.split(re#&#)|[]; p.reduce(function(a,b){a.put(var(b))},{}) } parse = function(text,domain) { dlpo = domain.length() + 1; text.split(newline) .filter(function(v){p=v.split(re#/#);p[0]==domain && p.length()==2}) .map(function(v){p=v.split(re#[?]#);[p[0].substr(dlpo),vars(p[1])]}) } } rule testmail_testevents { select when testmail testevents foreach parse(event:attr("text"),"aurora") setting(request) pre { type = request[0] attrs = request[1] } if request.length() == 2 then noop() fired { raise aurora event type attributes attrs; ent:lastRequest := "aurora/"+type } } |
...
The rule loops over the parsed events (line 20), setting the type (line 22) and attributes (line 23) of each, and raises the corresponding events (line 27).
Update
The complete ruleset 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, 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 include a clause in their meta
block like
Code Block |
---|
use module io.picolabs.mail alias mail |
so that parsing can be done with a line like
Code Block |
---|
foreach mail:parse(event:attr("text"),"aurora") setting(request) |
This is a basic use of User Defined Modules and has the advantage that the parsing functions do not need to be replicated into a ruleset for every pico which needs them.