diff --git a/config/install/workflow_participants.settings.yml b/config/install/workflow_participants.settings.yml
new file mode 100644
index 0000000..2b0f227
--- /dev/null
+++ b/config/install/workflow_participants.settings.yml
@@ -0,0 +1,6 @@
+enable_notifications: true
+participant_message:
+  subject: 'You have been added as workflow participant to [node:title]'
+  body:
+    value: "Greetings [user:name],\n\n You have been added as a workflow participant to [node:title].\n\n[node:url:absolute]"
+    format: plain_text
diff --git a/config/schema/workflow_participants.schema.yml b/config/schema/workflow_participants.schema.yml
index ae58474..7fae1c2 100644
--- a/config/schema/workflow_participants.schema.yml
+++ b/config/schema/workflow_participants.schema.yml
@@ -1,3 +1,21 @@
+# Workflow participant settings.
+workflow_participants.settings:
+  type: config_object
+  label: 'Workflow participant settings'
+  mapping:
+    enable_notifications:
+      type: boolean
+      label: 'Notify participants when they are added'
+    participant_message:
+      type: mapping
+      mapping:
+        subject:
+          type: string
+          label: 'Email subject'
+        body:
+          type: text_format
+          label: 'Email body'
+
 workflows.workflow.*.third_party.workflow_participants:
   type: mapping
   label: 'Workflow transitions that participants can make'
