Looking for a way to remove unwanted smtp addresses from public folders

We're migrating to O365, and we have 748 public folders, most are mail enabled, and I've been searching for a powershell script to remove unwanted/un-owned smtp: addresses.  Some are primary and should be re-set to our main domain, others are just unwanted (yahoo.com or .local) and can be removed.

This script is one I found on the interweb, script succeeds, writes the yahoo address to the text file, but doesn't actually remove it from the the public folder.  I also added a "test2@yahoo.com", and the script only writes "test@yahoo.com" to the text file.

This script also doesn't address setting the primary address to our main domain.com

Help from the community would be great.

$Mailboxes = Get-MailPublicFolder -result unlimited
$Mailboxes | foreach{
    for ($i=0;$i -lt $_.EmailAddresses.Count; $i++)
    {
        $address = $_.EmailAddresses[$i]
        if ($address.IsPrimaryAddress -eq $false -and $address.SmtpAddress -like "*yahoo.com")
        {

            Write-host($address.AddressString.ToString() | out-file C:\PFaddressesRemoved.txt -append )
            $_.EmailAddresses.RemoveAt($i)
            $i--
        }
    }

 }

Sceen shot  of SMTP Addresses to be removed
Wes HunterIT OperationsAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Wes HunterIT OperationsAuthor Commented:
Quick update, I changed the "IsPrimary -eq false" to "IsPrimary -eq true" and the script removed test2@yahoo.com, but did not remove test@yahoo.com, and it didn't create a textfile?
0
Todd NelsonSystems EngineerCommented:
First, make sure your email address policies aren't setting any email addresses for domains you do not own.

Second, when "Automatically update e-mail addresses based on e-mail address policy" is enabled the script you have will not be allowed to set the default reply address.

Third, if you don't want what is currently set as the default reply address, deselect the "Automatically update e-mail addresses based on e-mail address policy" option and set what you want.

Fourth, the command should look like the following if you want to remove addresses based on multiple domains (i.e. yahoo.com and *.local).

$Mailboxes = Get-MailPublicFolder -ResultSize Unlimited
$Mailboxes | foreach{
   for ($i=0;$i -lt $_.EmailAddresses.Count; $i++)
   {
      $address = $_.EmailAddresses[$i]
      if ($address.IsPrimaryAddress -eq $false -and $address.SmtpAddress -like "*yahoo.com" -or $address.SmtpAddress -like "*.local") 
      {
         Write-host( $address.AddressString.ToString() | out-file C:\PFaddressesRemoved.txt -append )
         $_.EmailAddresses.RemoveAt($i)
         $i--
      }
   }
   Set-MailPublicFolder -Identity $_.Identity -EmailAddresses $_.EmailAddresses
}

Open in new window


Let us know.
1
Ben Personick (Previously QCubed)Lead Network EngineerCommented:
This should do the needful, don't; have an exchange in front of me, so let me know if any syntax errors come up.

$DebugPreference = "ContinueSilently"
$DebugPreference = "Continue" # Comment out this line to turn off debug messaging

$AllEmailsLog = "C:\PF_ALL_EmailAddresses.txt"
$BadEmailsLog = "C:\PF_BAD_EmailAddresses.txt"
$ResultingEmailsLog = "C:\PF_RESULTING_EmailAddresses.txt"
$BadDomains = @(
"@yahoo.com",
"@SomeOtherDomain.com"
)
$BadDomainsTestSet=[String]::Join("|",$BadDomains)

$PubFolders = Get-MailPublicFolder -result unlimited

#Get only those mailboxes with more than one SMTP address, as it's unlikely they're bad
$PubFoldersWithMultipleEmail = $Mailboxes | ?{$_.EmailAddresses.Count -gt 1}

Write-Debug "These are the Public Folders matched:`r"
Write-Debug "`r"
$PubFoldersWithMultipleEmail | Write-Debug
Write-Debug "`r"

