Active Directory: Mail wenn Passwort abläuft

In diesem Artikel hatte ich bereits beschrieben, wie eine Webseite eingerichtet werden kann, auf der Benutzer ihr Passwort ändern können. Gerade Benutzer die mit einem Rechner arbeiten der nicht Mitglied des Active Directory ist, stellt die Passwortänderung oft ein Problem dar.

Mittels der Webseite haben diese Benutzer nun die Möglichkeit ihr Passwort rechtzeitig zu ändern. Allerdings müssen die Benutzer auch informiert werden, wenn das Passwort in naher Zukunft abläuft. Die einfachste Möglichkeit ist wohl eine Mail zu dem Benutzer zu schicken, so können auch externe Benutzer erreicht werden.

Um Benutzern rechtzeitig an die Passwortänderung zu erinnern, habe ich ein kleines PowerShell Script erstellt. Das Script kann hier runtergeladen werden:

Das Script muss natürlich noch etwas an die jeweilige Umgebung angepasst werden. Im wesentlichen müssen nur die Zeilen 1 – 32 an die eigenen Bedürfnisse angepasst werden:

Passwort Script

Zeile 2 enthält die Anzahl der Tage nachdem ein Passwort geändert werden muss. In Zeile 3 wird festgelegt wie viele Tage vor Ablauf des Passwortes der Benutzer informiert werden soll.

Die Zeilen 6 – 8 enthalten die Angaben zum Mail Server über den die E-Mails versendet werden sollen.

Zeile 14 – 29 enthält den Text der Mail der dem Benutzer zugesendet wird. Folgende Variablen können benutzt werden:

  • $GivenName: Vorname des AD Benutzers
  • $Surname: Nachname des AD Benutzers
  • $DaysBeforePasswordchange: Anzahl Tage bis zur Passwort Änderung
  • $PasswordExpireDate: Datum an dem das Passwort abläuft

Das Script benötigt die PowerShell CMDLets für das Active Directory (Get-ADUser). Die E-Mail wird im HTML Format an die E-Mail Adresse verschickt die dem Benutzer im Active Directory zugeordnet ist.

Update 05.01.17: Vielen Dank für die Kommentare. Die Hinweise habe ich entsprechend im Script ergänzt und eine neue Version hochgeladen.

