This is an automated email from the ASF dual-hosted git repository.

arm pushed a commit to branch arm
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git

commit 13448a2ec06d7724cae3253986d22b1a03577efe
Author: Alastair McFarlane <[email protected]>
AuthorDate: Fri Mar 13 15:29:20 2026 +0000

    #870 - Get email from CC if sent from external domain via mailing list and 
include name in tabulated votes
---
 atr/models/tabulate.py               |  2 ++
 atr/tabulate.py                      | 29 +++++++++++++++++++++--------
 atr/templates/resolve-tabulated.html | 18 ++++++++++--------
 3 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/atr/models/tabulate.py b/atr/models/tabulate.py
index da6fac30..6790ce13 100644
--- a/atr/models/tabulate.py
+++ b/atr/models/tabulate.py
@@ -37,6 +37,7 @@ class VoteStatus(enum.Enum):
 
 
 class VoteEmail(schema.Strict):
+    name: str = schema.example("Example User")
     asf_uid_or_email: str = schema.example("user")
     from_email: str = schema.example("[email protected]")
     status: VoteStatus = schema.example(VoteStatus.BINDING)
@@ -62,6 +63,7 @@ class VoteDetails(schema.Strict):
     votes: dict[str, VoteEmail] = schema.example(
         {
             "user": VoteEmail(
+                name="Example User",
                 asf_uid_or_email="user",
                 from_email="[email protected]",
                 status=VoteStatus.BINDING,
diff --git a/atr/tabulate.py b/atr/tabulate.py
index 2030437a..597439d0 100644
--- a/atr/tabulate.py
+++ b/atr/tabulate.py
@@ -155,18 +155,19 @@ async def votes(  # noqa: C901
     tabulated_votes = {}
     start_unixtime = None
     message_count = 0
-    async for _mid, msg in util.thread_messages(thread_id):
+    async for mid, msg in util.thread_messages(thread_id):
         message_count += 1
         if message_count > MAX_THREAD_MESSAGES:
             raise ValueError(f"Thread exceeds maximum of {MAX_THREAD_MESSAGES} 
messages")
         from_raw = msg.get("from_raw", "")
-        ok, from_email_lower, asf_uid = _vote_identity(from_raw, email_to_uid)
+        list_raw = msg.get("list_raw", "")
+        cc = msg.get("cc", "").split(",\n")
+        ok, name, from_email_lower, asf_uid = _vote_identity(from_raw, 
email_to_uid, list_raw, cc)
         if not ok:
             continue
 
         if asf_uid is not None:
             asf_uid_or_email = asf_uid
-            list_raw = msg.get("list_raw", "")
             status = await _vote_status(asf_uid, list_raw, committee)
         else:
             asf_uid_or_email = from_email_lower
@@ -196,6 +197,7 @@ async def votes(  # noqa: C901
         quotation = " // ".join([c[1] for c in castings])
 
         vote_email = models.tabulate.VoteEmail(
+            name=name,
             asf_uid_or_email=asf_uid_or_email,
             from_email=from_email_lower,
             status=status,
@@ -289,17 +291,28 @@ def _vote_continue(line: str) -> bool:
     return False
 
 
-def _vote_identity(from_raw: str, email_to_uid: dict[str, str]) -> tuple[bool, 
str, str | None]:
+def _vote_identity(
+    from_raw: str, email_to_uid: dict[str, str], list_email: str, cc: list[str]
+) -> tuple[bool, str, str, str | None]:
     from_email_lower = util.email_from_uid(from_raw)
     if not from_email_lower:
-        return False, "", None
+        return False, "", "", None
+    name = ""
     from_email_lower = from_email_lower.removesuffix(".invalid")
     asf_uid = None
     if from_email_lower.endswith("@apache.org"):
+        name = "-"
         asf_uid = from_email_lower.split("@")[0]
-    elif from_email_lower in email_to_uid:
-        asf_uid = email_to_uid[from_email_lower]
-    return True, from_email_lower, asf_uid
+    else:
+        if "via" in from_raw and from_email_lower.replace("@", ".") in 
list_email:
+            # Take the last CC, appended by ezmlm, and use that as the email. 
Otherwise, use their name
+            name = from_raw[: from_raw.index("via") - 1]
+            if cc:
+                from_email_lower = util.email_from_uid(cc[-1]) or 
from_email_lower
+        if from_email_lower in email_to_uid:
+            asf_uid = email_to_uid[from_email_lower]
+
+    return True, name, from_email_lower, asf_uid
 
 
 def _vote_outcome_format(
diff --git a/atr/templates/resolve-tabulated.html 
b/atr/templates/resolve-tabulated.html
index 843d72c6..56b4a0f1 100644
--- a/atr/templates/resolve-tabulated.html
+++ b/atr/templates/resolve-tabulated.html
@@ -27,6 +27,7 @@
       <thead>
         <tr>
           <th>ASF UID or email</th>
+          <th>Name</th>
           <th class="text-center">Vote</th>
           <th class="text-center">Status</th>
           <th class="text-center">Link</th>
@@ -34,20 +35,21 @@
         </tr>
       </thead>
       <tbody>
-        {% for asf_uid, vote_email in tabulated_votes.items() %}
+        {% for asf_uid, vote_detail in tabulated_votes.items() %}
           <tr>
-            <td class="atr-nowrap">{{ vote_email.asf_uid_or_email }}</td>
-            <td class="atr-nowrap text-center {% if vote_email.status.value == 
'Binding' %}fw-bold{% endif %} {% if vote_email.vote.value == 'Yes' 
%}atr-green{% elif vote_email.vote.value == 'No' %}atr-red{% endif %}">
-              {{ vote_email.vote.value }}
+            <td class="atr-nowrap">{{ vote_detail.asf_uid_or_email }}</td>
+            <td class="atr-nowrap">{{ vote_detail.name }}</td>
+            <td class="atr-nowrap text-center {% if vote_detail.status.value 
== 'Binding' %}fw-bold{% endif %} {% if vote_detail.vote.value == 'Yes' 
%}atr-green{% elif vote_detail.vote.value == 'No' %}atr-red{% endif %}">
+              {{ vote_detail.vote.value }}
             </td>
-            <td class="atr-nowrap text-center {% if vote_email.status.value == 
'Binding' %}fw-bold{% endif %}">
-              {{ vote_email.status.value }}
+            <td class="atr-nowrap text-center {% if vote_detail.status.value 
== 'Binding' %}fw-bold{% endif %}">
+              {{ vote_detail.status.value }}
             </td>
             <td class="atr-nowrap text-center">
-              <a href="https://lists.apache.org/thread/{{ vote_email.asf_eid 
}}"
+              <a href="https://lists.apache.org/thread/{{ vote_detail.asf_eid 
}}"
                  target="_blank">Email</a>
             </td>
-            <td>{{ vote_email.quotation }}</td>
+            <td>{{ vote_detail.quotation }}</td>
           </tr>
         {% endfor %}
       </tbody>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to