diff --git a/app/controllers/members/mailgun/permanent_failures_controller.rb b/app/controllers/members/mailgun/permanent_failures_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..685faa3469411e56181c6e23f2002cd05c6763f5
--- /dev/null
+++ b/app/controllers/members/mailgun/permanent_failures_controller.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module Members
+  module Mailgun
+    class PermanentFailuresController < ApplicationController
+      respond_to :json
+
+      skip_before_action :authenticate_user!
+      skip_before_action :verify_authenticity_token
+
+      before_action :ensure_feature_enabled!
+      before_action :authenticate_signature!
+      before_action :validate_invite_email!
+
+      feature_category :authentication_and_authorization
+
+      def create
+        webhook_processor.execute
+
+        head :ok
+      end
+
+      private
+
+      def ensure_feature_enabled!
+        render_406 unless Gitlab::CurrentSettings.mailgun_events_enabled?
+      end
+
+      def authenticate_signature!
+        access_denied! unless valid_signature?
+      end
+
+      def valid_signature?
+        return false if Gitlab::CurrentSettings.mailgun_signing_key.blank?
+
+        # per this guide: https://documentation.mailgun.com/en/latest/user_manual.html#webhooks
+        digest = OpenSSL::Digest.new('SHA256')
+        data = [params.dig(:signature, :timestamp), params.dig(:signature, :token)].join
+
+        hmac_digest = OpenSSL::HMAC.hexdigest(digest, Gitlab::CurrentSettings.mailgun_signing_key, data)
+
+        ActiveSupport::SecurityUtils.secure_compare(params.dig(:signature, :signature), hmac_digest)
+      end
+
+      def validate_invite_email!
+        # permanent_failures webhook does not provide a way to filter failures, so we'll get them all on this endpoint
+        # and we only care about our invite_emails
+        render_406 unless payload[:tags]&.include?(::Members::Mailgun::INVITE_EMAIL_TAG)
+      end
+
+      def webhook_processor
+        ::Members::Mailgun::ProcessWebhookService.new(payload)
+      end
+
+      def payload
+        @payload ||= params.permit!['event-data']
+      end
+
+      def render_406
+        # failure to stop retries per https://documentation.mailgun.com/en/latest/user_manual.html#webhooks
+        head :not_acceptable
+      end
+    end
+  end
+end
diff --git a/app/mailers/emails/members.rb b/app/mailers/emails/members.rb
index d18700658455ab35ec6e72fbeb0d3b40b384771f..738794a94e78fd6b189d6b866f670026b680b895 100644
--- a/app/mailers/emails/members.rb
+++ b/app/mailers/emails/members.rb
@@ -150,10 +150,10 @@ def invite_email_subject
     end
 
     def invite_email_headers
-      if Gitlab.dev_env_or_com?
+      if Gitlab::CurrentSettings.mailgun_events_enabled?
         {
-          'X-Mailgun-Tag' => 'invite_email',
-          'X-Mailgun-Variables' => { 'invite_token' => @token }.to_json
+          'X-Mailgun-Tag' => ::Members::Mailgun::INVITE_EMAIL_TAG,
+          'X-Mailgun-Variables' => { ::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY => @token }.to_json
         }
       else
         {}
diff --git a/app/services/members/mailgun.rb b/app/services/members/mailgun.rb
new file mode 100644
index 0000000000000000000000000000000000000000..43fb5a14ef1794353f66c5ca52c84d9945a1aac9
--- /dev/null
+++ b/app/services/members/mailgun.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module Members
+  module Mailgun
+    INVITE_EMAIL_TAG = 'invite_email'
+    INVITE_EMAIL_TOKEN_KEY = :invite_token
+  end
+end
diff --git a/app/services/members/mailgun/process_webhook_service.rb b/app/services/members/mailgun/process_webhook_service.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e359a83ad42344ae2da282397082dd70f16718cf
--- /dev/null
+++ b/app/services/members/mailgun/process_webhook_service.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module Members
+  module Mailgun
+    class ProcessWebhookService
+      ProcessWebhookServiceError = Class.new(StandardError)
+
+      def initialize(payload)
+        @payload = payload
+      end
+
+      def execute
+        @member = Member.find_by_invite_token(invite_token)
+        update_member_and_log if member
+      rescue ProcessWebhookServiceError => e
+        Gitlab::ErrorTracking.track_exception(e)
+      end
+
+      private
+
+      attr_reader :payload, :member
+
+      def update_member_and_log
+        log_update_event if member.update(invite_email_success: false)
+      end
+
+      def log_update_event
+        Gitlab::AppLogger.info "UPDATED MEMBER INVITE_EMAIL_SUCCESS: member_id: #{member.id}"
+      end
+
+      def invite_token
+        # may want to validate schema in some way using ::JSONSchemer.schema(SCHEMA_PATH).valid?(message) if this
+        # gets more complex
+        payload.dig('user-variables', ::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY) ||
+          raise(ProcessWebhookServiceError, "Failed to receive #{::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY} in user-variables: #{payload}")
+      end
+    end
+  end
+end
diff --git a/app/views/admin/application_settings/_mailgun.html.haml b/app/views/admin/application_settings/_mailgun.html.haml
index 6204f7df5dcc3444da7364da50d5cd84eb3421fb..40b4d5cac6d39b04a2fee32d343650b025f10ca7 100644
--- a/app/views/admin/application_settings/_mailgun.html.haml
+++ b/app/views/admin/application_settings/_mailgun.html.haml
@@ -1,5 +1,3 @@
-- return unless Feature.enabled?(:mailgun_events_receiver)
-
 - expanded = integration_expanded?('mailgun_')
 %section.settings.as-mailgun.no-animate#js-mailgun-settings{ class: ('expanded' if expanded) }
   .settings-header
