diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py
index 34d34aad97fd2cf9a26f43034a7f87ec3ad6c215..9c73cf58af0c4ee509159b6546f426993c069183 100644
--- a/app/models/formsemestre.py
+++ b/app/models/formsemestre.py
@@ -23,7 +23,7 @@ from sqlalchemy.sql import text
 from sqlalchemy import func
 
 import app.scodoc.sco_utils as scu
-from app import db, log
+from app import db, email, log
 from app.auth.models import User
 from app import models
 from app.models import APO_CODE_STR_LEN, CODE_STR_LEN, SHORT_STR_LEN
@@ -1093,9 +1093,58 @@ class FormSemestre(models.ScoDocModel):
             msg=f"inscription en semestre {self.titre_annee()}",
             commit=True,
         )
+        log(
+            f"inscrit_etudiant: {etud.nomprenom} ({etud.id}) au semestre {self.titre_annee()}"
+        )
+        # Notification mail
+        self._notify_inscription(etud)
         sco_cache.invalidate_formsemestre(formsemestre_id=self.id)
         return inscr
 
+    def desinscrit_etudiant(self, etud: Identite):
+        "Désinscrit l'étudiant du semestre (et notifie le cas échéant)"
+        inscr_sem = FormSemestreInscription.query.filter_by(
+            etudid=etud.id, formsemestre_id=self.id
+        ).first()
+        if not inscr_sem:
+            raise ScoValueError(
+                f"{etud.nomprenom} ({etud.id}) n'est pas inscrit au semestre !"
+            )
+        db.session.delete(inscr_sem)
+        Scolog.logdb(
+            method="desinscrit_etudiant",
+            etudid=etud.id,
+            msg=f"désinscription semestre {self.titre_annee()}",
+            commit=True,
+        )
+        log(
+            f"desinscrit_etudiant: {etud.nomprenom} ({etud.id}) au semestre {self.titre_annee()}"
+        )
+        self._notify_inscription(etud, action="désinscrit")
+        sco_cache.invalidate_formsemestre(formsemestre_id=self.id)
+
+    def _notify_inscription(self, etud: Identite, action="inscrit") -> None:
+        "Notifie inscription d'un étudiant: envoie un mail selon paramétrage"
+        destinations = (
+            sco_preferences.get_preference("emails_notifications_inscriptions", self.id)
+            or ""
+        )
+        destinations = [x.strip() for x in destinations.split(",")]
+        destinations = [x for x in destinations if x]
+        if not destinations:
+            return
+        txt = f"""{etud.nom_prenom()}
+        s'est {action}{etud.e}
+        en {self.titre_annee()}"""
+        subject = f"""Inscription de {etud.nom_prenom()} en {self.titre_annee()}"""
+        # build mail
+        log(f"_notify_inscription: sending notification to {destinations}")
+        log(f"_notify_inscription: subject: {subject}")
+        log(txt)
+        email.send_email(
+            "[ScoDoc] " + subject, email.get_from_addr(), destinations, txt
+        )
+
     def get_partitions_list(
         self, with_default=True, only_listed=False
     ) -> list[Partition]:
diff --git a/app/scodoc/sco_formsemestre_exterieurs.py b/app/scodoc/sco_formsemestre_exterieurs.py
index 4ba6a47ab9bb90ab30a24546ecfd20c457863e8d..b4c49c2102c27e2d619852dfe2749612743a495f 100644
--- a/app/scodoc/sco_formsemestre_exterieurs.py
+++ b/app/scodoc/sco_formsemestre_exterieurs.py
@@ -51,7 +51,6 @@ import app.scodoc.sco_utils as scu
 from app import log
 from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
 from app.scodoc import html_sco_header
-from app.scodoc import sco_formations
 from app.scodoc import sco_formsemestre
 from app.scodoc import sco_formsemestre_inscriptions
 from app.scodoc import sco_formsemestre_validation