foreach ( $PFolder in $PubFoldersWithMultipleEmail ) {

	## Really this is mostly for reporting and could be stripped if preffered.
	foreach ($Log in ($AllEmailsLog, $BadEmailsLog, $ResultingEmailsLog)) {
		$PFolder.Name | out-file $Log
	}
	$($PFolder.EmailAddresses) | ft isPrimaryAddress, SmtpAddress | out-file $AllEmailsLog
	$BadEmailAddresses = $($PFolder.EmailAddresses) | ?{$_.SmtpAddress -match $BadDomainsTestSet}
	$BadEmailAddresses | ft isPrimaryAddress, SmtpAddress | out-file $BadEmailsLog
	
	# Write debug info on the bad emails found
	Write-Debug "All Bad email addresses for $($PFolder.Name):`r"
	$BadEmailAddresses | ft isPrimaryAddress, SmtpAddress | Write-Debug
	Write-Debug "`r"
	
	
	#####
	#  Here is where the real work gets done
	
	## Create a list of the emails we WANT to keep.
	# List includes primary SMTP even if in bad emails as Author seems to only want to remove secondary emails.
	$GoodEmailAddresses = $($PFolder.EmailAddresses) | ?{( $_.SmtpAddress -nomatch $BadDomainsTestSet ) -or ($_.IsPrimaryAddress -eq $true)}
	$GoodEmailAddresses | ft isPrimaryAddress, SmtpAddress | out-file $ResultingEmailsLog
	
	Write-Output "Removing Secondary Bad Emails for $($PFolder.Name), Resulting emails are:"
	$GoodEmailAddresses | ft isPrimaryAddress, SmtpAddress | Write-Output
	
	## Change the email Addresses on the public folder:
	Set-MailPublicFolder -Identity $PFolder.Identity -EmailAddresses $GoodEmailAddresses
}

Open in new window


Edit, whoops, on the first post it didn't have the loop for putting the Public Folder names into the Log files. Fixed that bit.
1
Making Bulk Changes to Active Directory

Watch this video to see how easy it is to make mass changes to Active Directory from an external text file without using complicated scripts.

Wes HunterIT OperationsAuthor Commented:
Thank you Ben for the code, this looks very promising! I tried one pass and got this error:
You must provide a value expression on the right-hand side of the '-' operator.
At C:\Scripts\PFremSMTPold.ps1:44 char:73
+     $GoodEmailAddresses = $($PFolder.EmailAddresses) | ?{( $_.SmtpAddress - <<<< nomatch $BadDomainsTestSet ) -or ($_
.IsPrimaryAddress -eq $true)}
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : ExpectedValueExpression
0
Ben Personick (Previously QCubed)Lead Network EngineerCommented:
Hello Wes,

Okay that was just a small Typo, "-nomatch" needed to be "-notmatch", fixed below.


$DebugPreference = "ContinueSilently"
$DebugPreference = "Continue" # Comment out this line to turn off debug messaging

$AllEmailsLog = "C:\PF_ALL_EmailAddresses.txt"
$BadEmailsLog = "C:\PF_BAD_EmailAddresses.txt"
$ResultingEmailsLog = "C:\PF_RESULTING_EmailAddresses.txt"
$BadDomains = @(
"@yahoo.com",
"@SomeOtherDomain.com"
)
$BadDomainsTestSet=[String]::Join("|",$BadDomains)

$PubFolders = Get-MailPublicFolder -result unlimited

#Get only those mailboxes with more than one SMTP address, as it's unlikely they're bad
$PubFoldersWithMultipleEmail = $Mailboxes | ?{$_.EmailAddresses.Count -gt 1}

Write-Debug "These are the Public Folders matched:`r"
Write-Debug "`r"
$PubFoldersWithMultipleEmail | Write-Debug
Write-Debug "`r"

