Repository: pypi/warehouse

Issue:
Trusted publishing: "OIDC added" email does not specify full trust details
### Story

I asked my co-maintainer to configure trusted publishing on a project where I don't have owner privileges. I gave them detailed instructions.
When they added trusted publishing, I got this email:
https://github.com/pypi/warehouse/blob/0795e55d/warehouse/templates/email/trusted-publisher-added/body.html#L31

Specifically, this is what I saw:
> Publisher name: GitHub
> Publisher specification: ci-cd.yml

As you can see, the specification field only contains the workflow name. It does not say which *repository* is trusted, nor does it specify the *environment* name (which was the main piece of information I was looking out for).

### Expectations

I'd like to be able to see all the details of the trust configuration, including the optional fields.

### Motivation

This is useful for logging purposes, correctness verification, implementation matching. Especially since this information is not available on the web interface to the accounts with the maintainer-level access.


Discussion:
Thanks for the issue, I agree this could use more detail. The templates are here if anyone would like to work on this: https://github.com/pypi/warehouse/tree/main/warehouse/templates/email/trusted-publisher-added
I'll take it.
@Martolivna FYI, feel free to tag me and/or @tnytown for review on any changes here! We're partially funded to work on tasks like these.
Hello @woodruffw, thank you for your assistance. I have encountered some difficulties while resolving this issue, so once I have any updates or a potential solution, I will let you know. I apologize if it takes up too much time.
No problem at all! We're also happy to help with questions, if you have any. 

Resolving patch:
diff --git a/warehouse/email/__init__.py b/warehouse/email/__init__.py
--- a/warehouse/email/__init__.py
+++ b/warehouse/email/__init__.py
@@ -987,7 +987,9 @@ def send_trusted_publisher_added_email(request, user, project_name, publisher):
         "username": request.user.username,
         "project_name": project_name,
         "publisher_name": publisher.publisher_name,
-        "publisher_spec": str(publisher),
+        "publisher_workflow": str(publisher),
+        "publisher_repository": publisher.repository_name,
+        "publisher_environment": publisher.environment,
     }
 
 
@@ -998,7 +1000,9 @@ def send_trusted_publisher_removed_email(request, user, project_name, publisher)
         "username": request.user.username,
         "project_name": project_name,
         "publisher_name": publisher.publisher_name,
-        "publisher_spec": str(publisher),
+        "publisher_workflow": str(publisher),
+        "publisher_repository": publisher.repository_name,
+        "publisher_environment": publisher.environment,
     }
 
 


Test patch:
diff --git a/tests/unit/email/test_init.py b/tests/unit/email/test_init.py
--- a/tests/unit/email/test_init.py
+++ b/tests/unit/email/test_init.py
@@ -5724,7 +5724,11 @@ def test_trusted_publisher_emails(
         pyramid_request.registry.settings = {"mail.sender": "noreply@example.com"}
 
         project_name = "test_project"
-        fakepublisher = pretend.stub(publisher_name="fakepublisher")
+        fakepublisher = pretend.stub(
+            publisher_name="fakepublisher",
+            repository_name="fakerepository",
+            environment="fakeenvironment",
+        )
         # NOTE: Can't set __str__ using pretend.stub()
         monkeypatch.setattr(
             fakepublisher.__class__, "__str__", lambda s: "fakespecifier"
@@ -5741,7 +5745,9 @@ def test_trusted_publisher_emails(
             "username": stub_user.username,
             "project_name": project_name,
             "publisher_name": "fakepublisher",
-            "publisher_spec": "fakespecifier",
+            "publisher_workflow": "fakespecifier",
+            "publisher_repository": "fakerepository",
+            "publisher_environment": "fakeenvironment",
         }
         subject_renderer.assert_()
         body_renderer.assert_(username=stub_user.username, project_name=project_name)