Script to disable Clutter on new mailboxes created in Office 365

With the upcoming Clutter enhancements in June 2015 Microsoft will be changing the default behavior on new mailboxes that are created. This behavior will now have new mailboxes generated with Clutter turned on. While I personally love the Clutter feature some business may not be ready for Clutter or in the middle of a migration. While Microsoft at this time has not given the tenant owners the capability to change this new default behavior I wrote a quick script to turn Clutter off for new mailboxes and allow people to opt in to use Clutter rather than opt out when they are created.

 

The following script uses cached generic windows credentials in the control panel application Credential Manager. It connects to Office 365 and searches for mailboxes created within the last 2 days and sets clutter to disable on the mailboxes. You can then set a scheduled task on a server to run this script nightly.

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

#search for: $targetName = "GenriccachedCredname" # CHANGE HERE

# it is here that you call the name of the cached generic windows credential that was created in credential manger control panel app, this credential will need to have access to your tenants mailboxes.

#Get the current date and time.
$DateTime=Get-Date
$filedate = Get-Date -format "MMdyyyyHMs"

#Change the path of log file to a desired location below
$LogFilePath = "C:\Scripts\Output\"

#Build the log file name.  Do not update this variable
$LogFile = $LogFilePath + "DisableClutter" + $filedate + ".log"

Echo "Script Starting: $DateTime"  | Out-File $LogFile -Append

#Obtain Stored Creds

$ErrorActionPreference = "silentlycontinue"
$sig = @"
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct NativeCredential
{
    public UInt32 Flags;
    public CRED_TYPE Type;
    public IntPtr TargetName;
    public IntPtr Comment;
    public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
    public UInt32 CredentialBlobSize;
    public IntPtr CredentialBlob;
    public UInt32 Persist;
    public UInt32 AttributeCount;
    public IntPtr Attributes;
    public IntPtr TargetAlias;
    public IntPtr UserName;
    internal static NativeCredential GetNativeCredential(Credential cred)
    {
        NativeCredential ncred = new NativeCredential();
        ncred.AttributeCount = 0;
        ncred.Attributes = IntPtr.Zero;
        ncred.Comment = IntPtr.Zero;
        ncred.TargetAlias = IntPtr.Zero;
        ncred.Type = CRED_TYPE.GENERIC;
        ncred.Persist = (UInt32)1;
        ncred.CredentialBlobSize = (UInt32)cred.CredentialBlobSize;
        ncred.TargetName = Marshal.StringToCoTaskMemUni(cred.TargetName);
        ncred.CredentialBlob = Marshal.StringToCoTaskMemUni(cred.CredentialBlob);
        ncred.UserName = Marshal.StringToCoTaskMemUni(System.Environment.UserName);
        return ncred;
    }
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Credential
{
    public UInt32 Flags;
    public CRED_TYPE Type;
    public string TargetName;
    public string Comment;
    public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
    public UInt32 CredentialBlobSize;
    public string CredentialBlob;
    public UInt32 Persist;
    public UInt32 AttributeCount;
    public IntPtr Attributes;
    public string TargetAlias;
    public string UserName;
}
public enum CRED_TYPE : uint
    {
        GENERIC = 1,
        DOMAIN_PASSWORD = 2,
        DOMAIN_CERTIFICATE = 3,
        DOMAIN_VISIBLE_PASSWORD = 4,
        GENERIC_CERTIFICATE = 5,
        DOMAIN_EXTENDED = 6,
        MAXIMUM = 7,      // Maximum supported cred type
        MAXIMUM_EX = (MAXIMUM + 1000),  // Allow new applications to run on old OSes
    }
public class CriticalCredentialHandle : Microsoft.Win32.SafeHandles.CriticalHandleZeroOrMinusOneIsInvalid
{
    public CriticalCredentialHandle(IntPtr preexistingHandle)
    {
        SetHandle(preexistingHandle);
    }
    public Credential GetCredential()
    {
        if (!IsInvalid)
        {
            NativeCredential ncred = (NativeCredential)Marshal.PtrToStructure(handle,
                  typeof(NativeCredential));
            Credential cred = new Credential();
            cred.CredentialBlobSize = ncred.CredentialBlobSize;
            cred.CredentialBlob = Marshal.PtrToStringUni(ncred.CredentialBlob,
                  (int)ncred.CredentialBlobSize / 2);
            cred.UserName = Marshal.PtrToStringUni(ncred.UserName);
            cred.TargetName = Marshal.PtrToStringUni(ncred.TargetName`);
            cred.TargetAlias = Marshal.PtrToStringUni(ncred.TargetAlias);
            cred.Type = ncred.Type;
            cred.Flags = ncred.Flags;
            cred.Persist = ncred.Persist;
            return cred;
        }
        else
        {
            throw new InvalidOperationException("Invalid CriticalHandle!");
        }
    }
    override protected bool ReleaseHandle()
    {
        if (!IsInvalid)
        {
            CredFree(handle);
            SetHandleAsInvalid();
            return true;
        }
        return false;
    }
}
[DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CredRead(string target, CRED_TYPE type, int reservedFlag, out IntPtr CredentialPtr);
[DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)]
public static extern bool CredFree([In] IntPtr cred);
"@
Add-Type -MemberDefinition $sig -Namespace "ADVAPI32" -Name 'Util'
$targetName = "GenriccachedCredname" # CHANGE HERE
$nCredPtr= New-Object IntPtr
$success = [ADVAPI32.Util]::CredRead($targetName,1,0,[ref] $nCredPtr)
if($success){
    $critCred = New-Object ADVAPI32.Util+CriticalCredentialHandle $nCredPtr
    $cred = $critCred.GetCredential()
 $UserName = $cred.UserName;
    $Password = $cred.CredentialBlob;
 $Password = ConvertTo-SecureString -String $Password -AsPlainText -Force
 $objCreds = New-Object Management.Automation.PSCredential $UserName, $Password
}

#Validating MSOL creds
Import-Module MSOnline
Connect-MsolService -Credential $objCreds

$O365Session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $objCreds -Authentication Basic -AllowRedirection
Import-PSSession $O365Session

# Variable for mailboxes last created with 2 days

$datecreatecount=$(Get-Date).AddDays(-2)

# Get all mailbox users in O365
$mbxs = Get-mailbox -ResultSize unlimited | where { $_.WhenCreated -gt $datecreatecount }
# Iterate through the users and Set Clutter to False
foreach($mbx in $mbxs)
{
    $mbxcreatedate=$mbx.whencreated
    Set-clutter -Identity $mbx.PrimarySmtpAddress -enable $false
    Echo "Disabled Clutter for $mbx created on $mbxcreatedate"  | Out-File $LogFile -Append
}

#Get the current date and time.
$DateTime=Get-Date

Echo "Script Ending: $DateTime"  | Out-File $LogFile -Append

 

To view or add a comment, sign in

More articles by Nathan Swift

Others also viewed

Explore content categories