foreach ( $PFolder in $PubFoldersWithMultipleEmail ) {

	## Really this is mostly for reporting and could be stripped if preffered.
	foreach ($Log in ($AllEmailsLog, $BadEmailsLog, $ResultingEmailsLog)) {
		$PFolder.Name | out-file $Log
	}
	$($PFolder.EmailAddresses) | ft isPrimaryAddress, SmtpAddress | out-file $AllEmailsLog
	$BadEmailAddresses = $($PFolder.EmailAddresses) | ?{$_.SmtpAddress -match $BadDomainsTestSet}
	$BadEmailAddresses | ft isPrimaryAddress, SmtpAddress | out-file $BadEmailsLog
	
	# Write debug info on the bad emails found
	Write-Debug "All Bad email addresses for $($PFolder.Name):`r"
	$BadEmailAddresses | ft isPrimaryAddress, SmtpAddress | Write-Debug
	Write-Debug "`r"
	
	
	#####
	#  Here is where the real work gets done
	
	## Create a list of the emails we WANT to keep.
	# List includes primary SMTP even if in bad emails as Author seems to only want to remove secondary emails.
	$GoodEmailAddresses = $($PFolder.EmailAddresses) | ?{( $_.SmtpAddress -notmatch $BadDomainsTestSet ) -or ($_.IsPrimaryAddress -eq $true)}
	$GoodEmailAddresses | ft isPrimaryAddress, SmtpAddress | out-file $ResultingEmailsLog
	
	Write-Output "Removing Secondary Bad Emails for $($PFolder.Name), Resulting emails are:"
	$GoodEmailAddresses | ft isPrimaryAddress, SmtpAddress | Write-Output
	
	## Change the email Addresses on the public folder:
	Set-MailPublicFolder -Identity $PFolder.Identity -EmailAddresses $GoodEmailAddresses
}

Open in new window

0
Wes HunterIT OperationsAuthor Commented:
Ok, changed it, and here's the output:
DEBUG: These are the Public Folders matched:
DEBUG:
Write-Debug : Cannot bind argument to parameter 'Message' because it is null.
At C:\Users\csadmin\Desktop\PowerShell-Exchange\PFScripts\PFremSMTPold.ps1:20 char:43
+ $PubFoldersWithMultipleEmail | Write-Debug <<<<
    + CategoryInfo          : InvalidData: (:) [Write-Debug], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.WriteDebugC
   ommand

DEBUG:
DEBUG: All Bad email addresses for :
DEBUG:
Removing Secondary Bad Emails for , Resulting emails are:
Cannot bind argument to parameter 'Identity' because it is null.
    + CategoryInfo          : InvalidData: (:) [Set-MailPublicFolder], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Set-MailPublicFolder
0
Ben Personick (Previously QCubed)Lead Network EngineerCommented:
alright, lets make sure we grab identity, and also we probably only want to output the names of the public folders in that first anyway so going to fix that.

$DebugPreference = "ContinueSilently"
$DebugPreference = "Continue" # Comment out this line to turn off debug messaging

$AllEmailsLog = "C:\PF_ALL_EmailAddresses.txt"
$BadEmailsLog = "C:\PF_BAD_EmailAddresses.txt"
$ResultingEmailsLog = "C:\PF_RESULTING_EmailAddresses.txt"
$BadDomains = @(
"@yahoo.com",
"@SomeOtherDomain.com"
)
$BadDomainsTestSet=[String]::Join("|",$BadDomains)

$PubFolders = Get-MailPublicFolder -result unlimited | select Name,Identity,EmailAddresses

#Get only those mailboxes with more than one SMTP address, as it's unlikely they're bad
$PubFoldersWithMultipleEmail = $PubFolders | ?{$_.EmailAddresses.Count -gt 1}

Write-Debug "These are the Public Folders matched:`r"
Write-Debug "`r"
$PubFoldersWithMultipleEmail | select Name | Write-Debug
Write-Debug "`r"

