3

i'm getting some problem to get a specific row from a powershell body. HR team send email to us, a logic app get the body of email and pass it to a script that disable the user.

The body is like this:

Hi,

the following user have to be dismiss:

#mail: [email protected]
#mail: [email protected]
#mail: [email protected]


Bye
hr team

[email protected]
 

i would like to get only the specific row:

    #mail: [email protected]
    #mail: [email protected]
    #mail: [email protected]

to do this i did a trick with following code:

    $Body
    $SplitBody = $Body.split("").split(" ").Split("#")
    $objetbody = $SplitBody.Replace(" ","").Trim()

and i got following result:

Hi,
the
following
user
have
to
be
dismiss:

mail:
[email protected]

mail:
[email protected]

mail:
[email protected]
Bye
hr
team
[email protected]

after that i pass $objetbody into a foreach and loop all row(at the end of this foreach is put a break becouse it can disable HR mail). The flow work if HR sent only 1 mail to disable.

My question is there is a way to got that specific row that contains the mails?

Thanks

aynber
  • 22,380
  • 8
  • 50
  • 63
Emanuele
  • 193
  • 2
  • 13

2 Answers2

5

Here is a one-liner to output all email addresses using the .NET RegEx class:

[RegEx]::Matches( $body, '(?<=#mail:\s*)\S+' ).Value

The same can be achieved using Select-String:

($body | Select-String '(?<=#mail:\s*)\S+' -AllMatches).Matches.Value

RegEx breakdown:

  • (?<= ... starts a positive look behind pattern, meaning that the sub string we search for must be preceded by the given pattern, but this pattern won't be included in the result
    • #mail:\s* ... literal "#mail:" followed by optional whitespace
  • ) ... ends the look behind pattern
  • \S+ ... any sequence of non-whitespace characters -> the email address

I kept the email address pattern simple, because correctly matching email addresses using RegEx can be hard. Anyway you propably want to do validation as a separate step so you can report invalid addresses. This can be done much simpler using the .NET MailAddress class:

$mailAddresses = [RegEx]::Matches( $body, '(?<=#mail:\s*)\S+' ).Value

foreach( $adr in $mailAddresses) {
    try {
        [System.Net.Mail.MailAddress]::new( $adr )
    } catch {
        # The MailAddress constructor throws FormatException for invalid address
        Write-Error "Invalid mail address: '$adr'"
    }    
}
zett42
  • 25,437
  • 3
  • 35
  • 72
3

You could use a loop in addition to the -match operator and the use of the automatic variable $Matches:

foreach($line in $Body)
{
    if($line -match '^#mail: (.*@.*\.[\w\d]+)')
    {
        $Matches[1]
    }
}

From the example above, $Matches[1] would return the values for the matched capturing group:

[email protected]
[email protected]
[email protected]

If you want to keep #mail: use $Matches[0] instead.

Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • Hi santiago, i tried your code but i got this with $matches[0]: Name Value ---- ----- 0 @mycompany.com $matches[1] is empty i see. Looking forward to hearing from you. Thanks!! – Emanuele Jan 26 '22 at 10:51