Enabling Exchange Online SMTP Client Authentication with Powershell - powershell

I'm trying to enable Authenticated SMTP in Exchange Online via PowerShell.
I was semi successful with my attempts.
$Users = Get-CASMailbox -ResultSize unlimited
$Users | where {$_.SmtpClientAuthenticationDisabled -eq $true} | Set-CASMailbox -SmtpClientAuthenticationDisabled $False
This resulted in about 75% of the users having SMTP Authentication activated. But weirdly not all of them.
$Users = Get-CASMailbox -ResultSize unlimited
$Users | where {$_.SmtpClientAuthenticationDisabled -eq $true -or $null -or ""} | Set-CASMailbox -SmtpClientAuthenticationDisabled $False
Showed the same results.
As did:
$Users = Get-CASMailbox -ResultSize unlimited
$Users | where {$_.ImapEnabled -eq $true} | Set-CASMailbox -SmtpClientAuthenticationDisabled $False
So apparently this has nothing to do with the state of SmtpClientAuthenticationDisabled since I tried all possible states and used ImapEnabled -eq $true as a condition which is $true for every user.
I just started working with PowerShell and only have some basic programming knowledge. This setting has to be changed for about 80 accounts right now, but in a week or two about 4000 accounts will be synchronized with AzureAD and therefore Exchange Online. So far I haven't received an answer from the company which synchronizes the accounts on wether or not it's possible to set the state of SmtpClientAuthenticationDisabled when the synchronization happens. I expect that I will have to do it myself.
All users have an active Office 365 Licence and an active Exchange Online Plan.
Does anyone have some insight as to why only most but no all of the users accept this setting?
Edit:
When trying to execute your suggested script or when trying to execute my own commands I run into the issue that '$user' returns '$null' which I don't understand.
Setting SmtpClientAuthenticationDisabled for failed, error: Cannot bind argument to parameter 'Identity' because it is null.
This also happens when im only executing this:
$Users = Get-CASMailbox -ResultSize Unlimited
foreach($user in $users) {Write-Host "$($user.DisplayName)"}
It just returns nothing.
I think there is something fundamental that I don't understand.
If I just list the contents of '$users' PowerShell returns a list of all the users with the related settings like 'SmtpClientAuthenticationDisabled'.

If you want your complete organization to use the same setting, you should leave the values of the users $null. Instead set the TransportConfig.
Get-TransportConfig
Then check the value. If it is set to 'False', all users with a $null-value for SmtpClientAuthenticationDisabled will have the default setting of 'False'.
If set to 'True', change to 'False' instead:
Set-TransportConfig -SmtpClientAuthenticationDisabled $false
To answer your original question, of why the users are not updated properly. I think it has something to do with the fact that 'SmtpClientAuthenticationDisabled' is not a filterable attribute in the first place. So you will always have to query your complete dataset, which is not very elegant.
You could do something like the following to check and see what happens exactly:
$Users = Get-CASMailbox -ResultSize Unlimited
foreach($user in $Users){
if($user.SmtpClientAuthenticationDisabled -eq $null -or $user.SmtpClientAuthenticationDisabled -eq $true){
try{
Set-CASMailbox -Identity $user.ExchangeObjectId.guid -SmtpClientAuthenticationDisabled $false -ErrorAction Stop
Write-Host "$($user.DisplayName) succesfully set to correct state" -ForegroundColor Green
}catch{
Write-Host "Setting SmtpClientAuthenticationDisabled for $($user.DisplayName) failed, error: $_" -ForegroundColor Red
}
}else{
Write-Host "$($user.DisplayName) already has the correct state: $($user.SmtpClientAuthenticationDisabled)" -ForegroundColor Green
}
}
But personally I would change the above script to use it to set all values to $null:
Set-CASMailbox -Identity $user.ExchangeObjectId.guid -SmtpClientAuthenticationDisabled $null -ErrorAction Stop

Related

active directory show locked users which are not expired

Is there a way to show the locked users, not disabled (if the password has typed wrong 3 time), which are are not expired (account not expired) either with AD query or a powershell script.
I searched on the net but couldn't find a solution.
This should work if your looking for locked out accounts which are not yet expired or without an expiration date set:
Search-ADAccount -LockedOut | where { $_.AccountExpirationDate -gt (Get-Date) -or $_.AccountExpirationDate -eq $null }
There is a way. You could import ActiveDirectory module and use Search-ADAccount cmdlet.
Search-ADAccount -LockedOut -UsersOnly | Where-Object { $_.PasswordExpired -eq $false }

Log each Powershell process to text file through

