student ist ja ein indiziertes Array, z. B. ist student['mail'] die Mailadresse. Du musst also noch den richtigen Eintrag auswählen, also number = int(''.join(filter(str.isdigit, student['wasauchimmer']}))). Wenn Du print(student) ausgibst, siehst Du vielleicht,was Du brauchst. Oder Du schaust direkt im AD nach.
Sorry, ich war sehr beschäftigt die letzte Tage. Danke an Bertold für die Hinweise über ASCII und Jörg für die Hilfe.
Am einfachsten kann man die Nummer aus dem cn von dem User holen:
import re
from linuxmusterTools.ldapconnector import LMNLdapReader as lr, LMNStudent
MYCLASS = "25a"
MYJEAR = "25"
MYDOMAIN = "gym-ka.seminar-bw.de"
students = lr.get(f'/schoolclasses/{MYCLASS}/students')
for student in students:
MYSN = student['sophomorixSurnameASCII'].lower()
MYGIVENNAME = student['sophomorixFirstnameASCII'].lower()
number = ''
incr = re.findall(r'\d+', student['cn'])
if incr:
number = int(incr[-1])
new_mail = f"{MYGIVENNAME}.{MYSN}{number}.k{MYJEAR}@{MYDOMAIN}"
print(f"_{number}_ change the email of {student['cn']} {student['mail'][0]} to {new_mail}.")
Vielen Dank für die vielen Infos. Die haben mir sehr geholfen.
Gibt es denn eine Möglichkeit dieses Skript automatisch z.B. direkt nach einem User Import laufen zu lassen? ein Cron Job wäre theoretisch auch möglich, dauert mir aber vielleicht zu lange.
ich will das als hookscript an den sophomorix Lauf anbinden. Wie das geht, hatte ich, meine ich, in einem Post weiter Oben beschrieben.
Gerade hänge ich noch an anderen Sachen: will mich aber diese Woche drum kümmern (vor allem mal Arnauds script ausprobieren: das andere war ja etwas langsam).
danke für die Rückmeldung. Du hast nur geschrieben, dass du es vor hast/gemacht hast - aber nicht wie
Das Phyton Skript flutscht super. Ich habe es noch etwas optimiert, z.B. E-Mail nur setzen, falls diese unterschiedlich ist und alle Benutzer statt nur eine Schulklasse (weil ich das halt brauche). Auch die Idee von Rainer mit der CSV Datei habe ich eingebaut.
Das Skript rennt mit meinen 80 Usern in 2-3 Sekunden durch
ich denke, es reicht, wenn du das script ausführbar nach:
/etc/linuxmuster/sophomorix/default-school/hooks/
legst: ich denke unter sophomorix-update.d/
Dann wird es immer nach sophomorix-update ausgeführt.
ich hab mal in dein Script reingeschaut.
Übung in scripten hab ich keinerlei, aber ich versuch das mal zu lesen.
Du erschaffst also vorher selber eine csv Datei, die du nach /root/emails.csv bewegst mit zwei Spalten. Erste Spalte: cn und zweite Spalte die gewünschte email.
Das machst du, damit er nicht die user aus dem Dateibaum unter /schoolclasses/{MYCLASS}/students holen muss?
Das hat den Nachteil, dass man die Datei pflegen muss. Und es hat den Vorteil, dass man keine zwei scripte braucht (jetzt kommen ja die 2026er Refs, dann brauch ich eines für 2025 und eines für 2026).
Insofern: sehr interessant.
Du hast auch LMNStudent zu LMNUser geändert: du willst auch lehrermails dadurch setzen lassen, nciht nur Refs?
Das lesen und setzen der Zeit ist nett. Aber das wird ja nur auf der console ausgegeben, oder meinst du das landet im sophomorix.log? Das wäre schön.
Dein:
calculated_mail = f"{MYGIVENNAME}.{MYSN}@{MYDOMAIN}"
errechnet dann aber eine mailadresse, die sophomorix auch selber setzen kann, wenn du das in der school.conf vor gibst: dafür brauchst du doch garkein script?
Für VORNAME.NACHNAME@MEINEDOMAIN.de
Der skip ist natürlich auch nett. Der Passiert bei mir nur nie, weil sophomorix im lauf Davor die email „falsch“ setzt. Aber ich könnte ja versuchen, die in der school.conf gesetzten mailvorgaben für die students zu entfernen: dann setzt sophomorix sie vielelciht nicht mehr selber und ich hab mit dem skip einen echten vorteil…
Das werde ich mal probieren: Danke
LG
Holger
import re
from linuxmusterTools.ldapconnector import LMNLdapReader as lr, LMNStudent
MYCLASS = "25a"
MYJEAR = "25"
MYDOMAIN = "gym-ka.seminar-bw.de"
students = lr.get(f'/schoolclasses/{MYCLASS}/students')
for student in students:
MYSN = student['sophomorixSurnameASCII'].lower()
MYGIVENNAME = student['sophomorixFirstnameASCII'].lower()
oldmail = student['mail']
number = ''
incr = re.findall(r'\d+', student['cn'])
if incr:
number = int(incr[-1])
new_mail = f"{MYGIVENNAME}.{MYSN}{number}.k{MYJEAR}@{MYDOMAIN}"
print(f"_{number}_ change the email of {student['cn']} {student['mail'][0]} to {new_mail}.")
# Uncomment to save in LDAP
#writer = LMNStudent(student['cn'])
#writer.setattr(data={'mail': new_mail})
wenn ich da einen Nutzer mit dem Vornamen: Hans Peter habe (und dem Nachnamen Maier), dann generiert er die emailadresse:
hans peter.maier.k25@blabla
… also mit Leerzeichen drin: das gibt natürlich nix …
Kann ich das Leerzeichen durch einen Unterstrich ersetzen lassen, so es nötig wäre?
so will sophomorix das mailfeld im AD jedes NUtzers leeren.
Ich hab das gerade durch auskommentieren und dann sophomorix-check getestet: dann will er alle students „ändern“.
ich hab mir mit
sophomorix-user -iu NUTZERMITZWEIVORNAMEN
nochmal angeschaut, was wir so haben.
Leider immer das Leerzeichen zwischen den zwei Vornamen … außer bei der Mailadresse: da hat sophomorix schon den UNterstrich drin.
Meien Idee ist jetzt: wäre es nicht viel einfacher und schneller, wenn wir old_mail nehmen, welches so aussieht:
Für mich ist das script damit erstmal fertig.
Etwaige Nummern im Loginnamen, was wir ja behandeln im script, konnte ich aber nciht testen, da ich solche nicht habe.
Ichhab jetzt noch die erste Zeile hinzugefügt, damit das script ausführbar durch sophomorix ist.
Ich werde Morgen testen, ob das so klappt.
#! /usr/bin/env python3
import re
from linuxmusterTools.ldapconnector import LMNLdapReader as lr, LMNStudent
from datetime import datetime
now = datetime.now()
print(now.strftime("%d.%m.%Y %H:%M:%S"))
MYCLASS = "25a"
MYJEAR = "25"
MYDOMAIN = "gym-ka.seminar-bw.de"
students = lr.get(f'/schoolclasses/{MYCLASS}/students')
for student in students:
MYSN = student['sophomorixSurnameASCII'].lower()
MYGIVENNAME = student['sophomorixFirstnameASCII'].lower()
old_mail = student['mail'][0]
number = ''
incr = re.findall(r'\d+', student['cn'])
if incr:
number = int(incr[-1])
new_mail = f"{MYGIVENNAME}.{MYSN}{number}.k{MYJEAR}@{MYDOMAIN}"
new_mail = new_mail.replace(" ", "_")
print(f"_{number}_ change the email of {student['cn']} {student['mail'][0]} to {new_mail}.")
# Uncomment to save in LDAP
#writer = LMNStudent(student['cn'])
#writer.setattr(data={'mail': new_mail})
dann teste ich auch, was passiert, wenn es „scharf“ geschaltet wird und in welchen logdateien die Meldungen möglicherweise stehen.
ich habe die CSV Datei nur für die Fälle, in denen ich eine manuelle E-Mail (also nicht die errechnete) haben möchte.
Geht das irgendwie, dass ich zwischen vorname und nachname einen Punkt einfügen kann? Genau dafür habe ich eigentlich das Skript gemacht. Ich versuche mal deinen Konfigurationseintrag aus
MAIL_LOCAL_PART_SCHEME=firstname.lastname
Ich bin von Student auf User gewechselt, da ich auch die Eltern-E-Mail Adressen anpassen muss. Die Eltern nutzen die Nextcloud und helfen teilweise auch in der Verwaltung aus. Dann muss ich denen eine Mail schicken können.
klar geht der Punkt: so mache ich das seit Jahren.
Nur im Semianr brauche ich noch ein kKURS hinter den beiden Namen: deswegen das script.
Trag das einfach in die school.conf ein undlass einmal sophomorix-check laufen: dann sagt er dir, wieviele „updatebar“ sind: also bei wievielen er die email ändern würde (wenn es vorher 0 waren).
Und wegen der Eltern: da hab ich vor edulution für die zu nutzen, damit die dort ihre email adresse selebr eintragen und pflegen können.
Ich gehe davon aus, dass das im AD landet.
ich hab jetzt mal das script „scharf geschaltet“.
Es kommt folgende Fehlermeldung:
File "/root/mailscripte/./mailscript-seminar-k25.sh", line 38
writer = LMNStudent(student['cn'])
^
IndentationError: unindent does not match any outer indentation level
Das script siet so aus:
#! /usr/bin/env python3
import re
from linuxmusterTools.ldapconnector import LMNLdapReader as lr, LMNStudent
from datetime import datetime
now = datetime.now()
print(now.strftime("%d.%m.%Y %H:%M:%S"))
MYCLASS = "25a"
MYJEAR = "25"
MYDOMAIN = "gym-ka.seminar-bw.de"
students = lr.get(f'/schoolclasses/{MYCLASS}/students')
for student in students:
MYSN = student['sophomorixSurnameASCII'].lower()
MYGIVENNAME = student['sophomorixFirstnameASCII'].lower()
old_mail = student['mail'][0]
number = ''
incr = re.findall(r'\d+', student['cn'])
if incr:
number = int(incr[-1])
new_mail = f"{MYGIVENNAME}.{MYSN}{number}.k{MYJEAR}@{MYDOMAIN}"
new_mail = new_mail.replace(" ", "_")
# if old_mail == new_mail:
# print(f"SKIP {student['cn']}: mail unchanged ({old_mail})")
# continue
print(f"_{number}_ change the email of {student['cn']} {student['mail'][0]} to {new_mail}.")
# Uncomment to save in LDAP
writer = LMNStudent(student['cn'])
writer.setattr(data={'mail': new_mail})
ich hatte früher einmal den Ansatz mit einem sophomorix-hook-script die Mailadressen von bestimmten Klassen zu manipulieren - es ging mir dabei v.a. um die Mailadressen im SOGo von edulution. Deine Skripte haben mich daran erinnert.
Netzint hat mir aber eine für mich bessere, weil robustere Lösung eingerichtet. Hier der Ausschnitt aus der Doku:
Die Mail-Domain können Sie pro Benutzer-Liste / Klasse anpassen. Die Datei hierzu finden Sie unter /etc/linuxmuster/sophomorix/default-school/school.conf
Konkret habe ich unter der Sektion [userfile.extrastudents.csv]
das Attribut MAILDOMAIN_BY_GROUP
angepasst. Hier sind jetzt die Werte klassenname1=gewünschtemaildomain.de, klassenname2=gewünschtemaildomain.de, klassenname3=gewünschtemaildomain.de
eingetragen.
Vielleicht ist das auch ein Ansatz für Dich.
Gutes Gelingen!
Stefan
PS: Hier noch ein Hook-Skript, das für mich jetzt obsolet ist
#! /usr/bin/env python3
from linuxmusterTools.ldapconnector import (
LMNLdapReader as lr,
UserWriter as uw,
)
DOMAIN = "gewünschtemaildomain.de" # Passen Sie Ihre Domain an
WRITE = False # auf True setzen, um tatsächlich zu schreiben
# Klasse
# Alle Schüler aus dem angegebenen LDAP-Pfad mit dem Attribut 'cn' holen
users = lr.get('/schoolclasses/klassenname1/students', attributes=['cn']) # Passen Sie den Klassennamen an
for user in users:
cn = user['cn']
email = f"{cn.lower()}@{DOMAIN}"
print(f"{cn} → {email}")
if WRITE:
uw.setattr(cn, data={'mail': email})
# Klasse
# Alle Schüler aus dem angegebenen LDAP-Pfad mit dem Attribut 'cn' holen
users = lr.get('/schoolclasses/klassenname2/students', attributes=['cn']) # Passen Sie den Klassennamen an
for user in users:
cn = user['cn']
email = f"{cn.lower()}@{DOMAIN}"
print(f"{cn} → {email}")
if WRITE:
uw.setattr(cn, data={'mail': email})
PPS: Die edulution-docs-Seiten mit dem verwandten Themen kennst Du vielleicht schon:
super Info, vielen Dank .-)
Leider kann ich es nicht „normal“ machen, also sophomorix machen lassen, weil ich keine Änderungen Kursabhängig in der Maildomain brauche, sondern im localpart der Adresse, und da kann ich über
MAIL_LOCAL_PART_SCHEME=firstname.lastname
MAIL_LOCAL_PART_MAP=
Manipulationen machen: aber das kann ich nciht „Klassenabhängig“ machen: ich brauche also das script um das nachträglich in den AD zu schreiben.
Ich hatte auch mit Rüdiger direkt gesprochen: localpart und Klasse gibt es so nicht.