Skip to content

ProofPointPS - New Actions Addded#951

Open
KrishnaSharma06 wants to merge 38 commits into
mainfrom
proof_point_ps_fr
Open

ProofPointPS - New Actions Addded#951
KrishnaSharma06 wants to merge 38 commits into
mainfrom
proof_point_ps_fr

Conversation

@KrishnaSharma06

@KrishnaSharma06 KrishnaSharma06 commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Proofpoint PS FR for new actions.

Bug ID: b/509660833


Checklist:

Please ensure you have completed the following items before submitting your PR.
This helps us review your contribution faster and more efficiently.

General Checks:

  • I have read and followed the project's contributing.md guide.
  • My code follows the project's coding style guidelines.
  • I have performed a self-review of my own code.
  • My changes do not introduce any new warnings.
  • My changes pass all existing tests.
  • I have added new tests where appropriate to cover my changes. (If applicable)
  • I have updated the documentation where necessary (e.g., README, API docs). (If applicable)

Open-Source Specific Checks:

  • My changes do not introduce any Personally Identifiable Information (PII) or sensitive customer data.
  • My changes do not expose any internal-only code examples, configurations, or URLs.
  • All code examples, comments, and messages are generic and suitable for a public repository.
  • I understand that any internal context or sensitive details related to this work are handled separately in internal systems (Buganizer for Google team members).

For Google Team Members and Reviewers Only:

  • I have included the Buganizer ID in the PR title or description (e.g., "Internal Buganizer ID: 123456789" or "Related Buganizer: go/buganizer/123456789").
  • I have ensured that all internal discussions and PII related to this work remain in Buganizer.
  • I have tagged the PR with one or more labels that reflect the pull request purpose.

@KrishnaSharma06 KrishnaSharma06 requested a review from a team as a code owner June 16, 2026 12:17
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly expands the functionality of the ProofPointPS integration by introducing a suite of new actions for managing quarantined emails. Additionally, it refactors the core architecture to improve modularity and maintainability, ensuring the integration follows current development standards. These changes enhance the overall capability of the integration to handle complex security workflows.

Highlights

  • New Actions Added: Added seven new actions to the ProofPointPS integration, including Delete, Download, Forward, Move, Release, Resubmit, and Search, to enable comprehensive management of quarantined emails.
  • Core Refactoring: Migrated core logic to a new modular 'core' directory, replacing the legacy ProofPointPSManager with a more robust ProofPointPSApiClient and dedicated utility modules.
  • Dependency Updates: Updated project dependencies, including upgrading tipcommon and integration-testing, and adjusted the pyproject.toml configuration to support the new modular structure.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request upgrades the ProofPointPS integration to version 8.0, introducing several new actions to manage quarantined emails (Search, Release, Delete, Resubmit, Move, Forward, and Download) and refactoring existing actions (Enrich Entities and Ping) to use a new base action class and API client. The review feedback highlights a copy-paste error in the Enrich Entities output message, style guide violations regarding Ping action output formats, path handling using pathlib.Path in the Download action, and missing JSON result examples. Additionally, the reviewer recommends adding a unit test suite and avoiding generic exceptions in the Delete action.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread content/response_integrations/google/proof_point_ps/actions/Ping.py Outdated
Comment thread content/response_integrations/google/proof_point_ps/actions/enrich_entities.py Outdated
Comment thread content/response_integrations/google/proof_point_ps/pyproject.toml
@github-actions

Copy link
Copy Markdown

Integration Tests Failed

Click to view the full report

🧩 proof_point_ps

✅ Passed ❌ Failed ⏭️ Skipped
10 1 0

❌ Failed Tests