Firstly, I'm by no means a PS expert, total newbie - admission done. I have scoured the internet for what I need in order to get the script to do what I want, but I've reached a point where I'm struggling and in need of help.
Basically, I've created a script using ISE that grabs the users in an AD OU, processes them by disabling the accounts, renaming them, stripping out the groups and moving them to another folder. In order to automate the deactivation process for users. But I now need to create a log file every time this runs, to show a) if it found any Users in the original OU (ToBeProcessed) and b) what processes were run and if they were successful. Here is the code.
$OUToBeProcessed = "OU=ToBeProcessed,OU=Users,OU=World,DC=local"
$OURetired = "OU=RetiredUsers,OU=Users,OU=World,DC=local"
$Users = Get-ADUser -SearchBase $OUToBeProcessed -Filter 'name -Like "*"' -Properties MemberOf
ForEach($User in $Users){
$SAN = $User.SamAccountName
#Disable user account
Disable-ADAccount -Identity $SAN
#Remove membership from groups for user
$User.Memberof | Remove-ADGroupMember -Member $User -Confirm:$False
$NewDN = "zzz_" + $User.Name
#Change display name
set-aduser $User -Displayname $newDN -ErrorAction SilentlyContinue
#Change distinguished name
Get-ADUser $SAN | Rename-ADObject -Newname $NewDN
Write-Host "$SAN may already exist."
#Move account to RetiredUsers
Get-Aduser $SAN | Move-ADObject -TargetPath $OURetired
}
I'm assuming I'll need to either use a Write-Output or Log-File cmdlet, though someone had also suggested Transcript, but I don't think that's what I need.
I've tried a number of ways to incorporate the Write-Output into the script, it runs without errors, but no text file is produced. But I'm placing it within the loop which may be the issue. I've placed it outside the loop but I think because it's not being passed anything it's creating the file with nothing in it. Would really appreciate some help as to where the Write-Output might need to go if that is the right cmdlet.
Personally I tend to add a Log function to my scripts. Something like this (where I output to the host and file):
Function Log {
Param (
[Parameter(Mandatory=$true)] [string] $String,
[Parameter(Mandatory=$true)] [string] $LogFilePath,
[Parameter(Mandatory=$false)][ValidateSet("ERROR","WARN","INFO","DEBUG")] [string] $Level = "INFO"
)
$LogString = ((Get-Date -Format "s") +" $Level $env:USERNAME $String")
Write-Host $LogString
Out-File -Append -FilePath $LogFilePath -InputObject $LogString
}
Then you could do logging:
Log "Something wrong!" "c:\mylog.log" "WARN"
Log "Updated stuff" "c:\mylog.log"
Or search the http://www.powershellgallery.com/ for logging modules.
Example (haven't tried this one myself):
https://www.powershellgallery.com/packages/PSLogging/2.5.2

user to see Terms and conditions screen at password change

The company I am working for would like a splash screen that I did to pop up when ever a user changes password (90 day rule at present), this is mainly due to a external requirement.
One of the snags I have is that the system has no email to show me that a user is expiring, I am looking at a couple of things
A log output of expired accounts and locked accounts, ignoring accounts not logged on disabled accounts system etc.
On the 90 day policy a splash screen pops up with the t$c with an accept or decline window (they see this when they first turn the PC and pops up just before the logon box on basically saying by accepting you agree to have read blah and blah)
I do not know how to get either this to run as one script or have two separate scripts,
Any input greatly appreciated
Import-Module ActiveDirectory # Required for PowerShell 2.0 only
$a = (Get-Date).Date.AddDays(-89)
# The following line will build the variable based upon the noted criteria
$b = Get-ADUser `
-Property Name, SamAccountName, PasswordLastSet, CannotChangePassword, PasswordNeverExpires `
-Filter { (PasswordLastSet -lt $a) -and (PasswordNeverExpires -eq $false) } |
Where-Object { $_.CannotChangePassword -eq $false }
# The following line will display/export the data logging the accounts to be changed
# please note the Out-File path and change to suit your needs.
$b | Format-Table Name, PasswordLastSet, CannotChangePassword, PasswordNeverExpires -AutoSize |
Out-File -FilePath "C:\passwordchanges.txt"
# The following line will actually flag the accounts to require a password change
# (after -WhatIf is removed)
$b.SamAccountName | ForEach-Object {
Set-ADUser -Identity $_ -ChangePasswordAtLogon $true -WhatIf
}

migrate from get-qaduser to get-aduser

I have setup my script to disable inactive user in my Win 2003 AD server using Quest's AD tool GET-QADUSER, and now I am going to migrate AD to Win 2008 R2. Since there is Active Directory module and Quest's tool is no longer free to download (is that?), I am going to migrate to GET-ADUSER.
I am converting from:
Foreach ($ou in $searchBase) {
#$inactUsr += #(Get-QADUser -SearchRoot $ou -Enabled -PasswordNeverExpires:$false -NotLoggedOnFor $inactiveDays -CreatedBefore $creationCutoff -SizeLimit $sizeLimit | Select-Object Name,SamAccountName,LastLogonTimeStamp,Description,passwordneverexpires,canonicalName | Sort-Object Name)
}
to:
$inactUsr += #(Get-ADUser -SearchRoot $ou -Filter 'enabled -eq $true -and PasswordNeverExpires -eq $False' -Properties Name,SamAccountName,LastLogonTimeStamp,Description,passwordneverexpires,canonicalName | Select Name,SamAccountName,#{N='LastLogonTimeStamp'; E={[DateTime]::FromFileTime($_.LastLogonTimeStamp)}},Description,passwordneverexpires,canonicalName | Sort Name)
I am almost there and leave only -NotLogonFor (which select user that not logon for certain days) and -CreatedBefore (which give a grace period for newly created ID). I want to select ID NotLogon for 30 days and DO NOT want ID created less than 30 days.
Appreciate if anyone can let me know whether there is a built-in properties or any manual method to achieve that.
Edited:
I have the CreatedBefore solved by:
$inactUsrdraft += #(Get-ADUser -SearchBase $ou -Filter 'enabled -eq $true -and PasswordNeverExpires -eq $False -and whenCreated -le $CreationCutOff' -Properties Name,SamAccountName,LastLogonTimeStamp,Description,passwordneverexpires,canonicalName | Select Name,SamAccountName,#{N='LastLogonTimeStamp'; E={[DateTime]::FromFileTime($_.LastLogonTimeStamp)}},Description,passwordneverexpires,canonicalName | Sort Name)
:)
Now I need only need to filter ID not logon more than 30 days.
Any help is appreciated.
How about:
$LastLogonCutoff = (Get-Date).Date.AddDays(-30)
That's midnight 30 days ago. If you want it to the second, use (Get-Date).AddDays(-30).
Followed by changing the -Filter to include:
`-and (LastLogonTimeStamp -lt $LastLogonCutoff)`
Also beware that the LastLogonTimeStamp property is not very accurate. Laptop logins off-network that use saved credentials won't trigger, I believe. If you don't have "Wait for network" enabled, clients might never actually update this value, IIRC.

