Using RegEx to Extract an Authorization Code in Apple Mail

Hello!

I am looking to use regex to set a variable from an email.

I have the AppleScript set and I tested the AppleScript set the %TriggerValue% properly. It is the regex part not working for me. I think it could be because of the space in between "code" and "is"

Test Stuff.kmmacros (1.7 KB)

And the email looks like this:

Screen Shot 2022-12-07 at 10.56.22 AM

I just need the authorization code set to a variable so I can use it later on in a different macro.

Unless there is a way to embed this process into a macro, to pause - wait for email - AppleScript - set authorization code to variable - paste variable into field.

Your regex is (?m)^code is: (.*)$ -- the ^ means "the line starts with" and your line doesn't start with "code", so it fails to match.

You might get away with (?m)code is: (.*)$ if there are no other "code is:" strings in your email. Or you include the full line (?m)^Your authorization code is: (.*)$ if it does actually start with "Y" and not a space or similar.

That still may not do it, depending on how you are getting the text from the email -- you may have to remove styles (rich text content of) or HTML (HTML-based mail and source of) from the text.

2 Likes

Ahh I understand now. Ok, let me give that a shot. Thank you @Nige_S

@Nige_S Works great, thank you.

I do have another question you might be able to answer...

Where this fits in:

  • In the middle of Macro A, I get an authorization code emailed to me.

  • I want the AppleScript and macro B (this one) to run and retrieve that authorization code to variable local_code.

  • Then I want Macro A to continue running.

How would I embed this in macro A?

Seems like running Macro B as a subroutine should work.

Check out https://wiki.keyboardmaestro.com/action/Execute_a_Subroutine

I'm not sure it would -- at least, not on its own. It sounds as though macro A will have to pause until macro B returns a value, but macro B is going to be triggered by a Mail AppleScript rule.

If that's right then I'd go the "shared Global variable" route. Macro A does its thing until the "pause point" and then sets Global__authCode to 0. It then uses "Pause until Global__authCode is not 0" to hold.

Macro B gets triggered (eventually!) by the incoming email, parses out the authorisation code in Global_authCode and exits. As Global_authCode is no longer 0, Macro A continues.

That's a first, best, guess -- but a lot depends on implementation details. For example, if receipt of the code may take long enough that a computer restart might happen you'd need to separate the two parts of Macro A and have the second part triggered by Macro B, perhaps passing the code as a parameter (and OP might need to find a way to persist other values, too).

1 Like

The combo of your suggestions worked perfect and repeatably (which is most important). Thank you both!

Hey Mike,

You can put the regex search code in your AppleScript and probably skip some steps...

This is AppleScriptObjC:

--------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2016/05/08 00:59
# dMod: 2021/08/27 19:51
# Appl: AppleScriptObjC
# Task: Find-Replace or Change-Text Handler
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @ASObjC, @Find, @Replace, @Text, @RegEx, @cngStr, @Change
--------------------------------------------------------
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
--------------------------------------------------------

set dataString to "
Line 01
Line 02
Your authorization code is: YEXCYC34
Line 04
Line 05
"

set authCode to its cngStr:"(?mis).*?Your authorization code is:\\h*(\\w+).*" intoString:"$1" inString:dataString

--------------------------------------------------------
--» HANDLERS
--------------------------------------------------------
on cngStr:findString intoString:replaceString inString:dataString
   set anNSString to current application's NSString's stringWithString:dataString
   set dataString to (anNSString's ¬
      stringByReplacingOccurrencesOfString:findString withString:replaceString ¬
         options:(current application's NSRegularExpressionSearch) range:{0, length of dataString}) as text
end cngStr:intoString:inString:
--------------------------------------------------------

You can also do this using Keyboard Maestro instead of AppleScriptObjC:

--------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2022/12/07 21:30
# dMod: 2022/12/07 21:30 
# Appl: Keyboard Maestro Engine
# Task: Find & Replace with RegEx in AppleScript with Keyboard Maestro.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Keyboard_Maestro_Engine, @RegEx
--------------------------------------------------------

set dataStr to "
Line 01
Line 02
Your authorization code is: YEXCYC34
Line 04
Line 05
"

# These handlers are the same in function but the calls are formatted differently.
# kmCng:regExPat inStr:dataStr withStr:replacePat usingRegEx:regExBool 
# kmReplace(findPattern, replacePattern, dataStr, regExBool, caseBool, tokensBool)

set authCode1 to its kmCng:"(?mis).*Your authorization code is:\\h*(\\w+).+" inStr:dataStr withStr:"$1" usingRegEx:true usingCase:false usingTokens:false

set authCode2 to its kmReplace("(?mis).*Your authorization code is:\\h*(\\w+).+", "$1", dataStr, true, false, false) -- regEx, case, tokens

--------------------------------------------------------
--» kmCng()
--------------------------------------------------------
--  Task: Find and Replace with RegEx using Keyboard Maestro's AppleScript search command.
--  dMod: 2019/01/19 04:33
--------------------------------------------------------
on kmCng:regExPat inStr:dataStr withStr:replacePat usingRegEx:regExBool usingCase:caseBool usingTokens:tokensBool
   tell application "Keyboard Maestro Engine"
      set foundDataList to search dataStr for regExPat replace replacePat ¬
         regex regExBool case sensitive caseBool process tokens tokensBool
   end tell
end kmCng:inStr:withStr:usingRegEx:usingCase:usingTokens:
--------------------------------------------------------
--» kmReplace()
--------------------------------------------------------
--  Task: Find and Replace with RegEx using Keyboard Maestro's AppleScript search command.
--  dMod: 2018/04/06 04:55
--------------------------------------------------------
on kmReplace(findPattern, replacePattern, dataStr, regExBool, caseBool, tokensBool)
   tell application "Keyboard Maestro Engine"
      set foundDataList to search dataStr for findPattern replace replacePattern ¬
         regex regExBool case sensitive caseBool process tokens tokensBool
   end tell
end kmReplace
--------------------------------------------------------
2 Likes