tests/test_actions/test_enrich_entities.py::TestEnrichEntities::test_enrich_host_success
self = <test_enrich_entities.TestEnrichEntities object at 0x7ffb14b61ad0>
script_session = <proof_point_ps.tests.core.session.ProofPointPSSession object at 0x7ffb14ce6ed0>
action_output = MockActionOutput(_out=<_io.StringIO object at 0x7ffb14cfe3b0>, _err=<_io.StringIO object at 0x7ffb14cfdea0>)
proofpoint = ProofPointPSProduct(records={'Quarantine': [], 'Spam': [{'processingserver': 'pps-server-02', 'date': '2026-06-16T12:0...guid-222', 'host_ip': '2.2.2.2', 'localguid': 'local-guid-222'}], 'Virus': []}, actions_executed=[], email_contents={})

    @set_metadata(
        integration_config_file_path=CONFIG_PATH,
        entities=[HOST_ENTITY],
        input_context=get_deadline_context(),
    )
    def test_enrich_host_success(
        self,
        script_session: ProofPointPSSession,
        action_output: MockActionOutput,
        proofpoint: ProofPointPSProduct,
    ) -> None:
        """Test hostname entity enrichment success."""
        record = {
            "processingserver": "pps-server-02",
            "date": "2026-06-16T12:00:00Z",
            "subject": "Domain test",
            "messageid": "msg-222",
            "folder": "Spam",
            "size": 2000,
            "rcpts": ["some_user@example.com"],
            "from": "attacker@spam.com",
            "spamscore": 99,
            "guid": "guid-222",
            "host_ip": "2.2.2.2",
            "localguid": "local-guid-222",
        }
        proofpoint.add_record("Spam", record)
    
        enrich_entities.main()
    
        success_msg = (
            "Successfully enriched the following entities using "
            "Proofpoint Email Protection: EXAMPLE.COM"
        )
>       assert action_output.results.output_message == success_msg
E       AssertionError: assert 'None of the ...ere enriched.' == 'Successfully...: EXAMPLE.COM'
E         
E         - Successfully enriched the following entities using Proofpoint Email Protection: EXAMPLE.COM
E         + None of the provided entities were enriched.

tests/test_actions/test_enrich_entities.py:125: AssertionError

@github-actions

Copy link
Copy Markdown

Integration Tests Failed

Click to view the full report

🧩 proof_point_ps

✅ Passed ❌ Failed ⏭️ Skipped
10 1 0

❌ Failed Tests

tests/test_actions/test_enrich_entities.py::TestEnrichEntities::test_enrich_host_success
self = <test_enrich_entities.TestEnrichEntities object at 0x7f44a2ce7150>
script_session = <proof_point_ps.tests.core.session.ProofPointPSSession object at 0x7f44a2cd9290>
action_output = MockActionOutput(_out=<_io.StringIO object at 0x7f44a2e663b0>, _err=<_io.StringIO object at 0x7f44a2e65ea0>)
proofpoint = ProofPointPSProduct(records={'Quarantine': [], 'Spam': [{'processingserver': 'pps-server-02', 'date': '2026-06-16T12:0...guid-222', 'host_ip': '2.2.2.2', 'localguid': 'local-guid-222'}], 'Virus': []}, actions_executed=[], email_contents={})

    @set_metadata(
        integration_config_file_path=CONFIG_PATH,
        entities=[HOST_ENTITY],
        input_context=get_deadline_context(),
    )
    def test_enrich_host_success(
        self,
        script_session: ProofPointPSSession,
        action_output: MockActionOutput,
        proofpoint: ProofPointPSProduct,
    ) -> None:
        """Test hostname entity enrichment success."""
        record = {
            "processingserver": "pps-server-02",
            "date": "2026-06-16T12:00:00Z",
            "subject": "Domain test",
            "messageid": "msg-222",
            "folder": "Spam",
            "size": 2000,
            "rcpts": ["some_user@example.com"],
            "from": "attacker@spam.com",
            "spamscore": 99,
            "guid": "guid-222",
            "host_ip": "2.2.2.2",
            "localguid": "local-guid-222",
        }
        proofpoint.add_record("Spam", record)
    
        enrich_entities.main()
    
        success_msg = (
            "Successfully enriched the following entities using "
            "Proofpoint Email Protection: EXAMPLE.COM"
        )
>       assert action_output.results.output_message == success_msg
E       AssertionError: assert 'None of the ...ere enriched.' == 'Successfully...: EXAMPLE.COM'
E         
E         - Successfully enriched the following entities using Proofpoint Email Protection: EXAMPLE.COM
E         + None of the provided entities were enriched.

tests/test_actions/test_enrich_entities.py:125: AssertionError

@github-actions

Copy link
Copy Markdown

Integration Tests Failed

Click to view the full report

🧩 proof_point_ps

✅ Passed ❌ Failed ⏭️ Skipped
10 1 0

❌ Failed Tests

