Delete all alerts for a user in Sharepoint with this PowerShell script

When a user leaves an organisation, their account is usually cleaned up – either by disabling or deleting it.  In Sharepoint this cleaning up is not automatic – generally Sharepoint hangs on to user accounts so that information about that user is still linked to the documents the user worked on. One of the side effects of this is that any alerts that user may have set up will remain, at least in Sharepoint 2007.  This leads to a lot of undeliverable messages going to Site Administrators.  Manually removing the alerts for a user requires visiting each site that has alerts, going to the site settings, User Alerts, finding the user and deleting their alerts.  I wrote the following PowerShell script to remove all alerts for a given user in one step. The script requires my supporting functions script (Download SPFunctions) – you need to save this in the same directory as the script below.  It works in a similar way to my Edit-SPAdmins script – it allows you to select a Web Application via GUID (don’t worry, it lists all the Web Applications and their GUIDs), and then loops through all the site collections and sites, removing the users alerts as it goes. So – on with the script:

# Remove alerts for a given user from all SharePoint sites in a web application
# Usage:  delete-spalert.ps1  
# Example:  delete-spalert.ps1 DOMAINUser

# Validate arguments
if ($args.Count -lt 1)
{
    Write-Warning "Usage: alerts.ps1 "
	Write-Warning "Username must be in DOMAINuser format"
    exit
}

# check that arguement is in correct format including domain
if ($args[0] -inotmatch '^w+[\]w+$')
{
    Write-Warning "Username must be in DOMAINUser format"
    exit
}

# Load Sharepoint functions
.SPFunctions.ps1;

# store arguement in variable
$myuser = $args[0]

# Preamble
cls;
write-host "###################################################################################

This application adds or removes alerts for a user in a specified web application
Here is a list of all Web Applications on the farm" -foregroundcolor yellow;

# List the GUIDs of all web apps on this farm
List-SPWebApp-GUID;

write-host "Please copy the GUID for the web application you wish to use by selecting then
clicking the right mouse button."  -foregroundcolor yellow;

write-host "
Note that the Central Admin site collection has no name,
but does have a GUID!  Don't select this one by accident!
" -foregroundcolor red;

Write-Host "You can paste the GUID by clicking the Right mouse button again" -ForegroundColor yellow;
# Prompt user for GUID to use
$guid = Read-Host -Prompt "GUID";
$guid = $guid.Trim();

# Check GUID for correct format
Write-Host "Checking GUID";
switch(Check-GUID($guid)){
	"False" { Write-Host "Error: Invalid GUID.  Exiting..." -ForegroundColor red; return;}
}

# Get the specified web app
$webapp = Get-SPWebApp($guid);

# Check that webapp has been got and if not inform user
Write-Host "The following Web App will be affected: $($webapp.name)"
Write-Host "You will be removing alerts for the following user: $myuser"

$continue = Read-Host -Prompt "Continue? (y|n)>";
switch($continue){
	"y" {break;}
	default {Write-Host "Exiting..." -ForegroundColor red; return;}
}

$alertcount = 0

# For each site collection remove all alerts for the given user
$time = Measure-Command {
    foreach ($site in $webapp.Sites)
    {
        # get the collection of webs
        $webs = $site.AllWebs
        foreach ($web in $webs)
        {
            # get the alerts
            $alerts = $web.Alerts

            # if more than 0 alerts, iterate through these alerts to see if there is one for the user
            if ($alerts.Count -gt 0)
            {
                $myalerts = @()
                $mysites += $web.Url
                foreach ($alert in $alerts)
                {
                    if ($alert.User.LoginName -eq $myuser)
                    {
                        echo "Deleting $($alert.Title)"
                        $myalerts += $alert
                        $alertcount++
                    }
                }

                # now we have alerts for this site, we can delete them
                foreach ($alertdel in $myalerts)
                {
                    $alerts.Delete($alertdel.ID)
                }
            }
        }
    }
}

echo "Deleted $alertcount alerts in $($time.TotalSeconds) seconds"