diff --git a/config/feature_flags/development/mailgun_events_receiver.yml b/config/feature_flags/development/mailgun_events_receiver.yml
deleted file mode 100644
index 119d8d34f210e8a49396f45394d8dff60eff685f..0000000000000000000000000000000000000000
--- a/config/feature_flags/development/mailgun_events_receiver.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: mailgun_events_receiver
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64249
-rollout_issue_url:
-milestone: '14.1'
-type: development
-group: group::expansion
-default_enabled: false
diff --git a/config/routes.rb b/config/routes.rb
index a4404f9d3a8578ece3917acd195cdf90be6280ef..ff979d7da103f4cd083b50a871fbc91ede8c748c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -221,6 +221,7 @@
 
     draw :snippets
     draw :profile
+    draw :members
 
     # Product analytics collector
     match '/collector/i', to: ProductAnalytics::CollectorApp.new, via: :all
diff --git a/config/routes/members.rb b/config/routes/members.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e84f0987171ceaf1b58fb928e7294454fde8f7e7
--- /dev/null
+++ b/config/routes/members.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+namespace :members do
+  namespace :mailgun do
+    resources :permanent_failures, only: [:create]
+  end
+end
diff --git a/db/migrate/20210719192928_add_invite_email_success_to_member.rb b/db/migrate/20210719192928_add_invite_email_success_to_member.rb
new file mode 100644
index 0000000000000000000000000000000000000000..40feb13a564ad45f4f31280d69e56cb5b04a1de0
--- /dev/null
+++ b/db/migrate/20210719192928_add_invite_email_success_to_member.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddInviteEmailSuccessToMember < ActiveRecord::Migration[6.1]
+  def up
+    unless column_exists?(:members, :invite_email_success)
+      add_column :members, :invite_email_success, :boolean, null: false, default: true
+    end
+  end
+
+  def down
+    remove_column :members, :invite_email_success
+  end
+end
diff --git a/db/schema_migrations/20210719192928 b/db/schema_migrations/20210719192928
new file mode 100644
index 0000000000000000000000000000000000000000..b15de2220ed0b4b4635962cb478ac89bbfcd3f63
--- /dev/null
+++ b/db/schema_migrations/20210719192928
@@ -0,0 +1 @@
+eed403573697ac7f454ce47d6e4ab3561a10a62177caaaea40d5d70953068175
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index cadaa69a87d4717673e6747f9de3d0dcb87c6c9e..3f9d97d214f4ca068a2bdb9b151b2b744e891ee2 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -14708,6 +14708,7 @@ CREATE TABLE members (
     expires_at date,
     ldap boolean DEFAULT false NOT NULL,
     override boolean DEFAULT false NOT NULL,
+    invite_email_success boolean DEFAULT true NOT NULL,
     state smallint DEFAULT 0
 );
 