tests/test_actions/test_enrich_entities.py::TestEnrichEntities::test_enrich_host_success
self = <test_enrich_entities.TestEnrichEntities object at 0x7f80c8e8bcd0>
script_session = <proof_point_ps.tests.core.session.ProofPointPSSession object at 0x7f80c8d3ae10>
action_output = MockActionOutput(_out=<_io.StringIO object at 0x7f80c8ef63b0>, _err=<_io.StringIO object at 0x7f80c8ef5ea0>)
proofpoint = ProofPointPSProduct(records={'Quarantine': [], 'Spam': [{'processingserver': 'pps-server-02', 'date': '2026-06-16T12:0...guid-222', 'host_ip': '2.2.2.2', 'localguid': 'local-guid-222'}], 'Virus': []}, actions_executed=[], email_contents={})

    @set_metadata(
        integration_config_file_path=CONFIG_PATH,
        entities=[HOST_ENTITY],
        input_context=get_deadline_context(),
    )
    def test_enrich_host_success(
        self,
        script_session: ProofPointPSSession,
        action_output: MockActionOutput,
        proofpoint: ProofPointPSProduct,
    ) -> None:
        """Test hostname entity enrichment success."""
        record = {
            "processingserver": "pps-server-02",
            "date": "2026-06-16T12:00:00Z",
            "subject": "Domain test",
            "messageid": "msg-222",
            "folder": "Spam",
            "size": 2000,
            "rcpts": ["some_user@example.com"],
            "from": "attacker@spam.com",
            "spamscore": 99,
            "guid": "guid-222",
            "host_ip": "2.2.2.2",
            "localguid": "local-guid-222",
        }
        proofpoint.add_record("Spam", record)
    
        enrich_entities.main()
    
        success_msg = (
            "Successfully enriched the following entities using "
            "Proofpoint Email Protection: EXAMPLE.COM"
        )
>       assert action_output.results.output_message == success_msg
E       AssertionError: assert 'None of the ...ere enriched.' == 'Successfully...: EXAMPLE.COM'
E         
E         - Successfully enriched the following entities using Proofpoint Email Protection: EXAMPLE.COM
E         + None of the provided entities were enriched.

tests/test_actions/test_enrich_entities.py:125: AssertionError

@github-actions

Copy link
Copy Markdown

Integration Tests Failed

Click to view the full report

🧩 proof_point_ps

✅ Passed ❌ Failed ⏭️ Skipped
10 1 0

❌ Failed Tests

tests/test_actions/test_enrich_entities.py::TestEnrichEntities::test_enrich_host_success
self = <test_enrich_entities.TestEnrichEntities object at 0x7fe8e073d950>
script_session = <proof_point_ps.tests.core.session.ProofPointPSSession object at 0x7fe8e0713e90>
action_output = MockActionOutput(_out=<_io.StringIO object at 0x7fe8e08fe3b0>, _err=<_io.StringIO object at 0x7fe8e08fdea0>)
proofpoint = ProofPointPSProduct(records={'Quarantine': [], 'Spam': [{'processingserver': 'pps-server-02', 'date': '2026-06-16T12:0...guid-222', 'host_ip': '2.2.2.2', 'localguid': 'local-guid-222'}], 'Virus': []}, actions_executed=[], email_contents={})

    @set_metadata(
        integration_config_file_path=CONFIG_PATH,
        entities=[HOST_ENTITY],
        input_context=get_deadline_context(),
    )
    def test_enrich_host_success(
        self,
        script_session: ProofPointPSSession,
        action_output: MockActionOutput,
        proofpoint: ProofPointPSProduct,
    ) -> None:
        """Test hostname entity enrichment success."""
        record = {
            "processingserver": "pps-server-02",
            "date": "2026-06-16T12:00:00Z",
            "subject": "Domain test",
            "messageid": "msg-222",
            "folder": "Spam",
            "size": 2000,
            "rcpts": ["some_user@example.com"],
            "from": "attacker@spam.com",
            "spamscore": 99,
            "guid": "guid-222",
            "host_ip": "2.2.2.2",
            "localguid": "local-guid-222",
        }
        proofpoint.add_record("Spam", record)
    
        enrich_entities.main()
    
        success_msg = (
            "Successfully enriched the following entities using "
            "Proofpoint Email Protection: EXAMPLE.COM"
        )
>       assert action_output.results.output_message == success_msg
E       AssertionError: assert 'None of the ...ere enriched.' == 'Successfully...: EXAMPLE.COM'
E         
E         - Successfully enriched the following entities using Proofpoint Email Protection: EXAMPLE.COM
E         + None of the provided entities were enriched.

tests/test_actions/test_enrich_entities.py:125: AssertionError

