diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d02cae3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,124 @@
+# Zabbix Template – TLS-Zertifikatüberwachung für Mail- und Webdienste
+
+Dieses Zabbix-Template ermöglicht eine umfassende Überwachung von TLS-Zertifikaten, die für Webserver (HTTPS) sowie E-Mail-Dienste wie SMTP und IMAP verwendet werden. Es überprüft automatisch die Gültigkeit der Zertifikate, erkennt abgelaufene oder ungültige Zertifikate und gibt rechtzeitig Warnungen aus, bevor ein Zertifikat abläuft.
+
+
+
+## Funktionen
+
+Das Template bietet eine Vielzahl nützlicher Funktionen zur Zertifikatsüberwachung:
+
+- Automatische Prüfung der TLS-Zertifikatsgültigkeit (gültig oder ungültig)
+- Frühzeitige Benachrichtigung, wenn ein Zertifikat kurz vor dem Ablauf steht
+- Unterstützung mehrerer Protokolle, darunter HTTPS, SMTP und IMAP
+- Integration von Triggern für unterschiedliche Zustände, wie z. B. abgelaufene oder bald ablaufende Zertifikate
+- Konfigurierbare Schwellenwerte und Parameter mithilfe von Makros auf Host-Ebene
+- Unterstützung moderner TLS-Funktionen wie STARTTLS, Server Name Indication (SNI) und benutzerdefinierbarer Verbindungszeitüberschreitungen (Timeouts)
+
+
+
+## Aufbau und enthaltene Dateien
+
+Das Paket besteht aus folgenden zentralen Komponenten:
+
+- **`templatemailcert_check.xml`**: Das eigentliche Zabbix-Template, das über das Webinterface importiert wird.
+- **`userparameters_mailcert_check.conf`**: Konfigurationsdatei für den Zabbix-Agent, welche benutzerdefinierte Prüfbefehle bereitstellt.
+- **`mailcert_check.sh`**: Ein Bash-Skript, das die Zertifikatsinformationen abfragt und verarbeitet.
+
+
+
+## Installationsanleitung
+
+### Schritt 1: Skript installieren
+
+Kopiere das Bash-Skript in ein geeignetes Verzeichnis auf dem Zielsystem und mache es ausführbar:
+
+```bash
+sudo cp mailcert_check.sh /usr/local/bin/
+sudo chmod +x /usr/local/bin/mailcert_check.sh
+```
+
+### Schritt 2: Zabbix-Agent konfigurieren
+
+Die Datei mit den benutzerdefinierten Parametern muss in das Konfigurationsverzeichnis des Zabbix-Agenten kopiert werden. Anschließend ist ein Neustart des Agenten erforderlich:
+
+```bash
+sudo cp userparameters_mailcert_check.conf /etc/zabbix/zabbix_agentd.d/
+sudo systemctl restart zabbix-agent
+```
+
+### Schritt 3: Template in Zabbix importieren
+
+1. Melde dich im Zabbix-Frontend an.
+2. Navigiere zu **Configuration → Templates**.
+3. Klicke auf **Import**.
+4. Wähle die Datei `template_mailcert_check.xml` aus und lade sie hoch.
+5. Bestätige den Import.
+
+### Schritt 4: Template einem Host zuweisen
+
+1. Öffne im Zabbix-Frontend den gewünschten Host.
+2. Gehe zum Reiter **Templates**.
+3. Füge das Template **Template Mail Certificate Monitoring** hinzu.
+4. Speichere die Änderungen.
+
+
+
+## Konfiguration über Makros
+
+Auf Host-Ebene lassen sich mithilfe von Makros die zu überwachenden Ziele und Parameter definieren. Hier ein Beispiel für die SMTP-Zertifikatsüberwachung:
+
+```yaml
+{$TLS_SMTP_DOMAIN} = mail.example.com
+{$TLS_SMTP_PORT} = 587
+{$TLS_SMTP_STARTTLS} = smtp
+{$TLS_SMTP_SNI} = mail.example.com
+{$TLS_SMTP_TIMEOUT} = 10
+{$TLS_SMTP_UPDATEINTERVAL} = 3600
+{$TLS_SMTP_EXPIRESWITHIN} = 14
+```
+
+Diese Makros ermöglichen eine flexible und gezielte Konfiguration pro Host.
+
+
+
+## Beispielhafte Darstellung in Zabbix
+
+Nach erfolgreicher Einrichtung werden im Zabbix-Frontend automatisch Items und Trigger erstellt. Dazu zählen unter anderem:
+
+- Einträge zur Restlaufzeit (in Tagen) eines Zertifikats
+- Statusmeldungen zu ungültigen oder bald ablaufenden Zertifikaten
+- Trigger, die bei Erreichen der definierten Schwellenwerte Warnungen auslösen
+
+
+
+
+
+
+
+
+
+
+
+## Manueller Test des Prüfskripts
+
+Zur Überprüfung der Skriptfunktionalität kann ein manueller Aufruf wie folgt erfolgen:
+
+```
+/usr/local/bin/mailcert_check.sh expire mail.example.com 587/smtp mail.example.com 10
+```
+
+Dabei werden Domain, Port, Protokoll, SNI und Timeout übergeben.
+
+
+
+## Kompatibilität
+
+- Unterstützt wird **Zabbix ab Version 6.4**
+- Abhängigkeiten: `bash`, `openssl`
+
+
+
+## Lizenz
+
+Dieses Projekt steht unter der **MIT-Lizenz** und kann frei verwendet, modifiziert und verteilt werden.
\ No newline at end of file
diff --git a/assets/image-20250723220013360.png b/assets/image-20250723220013360.png
new file mode 100644
index 0000000..3616ef9
Binary files /dev/null and b/assets/image-20250723220013360.png differ
diff --git a/assets/image-20250726093817364.png b/assets/image-20250726093817364.png
new file mode 100644
index 0000000..bb21660
Binary files /dev/null and b/assets/image-20250726093817364.png differ
diff --git a/mailcert_check.sh b/mailcert_check.sh
new file mode 100755
index 0000000..2bb134b
--- /dev/null
+++ b/mailcert_check.sh
@@ -0,0 +1,188 @@
+#!/usr/bin/env bash
+
+DEBUG="${DEBUG:-0}" # Setze DEBUG=1 für Debug-Ausgaben
+
+debug() {
+ if [[ "$DEBUG" == "1" ]]; then
+ echo "[DEBUG] $*" >&2
+ fi
+}
+
+# Standardwerte
+timeout_sec=5
+err_code=-65535
+valid_codes=(0)
+
+print_usage() {
+ echo $err_code
+ if [ -t 1 ]; then
+ cat >&2 <<-EOT
+
+ Verwendung: $(basename "$0") expire|valid|json host|ip [port[/starttls-proto]] [tls_sni_domain] [timeout] [tls_option[,selfsigned_allowed]] [extra_s_client_args ... ]
+
+ Prüft SSL-Zertifikat auf Ablauf und Gültigkeit via OpenSSL.
+
+ Parameter:
+ - port: Standard 443
+ - starttls-proto: optional, z.B. smtp, ftp, ldap (z.B. 25/smtp)
+ - tls_sni_domain: Domain für TLS SNI, Standard: host
+ - timeout: max Wartezeit (Sek), Standard: $timeout_sec
+ - tls_option: tls1, tls1_2, tls_auto etc.
+ - selfsigned_allowed: erlaubt selbstsignierte Zertifikate
+ - extra_s_client_args: zusätzliche OpenSSL s_client Parameter
+
+ Rückgabewerte:
+ * expire:
+ Anzahl verbleibender Tage (0 oder negativ bei abgelaufen)
+ $err_code bei Fehler
+ * valid:
+ 1 = gültig, 0 = ungültig, $err_code bei Fehler
+ * json:
+ JSON mit expire_days, valid, return_code, return_text
+ Oder JSON mit error_code und error_message bei Fehler
+
+ Fehler werden auf der Konsole nur bei Terminalausgabe angezeigt.
+
+EOT
+ fi
+}
+
+exit_with_error() {
+ local msg="$*"
+ if [[ "$mode" == "json" ]]; then
+ echo "{\"error_code\": $err_code, \"error_message\": \"$msg\"}"
+ else
+ echo $err_code
+ if [ -t 1 ]; then echo "Fehler: $msg" >&2; fi
+ fi
+ exit 0
+}
+
+output_and_exit() {
+ echo "$1"
+ exit 0
+}
+
+calculate_days_left() {
+ local expiry_str
+ expiry_str=$(printf "%s" "$openssl_output" \
+ | sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' \
+ | openssl x509 -noout -dates 2>/dev/null \
+ | grep '^notAfter=' | cut -d= -f2)
+
+ debug "Ablaufdatum: $expiry_str"
+ [[ -z "$expiry_str" ]] && exit_with_error "Konnte Ablaufdatum nicht ermitteln"
+
+ expiry_epoch=$($date_cmd -d "$expiry_str" +%s) || exit_with_error "Ungültiges Datum: $expiry_str"
+ now_epoch=$($date_cmd +%s)
+
+ debug "Epoch-Zeitpunkte: jetzt=$now_epoch, ablauf=$expiry_epoch"
+
+ echo $(( (expiry_epoch - now_epoch) / 86400 ))
+}
+
+# Standard date Befehl ermitteln (Linux oder macOS mit gdate)
+date_cmd="date"
+if date --version 2>&1 | grep -qi 'busybox'; then
+ exit_with_error "Busybox date wird nicht unterstützt"
+fi
+
+# Prüfen auf benötigte Tools
+for tool in timeout openssl $date_cmd; do
+ type "$tool" >/dev/null 2>&1 || exit_with_error "Benötigtes Programm nicht gefunden: $tool"
+done
+
+# Eingabeparameter
+mode="$1"
+host="$2"
+port_and_proto="${3:-443}"
+tls_sni="${4:-$host}"
+timeout="${5:-$timeout_sec}"
+tls_opts="$6"
+extra_args=("${@:7}")
+
+debug "Modus: $mode"
+debug "Host: $host"
+debug "Port/Proto: $port_and_proto"
+debug "SNI: $tls_sni"
+debug "Timeout: $timeout"
+debug "TLS-Optionen: $tls_opts"
+debug "Extra-Args: ${extra_args[*]}"
+
+# Port und optionales starttls-Protokoll extrahieren
+IFS='/' read -r port proto <<< "$port_and_proto"
+starttls_flag=""
+starttls_proto=""
+if [[ -n "$proto" && "$proto" != "tls" ]]; then
+ starttls_flag="-starttls"
+ starttls_proto="$proto"
+fi
+
+# Parametervalidierung
+[[ "$mode" =~ ^(expire|valid|json)$ ]] || exit_with_error "Ungültiger Modus: $mode"
+[[ "$port" =~ ^[0-9]+$ ]] || exit_with_error "Port muss numerisch sein"
+(( port >= 1 && port <= 65535 )) || exit_with_error "Port muss zwischen 1 und 65535 liegen"
+[[ -z "$starttls_proto" || "$starttls_proto" =~ ^[a-z0-9]+$ ]] || exit_with_error "Ungültiges StartTLS-Protokoll"
+[[ "$timeout" =~ ^[0-9]+$ ]] || exit_with_error "Timeout muss numerisch sein"
+
+# Unterstützung für IDN Domains (Punycode)
+if type idn >/dev/null 2>&1; then
+ host=$(idn "$host" 2>/dev/null || echo "$host")
+ tls_sni=$(idn "$tls_sni" 2>/dev/null || echo "$tls_sni")
+fi
+
+# TLS Optionen parsen
+IFS=',' read -r -a tls_options_arr <<< "$tls_opts"
+tls_flag=""
+for opt in "${tls_options_arr[@]}"; do
+ if [[ "$opt" == "self_signed_ok" ]]; then
+ valid_codes+=(18 19 20 21)
+ elif [[ "$opt" == "tls_auto" ]]; then
+ :
+ elif [[ "$opt" == tls* || "$opt" == ssl* || "$opt" == dtls* ]]; then
+ tls_flag="-$opt"
+ fi
+done
+
+# Zertifikat abfragen
+debug "Aufruf: openssl s_client $starttls_flag $starttls_proto -connect $host:$port -servername $tls_sni -verify_hostname $tls_sni $tls_flag ${extra_args[*]}"
+
+openssl_output=$(timeout "$timeout" openssl s_client $starttls_flag $starttls_proto -connect "$host:$port" -servername "$tls_sni" -verify_hostname "$tls_sni" $tls_flag "${extra_args[@]}" 2>/dev/null <<<"")
+
+debug "OpenSSL-Ausgabe erhalten"
+debug "$(echo "$openssl_output" | head -n 10)"
+
+# Prüfung, ob Ausgabe gültig ist
+if ! grep -q '^ *Verify return code:' <<< "$openssl_output"; then
+ exit_with_error "Konnte Zertifikat nicht abrufen"
+fi
+
+if [[ "$mode" == "expire" ]]; then
+ days_left=$(calculate_days_left)
+ output_and_exit "$days_left"
+else
+ verify_line=$(grep '^ *Verify return code:' <<< "$openssl_output" | head -n1 | tr -s ' ')
+ verify_code=$(cut -d' ' -f4 <<< "$verify_line")
+ verify_text=$(sed -n 's/^ *Verify return code: [0-9]* (\(.*\))/\1/p' <<< "$verify_line")
+
+ debug "Verify Code: $verify_code"
+ debug "Verify Text: $verify_text"
+
+ valid=0
+ for code in "${valid_codes[@]}"; do
+ if [[ "$code" == "$verify_code" ]]; then
+ valid=1
+ break
+ fi
+ done
+
+ if [[ "$mode" == "valid" ]]; then
+ output_and_exit "$valid"
+ elif [[ "$mode" == "json" ]]; then
+ days_left=$(calculate_days_left)
+ printf '{"expire_days": %d, "valid": %d, "return_code": %s, "return_text": "%s"}\n' \
+ "$days_left" "$valid" "$verify_code" "$verify_text"
+ exit 0
+ fi
+fi
+
diff --git a/template_mailcert_check.xml b/template_mailcert_check.xml
new file mode 100644
index 0000000..469c713
--- /dev/null
+++ b/template_mailcert_check.xml
@@ -0,0 +1,267 @@
+
+
+ 6.4
+
+
+ a571c0d144b14fd4a87a9d9b2aa9fcd6
+ Templates/Applications
+
+
+
+
+ c2b74f8e940244aea1c469c8a63e3a3a
+ Template Mail Certificate Monitoring
+ Template Mail Certificate Monitoring
+
+
+ Templates/Applications
+
+
+
+ -
+ 161cd7c9ab6f4a15bd740ca33ab32c10
+ TLS: Days until WEB certificate expires
+ mailcert_check_expire[{$TLS_WEB_DOMAIN},{$TLS_WEB_PORT}/{$TLS_WEB_STARTTLS},{$TLS_WEB_SNI},{$TLS_WEB_TIMEOUT}]
+ {$TLS_WEB_UPDATEINTERVAL}
+ 7d
+ 14d
+ d
+
+
+ Application
+ Mail Certificates
+
+
+
+
+ dd76bdafc530428a99443a4e6211af38
+ last(/Template Mail Certificate Monitoring/mailcert_check_expire[{$TLS_WEB_DOMAIN},{$TLS_WEB_PORT}/{$TLS_WEB_STARTTLS},{$TLS_WEB_SNI},{$TLS_WEB_TIMEOUT}])<{$TLS_WEB_EXPIRESWITHIN}
+ WEB Certificate for {HOST.NAME} expires soon ({ITEM.VALUE} days left)
+ AVERAGE
+
+
+
+ -
+ 9e32e8f9af2740ea89437634e443c26e
+ TLS: WEB Certificate validity
+ mailcert_check_valid[{$TLS_WEB_DOMAIN},{$TLS_WEB_PORT}/{$TLS_WEB_STARTTLS},{$TLS_WEB_SNI},{$TLS_WEB_TIMEOUT}]
+ {$TLS_WEB_UPDATEINTERVAL}
+ 7d
+ 14d
+
+
+ Application
+ Mail Certificates
+
+
+
+
+ 81cd1ee8eda946ebb216e90c1bffbcd1
+ last(/Template Mail Certificate Monitoring/mailcert_check_valid[{$TLS_WEB_DOMAIN},{$TLS_WEB_PORT}/{$TLS_WEB_STARTTLS},{$TLS_WEB_SNI},{$TLS_WEB_TIMEOUT}])<>1
+ SSL certificate invalid
+ DISASTER
+
+
+
+ -
+ f2ab69c1fbb2436ca59b90cfe0efdd9b
+ TLS: Days until SMTP certificate expires
+ mailcert_check_expire[{$TLS_SMTP_DOMAIN},{$TLS_SMTP_PORT}/{$TLS_SMTP_STARTTLS},{$TLS_SMTP_SNI},{$TLS_SMTP_TIMEOUT}]
+ {$TLS_SMTP_UPDATEINTERVAL}
+ 7d
+ 14d
+ d
+
+
+ Application
+ Mail Certificates
+
+
+
+
+ 3baec6e0f5a04a43b3cc9a0729a97106
+ last(/Template Mail Certificate Monitoring/mailcert_check_expire[{$TLS_SMTP_DOMAIN},{$TLS_SMTP_PORT}/{$TLS_SMTP_STARTTLS},{$TLS_SMTP_SNI},{$TLS_SMTP_TIMEOUT}])<{$TLS_SMTP_EXPIRESWITHIN}
+ SMTP Certificate for {HOST.NAME} expires soon ({ITEM.VALUE} days left)
+ AVERAGE
+
+
+
+ -
+ 22b9d1c4f7bb4418be3adbdac6c3ecef
+ TLS: SMTP Certificate validity
+ mailcert_check_valid[{$TLS_SMTP_DOMAIN},{$TLS_SMTP_PORT}/{$TLS_SMTP_STARTTLS},{$TLS_SMTP_SNI},{$TLS_SMTP_TIMEOUT}]
+ {$TLS_SMTP_UPDATEINTERVAL}
+ 7d
+ 14d
+
+
+ Application
+ Mail Certificates
+
+
+
+
+ 18d377fe3b1c481f974fba1c18231804
+ last(/Template Mail Certificate Monitoring/mailcert_check_valid[{$TLS_SMTP_DOMAIN},{$TLS_SMTP_PORT}/{$TLS_SMTP_STARTTLS},{$TLS_SMTP_SNI},{$TLS_SMTP_TIMEOUT}])<>1
+ SSL certificate invalid
+ DISASTER
+
+
+
+ -
+ e39f1312f1ab4287afb41694f3504c76
+ TLS: Days until IMAP certificate expires
+ mailcert_check_expire[{$TLS_IMAP_DOMAIN},{$TLS_IMAP_PORT}/{$TLS_IMAP_STARTTLS},{$TLS_IMAP_SNI},{$TLS_IMAP_TIMEOUT}]
+ {$TLS_IMAP_UPDATEINTERVAL}
+ 7d
+ 14d
+ d
+
+
+ Application
+ Mail Certificates
+
+
+
+
+ 57517245a0c742559e36655cd85dd66d
+ last(/Template Mail Certificate Monitoring/mailcert_check_expire[{$TLS_IMAP_DOMAIN},{$TLS_IMAP_PORT}/{$TLS_IMAP_STARTTLS},{$TLS_IMAP_SNI},{$TLS_IMAP_TIMEOUT}])<{$TLS_IMAP_EXPIRESWITHIN}
+ IMAP Certificate for {HOST.NAME} expires soon ({ITEM.VALUE} days left)
+ AVERAGE
+
+
+
+ -
+ 78026be8b8ec4e009063c129c92493a1
+ TLS: IMAP Certificate validity
+ mailcert_check_valid[{$TLS_IMAP_DOMAIN},{$TLS_IMAP_PORT}/{$TLS_IMAP_STARTTLS},{$TLS_IMAP_SNI},{$TLS_IMAP_TIMEOUT}]
+ {$TLS_IMAP_UPDATEINTERVAL}
+ 7d
+ 14d
+
+
+ Application
+ Mail Certificates
+
+
+
+
+ 1f94230b59824b5f83277204b2acb484
+ last(/Template Mail Certificate Monitoring/mailcert_check_valid[{$TLS_IMAP_DOMAIN},{$TLS_IMAP_PORT}/{$TLS_IMAP_STARTTLS},{$TLS_IMAP_SNI},{$TLS_IMAP_TIMEOUT}])<>1
+ SSL certificate invalid
+ DISASTER
+
+
+
+
+
+
+ {$TLS_WEB_EXPIRESWITHIN}
+ 14
+ Number of days before the expiration of the certificate.
+
+
+ {$TLS_WEB_DOMAIN}
+
+ WEB Domainname or IP to check
+
+
+ {$TLS_WEB_SNI}
+
+ SNI value
+
+
+ {$TLS_WEB_PORT}
+ 443
+ Target port (usually 443)
+
+
+ {$TLS_WEB_STARTTLS}
+ tls
+ SSL Options (usually tls)
+
+
+ {$TLS_WEB_TIMEOUT}
+ 10
+ Timeout in seconds
+
+
+ {$TLS_WEB_UPDATEINTERVAL}
+ 3600
+ How often to update certificate information in seconds
+
+
+ {$TLS_SMTP_EXPIRESWITHIN}
+ 14
+ Number of days before the expiration of the certificate.
+
+
+ {$TLS_SMTP_DOMAIN}
+
+ SMTP Domainname or IP to check
+
+
+ {$TLS_SMTP_SNI}
+
+ SNI value
+
+
+ {$TLS_SMTP_PORT}
+ 587
+ Target port (usually 587)
+
+
+ {$TLS_SMTP_STARTTLS}
+ smtp
+ SSL Options (usually smtp)
+
+
+ {$TLS_SMTP_TIMEOUT}
+ 10
+ Timeout in seconds
+
+
+ {$TLS_SMTP_UPDATEINTERVAL}
+ 3600
+ How often to update certificate information in seconds
+
+
+ {$TLS_IMAP_EXPIRESWITHIN}
+ 14
+ Number of days before the expiration of the certificate.
+
+
+ {$TLS_IMAP_DOMAIN}
+
+ IMAP Domainname or IP to check
+
+
+ {$TLS_IMAP_SNI}
+
+ SNI value
+
+
+ {$TLS_IMAP_PORT}
+ 993
+ Target port (usually 993)
+
+
+ {$TLS_IMAP_STARTTLS}
+ tls
+ SSL Options (usually tls)
+
+
+ {$TLS_IMAP_TIMEOUT}
+ 10
+ Timeout in seconds
+
+
+ {$TLS_IMAP_UPDATEINTERVAL}
+ 3600
+ How often to update certificate information in seconds
+
+
+
+
+
+
diff --git a/userparameters_mailcert_check.conf b/userparameters_mailcert_check.conf
new file mode 100644
index 0000000..ba78a87
--- /dev/null
+++ b/userparameters_mailcert_check.conf
@@ -0,0 +1,5 @@
+# Parameters:
+# [port[/starttls protocol]] [domain for TLS SNI] [check timeout] [tls version] [tls_version,[self_signed_ok]]
+UserParameter=mailcert_check_valid[*], /usr/local/bin/mailcert_check.sh valid "$1" "$2" "$3" "$4" "$5"
+UserParameter=mailcert_check_expire[*], /usr/local/bin/mailcert_check.sh expire "$1" "$2" "$3" "$4" "$5"
+UserParameter=mailcert_check_json[*], /usr/local/bin/mailcert_check.sh json "$1" "$2" "$3" "$4" "$5"