41 thoughts on “Active Directory: Mail wenn Passwort abläuft”

  1. Hallo,
    falls die Kommentare für diesen doch schon in die Jahre gekommenen Artikel noch gelesen werden…

    Wie geht ihr damit um, wenn ein Benutzer zwar all das bekommt aber bis zum Tag des Passwortablaufs ignoriert? (oder auf Urlaub ist, …)

    Szenario:
    Passwort läuft am Montag, 1.1 um 09:00 Uhr ab
    User meldet sich um 07:00 Uhr an, ignoriert alles und kann sich ja noch anmelden, da noch 2 Stunden Zeit. Arbeitet also normal weiter. Ab 09:00 Uhr dann seltsame Probleme, dass plötzlich „etwas nicht mehr geht“
    Admin/Helpdesk hat das ggf. nicht im Blick und findet erst nach Zeit Y heraus, dass das Pwd abgelaufen ist, User aber eingeloggt.

    Ich habe deshalb im Script so gesetzt, dass es gegen 23 Uhr läuft und wenn ein Passwort am nächsten Tag abläuft, jetzt schon der Flag „User must change password at next logon“ gesetzt wird.

    In dem Szenario müsste der User also beim Anmelden um 07:00 Uhr schon erzwungenermaßen das Pwd ersetzten. Es wurde informiert, dass das Pwd am 1.1. abläuft – Uhrzeit wird hier dann ignoriert (bzw. gar nicht informiert)

    just my 5 cent

    Reply
  2. Bei mir stimmt da was leider nicht, einige User bekommen diese Nachricht.

    Your Active Directory password will expire on 10/20/2022 20:28:02.
    You have -4 days before your password will expire, you should consider to change your password now.

    Das Passwort wurde aber am 10/20/2022 schon geändert.

    Reply
    • Wie wäre es mit diesem Vorschlag: Sende die E-Mail 14 Tage, 7 Tage und 1 Tag vor dem Passwortverfall ab. Dazu einfach die If-Bedingung in Zeile 50 entsprechend modifizieren.

      Reply
  3. Mal die Frage an alle, das Script bereits einsetzen? Wann und wie oft lasst ihr das laufen? Das Script merkt sich ja nicht, wen es schon gewarnt hat. So bombadiert man dann die Nutzer, bis „von ganz oben“ der Befehl kommt „den Sch*** sein zu lassen“ oder die User bauen sich Filterregel, die die Mails dirkt löschen. Ziel in jedem Fall verfehlt.

    Reply
    • Wie wäre es mit diesem Vorschlag: Sende die E-Mail 14 Tage, 7 Tage und 1 Tag vor dem Passwortverfall ab. Dazu einfach die If-Bedingung in Zeile 50 entsprechend modifizieren.

      Reply
    • Hier die Lösung:

      Zeile #3 ändern nach: $WarningLevel = @(14, 7, 1, 0)
      Zeile #50 ändern nach: if ($DaysBeforePasswordchange -in $WarningLevel)

      Reply
  4. Servus,

    da ich absoluter Powershell Neuling bin, kurz die Frage, wie ich dieses Problem Lösen kann…

    You cannot call a method on a null-valued expression.
    At line:47 char:3
    + $PasswordExpireDate = $PasswordLastSet.AddDays(+$MaxPasswordAge)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Reply
  5. Hallo,

    kann mir bitte jemand sagen was folgende Fehlermeldung zu bedeuten hat?
    Es ist nicht möglich, eine Methode für einen Ausdruck aufzurufen, der den NULL hat.
    In C:\Install\PasswodReminder.ps1:48 Zeichen:3
    + $PasswordExpireDate = $PasswordLastSet.AddDays(+$MaxPasswordAge)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Verstehe nicht wie der Wert NULL sein kann, jeder der Ausdrucke hat einen Wert und wenn ich es richtig verstehe hat angeblich der Ausdruck MaxPasswordAge einen Wert von NULL, was auch nicht sein kann. Übersehe ich etwas?

    Viele Grüße,
    Dysis

    Reply
    • Zur Info für andere mit der gleichen Fehlermeldung
      (Es ist nicht möglich, eine Methode für einen Ausdruck aufzurufen, der den NULL hat….): Ich habe nun herausgefunden, dass bei mir die Werte (Ablaufdatum & Tage bis Ablauf) im Minusbereich herausgelesen bzw. angezeigt werden, wie man das löst oder woran das liegt, weiß ich leider noch nicht…. aber vielleicht jemand anderes:

      Displayname ExpiryDate ExpirationDays
      ———– ———- ————–
      User1 01.01.1601 01:00:00 -152803
      User2 01.01.1601 01:00:00 -152803
      User3 01.01.1601 01:00:00 -152803
      User4 01.01.1601 01:00:00 -152803

      Viele Grüße,
      Numan

      Reply
  6. Hallo,
    ich habe eure Kommentare gelesen um zu verstehen, wie ich das Script einschränken kann.
    so habe ich eingegeben:

    $AllADUsers = Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Searchbase „OU=.Ausb,OU=Produktiv(Abteilungen),OU=Test,DC=UnsereDomain,DC=local“ -Properties PasswordLastSet,mail

    Aber passiert folgender Fehler:

    Get-ADUser : Die Benennung „Get-ADUser“ wurde nicht als Name eines Cmdlet, einer Funktion, einer Skriptdatei oder eines ausführbaren Programms erkannt. Überprüfen Sie
    die Schreibweise des Namens, oder ob der Pfad korrekt ist (sofern enthalten), und wiederholen Sie den Vorgang.

    + $AllADUsers = Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -e …
    + ~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (Get-ADUser:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Ich freue mich auf eure Antwort.

    Danke & viele Grüße
    Hozan

    Reply
  7. Tolles Skript, vielen Dank für den Input.
    eine vermutlich doofe Frage, vielleicht übersehe ich den Hinweis auch:
    Das Skript muss doch dann täglich ausgeführt werden, z.b. per Aufgabenplanung, richtig?
    Viele Grüße,
    Basti

    Reply
  8. Weiterhin wäre die Frage geht dies auch mit SSL verschlüsselten SMTP Serven und wie kann ich mein Passwort dort eingeben?

    Reply
  9. Kurze Frage kann man dies auch für eine angelegte Gruppen einrichten und auch nur für User aus dieser Gruppe? Kann mir da jemand helfen?

    Reply
  10. Guten Tag,

    ich habe alle Parameter angepasst und auch leider noch einen Fehler:

    PS C:\> C:\PasswodReminder.ps1
    Es ist nicht möglich, eine Methode für einen Ausdruck aufzurufen, der den NULL hat.
    In C:\PasswodReminder.ps1:44 Zeichen:3
    + $PasswordExpireDate = $PasswordLastSet.AddDays(+$MaxPasswordAge)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Weiß wer, wie ich den Fehler ausmerzen kann?!

    Reply
  11. Hi,

    ich möchte gerne ein Log haben, wer von meine User das Mail bekommen hast.
    Kann man das leicht einbauen?

    Ich habe noch ein Problem: Ich habe bei einigen Usern die Tage falsch bei $DaysBeforePasswordchange. Es kommt zum Beispiel -4400 Tage wenn ich mir den User genau anschaue hat er vor 88 Tage das Passwort geändert.

    Reply
  12. Hallo Frank

    Wir lassen bei unserem Script MaxPasswordAge ermitteln:
    $MaxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge

    Gruss, M

    Reply
  13. Hallo Frank,

    vielen Dank für deine Hilfe. Damit wird das Datum in dem Format angezeigt wie ich es haben will.
    Habe allerdings noch ein Problem mit den Umlauten. Trotz der Zeile

    Send-MailMessage -SmtpServer $SMTPServer -To $MailAddress -From $From -Body $Body -BodyAsHtml -Subject $Subject -encoding ([System.Text.Encoding]::UTF8)

    werden die Umlaute in der Mail nicht richtig dargestellt.

    Gruß Stefan

    Reply
    • Hi Stefan,

      füge mal in Zeile 67 die folgende Zeile ein:

      $PasswordExpireDate = $PasswordExpireDate | get-date -Format dd.MM.yyyy

      Gruß, Frank

      Reply
  14. Hallo,

    habe zum Script eine frage.. bin eher fremdling was Scripte angehen tut, habe es aber nun so wie es mir passt für mein Unternehmen abgeändert, kann mir aber jemand sagen wo ich das Script ablegen / Einbinden muss etc ?

    Vielen danke

    Adnan

    Reply
  15. Hallo zusammen,

    hat jemand eine Idee wie ich User welche eine Mail Adresse außerhalb der Domain haben angesprochen bekomme? Als Kontakte sind diese angelegt um sie im globalen Adressbuch zu sehen. Ein Eintrag einer „fremden“ E-Mail im AD User Objekt führt nicht zum Erfolg.

    Danke

    Ingo

    Reply
  16. Hallo Frank!

    Nach der Migration unseres Mailservers von Ex13 (Server 2008 R2) auf Ex16 (Server 2012 R2) habe ich das Skript angepasst indem ich den neuen Server hinterlege. Nun bekomme ich folgende Fehlermeldung:
    „Get-ADUser : Die Benennung „Get-ADUser“ wurde nicht als Name eines Cmdlet, einer Funktion, einer Skriptdatei
    oder eines ausführbaren Programms erkannt. Überprüfen Sie die Schreibweise des Namens, oder ob der Pfad
    korrekt ist (sofern enthalten), und wiederholen Sie den Vorgang.
    In C:\Users\administrator.MEPPEN\Desktop\PasswordReminder.ps1:33 Zeichen:15
    + $AllADUsers = Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -e …
    + ~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (Get-ADUser:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException“

    Hast du ne Lösung?

    Gruß

    Hendrik

    Reply
  17. Hallo,

    die deutschen Umlaute werden trotz dieser Zeile
    Send-MailMessage -SmtpServer $SMTPServer -To $MailAddress -From $From -Body $Body -BodyAsHtml -Subject $Subject -encoding ([System.Text.Encoding]::UTF8)
    noch falsch dargestellt.

    Zweites Problem. Das Datum wird im amerikanischen Format angezeigt, also MM/DD/YYYY.
    Kann man das noch irgendwie ändern in DD/MM/YYYY

    Gruß
    Sven

    Reply
  18. Hallo zusammen,

    gibt es evtl. die Möglichkeit zu sagen x Werktage vor Ablauf des PW soll die Mail verschickt werden? Oder müsste man das umständlich Skripten?
    Wir haben Accounts ohne Mailadresse wo es aber auch gut wäre eine Benachrichtigung zu bekommen, wie müsste man eine Abfrage des Managers und Mailversand an diesen, bewerkstelligen?

    Grüße
    Oliver

    Reply
  19. Moin,

    falls jemand nicht die Muße hat, die von Franky beschriebene Website zur Passwortänderung zu erstellen, jedoch einen Exchange-Server im Einsatz hat, so kann man als Verweis auch folgenden Link in die Hinweismail einsetzen:

    https://MEINEXCHANGESERVER/ecp/?rfr=owa&owaparam=modurl%3D0&p=PersonalSettings/Password.aspx

    Das ist zwar kein Link, den sich jemand merken wird; aber als Hyperlink zum Anklicken reicht es…

    Ein schönes Wochenende allerseits!

    VG,
    Björn

    Reply
  20. Moin,
    ich habe die Zeile 34 wie folgt geändert um nur die User einer OU abzufragen:

    $AllADUsers = Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Searchbase „OU=KanzleiOU,DC=test,DC=local“ -Properties PasswordLastSet,mail
    Klappt auch ! Aber wie kann ich in diesem Kontext noch eine zweite OU abfragen?

    Danke….

    Reply
    • Hi Ingo,

      du kannst eine zweite OU wie folgt angeben:

      Zeile 34+35:

      $AllADUsers = Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Searchbase „OU=KanzleiOU,DC=test,DC=local“ -Properties PasswordLastSet,mail
      $AllADUsers += Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Searchbase „OU=ANDEREOU,DC=test,DC=local“ -Properties PasswordLastSet,mail

      Das erzeugt zwei Abfragen (KanzleiOU und ANDEREOU) beide Abfragen werden in $AllADUsers gespeichert (+=).
      Gruß, Frank

      Reply
  21. @Ingo:
    – Die Deutschen Umlaute sollten durch die Ergänzung der vorletzten Zeile funktionieren:
    Send-MailMessage -SmtpServer $SMTPServer -To $MailAddress -From $From -Body $Body -BodyAsHtml -Subject $Subject -encoding ([System.Text.Encoding]::UTF8)

    – Die Uhrzeit wird bei uns korrekt dargestellt – sowohl via net user, als auch in der Mail aus dem Script.

    Reply
    • HHmm,

      Umlaute sind geklärt. Das mit der Zeit finde ich seltsam…… Muss ich mir mal weitere Gedanken machen. Vielleicht fällt noch jemanden dazu etwas ein ?

      Danke vorerst…..

      Reply
  22. @Björn:
    Danke schön, soeben wollte ich auch darauf hinweisen das in Zeile 64 das Problem sich mit der Lösung wie von Dir beschrieben lösen lässt. Habe bis eben rumprobiert, aber auch nur so lernt man etwas.

    Auch beim zweiten Fehler gebe ich dir recht – wenn ich es auf die User bzw OU beschränke in welcher auch Passwörter gesetzt wurden ist auch dieser Fehler weg.

    Jetzt habe ich nur noch 2 Kleinigkeiten:
    – deutsche Umlaute im Mailtext werden nicht dargestellt? Hatte ich schon mal weiß aber die Lösung nicht mehr :-(
    – Uhrzeit bei Passwortablauf ist falsch und zwar genau um eine Stunde. net user Benutzername gibt als Uhrzeit 08:00 an, das Script genau eine Stunde später. Ist sicherlich ein Problem mit der MEZ, aber wie bekommt dies hin? Ideen ?

    Danke,

    Reply
  23. @Ingo:
    Der erste Fehler lässt sich durch ändern der Zeile 64 in $MailAddress = $ADUser.mailaddress beheben.

    Der zweite Fehler taucht bei mir nicht auf; ich hatte erst den Verschreiber („Passwoord…) im Verdacht, aber der zieht sich durch alle anderen Zeilen durch und wirkt sich somit nicht aus… Hattest du mal die Konten ohne Ablauf (wie in meinem ersten Kommentar beschrieben) gefiltert?
    Eine andere Idee: gibt es User, die angelegt wurden, denen aber nie ein Passwort zugeordnet wurde (so dass möglicherweise die Variable leer ist)?

    VG,
    Björn

    Reply
  24. Hi,
    gute Idee. Ich habe es mal probiert, allerdings bräuchte ich noch eine Einschränkung der Userabfrage auf eine bestimmte OU. Geht das, wenn ja wie ?
    Es läuft bei mir ansonsten auf einen Fehler welcher aus meiner Sicht darin begründet ist, das nicht alle User eine Mail haben.
    Fehlertext:
    end-MailMessage : Das Argument für den Parameter „To“ kann nicht überprüft werden. Das Argument ist NULL oder leer. Geben Sie ein Argument an, das nicht NULL oder leer ist,
    und führen Sie den Befehl erneut aus.
    In D:\PasswodReminder\PasswodReminder.ps1:70 Zeichen:48
    + Send-MailMessage -SmtpServer $SMTPServer -To $MailAddress -From $From -Body $B …
    + ~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage

    Ein anderer Fehler ist vollkommen unklar:
    Es ist nicht möglich, eine Methode für einen Ausdruck aufzurufen, der den NULL hat.
    In D:\PasswodReminder\PasswodReminder.ps1:47 Zeichen:3
    + $PasswoordExpireDate = $PasswordLastSet.AddDays(+$MaxPasswordAge)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Herzlichen Dank im voraus,

    Ingo

    Reply
  25. Herzlichen Dank für die tollen Beiträge und praktischen Lösungskonzepte!

    $MaxPasswordAge hat mich etwas irritiert, denn das AD müsste ja wissen, wann das Passwort abläuft :-)

    Mit dem nachfolgenden Zweizeiler erhält man die Liste der User, deren Passwort innerhalb der nächsten 14 Tage abläuft.

    Mit lieben Grüssen,
    Tom

    $WarningLevel = 14
    Get-ADUser -Filter { Enabled -Eq $True -And PasswordNeverExpires -Eq $False} -Properties DisplayName, ‚msDS-UserPasswordExpiryTimeComputed‘ | Select-Object -Property Displayname, @{ Name=’ExpiryDate‘; Expression={[datetime]::FromFileTime($_.’msDS-UserPasswordExpiryTimeComputed‘)}}, @{ Name=’ExpirationDays‘; Expression={(([datetime]::FromFileTime($_.’msDS-UserPasswordExpiryTimeComputed‘))-(Get-Date)).Days }} | Where-Object ExpirationDays -le $WarningLevel

    Reply
  26. Hi Franky,

    ich würde die Zeile 35 folgendermaßen ergänzen, um User ohne Passwortablauf auszuklammern:

    $AllADUsers = Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} -Properties PasswordLastSet,mail

    Sonst bekämen mail-aktivierte Dienstuser auch unnötigerweise einen Hinweis (so zumindest bei uns).

    Ansonsten wie immer ein sehr hilfreicher Artikel! Besten Dank dafür!

    VG,
    Björn

    Reply

Leave a Comment