diff --git a/src/Form/SettingsForm.php b/src/Form/SettingsForm.php
new file mode 100644
index 0000000..bea1819
--- /dev/null
+++ b/src/Form/SettingsForm.php
@@ -0,0 +1,154 @@
+<?php
+
+namespace Drupal\workflow_participants\Form;
+
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Workflow participants settings form.
+ */
+class SettingsForm extends ConfigFormBase {
+
+  /**
+   * The module handler service.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * Constructs the form.
+   *
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The factory for configuration objects.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler service.
+   */
+  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler) {
+    parent::__construct($config_factory);
+    $this->moduleHandler = $module_handler;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('config.factory'),
+      $container->get('module_handler')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEditableConfigNames() {
+    return ['workflow_participants.settings'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'workflow_participants_settings';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form = parent::buildForm($form, $form_state);
+
+    $config = $this->config('workflow_participants.settings');
+
+    $form['enable_notifications'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Enable notifications for new participants'),
+      '#description' => $this->t('If enabled, newly added workflow participants will be notified with the email configured below.'),
+      '#default_value' => $config->get('enable_notifications'),
+    ];
+
+    $form['participant_message'] = [
+      '#type' => 'details',
+      '#tree' => TRUE,
+      '#title' => $this->t('Notification email'),
+      '#states' => [
+        'visible' => [
+          ':input[name = "enable_notifications"]' => ['checked' => TRUE],
+        ],
+      ],
+      '#open' => TRUE,
+    ];
+
+    $form['participant_message']['subject'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Email subject'),
+      '#states' => [
+        'required' => [
+          ':input[name = "enable_notifications"]' => ['checked' => TRUE],
+        ],
+      ],
+      '#default_value' => $config->get('participant_message.subject'),
+    ];
+
+    $form['participant_message']['body'] = [
+      '#type' => 'text_format',
+      '#title' => $this->t('Email body'),
+      '#states' => [
+        'required' => [
+          ':input[name = "enable_notifications"]' => ['checked' => TRUE],
+        ],
+      ],
+      '#default_value' => $config->get('participant_message.body.value'),
+      '#format' => $config->get('participant_message.body.format'),
+    ];
+
+    if ($this->moduleHandler->moduleExists('token')) {
+      $form['participant_message']['token_tree'] = [
+        '#theme' => 'token_tree_link',
+        '#token_types' => 'all',
+        '#show_restricted' => TRUE,
+        '#theme_wrappers' => ['form_element'],
+      ];
+    }
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    parent::validateForm($form, $form_state);
+
+    // If notifications are enabled, require message body and subject.
+    if ($form_state->getValue('enable_notifications')) {
+      if (!$form_state->getValue(['participant_message', 'subject'])) {
+        $form_state->setErrorByName('participant_message][subject', $this->t('Email subject is required.'));
+      }
+      if (!$form_state->getValue(['participant_message', 'body', 'value'])) {
+        $form_state->setErrorByName('participant_message][body][value', $this->t('Email body is required.'));
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $config = $this->config('workflow_participants.settings');
+
+    foreach (['enable_notifications', 'participant_message'] as $key) {
+      $config->set($key, $form_state->getValue($key));
+    }
+
+    $config->save();
+
+    parent::submitForm($form, $form_state);
+  }
+
+}
diff --git a/src/ParticipantNotifier.php b/src/ParticipantNotifier.php
new file mode 100644
index 0000000..223e4ea
--- /dev/null
+++ b/src/ParticipantNotifier.php
@@ -0,0 +1,155 @@
+<?php
+
+namespace Drupal\workflow_participants;
+
+use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Mail\MailManagerInterface;
+use Drupal\Core\Utility\Token;
+use Drupal\token\TokenEntityMapperInterface;
+use Drupal\workflow_participants\Entity\WorkflowParticipantsInterface;
+
+/**
+ * Participant notificer service.
+ */
+class ParticipantNotifier implements ParticipantNotifierInterface {
+
+  /**
+   * Configuration factory service.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
+   * The entity type manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * The mail manager.
+   *
+   * @var \Drupal\Core\Mail\MailManagerInterface
+   */
+  protected $mail;
+
+  /**
+   * The token service.
+   *
+   * @var \Drupal\Core\Utility\Token
+   */
+  protected $token;
+
+  /**
+   * The optional token entity mapper.
+   *
+   * @var \Drupal\token\TokenEntityMapperInterface
+   */
+  protected $tokenEntityMapper;
+
+  /**
+   * Constructs the participant notifier service.
+   *
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config
+   *   The config factory service.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager service.
+   * @param \Drupal\Core\Mail\MailManagerInterface $mail_manager
+   *   The mail manager service.
+   * @param \Drupal\Core\Utility\Token $token
+   *   The token service.
+   * @param \Drupal\token\TokenEntityMapperInterface $entity_mapper
+   *   The optional entity mapper service if the token contrib module is
+   *   available.
+   */
+  public function __construct(ConfigFactoryInterface $config, EntityTypeManagerInterface $entity_type_manager, MailManagerInterface $mail_manager, Token $token, TokenEntityMapperInterface $entity_mapper = NULL) {
+    $this->configFactory = $config;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->mail = $mail_manager;
+    $this->token = $token;
+    $this->tokenEntityMapper = $entity_mapper;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getNewParticipants(WorkflowParticipantsInterface $participants) {
+    $new_participants = [];
+
+    if (isset($participants->original)) {
+      // This is being updated, diff the participants arrays.
+      /** @var \Drupal\workflow_participants\Entity\WorkflowParticipantsInterface $old */
+      $old = $participants->original;
+      $new_participants += array_diff_key($participants->getEditors(), $old->getEditors());
+      $new_participants += array_diff_key($participants->getReviewers(), $old->getReviewers());
+    }
+    else {
+      // They are all new!
+      $new_participants = $participants->getReviewers() + $participants->getEditors();
+    }
+
+    ksort($new_participants);
+    return $new_participants;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function processNotifications(WorkflowParticipantsInterface $participants) {
+    if ($this->configFactory->get('workflow_participants.settings')->get('enable_notifications')) {
+      $this->sendNotifications($this->getNewParticipants($participants), $participants->getModeratedEntity());
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function sendNotifications(array $accounts, EntityInterface $entity) {
+    $params = [
+      'moderated_entity' => $entity,
+    ];
+    $config = $this->configFactory->get('workflow_participants.settings');
+    $subject = $config->get('participant_message.subject');
+    $body = check_markup($config->get('participant_message.body.value'), $config->get('participants_message.body.format'));
+    $context = $this->getTokenContext($entity);
+
+    foreach ($accounts as $account) {
+      $params['account'] = $account;
+      $context['user'] = $account;
+
+      $params['subject'] = $this->token->replace($subject, $context);
+      $params['body'] = $this->token->replace($body, $context);
+
+      $this->mail->mail('workflow_participants', 'new_participant', $account->getEmail(), $account->getPreferredLangcode(), $params);
+    }
+  }
+
+  /**
+   * Get the token context.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity the participant has been added to.
+   *
+   * @return array
+   *   An array to be used as data for token replacement.
+   */
+  protected function getTokenContext(EntityInterface $entity) {
+    if ($this->tokenEntityMapper) {
+      $context = [
+        'entity' => $entity,
+        $this->tokenEntityMapper->getTokenTypeForEntityType($entity->getEntityTypeId(), TRUE) => $entity,
+      ];
+    }
+    else {
+      $context = [
+        'entity' => $entity,
+        $entity->getEntityTypeId() => $entity,
+      ];
+    }
+    return $context;
+  }
+
+}
diff --git a/src/ParticipantNotifierInterface.php b/src/ParticipantNotifierInterface.php
new file mode 100644
index 0000000..198146a
--- /dev/null
+++ b/src/ParticipantNotifierInterface.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Drupal\workflow_participants;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\workflow_participants\Entity\WorkflowParticipantsInterface;
+
+/**
+ * Defines an interface for participant notifications.
+ */
+interface ParticipantNotifierInterface {
+
+  /**
+   * Given an updated list of participants, finds newly added participants.
+   *
+   * @param \Drupal\workflow_participants\Entity\WorkflowParticipantsInterface $participants
+   *   The new or updated workflow participants entity.
+   *
+   * @return \Drupal\user\UserInterface[]
+   *   An array of newly added participants.
+   */
+  public function getNewParticipants(WorkflowParticipantsInterface $participants);
+
+  /**
+   * Processes notifications for participants.
+   */
+  public function processNotifications(WorkflowParticipantsInterface $participants);
+
+  /**
+   * Sends a notification to relevant recipients.
+   *
+   * @param \Drupal\user\UserInterface[] $accounts
+   *   List of accounts to notify. This should have already been filtered down
+   *   to only new recipients.
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity the users have been added to as participants.
+   */
+  public function sendNotifications(array $accounts, EntityInterface $entity);
+
+}
diff --git a/tests/src/Functional/Form/SettingsFormTest.php b/tests/src/Functional/Form/SettingsFormTest.php
new file mode 100644
index 0000000..3abf4fb
--- /dev/null
+++ b/tests/src/Functional/Form/SettingsFormTest.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace Drupal\Tests\workflow_participants\Form;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Settings form test.
+ *
+ * @group workflow_participants
+ */
+class SettingsFormTest extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['workflow_participants'];
+
+  /**
+   * Test the settings form submits properly.
+   */
+  public function testForm() {
+    $admin = $this->createUser([
+      'administer workflow participants',
+      'access administration pages',
+    ]);
+    $this->drupalLogin($admin);
+
+    $this->drupalGet('/admin/config/workflow');
+    $this->assertSession()->linkExists(t('Workflow participant settings'));
+    $this->clickLink(t('Workflow participant settings'));
+
+    $edit = [
+      'enable_notifications' => FALSE,
+      'participant_message[subject]' => '',
+      'participant_message[body][value]' => '',
+    ];
+    $this->drupalPostForm(NULL, $edit, t('Save configuration'));
+    $this->assertFalse(\Drupal::config('workflow_participants.settings')->get('enable_notifications'));
+    $this->assertEmpty(\Drupal::config('workflow_participants.settings')->get('participant_message.subject'));
+    $this->assertEmpty(\Drupal::config('workflow_participants.settings')->get('participant_message.body.value'));
+
+    // Enable notifications.
+    $edit = [
+      'enable_notifications' => TRUE,
+      'participant_message[subject]' => 'Test subject',
+      'participant_message[body][value]' => 'Test body [with:token].',
+    ];
+    $this->drupalPostForm(NULL, $edit, t('Save configuration'));
+    $this->assertTrue(\Drupal::config('workflow_participants.settings')->get('enable_notifications'));
+    $this->assertEquals('Test subject', \Drupal::config('workflow_participants.settings')->get('participant_message.subject'));
+    $this->assertEquals('Test body [with:token].', \Drupal::config('workflow_participants.settings')->get('participant_message.body.value'));
+
+    // Attempt to submit with notifications enabled, but no message body or
+    // subject should result in an error.
+    $edit = [
+      'enable_notifications' => TRUE,
+      'participant_message[subject]' => '',
+      'participant_message[body][value]' => '',
+    ];
+    $this->drupalPostForm(NULL, $edit, t('Save configuration'));
+    $this->assertSession()->pageTextContains(t('Email subject is required.'));
+    $this->assertSession()->pageTextContains(t('Email body is required.'));
+
+  }
+
+}
diff --git a/tests/src/Kernel/NotificationsTest.php b/tests/src/Kernel/NotificationsTest.php
index 9cc01f2..34b381b 100644
--- a/tests/src/Kernel/NotificationsTest.php
+++ b/tests/src/Kernel/NotificationsTest.php
@@ -4,8 +4,8 @@ namespace Drupal\Tests\workflow_participants\Kernel;
 
 use Drupal\Core\Test\AssertMailTrait;
 use Drupal\entity_test\Entity\EntityTestRev;
-use Drupal\simpletest\UserCreationTrait;
 use Drupal\Tests\content_moderation_notifications\Kernel\ContentModerationNotificationCreateTrait;
+use Drupal\Tests\user\Traits\UserCreationTrait;
 
 /**
  * Verify that notifications are sent via content moderation notifications.
@@ -25,7 +25,6 @@ class NotificationsTest extends WorkflowParticipantsTestBase {
    */
   public static $modules = [
     'content_moderation_notifications',
-    'filter',
     'filter_test',
   ];
 
@@ -58,6 +57,9 @@ class NotificationsTest extends WorkflowParticipantsTestBase {
       $account->save();
       $this->participants[$i] = $account;
     }
+
+    // Disable participant notifications, as those are tested elsewhere.
+    $this->config('workflow_participants.settings')->set('enable_notifications', FALSE)->save();
   }
 
   /**
diff --git a/tests/src/Kernel/ParticipantNotifierTest.php b/tests/src/Kernel/ParticipantNotifierTest.php
new file mode 100644
index 0000000..b0dfeff
--- /dev/null
+++ b/tests/src/Kernel/ParticipantNotifierTest.php
@@ -0,0 +1,145 @@
+<?php
+
+namespace Drupal\Tests\workflow_participants\Kernel;
+
+use Drupal\Core\Test\AssertMailTrait;
+use Drupal\entity_test\Entity\EntityTestRev;
+use Drupal\Tests\node\Traits\NodeCreationTrait;
+use Drupal\Tests\user\Traits\UserCreationTrait;
+
+/**
+ * Tests the notifier service.
+ *
+ * @group workflow_participants
+ *
+ * @coversDefaultClass \Drupal\workflow_participants\ParticipantNotifier
+ *
+ * @requires module token
+ */
+class ParticipantNotifierTest extends WorkflowParticipantsTestBase {
+
+  use AssertMailTrait;
+  use NodeCreationTrait;
+  use UserCreationTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['token'];
+
+  /**
+   * Test fixture.
+   *
+   * @var \Drupal\workflow_participants\ParticipantNotifierInterface
+   */
+  protected $notifier;
+
+  /**
+   * User accounts to be used as participants.
+   *
+   * @var \Drupal\user\UserInterface[]
+   */
+  protected $accounts;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->notifier = \Drupal::service('workflow_participants.notifier');
+
+    $this->installEntitySchema('node');
+
+    // Add some participants.
+    $this->installSchema('system', ['sequences']);
+    foreach (range(1, 5) as $i) {
+      $this->accounts[$i] = $this->createUser(['can be workflow participant']);
+    }
+  }
+
+  /**
+   * @covers ::getNewParticipants
+   */
+  public function testGetNewParticipants() {
+    $entity = EntityTestRev::create();
+    $entity->save();
+    $participants = $this->participantStorage->loadForModeratedEntity($entity);
+    $this->assertEmpty($this->notifier->getNewParticipants($participants));
+
+    // Add some participants.
+    $participants->editors = [
+      ['target_id' => $this->accounts[1]->id()],
+      ['target_id' => $this->accounts[2]->id()],
+    ];
+    $participants->reviewers = [
+      ['target_id' => $this->accounts[4]->id()],
+    ];
+    $expected = [
+      (int) $this->accounts[1]->id(),
+      (int) $this->accounts[2]->id(),
+      (int) $this->accounts[4]->id(),
+    ];
+    $this->assertSame($expected, array_keys($this->notifier->getNewParticipants($participants)));
+
+    // Save the participants.
+    $participants->save();
+
+    // Reload and save to mimic an update.
+    $this->participantStorage->resetCache();
+    $participants = $this->participantStorage->loadForModeratedEntity($entity);
+    $participants->save();
+    $participants->original = $this->participantStorage->loadUnchanged($participants->id());
+    $this->assertEmpty($this->notifier->getNewParticipants($participants));
+
+    $participants->reviewers[] = ['target_id' => $this->accounts[5]->id()];
+    $expected = [(int) $this->accounts[5]->id()];
+    $this->assertSame($expected, array_keys($this->notifier->getNewParticipants($participants)));
+  }
+
+  /**
+   * @covers ::processNotifications
+   */
+  public function testProcessNotifications() {
+    $config = \Drupal::configFactory()->getEditable('workflow_participants.settings');
+    $config->set('participant_message.subject', 'A subject [node:title]');
+    $config->set('participant_message.body.value', 'A body [node:url:absolute]');
+    $config->save();
+
+    $node = $this->createNode();
+    $node->save();
+    $participants = $this->participantStorage->loadForModeratedEntity($node);
+    $participants->save();
+
+    $this->assertEmpty($this->getMails());
+
+    $node = $this->createNode();
+    $node->save();
+    $participants = $this->participantStorage->loadForModeratedEntity($node);
+    $participants->editors = [
+      ['target_id' => $this->accounts[1]->id()],
+      ['target_id' => $this->accounts[2]->id()],
+    ];
+    $participants->reviewers = [
+      ['target_id' => $this->accounts[4]->id()],
+    ];
+    $participants->save();
+    $mails = $this->getMails();
+    $this->assertCount(3, $mails);
+
+    // Ensure token replacement.
+    $this->assertMail('subject', 'A subject ' . $node->label());
+    $this->assertMail('body', 'A body ' . $node->toUrl()->setAbsolute()->toString() . "\n\n");
+
+    // Add 2 new users.
+    $this->container->get('state')->set('system.test_mail_collector', []);
+    $participants->editors[] = ['target_id' => $this->accounts[5]->id()];
+    $participants->reviewers[] = ['target_id' => $this->accounts[3]->id()];
+    $participants->save();
+    $mails = $this->getMails();
+    $this->assertCount(2, $mails);
+
+    $mail = array_shift($mails);
+    $this->assertEquals($this->accounts[3]->getEmail(), $mail['to']);
+  }
+
+}
diff --git a/tests/src/Kernel/WorkflowParticipantsTestBase.php b/tests/src/Kernel/WorkflowParticipantsTestBase.php
index 9bc308b..a41ff16 100644
--- a/tests/src/Kernel/WorkflowParticipantsTestBase.php
+++ b/tests/src/Kernel/WorkflowParticipantsTestBase.php
@@ -24,6 +24,7 @@ abstract class WorkflowParticipantsTestBase extends KernelTestBase {
     'content_moderation',
     'dynamic_entity_reference',
     'entity_test',
+    'filter',
     'node',
     'system',
     'user',
@@ -42,7 +43,12 @@ abstract class WorkflowParticipantsTestBase extends KernelTestBase {
     $this->installEntitySchema('user');
     $this->installEntitySchema('content_moderation_state');
     $this->installEntitySchema('workflow_participants');
-    $this->installConfig('content_moderation');
+    $this->installConfig([
+      'filter',
+      'content_moderation',
+      'workflow_participants',
+      'system',
+    ]);
 
     $this->enableModeration();
 
diff --git a/workflow_participants.info.yml b/workflow_participants.info.yml
index 4e3ccaa..f4663df 100644
--- a/workflow_participants.info.yml
+++ b/workflow_participants.info.yml
@@ -6,6 +6,10 @@ package: Content moderation
 dependencies:
   - content_moderation:content_moderation
   - dynamic_entity_reference:dynamic_entity_reference
+  # @todo Remove hard-coded node dependency.
+  - drupal:node
+  - drupal:text
 test_dependencies:
   - content_moderation_notifications:content_moderation_notifications (3.x)
   - diff:diff
+  - token:token
diff --git a/workflow_participants.links.menu.yml b/workflow_participants.links.menu.yml
new file mode 100644
index 0000000..1575d50
--- /dev/null
+++ b/workflow_participants.links.menu.yml
@@ -0,0 +1,5 @@
+workflow_participants.settings:
+  title: 'Workflow participant settings'
+  route_name: workflow_participants.settings
+  description: 'Configure notifications and other settings for workflow participants.'
+  parent: system.admin_config_workflow
diff --git a/workflow_participants.module b/workflow_participants.module
index 622a3bd..7194447 100644
--- a/workflow_participants.module
+++ b/workflow_participants.module
@@ -12,6 +12,7 @@ use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Url;
 use Drupal\node\NodeInterface;
+use Drupal\workflow_participants\Entity\WorkflowParticipantsInterface;
 use Drupal\workflow_participants\EntityOperations;
 
 /**
@@ -78,6 +79,20 @@ function workflow_participants_entity_operation(EntityInterface $entity) {
 }
 
 /**
+ * Implements hook_workflow_participants_insert().
+ */
+function workflow_participants_workflow_participants_insert(WorkflowParticipantsInterface $entity) {
+  \Drupal::service('workflow_participants.notifier')->processNotifications($entity);
+}
+
+/**
+ * Implements hook_workflow_participants_update().
+ */
+function workflow_participants_workflow_participants_update(WorkflowParticipantsInterface $entity) {
+  \Drupal::service('workflow_participants.notifier')->processNotifications($entity);
+}
+
+/**
  * Implements hook_entity_delete().
  */
 function workflow_participants_entity_delete(EntityInterface $entity) {
@@ -93,6 +108,16 @@ function workflow_participants_entity_delete(EntityInterface $entity) {
 }
 
 /**
+ * Implements hook_mail().
+ */
+function workflow_participants_mail($key, &$message, $params) {
+  if ($key === 'new_participant') {
+    $message['subject'] = $params['subject'];
+    $message['body'] = [$params['body']];
+  }
+}
+
+/**
  * Implements hook_content_moderation_notification_mail_data_alter().
  */
 function workflow_participants_content_moderation_notification_mail_data_alter(EntityInterface $entity, array &$data) {
diff --git a/workflow_participants.permissions.yml b/workflow_participants.permissions.yml
index 70c6319..51c448d 100644
--- a/workflow_participants.permissions.yml
+++ b/workflow_participants.permissions.yml
@@ -1,3 +1,5 @@
+administer workflow participants:
+  title: 'Administer workflow participant settings'
 manage workflow participants:
   title: 'Manage workflow participants'
 manage own workflow participants:
diff --git a/workflow_participants.routing.yml b/workflow_participants.routing.yml
index c9d9659..3340847 100644
--- a/workflow_participants.routing.yml
+++ b/workflow_participants.routing.yml
@@ -1,3 +1,12 @@
+# Settings admin form.
+workflow_participants.settings:
+  path: '/admin/config/workflow/participants'
+  defaults:
+    _title: 'Workflow participant settings'
+    _form: 'Drupal\workflow_participants\Form\SettingsForm'
+  requirements:
+    _permission: 'administer workflow participants'
+
 # @todo Don't hard-code for nodes.
 entity.node.workflow_participants:
   path: '/node/{node}/workflow-participants'
diff --git a/workflow_participants.services.yml b/workflow_participants.services.yml
index 120e12d..d1c08f3 100644
--- a/workflow_participants.services.yml
+++ b/workflow_participants.services.yml
@@ -21,3 +21,6 @@ services:
     class: \Drupal\workflow_participants\StateTransitionValidation
     decorates: content_moderation.state_transition_validation
     arguments: ['@content_moderation.moderation_information', '@entity_type.manager']
+  workflow_participants.notifier:
+    class: \Drupal\workflow_participants\ParticipantNotifier
+    arguments: ['@config.factory', '@entity_type.manager', '@plugin.manager.mail', '@token', '@?token.entity_mapper']
