Skip to content

Conversation

@obenland
Copy link
Member

Summary

Users were incorrectly receiving mention email notifications for activities where they appeared in the CC field but were not actually mentioned in the content. This commonly occurred when users followed an actor and were automatically added to CC for federation purposes.

For example, this activity would incorrectly trigger a mention notification even though the local user is not mentioned:

{
  "actor": "https://sportsbots.xyz/users/NBA",
  "object": {
    "content": "<p>Join @NateDuncanNBA and @DannyLeroux...</p>",
    "tag": [
      {"type": "Mention", "href": "https://twitter.com/NateDuncanNBA"},
      {"type": "Mention", "href": "https://twitter.com/DannyLeroux"}
    ]
  },
  "cc": ["https://obietester.blog/?author=12082291"]
}

The local user is in CC but not in the tags array, yet they were receiving a mention notification.

Proposed changes:

  • Modified Mailer::mention() to verify that a user's actor ID appears in the activity's tag array with type: "Mention" before sending a mention notification
  • Previously, the function only checked if the user was in the cc field, which was incorrect per ActivityPub semantics

Other information:

  • Have you written new tests for your changes, if applicable?

Testing instructions:

  • Comprehensive test coverage has been added:
    • New test test_mention_requires_tag_not_just_cc verifies users in CC without mention tags don't receive notifications
    • New test test_mention_with_tag_sends_notification verifies users properly mentioned do receive notifications
    • Updated existing test to include proper mention tag structure
  • All 28 Mailer tests pass
  • Run tests with: npm run env-test -- --filter Test_Mailer

Changelog entry

  • Automatically create a changelog entry from the details below.
Changelog Entry Details

Significance

  • Patch
  • Minor
  • Major

Type

  • Added - for new features
  • Changed - for changes in existing functionality
  • Deprecated - for soon-to-be removed features
  • Removed - for now removed features
  • Fixed - for any bug fixes
  • Security - in case of vulnerabilities

Message

False mention email notifications for users in CC field without actual mention tags.

Copilot AI review requested due to automatic review settings November 24, 2025 19:46
@obenland obenland self-assigned this Nov 24, 2025
@obenland obenland requested a review from a team November 24, 2025 19:46
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a bug where users were incorrectly receiving mention email notifications when they appeared in an activity's CC field but were not actually mentioned in the activity's tag array. The fix ensures that mention notifications are only sent when a user's actor ID is present in both the CC field and the activity's tag array with type: "Mention".

Key changes:

  • Updated Mailer::mention() to verify user actor IDs exist in activity tags before sending notifications
  • Added comprehensive test coverage for the bug fix and proper mention scenarios
  • Includes substantial new Social Web admin interface infrastructure (TypeScript React application)

Reviewed changes

Copilot reviewed 87 out of 97 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
includes/class-mailer.php Fixed mention notification logic to check tag array
tests/phpunit/tests/includes/class-test-mailer.php Added tests for CC-only and proper mention scenarios
tests/phpunit/tests/includes/rest/class-test-actors-inbox-controller.php Updated test with attributedTo field
tests/phpunit/tests/includes/handler/class-test-create.php Updated test to use proper object structure
tests/phpunit/tests/includes/collection/class-test-posts.php Updated test with content for excerpt generation
includes/handler/class-create.php Removed conditional check for create_posts option
Multiple Social Web files New TypeScript/React admin interface components
Comments suppressed due to low confidence (2)

tests/phpunit/tests/includes/class-test-mailer.php:1

  • The test assumes Actors::get_by_id( $user_id )->get_id() will always succeed, but it could fail or return null. Consider adding validation or using a known valid actor ID to make the test more robust.
    src/social-web/utils.ts:1
  • Using any type defeats the purpose of TypeScript's type safety. These variables should be typed as number since they are the result of Math.floor().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@obenland obenland force-pushed the fix/mention-notification-cc-only branch from 47d0359 to bbbfea0 Compare November 24, 2025 19:52
@obenland obenland requested a review from Copilot November 24, 2025 19:53
Copilot finished reviewing on behalf of obenland November 24, 2025 19:56
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 352 to 359
if ( \in_array( $actor_id, (array) $activity['cc'], true ) && isset( $activity['object']['tag'] ) ) {
foreach ( (array) $activity['object']['tag'] as $tag ) {
if ( object_to_uri( $tag ) === $actor_id ) {
$recipients[ $user_id ] = $actor_id;
break;
}
}
}
Copy link

Copilot AI Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tag type should be explicitly checked to ensure it's a "Mention" before comparing the URI. Currently, any tag type with a matching href could trigger a notification. Consider adding a check like if ( isset( $tag['type'] ) && 'Mention' === $tag['type'] && object_to_uri( $tag ) === $actor_id ).

Copilot uses AI. Check for mistakes.
@obenland obenland force-pushed the fix/mention-notification-cc-only branch 2 times, most recently from fb59436 to 6da5de1 Compare November 24, 2025 19:59
@obenland
Copy link
Member Author

It looks like sportsbots.xyz replaces the followers URL in cc with individual actor IDs of their followers when they send out their activities.

This is the activity: https://browser.pub/https://sportsbots.xyz/users/FabrizioRomano/statuses/1993044518745334023

