Stuck in the Past! SharePoint Alerts Pointing to An Old URL After Migration?

I've run into this personally a couple of times and never really documented my own solution so that I had it for myself to reuse. If the URL for your SharePoint Farm ever changes you're more than likely to start hearing from your users that the alert subscription emails they get still point to the old Farm URL. I've encountered this on SP 2007 and SP 2010 Farms. As it turns out, each Alert Subscription contains a hard coded server root URL which is used when the alert email is generated to construct links. I wrote, and you'll see several other examples out there, the PowerShell script below to loop through all Web Applications of the server and perform an update on all Alert Subscriptions. I like my scripts that need to be run on all sites to run through my whole farm rather than one site at a time. This script works on both SP 2007 and SP2010. This script will Skip the Central Admin Web Application and Your SSP and MySite Sites.

 $oldrooturl = "https://<url>"  
  [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")> $null  
  [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Portal")> $null  
  [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Security")> $null  
  $farm = [Microsoft.SharePoint.Administration.SPFarm]::Local;  
  $services = @($farm.Services | where -FilterScript {$_.GetType() -eq [Microsoft.SharePoint.Administration.SPWebService]})  
  foreach ($service in $services)  
  {  
   foreach($app in $service.WebApplications)  
   {  
    $sites = $app.Sites  
    if ($app.DisplayName.Contains('Central Administration'))  
    {  
     continue  
    }  
    foreach ($site in $sites)  
    {    
     if (!$site.ServerRelativeUrl.Contains("ssp/") -and !$site.ServerRelativeUrl.Contains("MySite"))  
     {  
       $rooturl = $site.Url.Replace($site.ServerRelativeUrl, '')  
       foreach ($web in $site.AllWebs)  
       {  
         $updated = 0  
         $alerts = $web.alerts  
         Write-Host "Number of Alerts in: "$web.url ":" $alerts.count  
         if ($alerts.count -ne 0)  
         {  
           foreach ($alert in $alerts)  
           {           
            $alert.Status = [Microsoft.SharePoint.SPAlertStatus]::Off  
            $alert.Update()  
            if ($alert.Properties -ne $null)  
            {  
               $changed = $FALSE  
               $siteUrl = $alert.Properties["siteurl"]  
               if ($siteUrl -ne $null -and $siteUrl.Contains($oldrooturl))  
               {  
                $alert.Properties["siteurl"] = $siteUrl.Replace($oldrooturl, $rooturl)  
                $changed = $TRUE  
               }  
               $mobileUrl = $alert.Properties["mobileurl"]  
               if ($mobileUrl -ne $null -and $mobileUrl.Contains($oldrooturl))  
               {  
                $alert.Properties["mobileurl"] = $mobileUrl.Replace($oldrooturl, $rooturl)  
                $changed = $TRUE  
               }    
               if ($changed)  
               {  
                $updated++  
                write-host "Alert updated: " $alert.Title "For User: " $alert.User  
               }  
             }  
             $alert.Status = [Microsoft.SharePoint.SPAlertStatus]::On  
             $alert.Update()   
           }  
           Write-Host "Number of alerts updated: " $updated  
         }  
       }  
     }  
     $site.Dispose()  
    }  
   }  
  }