diff --git a/app/models/etudiants.py b/app/models/etudiants.py
index 6574047ee4df7a862931f026b523f00b0e52148b..669a4b031b9e840dbad71869419b5c53dfb42f48 100644
--- a/app/models/etudiants.py
+++ b/app/models/etudiants.py
@@ -522,7 +522,7 @@ class Identite(models.ScoDocModel):
         e_dict["date_naissance"] = ndb.DateISOtoDMY(e_dict.get("date_naissance", ""))
         e_dict["ne"] = self.e
         e_dict["nomprenom"] = self.nomprenom
-        adresse = self.adresses.first()
+        adresse: Adresse = self.adresses.first()
         if adresse:
             e_dict.update(adresse.to_dict(restrict=restrict))
         if with_inscriptions:
diff --git a/app/scodoc/sco_recapcomplet.py b/app/scodoc/sco_recapcomplet.py
index a9a109197ba336e1d70b4f6c9dbd328521d147e6..502576951c02bdffaefaf1c62f88789faf6411d2 100644
--- a/app/scodoc/sco_recapcomplet.py
+++ b/app/scodoc/sco_recapcomplet.py
@@ -33,8 +33,10 @@ import time
 from xml.etree import ElementTree
 
 from flask import abort, g, render_template, request, url_for
+from flask_login import current_user
 
 from app import log
+from app.auth.models import Permission
 from app.but import bulletin_but
 from app.comp import res_sem
 from app.comp.res_common import ResultatsSemestre
@@ -507,6 +509,7 @@ def gen_formsemestre_recapcomplet_html_table(
 
 def _gen_formsemestre_recapcomplet_table(
     res: ResultatsSemestre,
+    include_email_addresses=False,
     include_evaluations=False,
     mode_jury=False,
     convert_values: bool = True,
@@ -518,6 +521,7 @@ def _gen_formsemestre_recapcomplet_table(
     table = table_class(
         res,
         convert_values=convert_values,
+        include_email_addresses=include_email_addresses,
         include_evaluations=include_evaluations,
         mode_jury=mode_jury,
         read_only=not res.formsemestre.can_edit_jury(),
@@ -539,8 +543,10 @@ def gen_formsemestre_recapcomplet_excel(
     Attention: le tableau exporté depuis la page html est celui généré en js par DataTables,
      et non celui-ci.
     """
+    # En excel, ajoute les adresses mail, si on a le droit de les voir.
     table = _gen_formsemestre_recapcomplet_table(
         res,
+        include_email_addresses=current_user.has_permission(Permission.ViewEtudData),
         include_evaluations=include_evaluations,
         mode_jury=mode_jury,
         convert_values=False,
diff --git a/app/tables/recap.py b/app/tables/recap.py
index 36598f4ac1e78a5ad626b1f55bfdfa8843bf3200..5845cc9b1f4dccfb16c4d205218f88b88de8aae4 100644
--- a/app/tables/recap.py
+++ b/app/tables/recap.py
@@ -51,6 +51,7 @@ class TableRecap(tb.Table):
         self,
         res: ResultatsSemestre,
         convert_values=False,
+        include_email_addresses=False,
         include_evaluations=False,
         mode_jury=False,
         row_class=None,
@@ -61,6 +62,7 @@ class TableRecap(tb.Table):
         self.rows: list["RowRecap"] = []  # juste pour que VSCode nous aide sur .rows
         super().__init__(row_class=row_class or RowRecap, **kwargs)
         self.res = res
+        self.include_email_addresses = include_email_addresses
         self.include_evaluations = include_evaluations
         self.mode_jury = mode_jury
         self.read_only = read_only  # utilisé seulement dans sous-classes
@@ -618,6 +620,13 @@ class RowRecap(tb.Row):
             target=url_bulletin,
             target_attrs={"class": "etudinfo", "id": str(etud.id)},
         )
+        if self.table.include_email_addresses:
+            address = etud.adresses.first()
+            if address:
+                self.add_cell("email", "Email", address.email, "identite_detail")
+                self.add_cell(
+                    "emailperso", "Email perso", address.emailperso, "identite_detail"
+                )
 
     def add_abs(self):
         "Ajoute les colonnes absences"