foreach ( $PFolder in $PubFoldersWithMultipleEmail ) {

	## Really this is mostly for reporting and could be stripped if preffered.
	foreach ($Log in ($AllEmailsLog, $BadEmailsLog, $ResultingEmailsLog)) {
		$PFolder.Name | out-file $Log
	}
	$($PFolder.EmailAddresses) | ft isPrimaryAddress, SmtpAddress | out-file $AllEmailsLog
	$BadEmailAddresses = $($PFolder.EmailAddresses) | ?{$_.SmtpAddress -match $BadDomainsTestSet}
	$BadEmailAddresses | ft isPrimaryAddress, SmtpAddress | out-file $BadEmailsLog
	
	# Write debug info on the bad emails found
	Write-Debug "All Bad email addresses for $($PFolder.Name):`r"
	$BadEmailAddresses | ft isPrimaryAddress, SmtpAddress | Write-Debug
	Write-Debug "`r"
	
	
	#####
	#  Here is where the real work gets done
	
	## Create a list of the emails we WANT to keep.
	# List includes primary SMTP even if in bad emails as Author seems to only want to remove secondary emails.
	$GoodEmailAddresses = $($PFolder.EmailAddresses) | ?{( $_.SmtpAddress -notmatch $BadDomainsTestSet ) -or ($_.IsPrimaryAddress -eq $true)}
	$GoodEmailAddresses | ft isPrimaryAddress, SmtpAddress | out-file $ResultingEmailsLog
	
	Write-Output "Removing Secondary Bad Emails for $($PFolder.Name), Resulting emails are:"
	$GoodEmailAddresses | ft isPrimaryAddress, SmtpAddress | Write-Output
	
	## Change the email Addresses on the public folder:
	Set-MailPublicFolder -Identity $PFolder.Identity -EmailAddresses $GoodEmailAddresses
}

Open in new window


Edit: Whoops, I just noticed I was still using one of your original variable names

Likely that was the whole problem but I left both changes in.
1

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Wes HunterIT OperationsAuthor Commented:
Major thank you to you Ben, I ran 2 passes, one with the update email policy checked, and another pass with it unchecked and both worked flawlessly!
0
Wes HunterIT OperationsAuthor Commented:
Hi Ben,

It looks like it didn't remove all of the domains.  Just doing a few spot checks here and there, I'm finding one of the last domains I tried to remove.  I also noticed in the $ResultingEmailsLog it only displayed an unwanted domain that I added to the test pf, and no other folders were listed.
1
Wes HunterIT OperationsAuthor Commented:
It looks like the Automatically update emails based on policy does need to be unchecked. Not sure why this worked with the test folder, but other folders need to have it unchecked for the script to work.   Is there a way to mass disable this option on all folders?
1
Ben Personick (Previously QCubed)Lead Network EngineerCommented:
will have to look into how tomorrow
0
Wes HunterIT OperationsAuthor Commented:
Hi Ben,

Just curious if you found anything on mass updating the public folder "Auto update email address based on email address policy" to unchecked.    Your script will only work with that check box unchecked.  From what I've read, it looks like it may be tied to the Organization Configuration > Hub > Default Email Address Policy.  Some threads say to create new policy and assign it to "Lowest" (lowest apparently takes priority over higher numbers).   Not finding anything where powershell will address the public folder setting directly.
0
Ben Personick (Previously QCubed)Lead Network EngineerCommented:
Hey Wes,

  Thatnks for poking the Q I'd not had a chance to check back and forgotten.

  To change the Policy on all your current mailboxes you can run the following:

Get-mailbox | Set-mailbox  $_.Identity -EmailAddressPolicyEnabled $false

Open in new window


That should work for your needs here.

 Alternatively, you may want to look into your "email address policy" setting sin Exchange and see if it makes more sense to manage the emails through it, but up to you.

 However you might want to look into changing the
0
Wes HunterIT OperationsAuthor Commented:
Thank you Ben, just a quick question on this, what impact does this have on our current active mailbox users by disabling it?
0
Ben Personick (Previously QCubed)Lead Network EngineerCommented:
Hello Wes,

  I'm not very familiar with this setting, but I believe the outcome is simply that they will stop being updated by the policy, and whatever they currently have assigned by the policy will still be in place.

