Enable or disable POP3 and IMAP4 by group membership in Exchange 2007

As you know, Exchange 2007 supports POP3 and IMAP4 protocols. Mostly, these protocols are shutdown (due to many concerns).

In certain cases, for you as the administrator, there is no other choice, but to enable this feature.

The next thing, you may consider, is to limit the usage of those protocols for certain users only. What you will find, that you can either enable or disable this per user (from the TechNet – How to Enable or Disable POP3 Access for a User).

Now the problem starts! You can start managing your users one by one, enabling or disabling them for POP3/IMAP4. But what would you do with the new users? They will be enabled by default!

The following guide describes the possibility to limit POP3 and IMAP4 protocols using Active Directory group. We will utilize two major PowerShell functions:

Get-Mailbox -Filter{(memberofgroup -eq GroupDistinguishedName)} -ResultSize:unlimited

and

Set-CASMailbox -Identity:MailboxDistinguishedName -PopEnabled:$true|$false

where in first function, the term GroupDistinguishedName will point to the distinguished name of the group, containing the list of POP3-enabled users.

Let the fun begin!

First we have to get the list of all enabled mailboxes into variable:

$mailboxes = Get-Mailbox -ResultSize:unlimited

Next, we will get the mailboxes, that their corresponding users are members of the group “POP3EnabledUsers“:

$groupidentity = $(Get-Group "POP3EnabledUsers").Identity.DistinguishedName
$pop3Enabled = Get-Mailbox -Filter{(memberofgroup -eq $groupidentity)} -ResultSize:unlimited

After this, we will loop through all mailboxes from the $mailboxes collection:

foreach ($mailbox in $mailboxes)
{
... code goes here ...
}

Now, it is just a matter of using temporary variable $enablePop3, that will include the “verdict” per each mailbox, wherever to enable or disable this particular mailbox for POP3:

$enablePop3 = $false
foreach ($pop3 in $pop3Enabled)
{
if ($pop3.DistinguishedName -eq $mailbox.DistinguishedName)
{
$enablePop3 = $true
}
}

Technically, this will return $true, only in case the $mailbox, currently the main loop runs on, appears in $pop3Enabled.

Finally, we can combine all pieces together. Working code will look like this:

###

$mailboxes = Get-Mailbox -ResultSize:unlimited
$groupidentity = $(Get-Group "POP3EnabledUsers").Identity.DistinguishedName
$pop3Enabled = Get-Mailbox -Filter{(memberofgroup -eq $groupidentity)} -ResultSize:unlimited
foreach ($mailbox in $mailboxes)
{
$enablePop3 = $false
foreach ($pop3 in $pop3Enable)
{
if ($pop3.DistinguishedName -eq $mailbox.DistinguishedName)
{
$enablePop3 = $true
}
}
if ($enablePop3 -eq $true)
{
if ((Get-CASMailbox -Identity:$mailbox.DistinguishedName).PopEnabled -ne $true)
{
$Pop3Enabled++
Set-CASMailbox -Identity:$mailbox.DistinguishedName -PopEnabled:$true
}
}
else
{
if ((Get-CASMailbox -Identity:$mailbox.DistinguishedName).PopEnabled -ne $false)
{
Set-CASMailbox -Identity:$mailbox.DistinguishedName -PopEnabled:$false
}
}
}

Voila! The result of this, will enable the POP3 option only for members of the group. All other mailboxes will be disabled. Run this code on the schedule basis, in order to keep the situation up to date. The same, with the slight changes, works for IMAP4.

I would like to express my special thanks to ilantz for his valuable help in creation of this code.

Any comments will be highly appreciated!

Advertisements