And this is what arrived in my inbox:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    {
      "Hashtag": "as:Hashtag",
      "sensitive": "as:sensitive",
      "dcterms": "http://purl.org/dc/terms/",
      "gts": "https://gotosocial.org/ns#",
      "interactionPolicy": {
        "@id": "gts:interactionPolicy",
        "@type": "@id"
      },
      "canQuote": {
        "@id": "gts:canQuote",
        "@type": "@id"
      },
      "canReply": {
        "@id": "gts:canReply",
        "@type": "@id"
      },
      "canLike": {
        "@id": "gts:canLike",
        "@type": "@id"
      },
      "canAnnounce": {
        "@id": "gts:canAnnounce",
        "@type": "@id"
      },
      "automaticApproval": {
        "@id": "gts:automaticApproval",
        "@type": "@id"
      },
      "manualApproval": {
        "@id": "gts:manualApproval",
        "@type": "@id"
      },
      "always": {
        "@id": "gts:always",
        "@type": "@id"
      }
    }
  ],
  "id": "https://sportsbots.xyz/users/FabrizioRomano/activities/1993044518745334023",
  "type": "Create",
  "published": "2025-11-24T19:50:16.000Z",
  "to": [
    "https://www.w3.org/ns/activitystreams#Public"
  ],
  "cc": [
    "https://obietester.blog/?author=12082291"
  ],
  "interactionPolicy": {
    "canQuote": {
      "automaticApproval": [
        "https://www.w3.org/ns/activitystreams#Public"
      ]
    }
  },
  "object": {
    "id": "https://sportsbots.xyz/users/FabrizioRomano/statuses/1993044518745334023",
    "type": "Note",
    "attachment": [
      {
        "type": "Document",
        "mediaType": "image/jpeg",
        "url": "https://pbs.twimg.com/media/G6i3bLMW8AAUgoD.jpg",
        "name": null,
        "blurhash": "UMDlA{NxFz%2~WShOZW=58%0$4NG57$|wvs+",
        "width": 1343,
        "height": 1343
      },
      {
        "type": "Document",
        "mediaType": "image/jpeg",
        "url": "https://pbs.twimg.com/media/G6i3bK9WIAA5Un4.jpg",
        "name": null,
        "blurhash": "UDC6DcJ~AA~BKh$kwOIqD%IoI[xbx^I.$x%f",
        "width": 544,
        "height": 544
      }
    ],
    "attributedTo": "https://sportsbots.xyz/users/FabrizioRomano",
    "content": "<p>🚨 Hansi Flick: “I’m happy to have Rashford here at Barça. I’ve always been impressed by his quality and what he can do in the box, and he’s showing that in Barcelona”.</p><p>“New football, in Barcelona, with good weather… it’s incredible to see how he’s always smiling”.</p>",
    "contentMap": {
      "en": "<p>🚨 Hansi Flick: “I’m happy to have Rashford here at Barça. I’ve always been impressed by his quality and what he can do in the box, and he’s showing that in Barcelona”.</p><p>“New football, in Barcelona, with good weather… it’s incredible to see how he’s always smiling”.</p>"
    },
    "published": "2025-11-24T19:50:16.000Z",
    "tag": [],
    "url": "https://twitter.com/FabrizioRomano/status/1993044518745334023",
    "to": [
      "https://www.w3.org/ns/activitystreams#Public"
    ],
    "cc": [
      "https://obietester.blog/?author=12082291"
    ],
    "replies": {
      "id": "https://sportsbots.xyz/replies/1993044518745334023",
      "type": "Collection",
      "first": "https://sportsbots.xyz/replies/1993044518745334023/1"
    },
    "sensitive": false,
    "interactionPolicy": {
      "canQuote": {
        "automaticApproval": [
          "https://www.w3.org/ns/activitystreams#Public"
        ]
      }
    }
  },
  "actor": "https://sportsbots.xyz/users/FabrizioRomano"
}

Users were incorrectly receiving mention email notifications when they
appeared in the CC field of an activity but were not actually mentioned
in the content. This commonly occurred when users followed an actor and
were added to CC for federation purposes.

The fix verifies that a user's actor ID appears in the activity's tag
array with type "Mention" before sending a mention notification, rather
than just checking if they're in the CC field.

Changes:
- Add validation in Mailer::mention() to check for actual mention tags
- Add object_to_uri() support for Mention type objects
- Add test case for users in CC without mention tags (should not notify)
- Add test case for users properly mentioned (should notify)
@obenland obenland force-pushed the fix/mention-notification-cc-only branch from 9b55ceb to ae3ce13 Compare November 24, 2025 20:04
@pfefferle
Copy link
Member

Why is your blog in CC?

@obenland
Copy link
Member Author

No idea! 🙂

I assume sportsbots.xyz replaces the followers URL in cc with individual actor IDs of their followers when they send out their activities.

Update mention logic to use 'object.tag' for mentions instead of 'cc' recipients. Simplifies recipient mapping by filtering and mapping mention tags.
Copilot finished reviewing on behalf of obenland November 26, 2025 16:44
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +341 to +342
$mentions = wp_list_filter( (array) $activity['object']['tag'], array( 'type' => 'Mention' ) );
$mentions = array_map( '\Activitypub\object_to_uri', $mentions );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$mentions = wp_list_filter( (array) $activity['object']['tag'], array( 'type' => 'Mention' ) );
$mentions = array_map( '\Activitypub\object_to_uri', $mentions );
$mentions = \wp_list_filter( (array) $activity['object']['tag'], array( 'type' => 'Mention' ) );
$mentions = \array_map( '\Activitypub\object_to_uri', $mentions );

Copy link
Member

@pfefferle pfefferle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one! ♥️

@obenland obenland merged commit 1932704 into trunk Dec 1, 2025
15 checks passed
@obenland obenland deleted the fix/mention-notification-cc-only branch December 1, 2025 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants