37

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. 🙂

Kennwort läuft ab

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
mail senden

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 😉

Johannes Huber
 

In seiner Freizeit macht Johannes nichts lieber, als für ITnator Beiträge zu schreiben. Input bekommt er hierfür von Problemen in der IT Administration von Servern, Clients und vielen weiteren IT Komponenten.

  • Thomas sagt:

    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 ?

  • Rüdiger sagt:

    Hallo,

    tolle Sache!
    Eine Logrotation würde das Ganze jetzt noch perfekt machen ;=)

  • Schneider sagt:

    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 }

  • Patrick sagt:

    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

      • Dominik sagt:

        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?

  • Martin sagt:

    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.

  • Nuri sagt:

    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 ?

  • Dirk sagt:

    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

    • Johannes sagt:

      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

  • Snuggls sagt:

    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

    • Johannes sagt:

      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

      • Snuggls sagt:

        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

        • Johannes sagt:

          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

  • Tobias Lauterbach sagt:

    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

    • Johannes sagt:

      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

  • Oliver sagt:

    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

    • Johannes sagt:

      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

  • Oliver sagt:

    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

  • Snuggls sagt:

    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.

  • Peter W sagt:

    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.

  • Donner sagt:

    Hallo, das Skript ist super!
    Allerdings sendet mir das Script die Mails an das Konto, mit dem ich die Mails auch verschicke, anstatt an die User selbst, die von der Kennwortänderung betroffen sind..

    • Johannes sagt:

      Guten Tag Donner,
      das kann ich mir nicht erklären.
      In Zeile 38 ist wird die Email-Adresse des jeweiligen Benutzers im AD hinterlegt:
      $emailaddress = $user.emailaddress

      Gruß Johannes

      • Donner sagt:

        Hallo Johannes,

        Hat sich erledigt.
        Bei mir war in Zeile 38

        $emailaddress = $testrecipient eingetragen. Habe dies nun umgemünzt, auf $user.emailaddress und es funktioniert. Danke & einen angenehmen Tag!

        • Donner sagt:

          Hallo,

          Ich habe doch noch eine kurze Frage.
          Kann die C:mail.csv nach erneutem ausführen gelöscht werden? Momentan schreibt er immer wieder die neuen Daten in die selbe .csv Datei

  • Donner sagt:

    Hallo Johannes,

    Ich nochmal.
    Gibt es die Möglichkeit, die Daten in der exportierten mail.csv Datei deutlicher darzustellen? Bzw. die verschiedenen Reiter “Name, Date…” in einzelnen Spalten darzustellen?

  • Donner sagt:

    Hi Johannes,

    Eine kurze Frage noch..
    GIbt es die Möglichkeit, das Datum in unserem Format auszugeben? Sprich dd/mm/yyyy und nicht wie momentan mm/dd/yyyy?

    LG

  • sidebar
    >