@github-actions

Copy link
Copy Markdown

Integration Tests Failed

Click to view the full report

🧩 proof_point_ps

✅ Passed ❌ Failed ⏭️ Skipped
10 1 0

❌ Failed Tests

tests/test_actions/test_enrich_entities.py::TestEnrichEntities::test_enrich_host_success
self = <test_enrich_entities.TestEnrichEntities object at 0x7f8fc22f6090>
script_session = <proof_point_ps.tests.core.session.ProofPointPSSession object at 0x7f8fc212b6d0>
action_output = MockActionOutput(_out=<_io.StringIO object at 0x7f8fc22ca440>, _err=<_io.StringIO object at 0x7f8fc22c9f30>)
proofpoint = ProofPointPSProduct(records={'Quarantine': [], 'Spam': [{'processingserver': 'pps-server-02', 'date': '2026-06-16T12:0...guid-222', 'host_ip': '2.2.2.2', 'localguid': 'local-guid-222'}], 'Virus': []}, actions_executed=[], email_contents={})

    @set_metadata(
        integration_config_file_path=CONFIG_PATH,
        entities=[HOST_ENTITY],
        input_context=get_deadline_context(),
    )
    def test_enrich_host_success(
        self,
        script_session: ProofPointPSSession,
        action_output: MockActionOutput,
        proofpoint: ProofPointPSProduct,
    ) -> None:
        """Test hostname entity enrichment success."""
        record = {
            "processingserver": "pps-server-02",
            "date": "2026-06-16T12:00:00Z",
            "subject": "Domain test",
            "messageid": "msg-222",
            "folder": "Spam",
            "size": 2000,
            "rcpts": ["some_user@example.com"],
            "from": "attacker@spam.com",
            "spamscore": 99,
            "guid": "guid-222",
            "host_ip": "2.2.2.2",
            "localguid": "local-guid-222",
        }
        proofpoint.add_record("Spam", record)
    
        enrich_entities.main()
    
        success_msg = (
            "Successfully enriched the following entities using "
            "Proofpoint Email Protection: EXAMPLE.COM"
        )
>       assert action_output.results.output_message == success_msg
E       AssertionError: assert 'None of the ...ere enriched.' == 'Successfully...: EXAMPLE.COM'
E         
E         - Successfully enriched the following entities using Proofpoint Email Protection: EXAMPLE.COM
E         + None of the provided entities were enriched.

tests/test_actions/test_enrich_entities.py:125: AssertionError

@github-actions

Copy link
Copy Markdown

Integration Tests Failed

Click to view the full report

🧩 proof_point_ps

✅ Passed ❌ Failed ⏭️ Skipped
10 1 0

❌ Failed Tests

tests/test_actions/test_enrich_entities.py::TestEnrichEntities::test_enrich_host_success
self = <test_enrich_entities.TestEnrichEntities object at 0x7f68e18e82d0>
script_session = <proof_point_ps.tests.core.session.ProofPointPSSession object at 0x7f68e194f510>
action_output = MockActionOutput(_out=<_io.StringIO object at 0x7f68e198cc10>, _err=<_io.StringIO object at 0x7f68e198cdc0>)
proofpoint = ProofPointPSProduct(records={'Quarantine': [], 'Spam': [{'processingserver': 'pps-server-02', 'date': '2026-06-16T12:0...guid-222', 'host_ip': '2.2.2.2', 'localguid': 'local-guid-222'}], 'Virus': []}, actions_executed=[], email_contents={})

    @set_metadata(
        integration_config_file_path=CONFIG_PATH,
        entities=[HOST_ENTITY],
        input_context=get_deadline_context(),
    )
    def test_enrich_host_success(
        self,
        script_session: ProofPointPSSession,
        action_output: MockActionOutput,
        proofpoint: ProofPointPSProduct,
    ) -> None:
        """Test hostname entity enrichment success."""
        record = {
            "processingserver": "pps-server-02",
            "date": "2026-06-16T12:00:00Z",
            "subject": "Domain test",
            "messageid": "msg-222",
            "folder": "Spam",
            "size": 2000,
            "rcpts": ["some_user@example.com"],
            "from": "attacker@spam.com",
            "spamscore": 99,
            "guid": "guid-222",
            "host_ip": "2.2.2.2",
            "localguid": "local-guid-222",
        }
        proofpoint.add_record("Spam", record)
    
        enrich_entities.main()
    
        success_msg = (
            "Successfully enriched the following entities using "
            "Proofpoint Email Protection: EXAMPLE.COM"
        )
        try:
