track the date an email address was confirmed
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index ac83b28..76b02db 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -360,6 +360,7 @@ def _verify_addr(self, addr, do_auth_check=True):
                 send_system_mail_to_user(user, 'New Email Address Added', email_body)
 
             addr.confirmed = True
+            addr.confirmed_date = datetime.utcnow()
             flash('Email address confirmed')
             h.auditlog_user('Email address verified: %s',  addr.email, user=user)
             if user.get_pref('email_address') is None:
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 630e6c5..ed9bbac 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -88,6 +88,7 @@ class __mongometa__:
     email = FieldProperty(str)
     claimed_by_user_id = FieldProperty(S.ObjectId, if_missing=None)
     confirmed = FieldProperty(bool, if_missing=False)
+    confirmed_date = FieldProperty(datetime)
     nonce = FieldProperty(str)
     valid_address = FieldProperty(bool, if_missing=None)
     valid_details = FieldProperty(S.Anything, if_missing=None)
@@ -189,6 +190,15 @@ def send_verification_link(self):
             message_id=h.gen_message_id(),
             text=text)
 
+    @property
+    def confirmed_date_with_fallback(self) -> datetime | None:
+        # since confirmed_date was only added in 2025, use _id as approximate fallback
+        if self.confirmed_date:
+            return self.confirmed_date
+        if self.confirmed and self._id:
+            return self._id.generation_time.replace(tzinfo=None)
+        return None
+
 
 class AuthGlobals(MappedClass):
     class __mongometa__:
diff --git a/Allura/allura/tests/model/test_auth.py b/Allura/allura/tests/model/test_auth.py
index 7afb845..36a7727 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -22,6 +22,7 @@
 import textwrap
 from datetime import datetime, timedelta
 
+from bson import ObjectId
 from tg import tmpl_context as c, app_globals as g, request as r
 from webob import Request
 from mock import patch, Mock
@@ -113,6 +114,23 @@ def test_email_address_send_verification_link(self):
         return_path, rcpts, body = _client.sendmail.call_args[0]
         assert rcpts == ['test_admin@domain.net']
 
+    def test_email_address_confirmed_date_with_fallback(self):
+        assert M.EmailAddress().confirmed_date_with_fallback is None
+
+        test_date = datetime(2025, 1, 1)
+
+        assert M.EmailAddress(confirmed_date=test_date).confirmed_date_with_fallback == test_date
+
+        assert M.EmailAddress(
+            _id=ObjectId.from_datetime(test_date),
+            confirmed=False,
+        ).confirmed_date_with_fallback is None
+
+        assert M.EmailAddress(
+            _id=ObjectId.from_datetime(test_date),
+            confirmed=True,
+        ).confirmed_date_with_fallback == test_date
+
     @td.with_user_project('test-admin')
     def test_user(self):
         assert c.user.url() .endswith('/u/test-admin/')
diff --git a/Allura/allura/websetup/bootstrap.py b/Allura/allura/websetup/bootstrap.py
index 18989a0..c7a903f 100644
--- a/Allura/allura/websetup/bootstrap.py
+++ b/Allura/allura/websetup/bootstrap.py
@@ -209,6 +209,7 @@ def set_nbhd_wiki_content(nbhd_proj, content):
 
             admin_email = M.EmailAddress.get(email='test-admin@users.localhost')
             admin_email.confirmed = True
+            admin_email.confirmed_date = datetime.utcnow()
         else:
             u_admin = make_user('Admin 1', username='admin1')
             # Admin1 is almost root, with admin access for Users and Projects
@@ -330,6 +331,7 @@ def create_user(display_name, username=None, password='foo', make_project=False)
     kw = {"email": email}
     em = EmailAddress.get(**kw)
     em.confirmed = True
+    em.confirmed_date = datetime.utcnow()
     em.set_nonce_hash()
     user.set_pref('email_address', email)
     fast_set_pwd(user, password)