23

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

  • sidebar
    >