Powershell command to hide user from exchange address lists

I'm trying to write powershell script which hides user from exchange lists.
I was able to find following command:
Set-Mailbox -Identity [user id here] -HiddenFromAddressListsEnabled $true
And it doesn't give me an error message, and when I run the command twice, I get following warning:
WARNING: The command completed successfully but no settings of '[user id here]' have been modified.
Which probably means that the command did actually work.
but when I go to Exchange Management Console, and open user profile, "hide user from exchange address lists" check box is off.
What could be the reason?
I use this as a daily scheduled task to hide users disabled in AD from the Global Address List
$mailboxes = get-user | where {$_.UserAccountControl -like '*AccountDisabled*' -and $_.RecipientType -eq 'UserMailbox' } | get-mailbox | where {$_.HiddenFromAddressListsEnabled -eq $false}
foreach ($mailbox in $mailboxes) { Set-Mailbox -HiddenFromAddressListsEnabled $true -Identity $mailbox }
You can use the following script, just replace DOMAIN with the name of your domain. When executed it will prompt you for a userlogin then hide that user's account from the address lists.
$name=Read-Host "Enter login name of user to hide"
Set-Mailbox -Identity DOMAIN\$name -HiddenFromAddressListsEnabled $true
Brian.
I was getting the exact same error, however I solved it by running $false first and then $true.
You will have to pass one of the valid Identity values like DN, domain\user etc to the Set-Mailbox cmdlet. Currently you are not passing anything.
"WARNING: The command completed successfully but no settings of '[user id here]' have been modified."
This warning means the setting was already set like what you want it to be. So it didn't change anything for that object.
For Office 365 users or Hybrid exchange, go to using Internet Explorer or Edge, go to the exchange admin center, choose hybrid, setup, chose the right button for hybrid or exchange online.
To connect:
Connect-EXOPSSession
To see the relevant mailboxes:
Get-mailbox -filter {ExchangeUserAccountControl -eq 'AccountDisabled'
-and RecipientType -eq 'UserMailbox' -and RecipientTypeDetails -ne 'SharedMailbox' }
To block based on the above idea of 0KB size:
Get-mailbox -filter {ExchangeUserAccountControl -eq 'AccountDisabled'
-and RecipientTypeDetails -ne 'SharedMailbox' -and RecipientType -eq 'UserMailbox' } | Set-Mailbox -MaxReceiveSize 0KB
-HiddenFromAddressListsEnabled $true