23 thoughts on “Enable or disable POP3 and IMAP4 by group membership in Exchange 2007

  1. Going to sound like a total Powershell noob here but can you give an example of how to run this? Even better would be to show how to set this as a scheduled task to run once a week on the exchange server.

    1. This particular peice of code you can run from the “Exchange Management Console”. Just paste it into the console window (hit extra Enter or two at the end). Replace the “POP3EnabledUsers” by your own or create the one with this name.
      It is definitely possible to run this on schedule. This will require more work to be done, like adding required snapins and loading needed modules.
      Please contact me, if any help needed!

  2. Wouldn’t it be more efficient to create a string array from your “approved” group, then simply do a -contains check?

    For example (I did mine for activesync based on your excellent idea for pop 🙂 )

    $activeSyncGroupMembers = Get-DistributionGroupMember -Identity ‘system.activesync.users’

    ##Get those users that are enabled
    $activeSyncEnabled = Get-CASMailbox -resultSize unlimited -filter {(activeSyncEnabled -eq $true)}

    ##Create string array
    $stringASArray = New-Object System.Collections.ArrayList

    ##build string array from distinguished name value only
    foreach ($mailbox in $activeSyncGroupMembers){
    [void] $stringASArray.Add(“$mailbox.DistinguishedName”)
    }

    foreach ($mailbox in $activeSyncEnabled){
    if($stringASArray -contains “$mailbox.distinguishedName”){
    Set-CASMailbox -Identity:$mailbox.DistinguishedName -ActiveSyncEnabled:$true
    }
    else{
    Set-CASMailbox -Identity:$mailbox.DistinguishedName -ActiveSyncEnabled:$false
    }
    }

    —-
    Primary difference is that you only loop through each feature once. Once through the ActiveSync/POP/IMAP/ETC and once through each mailbox. In a small environment (under 50 mailboxes or so I guess) there is a negligable difference I’m sure, but when you scale up past 100 or so this could introduce some issues.
    Also.. less loops is just what I’d be more comfortable with 🙂

    1. Thank you for your reply. The problem here, if you remove the user from the group, the script will not disable this user for POP3/IMAP/etc. Am I right?

  3. Good point, actually the opposite will happen: it will capture the removals (it collects the group of users that are enabled and validates against the group for those that are enabled); however the problem I didn’t consider is that this would only work for removal. It just happens to work for us since activesync is automatically enabled, you only really need to disable a user in our environment. Still.. I would prefer it to be fully automated if possible 🙂

    Here’s an update that I’m applying (this will also enable new members – note that your DC must propogate completely for the change to be recognised, on my systems it takes a few minutes before the script actially acknowledges the group membership change). Though I’m sure I still missed something somewhere.. :S

    $activeSyncGroupMembers = Get-DistributionGroupMember -Identity ‘your activesync group’

    ##Get those users that are enabled
    $activeSyncEnabled = Get-CASMailbox -resultSize unlimited -filter {(activeSyncEnabled -eq $true)}

    ##Create string array
    $stringASArray = New-Object System.Collections.ArrayList

    ##build string array from distinguished name value only
    foreach ($mailbox in $activeSyncGroupMembers){
    [void] $stringASArray.Add(“$mailbox.DistinguishedName”)
    Set-CASMailbox -Identity:$mailbox.DistinguishedName -ActiveSyncEnabled:$true
    }

    foreach ($mailbox in $activeSyncEnabled){
    if($stringASArray -contains “$mailbox.distinguishedName”){
    #do nothing – this is done in the group loop
    }
    else{
    Set-CASMailbox -Identity:$mailbox.DistinguishedName -ActiveSyncEnabled:$false
    }
    }

  4. Whome: Any ideas on the proper way to identify if the “Enabled Mailbox” is a Resource mailbox and take that subset and convert the mailbox to a “Regular Mailbox” Disable Pop and then convert that subset back to “Room Mailbox”?

    Maybe that is two seperate scripts…. I’ve toyed with a few options and can’t seem to get the result to work.

  5. flyer:
    That’s an interesting problem… not sure offhand. Haven’t come across the need to convert the mailbox to regular though I’m guessing a compound piped query should allow this to be done on the fly?

    Do you have a need to convert first to regular mailbox? I can take a look but um.. wanted to make sure I’m not interfering with podisk’s article as well.

  6. Yeah for POP3 there is no real need to do that but you can’t disable activesync on a room account that was created with it turned on. For small implementations there is no big deal to convert to regular inbox and run the tool and convert back to room but when you have a couple hundred or thousand room mailboxes that becomes a big chore.

    Let me know if you have any ideas.

  7. Thanks for this script, this is exactly what I was looking for. I implemented it nearly as-is on my company’s Exchange 2010 server. Here are the two modifications I had to make:

    First, you have a typo in the second foreach statement. It should say “$pop3Enabled” and not “$pop3Enable”.

    Also if, like me, one is using Exchange 2010 the filter in get-mailbox doesn’t work. One needs to use
    -Filter “memberofgroup -eq ‘$groupidentity'”
    instead of
    -Filter{(memberofgroup -eq $groupidentity)}

    Anyway, thanks again for this great script!

  8. Trying to remove Room mailboxes from the string array but not having luck. Can anyone provide some feedback? When I run with the room mailboxes in it hits a chunk of them and just stops without any indicated error. Following Flyer78’s idea of converting the box to a regular and back seems to allow the script to complete but we loose all the attributes of the room like capacity and such. I’m thinking If I can remove those mailboxes from the array before I do the set command that would be ideal…

    Script:

    $activeSyncGroupMembers = Get-DistributionGroupMember -Identity ‘Active Sync Enabled Users’

    ##Get those users that are enabled
    $activeSyncEnabled = Get-CASMailbox -resultSize unlimited -filter {(activeSyncEnabled -eq $true)}
    $RoomAccount = Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails RoomMailbox

    ##Create string array
    $stringASArray = New-Object System.Collections.ArrayList

    ##build string array from distinguished name value only
    foreach ($mailbox in $activeSyncGroupMembers){
    [void] $stringASArray.Add(“$mailbox.DistinguishedName”)
    }
    foreach ($mailbox in $RoomAccount){
    [void] $stringASArray.Remove(“$mailbox.DistinguishedName”)
    Set-CASMailbox -Identity:$mailbox.DistinguishedName -ActiveSyncEnabled:$true
    }

    foreach ($mailbox in $activeSyncEnabled){
    if($stringASArray -contains “$mailbox.distinguishedName”){
    #do nothing – this is done in the group loop
    }

    else{Set-CASMailbox -Identity:$mailbox.DistinguishedName -ActiveSyncEnabled:$false}
    }

  9. In my case I’m not even excluding the rooms, in fact I use the following to get who should be and who is set:
    #who should be set
    $validASMembers = Get-DistributionGroupMember -Identity ‘system.activesync.users’

    #who is set
    $enabledASFeatures = Get-CASMailbox -resultSize unlimited -filter {(activeSyncEnabled -eq $true)}

    Loops added for AS
    foreach ($mailbox in $validASMembers){
    if($mailbox){
    $resulted = $stringASArray.Add($mailbox.DistinguishedName)
    if ((Get-CASMailbox -Identity $mailbox.DistinguishedName).activeSyncEnabled){
    ##already enabled, leave alone
    }
    else{
    Set-CASMailbox -Identity:$mailbox.DistinguishedName -ActiveSyncEnabled:$true
    }
    }
    }

    foreach ($mailbox in $enabledASFeatures){
    if($mailbox){
    if($stringASArray -contains $mailbox.distinguishedName){
    ##no need to do anything – this is already done in the group loop
    }
    elseif (“UserMailbox” -eq (get-Mailbox $mailbox.distinguishedName).recipientTypeDetails){
    Set-CASMailbox -Identity:$mailbox.DistinguishedName -ActiveSyncEnabled:$false
    }
    }
    }

    That’s essentially it… the script I use is a bit more complex as I also block pop and imap (same thing just different vars and check popEnabled and imapEnabled).

    Are you excluding rooms because they’re coming up?

  10. So I have taken your script and basically substitued my AD group and I get an error. Here is the script as I am running it:
    ## To see errors…Copy Paste the Below into an EMC session. You will have several warnings for accounts where no change was required and may need to hit enter at the end.

    #Collect list of users who SHOULD have Active Sync set
    $validASMembers = Get-DistributionGroupMember -Identity ‘Active Sync Enabled Users’

    #Collect list of users who DO have Active Sync Set
    $enabledASFeatures = Get-CASMailbox -resultSize unlimited -filter {(activeSyncEnabled -eq $true)}

    #Loops added for AS
    foreach ($mailbox in $validASMembers){
    if($mailbox){
    $resulted = $stringASArray.Add($mailbox.DistinguishedName)
    if ((Get-CASMailbox -Identity $mailbox.DistinguishedName).activeSyncEnabled){
    ##Determin status of existing users. Already enabled?, leave alone
    }
    else{
    Set-CASMailbox -Identity:$mailbox.DistinguishedName -ActiveSyncEnabled:$true
    }
    }
    }

    foreach ($mailbox in $enabledASFeatures){
    if($mailbox){
    if($stringASArray -contains $mailbox.distinguishedName){
    ##no need to do anything – this is already done in the group loop
    }
    elseif (“UserMailbox” -eq (get-Mailbox $mailbox.distinguishedName).recipientTypeDetails){
    Set-CASMailbox -Identity:$mailbox.DistinguishedName -ActiveSyncEnabled:$false
    }
    }
    }

    Here is the associated error:
    You cannot call a method on a null-valued expression.
    At C:\MyScripts\ActiveSyncSetScript-WithoutRoom.ps1:12 char:32
    + $resulted = $stringASArray.Add <<<< ($mailbox.DistinguishedName)
    + CategoryInfo : InvalidOperation: (Add:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At C:\MyScripts\ActiveSyncSetScript-WithoutRoom.ps1:12 char:32
    + $resulted = $stringASArray.Add <<<< ($mailbox.DistinguishedName)
    + CategoryInfo : InvalidOperation: (Add:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At C:\MyScripts\ActiveSyncSetScript-WithoutRoom.ps1:12 char:32
    + $resulted = $stringASArray.Add <<<< ($mailbox.DistinguishedName)
    + CategoryInfo : InvalidOperation: (Add:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At C:\MyScripts\ActiveSyncSetScript-WithoutRoom.ps1:12 char:32
    + $resulted = $stringASArray.Add <<<< ($mailbox.DistinguishedName)
    + CategoryInfo : InvalidOperation: (Add:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At C:\MyScripts\ActiveSyncSetScript-WithoutRoom.ps1:12 char:32
    + $resulted = $stringASArray.Add <<<< ($mailbox.DistinguishedName)
    + CategoryInfo : InvalidOperation: (Add:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At C:\MyScripts\ActiveSyncSetScript-WithoutRoom.ps1:12 char:32
    + $resulted = $stringASArray.Add <<<< ($mailbox.DistinguishedName)
    + CategoryInfo : InvalidOperation: (Add:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    As you can see it errors out many times in a row.

    It looks like that function is basically trying to add each user from the group into a string array. I checked the group to see if there were diabled users or something that might trigger a null type scenario and there are only active users in there.

    Any ideas?

    Per you question about excluding the rooms… We originally setup our loops to disable it for everyone and then re-enable it for those in the group. In the process of disabling the lot it was hitting room mailboxes as well. I like your idea of creating the two groups who has it and who has it that shouldn't and working from that.

  11. Figured it out. forgot to define the string array. Added $stringASArray = New-Object System.Collections.ArrayList.

    Thanks for the help. Your script is working as expected.

  12. I really wanted to jot down a quick comment to express gratitude to you for some of the remarkable recommendations you are sharing at this site. My rather long internet search has finally been rewarded with really good concept to exchange with my great friends. I would tell you that most of us website visitors are unequivocally endowed to dwell in a notable website with many awesome people with great suggestions. I feel really privileged to have used your entire web page and look forward to so many more awesome moments reading here. Thanks a lot once more for everything.

  13. Hello,

    Thank you for a very useful post! I do have a question though regarding an error I am getting.

    This is with Exchange 2007 SP3 with your script being put into a ps1 file and being executed within the Exchange Management Shell, the first time runs fine and then I modify user membership of the group and run the same script again within the existing management shell and get this error.

    The ‘++’ operator works only on numbers. The operand is a ‘System.Object[]’.
    At C:\AJ_temp\enablepop3.ps1:18 char:2
    + $Pop3Enabled++
    + ~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : OperatorRequiresNumber

    The script still does what I expect it too but I wonder what this error actually means and how I go about resolving it?

    Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s