27 thoughts on “Delete all alerts for a user in Sharepoint with this PowerShell script

  1. Hi!

    This is exactly what I needed, but I wasn’t able to run the script.

    1. The validator doesn’t recognize dashes in the domain name. My domain name is “ABC-DOMAIN”, so I changed the line number 24 to “$myuser = ‘ABC-DOMAINuser'”. I understand that it’s not a good style but I’m not a programmer.

    2. Then after entering something that passes the validator, I got an error:
    “Unable to find type [Microsoft.SharePoint.Administration.SPFarm]: make sure that the assembly containing this type is loaded”.
    To solve it you need to execute “[System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint”)” from the PowerShell command line before starting the script.

    3. After that the script still doesn’t work for me. After entering GUID I get a lot of errors:
    “An exception was thrown when trying to enumerate the collection: “Access is denied. (Exception from HRESULT: 0x80070005
    (E_ACCESSDENIED))”.
    At D:Scriptdelete-spalert.ps1:76 char:16
    + foreach <<<< ($web in $webs)".
    I'm a domain and SharePoint administrator, so I have no ideas why I'm getting "access denied".

    Could you please give me an idea how to troubleshoot the issue? If I was able just to find at which sites these alerts are located, it would be a great help, because at least it would be possible to delete them manually.

    Thank you!

    • Hi Sergei – it can be a bit tricky to figure out what is causing these errors. If you look at the error message more closely you can get some clues.

      At D:Scriptdelete-spalert.ps1:76 char:16

      means the error occurred on line 76 of the script. I’ve added the line numbers to the post above so you can find this:

      foreach ($web in $webs)

      This part of the code loops through all your sites (Sharepoint calls sites webs under the hood, and site collections are called sites – very confusing). So it is likely that one of your sites has a permission set that is causing the problem. If you edit the script to add a new line immediately after line 76:

      echo $web.url

      then when you run the script it should give the URL for each site it is running against. When you hit the error, the URL you see listed immediately beforehand should be the one that is causing the problem.

      At some point I should update the script so the validator accepts all legal characters in a domain name. Someone warned me this might happen when I was trying to figure out the regular expression, but I wanted to keep it simple. You found a valid workaround 🙂

      For all PowerShell scripts relating to Sharepoint you’ll need to load the Microsoft.SharePoint assembly. Since you are likely only running Sharepoint related PowerShell scripts on a SharePoint server, you may want to add the call to this assembly in your PowerShell profile script.

      Hope all this helps. Please leave another comment to say if it did or not.

  2. Duncan;

    Thanks for the script very insightful… I’m curious at line 21 you reference .SPFunctions.ps1 what is this?

    Thanks
    Gerald

    • Thanks for letting me know. After migrating to a new WordPress platform, I lost all my ZIP files. I have now fixed this, and the files are available again. Please let me know if they work well for you!

    • Hi, thanks for the response. I can certainly understand how that can be. I guess at some point or another we have all been there.

      I just tried the link and I am still getting the 404 error. Any chance you can send me the files? or maybe the URL to download them directly.

    • ok, I was able to get to the file. Basically the location that i put on the initial posting was changed. But thank goodness for that.

      Now I have another issue completly… It is having issues trying to run get-spwebapplication. I was able to work thought that, but the issue that I am running into is with the ft name, id; section. It can not format the table as requested. If I remove the ft name, id; it then lists everything so it makes it that much harder to read.

      Any help with that?

    • Josh – sorry for the extreme delay in replying!

      The get-spwebapplication bit is only displaying the name and guids for each of your web applications, so you can then feed it into the script later (by copy and paste – very manual).

      You could find a different way to get your guids and comment that line out of the script. Since you probably don’t add web-applications that often, it shouldn’t be that much of a problem to keep a list of the guids, and use that in the script.

      I can’t say why the format-table(ft) isn’t working for you – are you running this against Sharepoint 2010 by any chance?

    • Hi Josh – I just updated all the SharePoint scripts, as another reader spotted some bugs. The scripts above, and the downloads have all been updated.

  3. what were the code written in this code SPFunctions.ps1, i am not able to find the link page to this file?

    • After migrating to a new WordPress platform, I lost all my ZIP files. I have now fixed this, and the files are available again.

    • It depends what you mean by “dead” accounts. If you mean accounts that have been deleted from AD, but still have alerts associated with them – YES! That is what the script is designed to do.

  4. hi cant find what the error is and cant find the GUID, which one is for the 80 port site.

    ###################################################################################

    This application adds or removes alerts for a user in a specified web application
    Here is a list of all Web Applications on the farm
    The term ‘Get-SPWebApplication’ is not recognized as the name of a cmdlet, function, script file, or operable program.
    Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At C:UserswssadminDesktopdelete-spalert.ps1:34 char:21
    + Get-SPWebApplication <<<< | ft name, id;
    + CategoryInfo : ObjectNotFound: (Get-SPWebApplication:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Please copy the GUID for the web application you wish to use by selecting then
    clicking the right mouse button.

    Note that the Central Admin site collection has no name,
    but does have a GUID! Don't select this one by accident!

    You can paste the GUID by clicking the Right mouse button again
    GUID: SharePoint – 80
    Checking GUID
    The term 'Check-GUID' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
    spelling of the name, or if a path was included, verify that the path is correct and try again.
    At C:UserswssadminDesktopdelete-spalert.ps1:51 char:18
    + switch(Check-GUID <<<< ($guid)){
    + CategoryInfo : ObjectNotFound: (Check-GUID:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    The term 'Get-SPWebApp' is not recognized as the name of a cmdlet, function, script file, or operable program. Check th
    e spelling of the name, or if a path was included, verify that the path is correct and try again.
    At C:UserswssadminDesktopdelete-spalert.ps1:56 char:23
    + $webapp = Get-SPWebApp <<<

    please guide

  5. sorry to mention that i am using Sharepoint 2010 SP1.
    and which GUID to use as from IIS i can see GUID but they are for services. I only want to select the site at port 80 and also from port 9000.

    Thank you.

    • Hi Moz – these scripts are for SharePoint 2007. I don’t know if they would work with SharePoint 2010 at all. I have made an update to the script prompted by another reader, which changes the way the GUIDs for the web apps are listed. If you download SPFunctions.ps1 and delete-spalert.ps1 again, you may get different results, but again, I’ve only tried it in Sharepoint 2007.

    • I have a need for a similar type of program. In my case, the user is still here. He is getting email from an alert, however, that was created on a site that has, since that time, been deleted. The alert keeps sending email saying a workflow task is overdue, but the user cannot reach the site to do anything about it.

      Is there a way for your script to display all the alerts from the person and to allow me to indicate yes or no regarding deleting of the alert? I have the old URL where the alert was originally created, if there is a way to filter the alerts examined so that one sees a lesser number of alerts.

    • Alerts are set up on the site collection, rather than the site so if that still exists you can probably easily enough get rid of it through the standard web interface. That probably makes more sense than rewriting the script to filter for a specific site.

      In terms of changes to the script, it should be possible to display the details of each alert found for a given user. in fact I think when I was originally writing the script I did this as part of my debugging, but removed from the final version as I didn’t want or need that level of verbosity.

      The yes/no functionality is much more of a challenge in PowerShell. I am sure you can do it, but you may find it is not worth the effort where you only occasionally want to delete a specific alert for a specific user. My use case was something I was doing a couple of times a month to get rid of alerts for staff who had left – I didn’t particularly care which alerts I was deleting.

      I’d be delighted if you used my script as the basis for resolving your specific issue. If you do, please share with the wider SharePoint community.

      It may also be worth asking at Sharepoint Stack Exchange or other fora where someone may have shared something closer to what you are trying to achieve.

    • I am uncertain how to find alerts at the site collection level – anyone have a keyword for me to google to find more info? Thanks!

    • If you have the URL for the deleted site, you should be able to figure out the Site Collection URL (it will be part of the path – probably starting http://servername/site/collectionname) – go to that, or another site in that, and then go to Alerts. Alternatively, you can find all your site collections in Central Admin under Application Management > Sharepoint Site Management > Site Collection List – from there you can get to the management pages for the site collection and find all the alerts and workflows that exist, and figure out why your user is getting the specific alerts.

    • So, I went to a sibling site, then to the _layouts/sitesubs.aspx page, which the site collection site settings called the user alerts page. There are no alerts listed there.
      Is that the page to which you referred? Note that this recurring email alert appears to be telling the user that a sharepoint out of the box approval workflow task is overdue – would those show up as user alerts?

    • That is the page which I referred to. However, messages generated by workflows are different altogether – I missed your reference to workflow in your original comment. The workflows relate to a list, and the out of box workflow messages will link to the list in question.

      What happens if you go to the address in the email? What happens if you go to the _layouts/settings.aspx URL corresponding to the site/site collection linked to? You need to find where the actual workflow is stored (clue is the link in the messages) and then use SharePoint Designer to access the Workflow list, where you should be able to deal with it.

  6. Hi Duncan – how would the script be updated to delete ALL alerts from a site collection not just those for one user? I’m migrating old content and alerts are being thrown once the content gets to O365. I want to remove all of them from the 2007 environment before upgrading. Thanks!

Leave a comment