Home > Mobile >  Send 1 email to each person with all their codes
Send 1 email to each person with all their codes

Time:05-17

I need to write a script that sends a single email to each person. That email will have unique codes for the person. Each person can get any number of codes.

The data looks like this

Email,Codes
[email protected],213
[email protected],999
[email protected],111
[email protected],123
[email protected],643
[email protected],809
[email protected],722
[email protected],013

I think the script will go something like this.

#get the data
$PeopleAndCodes = Import-Csv C:\temp\PeopleCodes.csv

#Count how many groups of unique people
[array]$CountOfPeople = $PeopleAndCodes.email | Group-Object -noelement | Select-Object Count

#Loop through unique people
$Index = 0;
while ($Index -lt $CountOfPeople.count) {
    $Index  

#THIS BELOW EXITS BEFORE GETTING THROUGH ALL THE CODES FOR ONE PERSON
    [int]$DCodes = 0
    foreach ($DCodes in [int]$CountOfPeople[$DCodes].count) {
        $DCodes  

        Write-Host $DCodes DCODES
        Write-Host $CountOfPeople[$DCodes].count CountOfPeople
        Write-Host $PeopleAndCodes[$DCodes].codes
    }
}

The problem is that my 2nd loop stops as soon as number of unique people is reached and then moves to the next person.

I don't understand why the 2nd loop is not going through the codes and then to the next person?

CodePudding user response:

You are very close, I would make some small tweaks to your code and we can get it there.

First, instead of indexing through the array, let's select all of the unique e-mails from the list of codes.

$uniqueUsers = $PeopleAndCodes | select -Unique Email

Next, we can foreach loop our way through the list of $uniqueUsers, and for each, find any matching codes for them.

foreach($uniqueUser in $uniqueUsers){
    $thisEmail = $uniqueUser.Email

    $matchingCodes = $PeopleAndCodes | Where Email -Match $uniqueUser.Email |
         Select-Object -ExpandProperty Codes

Now we have within this loop a $thisEmail var that holds the email address of the user, and then an array of all of the matching codes for the user, called $matchingCodes. We don't need to index through these either. In fact that second loop was likely causing the issue, as there are more items in the list than unique users.

Your limiting condition was the number of unique users, not the number of items in the list.

So, to avoid confusion and get the desired output, just remove that second loop entirely since it isn't helping us.

        Write-Host "Person - $thisEmail"
        Write-Host "Person has $($matchingCodes.Count) codes"
        $matchingCodes -join ","

Gives an output of

Person - [email protected]
Person has 2 codes
213,999
--------------------
Person - [email protected]
Person has 5 codes
111,123,643,809,722

Completed Code

$PeopleAndCodes = Import-Csv C:\temp\PeopleCodes.csv
$uniqueUsers = $PeopleAndCodes | select -Unique Email

foreach($uniqueUser in $uniqueUsers){
    $thisEmail = $uniqueUser.Email

    $matchingCodes = $PeopleAndCodes | where Email -Match $uniqueUser.Email | Select-Object -ExpandProperty Codes

    Write-Host "Person - $thisEmail"
    Write-Host "Person has $($matchingCodes.Count) codes"
    $matchingCodes -join ","

    Write-Host "--------------------"
}

CodePudding user response:

I want to point out that while above is the best answer. In the comments is another answer that works with my original code as well.

#get the data
$PeopleAndCodes = Import-Csv C:\temp\PeopleCodes.csv

#Count how many groups of unique people
[array]$CountOfPeople = $PeopleAndCodes.email | Group-Object -noelement | Select-Object Count

#Loop through unique people
$Index = 0;
while ($Index -lt $CountOfPeople.count) {
    $Index  

#This loops through each person and gets their code(s)
    [int]$DCodes = 0
    foreach ($DCodes in 0..[int]$CountOfPeople[$DCodes].count) {

        Write-Host $PeopleAndCodes[$DCodes].email
        Write-Host $PeopleAndCodes[$DCodes].codes
        $DCodes  
    }
}
  • Related