Kennwort läuft ab Mail verschicken mit PowerShell
In manchen ActiveDirectory Umgebungen ist es notwendig, dass Benutzer eine Mail erhalten, wenn ihr Passwort / Kennwort bald abläuft, da die Windows Benachrichtigungen nicht funktionieren. Wie man solche eine Kennwort läuft ab Mail versenden kann, mit einem einfachen PowerShell Script, seht ihr hier bei uns. 🙂
raphaelsilva / Pixabay
Die Kennwort läuft ab Mail versenden
Da Benutzer nicht immer an Ihren Windows-Computer angemeldet sind, sondern in Web-Portalen, so kann es vorkommen, dass das Windows-Kennwort nicht früh genug geändert wird und somit kein Login mehr möglich ist. Abhilfe schafft hier ein PS-Script. Dies ist sehr simpel mit einem kleinen Powershell Script umzusetzen:
(passwordnotificationmail.ps1 – Powershell)
################################################################################################################# # Requires: Windows PowerShell Module for Active Directory ################################################################################################################## # Please Configure $smtpServer="0.0.0.0." #IP mail server $expireindays = 7 #days before reminding $from = "Support <[email protected]>" $logging = "Enabled" # Set to Disabled to Disable Logging $logFile = "C:\mail.csv" # ie. c:\mylog.csv $testing = "Enabled" # Set to Disabled to Email Users $testRecipient = "[email protected]" # If Testing Is Enabled - Email Administrator ONLY # ################################################################################################################### # Check Logging Settings if (($logging) -eq "Enabled") { # Test Log File Path $logfilePath = (Test-Path $logFile) if (($logFilePath) -ne "True") { # Create CSV File and Headers New-Item $logfile -ItemType File Add-Content $logfile "Date,Name,EmailAddress,DaystoExpire,ExpiresOn,Notified" } } # End Logging Check # System Settings $textEncoding = [System.Text.Encoding]::UTF8 $date = Get-Date -format ddMMyyyy # End System Settings # Get Users From AD who are Enabled, Passwords Expire and are Not Currently Expired Import-Module ActiveDirectory $users = get-aduser -filter * -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |where {$_.Enabled -eq "True"} | where { $_.PasswordNeverExpires -eq $false } | where { $_.passwordexpired -eq $false } $DefaultmaxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge # Process Each User for Password Expiry foreach ($user in $users) { $Name = $user.Name $emailaddress = $user.emailaddress $passwordSetDate = $user.PasswordLastSet $PasswordPol = (Get-AduserResultantPasswordPolicy $user) $sent = "" # Reset Sent Flag # Check for Fine Grained Password if (($PasswordPol) -ne $null) { $maxPasswordAge = ($PasswordPol).MaxPasswordAge } else { # No FGP set to Domain Default $maxPasswordAge = $DefaultmaxPasswordAge } $expireson = $passwordsetdate + $maxPasswordAge $today = (get-date) $daystoexpire = (New-TimeSpan -Start $today -End $Expireson).Days # Set Greeting based on Number of Days to Expiry. # Check Number of Days to Expiry $messageDays = $daystoexpire if (($messageDays) -gt "1") { $messageDays = "in " + "$daystoexpire" + " Tagen" } else { $messageDays = "HEUTE" } # Email Subject Set Here $subject="Ihr Kennwort läuft $messageDays ab." # Email Body Set Here, Note You can use HTML, including Images. $body =" <p style=""font-family:'Segoe UI', Segoe UI;""> Hallo $name, <br><br> Ihr Windows-Kennwort wird $messageDays ablaufen.<br> Um Ihr Kennwort zu ändern, drücken Sie STRG-ALT-ENTF und wählen Sie 'Kennwort ändern'.<br><br> Dein Support Team.<br> (Bitte antworten Sie NICHT auf diese Email. Bei Fragen wenden Sie sich per Mail an <a href=""mailto:[email protected]"">[email protected]</a>) </P>" # If Testing Is Enabled - Email only Administrator if (($testing) -eq "Enabled") { $emailaddress = $testRecipient } # End Testing # If a user has no email address listed if (($emailaddress) -eq $null) { $emailaddress = $testRecipient }# End No Valid Email # Send Email Message if (($daystoexpire -ge "0") -and ($daystoexpire -lt $expireindays)) { $sent = "Yes" # If Logging is Enabled Log Details if (($logging) -eq "Enabled") { Add-Content $logfile "$date,$Name,$emailaddress,$daystoExpire,$expireson,$sent" } # Send Email Message Send-Mailmessage -smtpServer $smtpServer -from $from -to $emailaddress -subject $subject -body $body -bodyasHTML -priority High -Encoding $textEncoding } # End Send Message else # Log Non Expiring Password { $sent = "No" # If Logging is Enabled Log Details if (($logging) -eq "Enabled") { Add-Content $logfile "$date,$Name,$emailaddress,$daystoExpire,$expireson,$sent" } } } # End User Processing # End
Folgende Zeilen müssen im Script angepasst werden, um die Mail zum Kennwort korrekt zu senden:
- Zeile 4 – 12: Grundkonfiguration zum Mail – Server und Funktion
- Zeile 76 – 86: Content / Text der E-Mail
Pexels / Pixabay
Tipp
Diese Kennwort läuft ab Mail sollte dann nur noch 1x täglich per Aufgabenplanung ausgeführt werden. Wenn das Script nur wöchentlich ausgeführt wird, nützt es natürlich nichts 😉
Das Skript läuft leider nicht wenn ein anderer Port für SMTP genutzt wird.
wie bekommt man den Port geändert wenn die Variable -Port nicht erkannt wird
in der Zeile Send-Mailmessage ?
Hallo Thomas,
du brauchst in der Zeile 111 bei “Send-Mailmessage” noch ein “-Port 123”.
Also in deinem Fall:
Send-Mailmessage -smtpServer $smtpServer -port 123 -from $from -to $emailaddress -subject $subject -body $body -bodyasHTML -priority High -Encoding $textEncoding
Diese Zeile habe ich gerade gestestet – funktioniert.
Hast du evtl. einen Tippfehler oder ähnliches ?
Weitere Infos unter:
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/send-mailmessage?view=powershell-5.1
Hallo,
tolle Sache!
Eine Logrotation würde das Ganze jetzt noch perfekt machen ;=)
Hallo Rüdiger,
wir schauen uns das gerne mal an
Hallo zusammen,
wie kann hier noch eine OU einschränkung hinzugefügt werden?
VG
Schneider
Guten Tag,
In der Zeile 35 werden die AD-Benutzer ausgelesen.
Dort muss nach “Get-ADUser” ein
-SearchBase "OU=Abteilung1,OU=RootOU,DC=yourdomain,DC=com"
angehängt werden.
Die Zeile 35 wird also abgeändert auf:
$users = get-aduser -SearchBase "OU=Abteilung1,OU=RootOU,DC=yourdomain,DC=com" -filter * -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |where {$_.Enabled -eq "True"} | where { $_.PasswordNeverExpires -eq $false } | where { $_.passwordexpired -eq $false }
Hallo, super Skript, herzlichen Dank dafür 🙂 Ich möchte die User nur 14, 7 und 3 Tage vor Ablauf des Passwortes informieren. Wie muss ich das hinterlegen?
Hallo Patrick,
in Zeile 87 wird mit
$daystoexpire -lt $expireindays
geprüft:Wenn “daystoexpire” KLEINER “expireindays” ist, dann wird eine Mail gesendet.
Hier muss die Zeile auf folgendes geändert werden (ungetestet):
if (($daystoexpire -ge "0") -and (($daystoexpire -ge "14") -or ($daystoexpire -ge "7") -or ($daystoexpire -ge "3")))
Gruß Johannes
Müsste es nicht eigentlich lauten:
if (($daystoexpire -eq “14”) -or ($daystoexpire -eq “7”) -or ($daystoexpire -eq “3”))
Er will ja nur extakt an den Tagen 14,7,3
Bei -ge “14”, also größer gleich 14 würde doch jeder eine Mail bekommen oder habe ich hier einen Denkfehler?
Da hast du Recht – danke für den Hinweis! 🙂
Scirpt funktioniert, nur werden lediglich die ersten 5 Emails bei einen Zyklus übertragen, mehr geht. Obwohl ich im SMTP-Log der Connector für jeden einen Verbindung sehe.
Hallo und Vielen Dank für dieses Script,
leider werden unter exchange 2016 / outlook 2019 die umlaute fehlerhaft dargestellt. Hast du eine idee dafür ?
Das liegt an der Kodierung der HTML Datei.
Das sollte dir weiter helfen:
https://www.designerinaction.de/tipps-tricks/web-development/html-umlaute-sonderzeichen/#html-umlaute-utf8
Falls noch mehr Leute das Problem haben, du musst die Kodierung des Scripts in UTF-8-BOM ändern.
Das geht am einfachsten mit Notepad++. Dort gehst du auf Kodierung -> Konvertiere zu UTF-8-BOM und speichert das Script erneut ab.
Alternativ das Script mit der PowerShell ISE erstellen, dann sollte die Kodierung auch passen.
Hallo, gutes Script! Kann man es auch so umstellen, dass Vorname Nachname ausgegeben wird? Im Moment wird es aufgrund der Eintragung im AD genau anders rum dargestellt z.B. Hallo Müller, Anton
Hallo Dirk,
klar, das sollte kein Problem sein. 🙂
In Zeile 37 wird der (komplette) Name aus dem AD ausgelesen und in der Variable
$Name
gespeichert.Du benötigst jeweils die AD-User-Attribute
– givenName (Vorname)
– sn (Nachname)
Die Reihenfolge legst du dann fest. UNGETESTET sollte Zeile 37 dann folgendermaßen lauten:
$Name = $user.sn, $user.givenName
Gruß Johannes
Hallo, ich finde das Script, im Vergleich zu all den anderen echt Top!
Leider komme ich nicht weiter miot dem SMTPServer und Office…
So sieht es bei mir aus:
Send-Mailmessage : Verarbeitungsfehler. Die Serverantwort war: 5.7.3 STARTTLS is required to send mail [PR0P264CA0164.FRAP264.PROD.OUTLOOK.COM]
In C:Usersadministrator.*****Desktoppasswordnotificationmail.ps1:96 Zeichen:1
+ Send-Mailmessage -smtpServer $smtpServer -port 587 -from $from -to $emailaddress …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpException
+ FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
Hat da jemand eine Lösung?
Viele Grüße
Guten Tag,
in deiner Fehlermeldung ist das Problem schon ganz gut zu erkennen: “STARTTLS is required to send mail”.
Das bedeutet, im Script Zeile 96 muss bei Send-Mail der Port und SSL als Parameter mitgegeben werden:
-Port 587 -UseSsl
Oder alternativ am Anfang das Security-Protokoll angeben:
[System.Net.ServicePointManager]::SecurityProtocol = 'Tls,TLS11,TLS12'
Vielleicht hilft das weiter. Anbei noch ein Link:
https://stackoverflow.com/questions/39967359/can-i-use-tls-with-send-mailmessage-cmdlet
Gruß Johannes
Hallo Johannes,
Danke für deine prompte Antwort.
Mit deiner Hilfe bin ich schon einen Schritt weiter, allerdings hackt es schon wieder. Sorry wenn ich mich gerade zu dumm anstelle. Sehe gerade vor lauter Bäumen den Wald nicht.
Hier mein Fehlercode:
Send-Mailmessage : Für den SMTP-Server ist eine sichere Verbindung erforderlich, oder der Client wurde nicht authentifiziert. Die Serverantwort war: 5.7.57 Client not authenticated to send
mail. [PR3P192CA0002.EURP192.PROD.OUTLOOK.COM]
In C:Usersadministrator.*****DesktopUnbenannt1.ps1:96 Zeichen:1
+ Send-Mailmessage -smtpServer $smtpServer -Port 587 -UseSsl -from $from -to $emai …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpException
+ FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
Hallo Snuggls,
wenn ich die Fehlermeldung “Client not authenticated to send mail” richtig deute, dann ist ein anonymes Mail-Senden nicht zulässig. Somit muss ein User & Passwort (in Zeile 96) angegeben werden:
$secpasswd = ConvertTo-SecureString "YOURPassword" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("YOURUSERNAME", $secpasswd)
Send-Mailmessage -smtpServer $smtpServer -Credential $cred -from $from -to $emailaddress -subject $subject -body $body -bodyasHTML -priority High -Encoding $textEncoding
Lieber Johannes,
ich danke dir vielmals, es läuft 🙂
VG Snuggls
Hallo,
das Script ist bei uns schon einige Zeit erfolgreich im Einsatz.
Jedoch haben wir das Problem, dass bei einigen Benutzern mit vorhandenen Postfächern (wie z.B. Admins) die E-Mails an eine andere Adresse verschickt werden müssen, da ihre Postfächer nicht regelmäßig eingesehen werden.
Wie ist das Script in diesem Fall umzubaun?
Vielen Dank
Grüße
Hallo Tobias,
in Zeile 38 wird die Email-Adresse vom Benutzerobjekt gelesen.
Wenn diese abweichend sein soll, müsste man soetwas einbauen:
# Wenn der User ein Admin ist...
if ($Name -eq "user-admin") {
# abweichende Mail verwenden
$emailaddress = "[email protected]"}
else {
# wenn nicht, dann mail aus User-Objekt
$emailaddress = $user.emailaddress}
(UNGETESTET)
Gruß Johannes
Hallo,
der Filter auf eine OU würde bei uns nicht reichen, da dort leider zu viele Accounts sind, die nicht erinnert werden müssen.
Wie binde ich am besten eine Liste von Accounts ein, die dann ausgewertet und informiert werden?
Viele Grüße,
Oliver
Hallo Oliver,
in Zeile 32 wird die Variable $users gefüllt (mit den Inhalten den AD-Abfrage).
Hier könntest du statt
Get-ADuser
auch den Inhalt einer Textdatei lesen:$users = Get-Content C:\yourfile.txt
Hallo,
habe noch was vergessen.
Was müsste man anpassen, wenn der Manager des Accounts angeschrieben werden soll?
Beim Account ist ja nur der Manager angegeben und nicht seine Emailadresse.
Da müsste dann noch die Emailadresse des Managers rausgesucht werden. Aber leider bin ich im Skripten nicht so gut, das ich da etwas auf dem Schlauch stehe.
Danke
Hallo Oliver,
du müsstest für jeden User noch den Manager auslesen. Das kann relativ einfach mit Powershell erledigt werden:
Get-ADUser -Filter { Enabled -eq $true } -Properties Title,Department,Manager | select Name, Title, Department, @{n="ManagerName";e={get-aduser $_.manager | select -ExpandProperty name}}, @{n="ManagerMail";e={get-aduser $_.manager -properties mail | select -ExpandProperty mail}}
https://www.reddit.com/r/PowerShell/comments/8mxub7/getaduser_with_manager_information/
Guten Morgen, ich habe das Script schon seit Mai´21 erfolgreich im Einsatz. Jetzt habe ich festgestellt, dass seit ca. 4 Wochen keine Mails mehr verschickt werden. Es wurde nichts am DC, am Versenderkonto, am Kennwort oder weiterem geändert.
Folgende Meldung wird ausgegeben:
Send-Mailmessage : Von der Übertragungsverbindung können keine Daten gelesen werden: net_io_connectionclosed.
In C:Windowspasswordnotificationmail_km.ps1:100 Zeichen:1
+ Send-Mailmessage -smtpServer $smtpServer -Port 587 -UseSsl -Credential $cred -fr …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) [Send-MailMessage], SmtpException
+ FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
Haben Sie eine Idee?
Vielen Dank im voraus.
Hallo 🙂
Das Problem haben wohl mehrere. Es scheint an TLS zu liegen.
Die Lösung gibts hier:
https://docs.microsoft.com/answers/questions/730242/what-could-be-the-reason-of-34net-io-connectionclo.html
Hallo, das Script finde ich klasse, leider ist bei uns ein Tagesversatz von 3 Tagen zu erkennen. Also der letzte Passwortset vom User war vor 362 Tagen und er bekommt eine Mail, dass heute sein Kennwort abläuft. Die Policy beruht aber auf 365 Tage..
Herzliche Grüße Peter W.
Hallo Peter, den Versatz von 3 Tagen kann ich mir nicht erklären. Es ist auch nichts in diese Richtung im Script hinterlegt.
Lasst ihr das Script auch täglich laufen?