-3

I regularly receive emails from the same person, each containing one or more unique identifying codes. I need to get those codes.

The email body contains a host of inconsistent email content, but it is the strings I am interested in. They look like...

  • loYm9vYzE6Z-aaj5lL_Og539wFer0KfD
  • FuZTFvYzE68y8-t4UgBT9npHLTGmVAor
  • JpZDRwYzE6dgyo1legz9sqpVy_F21nx8
  • ZzZ3RwYzE63P3UwX2ANPI-c4PMo7bFmj

What the strings seem to have in common is, they are all 32 characters in length and all composed of a mixture of both uppercase, lowercase, numbers and symbols. But a given email may contain none, one or multiple, and the strings will be in an unpredictable position, not on adjacent lines as above.

I wish to make a Zap workflow in Zapier, the linking tool for web services, to find these strings and use them in another app - ie. whenever a string is found, create a new Trello card.

I have already started the workflow with Zapier's "Gmail" integration as a "trigger", specifically a search using the "from:" field corresponding to the regular sender. That's the easy part.

But the actual parsing of the email body is foxing me. Zapier has a rudimentary email parser, but it is not suitable for this task. What is suitable is using Zapier's own "Code" integration to execute freeform code - namely, a regular expression to identify those strings.

I have never done this before and am struggling to formulate working code. Zapier Code can take either Python (documentation) or Javascript (documentation). It supports data variables "input_data" (Python) or "inputData" (Javascript) and "output" (both).

See, below, how I insert the Gmail body in to "body" for parsing...

Zap workflow

I need to use the Code box to construct a regular expression to find each unique identifier string and output it as input to the next integration in the workflow, ie. Trello.

For info, in the above screengrab, the existing "hello world" code in the box is Zapier's own test code. The fields "id" and "hello" are made available to the next workflow app in the chain.

But I need to do my process for all of the strings found within an email body - ie. if an email contains just one code, create one Trello card; but if an email contains four codes, create a Trello card for each of the four.

That is, there could be multiple outputs. I have no idea how this could work, since I think these workflows are only supposed to accommodate one action.

I could use some help getting over the hill. Thank-you.

Robert Andrews
  • 1,209
  • 4
  • 23
  • 47

1 Answers1

1

David here, from the Zapier Platform team.

I'm glad you're showing interest in the code step. Assuming your assumptions (32 characters exactly) is always going to be true, this should be fairly straightforward.

First off, the regex. We want to look for a character that's a letter, number, or punctuation. Luckily, javascript's \w is equivalent to [A-Z0-9a-z_], which covers the bases in all of your examples besides the -, which we'll include manually. Finally, we want exactly 32 character length strings, so we'll ask for that. We also want to add the global flag, so we find all matches, not just the first. So we have the following:

/[\w-]{32}/g

You've already covered mapping the body in, so that's good. The javascript code will be as follows:

// stores an array of any length (0 or more) with the matches
var matches = inputData.body.match(/[\w-]{32}/g) 

// the .map function executes the nameless inner function once for each 
// element of the array and returns a new array with the results
// [{str: 'loYm9vYzE6Z-aaj5lL_Og539wFer0KfD'}, ...]
return (matches || []).map(function (m) { return {str: m} })

Here, you'll be taking advantage of an undocumented feature of code steps: when you return an array of objects, subsequent steps are executed once for each object. If you return an empty array (which is what'll happen if no keys are found), the zap halts and nothing else happens. When you're testing, there'll be no indicator that anything besides the first result does anything. Once your zap is on and runs for real though, it'll fan out as described here.

That's all it takes! Hopefully that all makes sense. ​Let me know if you've got any other questions!

xavdid
  • 5,092
  • 3
  • 20
  • 32
  • @xaadavid, thanks for weighing in - this is very clear. However, whilst the regex seems to work well, and I can the "Run Javascript" action to identify ONE such string from a "Gmail: New Email Matching Search" trigger, it stops at ONE (same one you commented-out. My test email body includes THREE such codes. The action I am testing with (including running live from the dashboard) is to send an email back to myself using "str", the product output from "Run Javascript". But only one email action is sent. How can I get multiple actions happening, one for each item found, as you suggest? – Robert Andrews Sep 20 '17 at 10:46
  • No problem, glad I could help. The fanout *should* just work, if you are successfully returning multiple objects from the code step. to verify this, yo could tweak the above code to return the result of the second line as a subkey rather than the object. That is, `return {results: [{str: 'asdf'}, ...]}`. Then you can verify the regex is finding all the keys you expect and go from there. – xavdid Sep 21 '17 at 00:29
  • Result: `Bargle. We hit an error creating a run javascript. :-( Error: SyntaxError: Unexpected token ]` What am I not understanding, maybe about `...`? – Robert Andrews Sep 21 '17 at 09:15
  • Correction to that - if I let it run on live data and new emails in the real world, it seems to work nicely. This looks amazing. Thanks, xavdid! – Robert Andrews Sep 21 '17 at 16:20
  • ah yeah, the `...` was just to illustrate that there's more code there. Glad it worked though! If it solved your problem, make sure to mark my answer as accepted to help future searchers. – xavdid Sep 21 '17 at 18:22
  • Indeed. Confirming it works again. Now I have a separate Zapier dilemma bubbling... – Robert Andrews Sep 21 '17 at 20:51
  • I'm not sure this regex is right. It is triggered by the string aHR0cHM6Ly9hcHAuZTJtYS5uZXQvYXBwMi9hdWRpZW5jZS9vcHRfb3V0LzE0MDEwMTQvMTQwMDgxNC81NjQ2MzE4Lw==, where two sets of 32-character strings are identified - aHR0cHM6Ly9hcHAuZTJtYS5uZXQvYXBw and Mi9hdWRpZW5jZS9vcHRfb3V0LzE0MDEw. That's not right. – Robert Andrews Oct 03 '17 at 22:11
  • Ah, sure. I'm not sure what's in the input, but if there's something that always comes directly before/after the string, that would help prevent false positives. Is there a leading or trailing space? – xavdid Oct 04 '17 at 05:29
  • Usual and intended input (in a Gmail body) is string like `loYm9vYzE6Z-aaj5lL_Og539wFer0KfD` on a distinct line. But the regex is also picking out 32-char portions of longer gobbledygook strings in the email body - specifically, the long string is a URL query parameter in a mailing list "unsubscribe" link, which is long enough to contain multiple 32-char portions but which I want ignored. Answers to separate question confirm my suspicion this needs boundaries added (?) https://stackoverflow.com/questions/46554305/regex-to-match-32-character-mixed-char-string/46554993#46554993 – Robert Andrews Oct 04 '17 at 09:07
  • Re: "If you return an empty array (which is what'll happen if no keys are found), the zap halts and nothing else happens" - just wanted to add: I am finding that, if no strings are matched, the zap halts with an "error". It's right to halt, but that's not an error. Zapier support advises I add output of "false" where no strings are matched, then filter out content containing the string "false". So that at least the step in question here would get to return *something*. – Robert Andrews Oct 06 '17 at 21:01
  • Ah, are you seeing `Uncaught TypeError: Cannot read property 'map' of null`? That's because I had an error in the js code. I've edited my answer to return `[]` if there are no matches, which will halt the zap sans error. No need for any extra steps. – xavdid Oct 06 '17 at 23:32