diff --git a/app/scodoc/sco_formsemestre_inscriptions.py b/app/scodoc/sco_formsemestre_inscriptions.py
index f77d1d85e931328f35dc88b966e116a3e4d0c760..a7650be26e406ea17ed9420eb6ecfc2d9c3ecbb1 100644
--- a/app/scodoc/sco_formsemestre_inscriptions.py
+++ b/app/scodoc/sco_formsemestre_inscriptions.py
@@ -182,12 +182,11 @@ def do_formsemestre_desinscription(
     if check_has_dec_jury:
         check_if_has_decision_jury(formsemestre, [etudid])
 
-    insem = do_formsemestre_inscription_list(
-        args={"formsemestre_id": formsemestre_id, "etudid": etudid}
-    )
-    if not insem:
+    inscr_sem = FormSemestreInscription.query.filter_by(
+        etudid=etudid, formsemestre_id=formsemestre_id
+    ).first()
+    if not inscr_sem:
         raise ScoValueError(f"{etud.nomprenom} n'est pas inscrit au semestre !")
-    insem = insem[0]
     # -- desinscription de tous les modules
     cnx = ndb.GetDBConnexion()
     cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor)
@@ -211,10 +210,8 @@ def do_formsemestre_desinscription(
     Partition.formsemestre_remove_etud(formsemestre_id, etud)
 
     # -- désincription du semestre
-    do_formsemestre_inscription_delete(
-        insem["formsemestre_inscription_id"], formsemestre_id=formsemestre_id
-    )
-    sco_cache.invalidate_formsemestre(formsemestre_id=formsemestre_id)
+    formsemestre.desinscrit_etudiant(etud)
+
     # --- Semestre extérieur
     if formsemestre.modalite == "EXT":
         if 0 == len(formsemestre.inscriptions):
@@ -226,13 +223,6 @@ def do_formsemestre_desinscription(
             db.session.commit()
             flash(f"Semestre extérieur supprimé: {formsemestre.titre_annee()}")
 
-    Scolog.logdb(
-        method="formsemestre_desinscription",
-        etudid=etudid,
-        msg=f"desinscription semestre {formsemestre_id}",
-        commit=True,
-    )
-
 
 def do_formsemestre_inscription_with_modules(
     formsemestre_id,
diff --git a/app/scodoc/sco_preferences.py b/app/scodoc/sco_preferences.py
index 6b940076daf6b6f890929a3e03e6ad79ebc2bed2..90d4cc435b4c6579d16c0d466bea4b1337be5878 100644
--- a/app/scodoc/sco_preferences.py
+++ b/app/scodoc/sco_preferences.py
@@ -369,10 +369,23 @@ class BasePreferences:
                 "emails_notifications",
                 {
                     "initvalue": "",
-                    "title": "e-mails à qui notifier les opérations",
+                    "title": "e-mail(s) à qui notifier les opérations",
                     "size": 70,
-                    "explanation": """adresses séparées par des virgules; notifie les opérations
-                        (saisies de notes, etc).
+                    "explanation": """optionnel; adresses séparées par des virgules;
+                        notifie les opérations (saisies de notes, etc).
+                    """,
+                    "category": "general",
+                    "only_global": False,  # peut être spécifique à un semestre
+                },
+            ),
+            (
+                "emails_notifications_inscriptions",
+                {
+                    "initvalue": "",
+                    "title": "e-mail(s) à qui notifier les inscriptions d'étudiants",
+                    "size": 70,
+                    "explanation": """optionnel; adresses séparées par des virgules;
+                        notifie les inscriptions/désincriptions de chaque individu.
                     """,
                     "category": "general",
                     "only_global": False,  # peut être spécifique à un semestre
@@ -2321,6 +2334,7 @@ class BasePreferences:
                             <option value="create">Spécifier valeur pour ce
                             semestre seulement</option>
                         </select>
+                        <span class="pref-comment">{descr["comment"]}</span>
                         """
                         descr["explanation"] = menu_global
 
@@ -2385,7 +2399,6 @@ class SemPreferences:
     def edit(self, categories=[]):
         """Dialog to edit semestre preferences in given categories"""
         from app.scodoc import html_sco_header
-        from app.scodoc import sco_formsemestre
 
         if not self.formsemestre_id:
             raise ScoValueError(
diff --git a/app/static/css/scodoc.css b/app/static/css/scodoc.css
index 783ac66691ec5410d332c369313757da1853ea6a..5b80c194a921e78bcb34e9b0c3c714731f2a0ef6 100644
--- a/app/static/css/scodoc.css
+++ b/app/static/css/scodoc.css
@@ -3320,6 +3320,12 @@ li.tf-msg {
   padding-bottom: 5px;
 }
 
+.pref-comment {
+  font-style: italic;
+  font-size: small;
+  color: var(--sco-color-explication);
+}
+
 div.formsemestre-warning-box {
   background-color: yellow;
   border-radius: 4px;