Script Repository


Allow users to add themselves to groups by e-mail

February 24, 2021
1848

The script enables users to add themselves to Active Directory groups by sending an email to an Exchange mailbox. The mail message must have a subject that conforms to a certain predefined format. In the below example, the subject format is Automated task. Add me to: <Group Name>, where <Group Name> specifies the Group Name (pre-Windows 2000) of the group to add a user to. Users are added by their email address specified in the From field of the mail message. The email address must be specified in one of the following attributes of the AD user account:

  • Email (LDAP name mail)
  • Email Proxy Addresses (LDAP name proxyAddresses)

For information on how to grant necessary permissions to the Azure application used to register the Microsoft 365 tenant in Adaxes, see Authenticate an EWS application by using OAuth.

To be able to launch the script, download and install Microsoft Exchange Web Services Managed API on the computer where Adaxes service runs.

Parameters:

  • $exchangeWebServiceDllPath - Specifies the full path to the Microsoft Exchange Web Services dll module.
  • $exchangeServer - Specifies the fully qualified domain name (FQDN) of your Exchange Server. Specify $NULL if you want to pull email messages from an Exchange Online mailbox.
  • $subject - Specify the format for the message subject. The script will search for the group name at the very end of the subject.
  • $mailboxMailAddress - Specifies the address of the mailbox where requests to be added to a group will be sent.
    You can use value references in the mailbox address. For example, if you specify %mail%, the script will search in the mailbox of the user on which the script is executed.
Edit Remove
PowerShell
# Exchange settings
$exchangeWebServiceDllPath = "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll" # TODO: modify me
$exchangeServer = "ExchangeServer.domain.com" # TOOD: modify me. If $NULL, connect to Exchange Online
$subject = "Automated task. Add me to" # TOOD: modify me
$mailboxMailAddress = "recipient@domain.com" # TOOD: modify me

Import-Module $exchangeWebServiceDllPath

function SearchObjects($filter, $propertiesToLoad)
{
    $searcher = $Context.BindToObject("Adaxes://rootDSE")
    $searcher.SearchFilter = $filter
    $searcher.SearchScope = "ADS_SCOPE_SUBTREE"
    $searcher.PageSize = 500
    $searcher.ReferralChasing = "ADS_CHASE_REFERRALS_NEVER"
    $searcher.SetPropertiesToLoad($propertiesToLoad)
    $searcher.VirtualRoot = $True
    
    try
    {
        $searchResultIterator = $searcher.ExecuteSearch()
        $searchResults = $searchResultIterator.FetchAll()
        
        return ,$searchResults
    }
    finally
    {
        # Release resources
        if ($searchResultIterator){ $searchResultIterator.Dispose() }
    }
}

if ($exchangeServer -eq $NULL)
{
    # Connect to Exchange Online via the Exchange Web Services API
    $exchangeWebService = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService
    $exchangeWebService.Url = "https://outlook.office365.com/EWS/Exchange.asmx"
    $token = $Context.CloudServices.GetAzureAuthAccessToken("https://outlook.office365.com/")
    $OAuthCredentials = New-Object Microsoft.Exchange.WebServices.Data.OAuthCredentials($token)
    $exchangeWebService.Credentials = $OAuthCredentials
    $exchangeWebService.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $mailboxMailAddress)
}
else
{
    # Connect to Exchange on-premises via the Exchange Web Services API
    $exchangeWebService = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010)
    $exchangeWebService.Url = "https://$exchangeServer/ews/exchange.asmx"
}

# Build filter to find the necessary mail message
$searchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Subject, $subject)
$searchFilterCollection = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And)
$searchFilterCollection.Add($searchFilter)

# Bind to the Inbox folder
$folderID = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox, $mailboxMailAddress)
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($exchangeWebService, $folderID)

# Set order
$itemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)
$itemView.OrderBy.Add([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, [Microsoft.Exchange.WebServices.Data.SortDirection]::Descending)

# Find message
$searchResults = $inbox.FindItems($searchFilterCollection, $itemView)
if ($searchResults.Items.Count -eq 0)
{
    return # No messages to process
}

# Process mail
foreach ($item in $searchResults.Items)
{
    $item.Load()
    $groupName = $item.Subject.Replace($subject, "").Trim()

    # Search group
    $searchResults = SearchObjects "(&(objectCategory=group)(sAMAccountName=$groupName))" @()
    
    if ($searchResults.Length -eq 0)
    {
        $Context.LogMessage("Group '$groupName' not found", "Warning")
        continue
    }
    elseif ($searchResults.Length -gt 1)
    {
        $Context.LogMessage("Found more than one group with name '$groupName'", "Warning")
        continue
    }
    $groupPath = $searchResults[0].AdsPath
    
    # Get sender address
    $senderMmailAddress = $item.Sender.Address
    
    # Find the user in AD
    $searchResults = SearchObjects "(&(sAMAccountType=805306368)(|(mail=$senderMmailAddress)(proxyAddresses=$senderMmailAddress)))" @()
    
    if ($searchResults.Length -eq 0)
    {
        $Context.LogMessage("Requesting user not found. Email address: '$senderMmailAddress'", "Warning")
        continue
    }
    elseif ($searchResults.Length -gt 1)
    {
        $Context.LogMessage("Cannot identify a requesting user. Found more than one user with mail '$senderMmailAddress'", "Warning")
        continue
    }

    $userPath = $searchResults[0].AdsPath
    
    # Add user to group
    $group = $Context.BindToObjectEx($groupPath, $True)

    try
    {
        $group.Add($userPath)
    }
    catch
    {
        $username = $Context.GetDisplayNameFromAdsPath($userPath)
        $Context.LogMessage("An error occurred when adding user '$username' to group '$groupName'", "Warning")
    }
    
    # Remove message
    $item.Delete("MoveToDeletedItems")
}


Comments ( 0 )
No results found.
Leave a comment