diff --git a/doc/administration/integration/mailgun.md b/doc/administration/integration/mailgun.md
new file mode 100644
index 0000000000000000000000000000000000000000..6486cc9de045f45d9c914f7dc13ad733e5104b08
--- /dev/null
+++ b/doc/administration/integration/mailgun.md
@@ -0,0 +1,41 @@
+---
+stage: Growth
+group: Expansion
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference, howto
+---
+
+# Mailgun and GitLab **(FREE SELF)**
+
+When you use Mailgun to send emails for your GitLab instance and [Mailgun](https://www.mailgun.com/)
+integration is enabled and configured in GitLab, you can receive their webhook for
+permanent invite email failures. To set up the integration, you must:
+
+1. [Configure your Mailgun domain](#configure-your-mailgun-domain).
+1. [Enable Mailgun integration](#enable-mailgun-integration).
+
+After completing the integration, Mailgun `permanent_failure` webhooks are sent to your GitLab instance.
+
+## Configure your Mailgun domain
+
+Before you can enable Mailgun in GitLab, set up your own Mailgun permanent failure endpoint to receive the webhooks.
+
+Using the [Mailgun webhook guide](https://www.mailgun.com/blog/a-guide-to-using-mailguns-webhooks/):
+
+1. Add a webhook with the **Event type** set to **Permanent Failure**.
+1. Fill in the URL of your instance and include the `/-/members/mailgun/permanent_failures` path.
+   - Example: `https://myinstance.gitlab.com/-/members/mailgun/permanent_failures`
+
+## Enable Mailgun integration
+
+After configuring your Mailgun domain for the permanent failures endpoint,
+you're ready to enable the Mailgun integration:
+
+1. Sign in to GitLab as an [Administrator](../../user/permissions.md) user.
+1. On the top bar, select **Menu >** **{admin}** **Admin**.
+1. In the left sidebar, go to **Settings > General** and expand the **Mailgun** section.
+1. Select the **Enable Mailgun** check box.
+1. Enter the Mailgun HTTP webhook signing key as described in
+   [the Mailgun documentation](https://documentation.mailgun.com/en/latest/user_manual.html#webhooks) and
+   shown in the [API security](https://app.mailgun.com/app/account/security/api_keys) section for your Mailgun account.
+1. Select **Save changes**.
diff --git a/doc/api/settings.md b/doc/api/settings.md
index e3366cf176cfa923c0cab263d36538d2ace40c62..671a9c008fcae6785f6563824a4564abb1dd811a 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -328,7 +328,7 @@ listed in the descriptions of the relevant settings.
 | `issues_create_limit`                    | integer          | no                                   | Max number of issue creation requests per minute per user. Disabled by default.|
 | `keep_latest_artifact`                   | boolean          | no                                   | Prevent the deletion of the artifacts from the most recent successful jobs, regardless of the expiry time. Enabled by default. |
 | `local_markdown_version`                 | integer          | no                                   | Increase this value when any cached Markdown should be invalidated. |
-| `mailgun_signing_key`                    | string           | no                                   | The Mailgun HTTP webhook signing key for receiving events from webhook |
+| `mailgun_signing_key`                    | string           | no                                   | The Mailgun HTTP webhook signing key for receiving events from webhook. |
 | `mailgun_events_enabled`                 | boolean          | no                                   | Enable Mailgun event receiver. |
 | `maintenance_mode_message`               | string           | no                                   | **(PREMIUM)** Message displayed when instance is in maintenance mode. |
 | `maintenance_mode`                       | boolean          | no                                   | **(PREMIUM)** When instance is in maintenance mode, non-administrative users can sign in with read-only access and make read-only API requests. |
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index 6f8aa6a2e041ebb95d98b4fd256a1f6073ca4076..92b8cd0300967892d6a68eabd2346ee2b183e6b5 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -39,6 +39,7 @@ To access the default page for Admin Area settings:
 | ------ | ----------- |
 | [Elasticsearch](../../../integration/elasticsearch.md#enabling-advanced-search) | Elasticsearch integration. Elasticsearch AWS IAM. |
 | [Kroki](../../../administration/integration/kroki.md#enable-kroki-in-gitlab) | Allow rendering of diagrams in AsciiDoc and Markdown documents using [kroki.io](https://kroki.io). |
+| [Mailgun](../../../administration/integration/mailgun.md) | Enable your GitLab instance to receive invite email bounce events from Mailgun, if it is your email provider. |
 | [PlantUML](../../../administration/integration/plantuml.md) | Allow rendering of PlantUML diagrams in documents. |
 | [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) **(FREE SAAS)** | Slack integration allows you to interact with GitLab via slash commands in a chat window. This option is only available on GitLab.com, though it may be [available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164). |
 | [Third party offers](third_party_offers.md) | Control the display of third party offers. |
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index fe4c532060bae0a4cd3af35e3ff6cfe7e8c706e8..cc65e5753c0b10813eea74219b5e4b4732770c4d 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -269,10 +269,7 @@
     end
 
     context 'Integrations page' do
-      let(:mailgun_events_receiver_enabled) { true }
-
       before do
-        stub_feature_flags(mailgun_events_receiver: mailgun_events_receiver_enabled)
         visit general_admin_application_settings_path
       end
 
@@ -286,26 +283,16 @@
         expect(current_settings.hide_third_party_offers).to be true
       end
 
-      context 'when mailgun_events_receiver feature flag is enabled' do
-        it 'enabling Mailgun events', :aggregate_failures do
-          page.within('.as-mailgun') do
-            check 'Enable Mailgun event receiver'
-            fill_in 'Mailgun HTTP webhook signing key', with: 'MAILGUN_SIGNING_KEY'
-            click_button 'Save changes'
-          end
-
-          expect(page).to have_content 'Application settings saved successfully'
-          expect(current_settings.mailgun_events_enabled).to be true
-          expect(current_settings.mailgun_signing_key).to eq 'MAILGUN_SIGNING_KEY'
+      it 'enabling Mailgun events', :aggregate_failures do
+        page.within('.as-mailgun') do
+          check 'Enable Mailgun event receiver'
+          fill_in 'Mailgun HTTP webhook signing key', with: 'MAILGUN_SIGNING_KEY'
+          click_button 'Save changes'
         end
-      end
-
-      context 'when mailgun_events_receiver feature flag is disabled' do
-        let(:mailgun_events_receiver_enabled) { false }
 
-        it 'does not have mailgun' do
-          expect(page).not_to have_selector('.as-mailgun')
-        end
+        expect(page).to have_content 'Application settings saved successfully'
+        expect(current_settings.mailgun_events_enabled).to be true
+        expect(current_settings.mailgun_signing_key).to eq 'MAILGUN_SIGNING_KEY'
       end
     end
 
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 77d126e012e316a072fe4461a636b94384877d3f..10162ade48bdb1582e2fe293baed58fe465d1b9d 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -167,6 +167,7 @@ ProjectMember:
 - expires_at
 - ldap
 - override
+- invite_email_success
 User:
 - id
 - username
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index ae956adf563aa949871cb2b48c485d402c29ba3a..64fb10d1556a41ca17d07ea355334dfb25d44076 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -827,15 +827,15 @@ def invite_to_project(project, inviter:, user: nil)
         end
       end
 
-      context 'when on gitlab.com' do
+      context 'when mailgun events are enabled' do
         before do
-          allow(Gitlab).to receive(:dev_env_or_com?).and_return(true)
+          stub_application_setting(mailgun_events_enabled: true)
         end
 
         it 'has custom headers' do
           aggregate_failures do
-            expect(subject).to have_header('X-Mailgun-Tag', 'invite_email')
-            expect(subject).to have_header('X-Mailgun-Variables', { 'invite_token' => project_member.invite_token }.to_json)
+            expect(subject).to have_header('X-Mailgun-Tag', ::Members::Mailgun::INVITE_EMAIL_TAG)
+            expect(subject).to have_header('X-Mailgun-Variables', { ::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY => project_member.invite_token }.to_json)
           end
         end
       end
diff --git a/spec/requests/members/mailgun/permanent_failure_spec.rb b/spec/requests/members/mailgun/permanent_failure_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e47aedf8e9411bf3380b3de67d0fc2701f275daf
--- /dev/null
+++ b/spec/requests/members/mailgun/permanent_failure_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'receive a permanent failure' do
+  describe 'POST /members/mailgun/permanent_failures', :aggregate_failures do
+    let_it_be(:member) { create(:project_member, :invited) }
+
+    let(:raw_invite_token) { member.raw_invite_token }
+    let(:mailgun_events) { true }
+    let(:mailgun_signing_key) { 'abc123' }
+
+    subject(:post_request) { post members_mailgun_permanent_failures_path(standard_params) }
+
+    before do
+      stub_application_setting(mailgun_events_enabled: mailgun_events, mailgun_signing_key: mailgun_signing_key)
+    end
+
+    it 'marks the member invite email success as false' do
+      expect { post_request }.to change { member.reload.invite_email_success }.from(true).to(false)
+
+      expect(response).to have_gitlab_http_status(:ok)
+    end
+
+    context 'when the change to a member is not made' do
+      context 'with incorrect signing key' do
+        context 'with incorrect signing key' do
+          let(:mailgun_signing_key) { '_foobar_' }
+
+          it 'does not change member status and responds as not_found' do
+            expect { post_request }.not_to change { member.reload.invite_email_success }
+
+            expect(response).to have_gitlab_http_status(:not_found)
+          end
+        end
+
+        context 'with nil signing key' do
+          let(:mailgun_signing_key) { nil }
+
+          it 'does not change member status and responds as not_found' do
+            expect { post_request }.not_to change { member.reload.invite_email_success }
+
+            expect(response).to have_gitlab_http_status(:not_found)
+          end
+        end
+      end
+
+      context 'when the feature is not enabled' do
+        let(:mailgun_events) { false }
+
+        it 'does not change member status and responds as expected' do
+          expect { post_request }.not_to change { member.reload.invite_email_success }
+
+          expect(response).to have_gitlab_http_status(:not_acceptable)
+        end
+      end
+
+      context 'when it is not an invite email' do
+        before do
+          stub_const('::Members::Mailgun::INVITE_EMAIL_TAG', '_foobar_')
+        end
+
+        it 'does not change member status and responds as expected' do
+          expect { post_request }.not_to change { member.reload.invite_email_success }
+
+          expect(response).to have_gitlab_http_status(:not_acceptable)
+        end
+      end
+    end
+
+    def standard_params
+      {
+        "signature": {
+          "timestamp": "1625056677",
+          "token": "eb944d0ace7227667a1b97d2d07276ae51d2b849ed2cfa68f3",
+          "signature": "9790cc6686eb70f0b1f869180d906870cdfd496d27fee81da0aa86b9e539e790"
+        },
+        "event-data": {
+          "severity": "permanent",
+          "tags": ["invite_email"],
+          "timestamp": 1521233195.375624,
+          "storage": {
+            "url": "_anything_",
+            "key": "_anything_"
+          },
+          "log-level": "error",
+          "id": "_anything_",
+          "campaigns": [],
+          "reason": "suppress-bounce",
+          "user-variables": {
+            "invite_token": raw_invite_token
+          },
+          "flags": {
+            "is-routed": false,
+            "is-authenticated": true,
+            "is-system-test": false,
+            "is-test-mode": false
+          },
+          "recipient-domain": "example.com",
+          "envelope": {
+            "sender": "bob@mg.gitlab.com",
+            "transport": "smtp",
+            "targets": "alice@example.com"
+          },
+          "message": {
+            "headers": {
+              "to": "Alice <alice@example.com>",
+              "message-id": "20130503192659.13651.20287@mg.gitlab.com",
+              "from": "Bob <bob@mg.gitlab.com>",
+              "subject": "Test permanent_fail webhook"
+            },
+            "attachments": [],
+            "size": 111
+          },
+          "recipient": "alice@example.com",
+          "event": "failed",
+          "delivery-status": {
+            "attempt-no": 1,
+            "message": "",
+            "code": 605,
+            "description": "Not delivering to previously bounced address",
+            "session-seconds": 0
+          }
+        }
+      }
+    end
+  end
+end
diff --git a/spec/services/members/mailgun/process_webhook_service_spec.rb b/spec/services/members/mailgun/process_webhook_service_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d6a2118339519658cb81992e33cbee8be2796c46
--- /dev/null
+++ b/spec/services/members/mailgun/process_webhook_service_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Members::Mailgun::ProcessWebhookService do
+  describe '#execute', :aggregate_failures do
+    let_it_be(:member) { create(:project_member, :invited) }
+
+    let(:raw_invite_token) { member.raw_invite_token }
+    let(:payload) { { 'user-variables' => { ::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY => raw_invite_token } } }
+
+    subject(:service) { described_class.new(payload).execute }
+
+    it 'marks the member invite email success as false' do
+      expect(Gitlab::AppLogger).to receive(:info).with(/^UPDATED MEMBER INVITE_EMAIL_SUCCESS/).and_call_original
+
+      expect { service }.to change { member.reload.invite_email_success }.from(true).to(false)
+    end
+
+    context 'when member can not be found' do
+      let(:raw_invite_token) { '_foobar_' }
+
+      it 'does not change member status' do
+        expect(Gitlab::AppLogger).not_to receive(:info).with(/^UPDATED MEMBER INVITE_EMAIL_SUCCESS/)
+
+        expect { service }.not_to change { member.reload.invite_email_success }
+      end
+    end
+
+    context 'when invite token is not found in payload' do
+      let(:payload) { {} }
+
+      it 'does not change member status and logs an error' do
+        expect(Gitlab::AppLogger).not_to receive(:info).with(/^UPDATED MEMBER INVITE_EMAIL_SUCCESS/)
+        expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
+          an_instance_of(described_class::ProcessWebhookServiceError))
+
+        expect { service }.not_to change { member.reload.invite_email_success }
+      end
+    end
+  end
+end