Ben
1
Todd NelsonSystems EngineerCommented:
Correct, Ben.  It has no affect on the existing email addresses currently assigned.
2
Wes HunterIT OperationsAuthor Commented:
The script returned the following error, also, will this also traverse through PF's too even though it's "Set-Mailbox" vs. "Set-MailPublicFolder"
Cannot bind argument to parameter 'Identity' because it is null.
    + CategoryInfo          : InvalidData: (:) [Set-Mailbox], ParameterBindingValidationExcep
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Set-Mailbox

Invoke-Command : Cannot write input as there are no more running pipelines
At C:\AppData\Roaming\Microsoft\Exchange\RemotePowerShell\ca-exch03p.cog.local\
51668 char:29
+             $scriptCmd = { & <<<<  $script:InvokeCommand `
    + CategoryInfo          : InvalidOperation: (:) [Invoke-Command], PSInvalidOperationExcep
    + FullyQualifiedErrorId : NoMoreInputWrite,Microsoft.PowerShell.Commands.InvokeCommandCom
0
Todd NelsonSystems EngineerCommented:
will this also traverse through PF's too even though it's "Set-Mailbox" vs. "Set-MailPublicFolder"

No.
1
Wes HunterIT OperationsAuthor Commented:
Thank you Todd for the confirmation.  This is so frustrating that as a requirement for moving public folders, Microsoft doesn't provide any way to bulk change this setting.  Ben Thank you as well for your help in this, I may need to post a separate question to ask for assistance with disabling public folder "Auto update email address based on email address policy".  I really appreciate your help to this point gentlemen!
0
Wes HunterIT OperationsAuthor Commented:
This did the job.  Gotta run this before Ben's script and all works as expected.  

get-mailpublicfolder | set-mailpublicfolder -EmailAddressPolicyEnabled $false

One last thing Ben, if I want the script to find "any.yahoo.com", how should the script change?  Can we add a wildcard "*" in the emailaddress to find on line 8 and 9.
(adding wildcard produced errors)
"@*.yahoo.com",
"@*.SomeOtherDomain.com"
0
Todd NelsonSystems EngineerCommented:
Wes, take a look at the script I provided near the beginning of this thread. I believe it answers your question to Ben.
1
Ben Personick (Previously QCubed)Lead Network EngineerCommented:
hey Wes,

Wildcards are implied

use as follows

".yahoo.com",
".SomeOtherDomain.com",
".yet.another.domain.us",
"@this.domain.exactly.org"
1
Todd NelsonSystems EngineerCommented:
Wes,

For the script you provided and I fixed for you, wildcards are not implied.
1
Wes HunterIT OperationsAuthor Commented:
OMG!! and here we go again, I ran into another snafu!  I think I mentioned it at the beginning of my post, but some of these unwanted domains were not removed by your script Ben, due to the email address being the primary (Set as Reply) address, probably an old email policy which no longer exists.  It looks like all public folders must first be have Set As Reply be marked for our primary domain before the unwanted can be deleted (the delete X is greyed out until this is done).  In the Gui it's simple, select the new address you wan't as primary and chose Set as Reply.
Any chance this can be incorporated into your script?Capture.JPG
0
Ben Personick (Previously QCubed)Lead Network EngineerCommented:
I specifically DO NOT REMOVE the primary SMTP Address.  I specifically called this out in the script and my comment because I got the impression you DID NOT want to do it.. Perhaps I have misunderstood.
0
Wes HunterIT OperationsAuthor Commented:
I was probably unclear, not sure if it can be done, but I think logic should be IF primary domain = unwanted domain, set primary domain = our domain, we're also running into a weird issue as well, where the domians all look correct via gui, I run the 365 sync pf script, it's throwing multiple errors of (UpdateMailEnabledPublicFolder : You can't use the domain  because it's not an accepted domain for your organization.)
In the summary file, I see one of the unwanted domains being reported, however, when I look in the gui, the unwanted domain is not listed and everything looks ok.  I even checked ADSI Exchange Objects, and it's not listed there either.... So where in the heck is it finding that domain if we removed it already?
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.