>           assert action_output.results.output_message == success_msg
E           AssertionError: assert 'None of the ...ere enriched.' == 'Successfully...: EXAMPLE.COM'
E             
E             - Successfully enriched the following entities using Proofpoint Email Protection: EXAMPLE.COM
E             + None of the provided entities were enriched.

tests/test_actions/test_enrich_entities.py:132: AssertionError

The above exception was the direct cause of the following exception:

self = <test_enrich_entities.TestEnrichEntities object at 0x7f68e18e82d0>
script_session = <proof_point_ps.tests.core.session.ProofPointPSSession object at 0x7f68e194f510>
action_output = MockActionOutput(_out=<_io.StringIO object at 0x7f68e198cc10>, _err=<_io.StringIO object at 0x7f68e198cdc0>)
proofpoint = ProofPointPSProduct(records={'Quarantine': [], 'Spam': [{'processingserver': 'pps-server-02', 'date': '2026-06-16T12:0...guid-222', 'host_ip': '2.2.2.2', 'localguid': 'local-guid-222'}], 'Virus': []}, actions_executed=[], email_contents={})

    @set_metadata(
        integration_config_file_path=CONFIG_PATH,
        entities=[HOST_ENTITY],
        input_context=get_deadline_context(),
    )
    def test_enrich_host_success(
        self,
        script_session: ProofPointPSSession,
        action_output: MockActionOutput,
        proofpoint: ProofPointPSProduct,
    ) -> None:
        """Test hostname entity enrichment success."""
        record = {
            "processingserver": "pps-server-02",
            "date": "2026-06-16T12:00:00Z",
            "subject": "Domain test",
            "messageid": "msg-222",
            "folder": "Spam",
            "size": 2000,
            "rcpts": ["some_user@example.com"],
            "from": "attacker@spam.com",
            "spamscore": 99,
            "guid": "guid-222",
            "host_ip": "2.2.2.2",
            "localguid": "local-guid-222",
        }
        proofpoint.add_record("Spam", record)
    
        enrich_entities.main()
    
        success_msg = (
            "Successfully enriched the following entities using "
            "Proofpoint Email Protection: EXAMPLE.COM"
        )
        try:
            assert action_output.results.output_message == success_msg
            assert action_output.results.execution_state == ExecutionState.COMPLETED
        except AssertionError as e:
            try:
                extracted = tldextract.extract(HOST_ENTITY.identifier)
                extracted_str = f"domain={extracted.domain}, suffix={extracted.suffix}"
            except Exception as ex:  # noqa: BLE001
                extracted_str = f"Error extracting: {ex}"
            debug_info = (
                f"\n=== DEBUG INFO ===\n"
                f"HOST_ENTITY.identifier: {HOST_ENTITY.identifier}\n"
                f"tldextract extraction: {extracted_str}\n"
                f"action_output.results.output_message: {action_output.results.output_message}\n"
                f"action_output.results.execution_state: {action_output.results.execution_state}\n"
                f"proofpoint.records: {proofpoint.records}\n"
                f"=================="
            )
>           raise AssertionError(str(e) + debug_info) from e
E           AssertionError: assert 'None of the ...ere enriched.' == 'Successfully...: EXAMPLE.COM'
E             
E             - Successfully enriched the following entities using Proofpoint Email Protection: EXAMPLE.COM
E             + None of the provided entities were enriched.
E           === DEBUG INFO ===
E           HOST_ENTITY.identifier: EXAMPLE.COM
E           tldextract extraction: Error extracting: path '/list/public_suffix_list.dat' doesn't match with any of the other 'GET' routes patterns: ['/rest/v1/quarantine']
E           action_output.results.output_message: None of the provided entities were enriched.
E           action_output.results.execution_state: ExecutionState.COMPLETED
E           proofpoint.records: {'Quarantine': [], 'Spam': [{'processingserver': 'pps-server-02', 'date': '2026-06-16T12:00:00Z', 'subject': 'Domain test', 'messageid': 'msg-222', 'folder': 'Spam', 'size': 2000, 'rcpts': ['some_user@example.com'], 'from': 'attacker@spam.com', 'spamscore': 99, 'guid': 'guid-222', 'host_ip': '2.2.2.2', 'localguid': 'local-guid-222'}], 'Virus': []}
E           ==================

tests/test_actions/test_enrich_entities.py:149: AssertionError

@KrishnaSharma06

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@KrishnaSharma06

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@KrishnaSharma06

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@KrishnaSharma06 KrishnaSharma06 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

SecOps Code Re-Review: Most comments are resolved. Just one remaining type incompatibility issue causing mypy to fail.

Comment thread content/response_integrations/google/proof_point_ps/actions/enrich_entities.py Outdated
@github-actions

Copy link
Copy Markdown

Integration Tests Failed

Click to view the full report

🧩 proof_point_ps

✅ Passed ❌ Failed ⏭️ Skipped
28 1 0

❌ Failed Tests

tests/test_actions/test_delete_quarantined_email.py::TestDeleteQuarantinedEmail::test_delete_success
self = <proof_point_ps.tests.test_actions.test_delete_quarantined_email.TestDeleteQuarantinedEmail object at 0x7f54aa9f8790>
script_session = <proof_point_ps.tests.core.session.ProofPointPSSession object at 0x7f54aab7ac50>
action_output = MockActionOutput(_out=<_io.StringIO object at 0x7f54ac8ffac0>, _err=<_io.StringIO object at 0x7f54ac8ffd00>)
proofpoint = ProofPointPSProduct(records={'Quarantine': [], 'Spam': [], 'Virus': [], 'Trash': []}, actions_executed=[{'action': 'de...}, {'action': 'delete', 'folder': 'Quarantine', 'localguid': 'guid-222', 'deletedfolder': 'Trash'}], email_contents={})

    @set_metadata(
        integration_config_file_path=CONFIG_PATH,
        parameters=PARAMETERS_SUCCESS,
    )
    def test_delete_success(
        self,
        script_session: ProofPointPSSession,
        action_output: MockActionOutput,
        proofpoint: ProofPointPSProduct,
    ) -> None:
        """Test successful deletion of all requested quarantined emails."""
        proofpoint.add_record(
            "Quarantine",
            {
                "guid": "guid-111",
                "localguid": "local-111",
                "folder": "Quarantine",
            },
        )
        proofpoint.add_record(
            "Quarantine",
            {
                "guid": "guid-222",
                "localguid": "local-222",
                "folder": "Quarantine",
            },
        )
        proofpoint.records["Trash"] = []
    
        delete_quarantined_email.main()
    
        assert len(script_session.request_history) == 7
        assert proofpoint.actions_executed[0]["action"] == "delete"
        assert proofpoint.actions_executed[0]["localguid"] == "guid-111"
        assert proofpoint.actions_executed[1]["localguid"] == "guid-222"
    
        success_msg = "Successfully deleted quarantined email(s): guid-111, guid-222"
        assert action_output.results is not None
>       assert action_output.results.output_message == success_msg
E       AssertionError: assert 'Successfully...11, guid-222.' == 'Successfully...111, guid-222'
E         
E         Skipping 50 identical leading characters in diff, use -v to show
E         - 1, guid-222
E         + 1, guid-222.
E         ?            +

tests/test_actions/test_delete_quarantined_email.py:80: AssertionError

@github-actions

Copy link
Copy Markdown

Integration Tests Failed

Click to view the full report

🧩 proof_point_ps

✅ Passed ❌ Failed ⏭️ Skipped
28 1 0

❌ Failed Tests

tests/test_actions/test_delete_quarantined_email.py::TestDeleteQuarantinedEmail::test_delete_success
self = <proof_point_ps.tests.test_actions.test_delete_quarantined_email.TestDeleteQuarantinedEmail object at 0x7fdb6bda9cd0>
script_session = <proof_point_ps.tests.core.session.ProofPointPSSession object at 0x7fdb69db0090>
action_output = MockActionOutput(_out=<_io.StringIO object at 0x7fdb6bbf3ac0>, _err=<_io.StringIO object at 0x7fdb6bbf3d00>)
proofpoint = ProofPointPSProduct(records={'Quarantine': [], 'Spam': [], 'Virus': [], 'Trash': []}, actions_executed=[{'action': 'de...}, {'action': 'delete', 'folder': 'Quarantine', 'localguid': 'guid-222', 'deletedfolder': 'Trash'}], email_contents={})

    @set_metadata(
        integration_config_file_path=CONFIG_PATH,
        parameters=PARAMETERS_SUCCESS,
    )
    def test_delete_success(
        self,
        script_session: ProofPointPSSession,
        action_output: MockActionOutput,
        proofpoint: ProofPointPSProduct,
    ) -> None:
        """Test successful deletion of all requested quarantined emails."""
        proofpoint.add_record(
            "Quarantine",
            {
                "guid": "guid-111",
                "localguid": "local-111",
                "folder": "Quarantine",
            },
        )
        proofpoint.add_record(
            "Quarantine",
            {
                "guid": "guid-222",
                "localguid": "local-222",
                "folder": "Quarantine",
            },
        )
        proofpoint.records["Trash"] = []
    
        delete_quarantined_email.main()
    
        assert len(script_session.request_history) == 7
        assert proofpoint.actions_executed[0]["action"] == "delete"
        assert proofpoint.actions_executed[0]["localguid"] == "guid-111"
        assert proofpoint.actions_executed[1]["localguid"] == "guid-222"
    
        success_msg = "Successfully deleted quarantined email(s): guid-111, guid-222"
        assert action_output.results is not None
>       assert action_output.results.output_message == success_msg
E       AssertionError: assert 'Successfully...11, guid-222.' == 'Successfully...111, guid-222'
E         
E         Skipping 50 identical leading characters in diff, use -v to show
E         - 1, guid-222
E         + 1, guid-222.
E         ?            +

tests/test_actions/test_delete_quarantined_email.py:80: AssertionError

@Sahithya1357

Copy link
Copy Markdown
Contributor

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request upgrades the Proofpoint Email Protection (ProofPointPS) integration to version 8.0, refactoring the codebase to use a modular core API client and adding seven new actions for managing quarantined emails, complete with HTML widgets and unit tests. The code review identified several important issues: a potential AttributeError in the API client when parsing non-dictionary JSON responses, dead exception-handling code in the download action due to incorrect inheritance ordering, and silent failures in the delete action when handling multiple GUIDs. Additionally, the reviewer pointed out style guide violations regarding the mandatory soar_sdk.* namespace for SDK imports and the requirement that successful queries with empty results must return a successful execution state.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread content/response_integrations/google/proof_point_ps/core/api_client.py Outdated
Comment thread content/response_integrations/google/proof_point_ps/actions/enrich_entities.py Outdated

@AmitJ98 AmitJ98 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review Feedback

Overall, the PR is well-structured and introduces useful actions for managing quarantined emails. However, there are a few significant issues related to performance and code duplication that should be addressed:

1. Inefficient Search/Validation by GUID (Major Performance Issue)

In several places, the code fetches up to 30 days of emails (for sender *) and filters them locally in Python instead of passing the guid to the Proofpoint API. This will cause slow execution, large memory usage, potential timeouts, and missed records if the API truncates the result set (due to limits).

Affected Files:

  • content/response_integrations/google/proof_point_ps/core/base_action.py (_validate_folder_and_guids)
  • content/response_integrations/google/proof_point_ps/core/api_client.py (get_record_by_guid)
  • content/response_integrations/google/proof_point_ps/actions/search_quarantined_emails.py (Local filtering for guid and msgid)
  • content/response_integrations/google/proof_point_ps/actions/delete_quarantined_email.py (Duplicated logic)

Recommendation:
Since api_client.search() already accepts guid and msgid as parameters, you should pass these directly to the API in your search calls. For example, instead of fetching all emails in a folder and iterating through them, you should query the specific guid:

records = self.api_client.search(guid=guid, folder=folder_name)

In search_quarantined_emails.py, ensure that self.params.guid and self.params.msgid are passed to self.api_client.search() rather than filtering the list in Python afterwards.

2. Code Duplication

The delete_quarantined_email.py action contains a nearly exact inline copy of the _validate_folder_and_guids logic that is already implemented in base_action.py.

Recommendation:
Refactor delete_quarantined_email.py to use self._validate_folder_and_guids(guids, folder_name) directly, just as move_quarantined_email.py and forward_quarantined_email.py do.

3. Brittle Error Handling

In actions like delete_quarantined_email.py, forward_quarantined_email.py, and move_quarantined_email.py, the error handling checks strings like:

if "deletedfolder" in str(e):

Recommendation:
If the Proofpoint API modifies its error message text, these checks will break. If the API provides specific status codes or error identifiers in the JSON response, it is much safer to rely on those rather than substring matches of the error message text.

Comment thread content/response_integrations/google/proof_point_ps/release_notes.yaml Outdated
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.

3 participants