## On this page

Some server actions send email messages to users. For example, when a user creates a new account, the server sends a "Welcome" email message. On Medplum's hosted environment, the email will include a link to "[https://app.medplum.com/setpassword/](https://app.medplum.com/setpassword/)"...

The two main email messages are:

1. Welcome email - when a new user account is created
2. Password reset email - when a user requests a password reset

Medplum fully supports creating a white-label experience where users do not see any Medplum branding. That includes overriding all email behavior.

This document describes the steps to send custom email messages. To send emails through your own SMTP relay and sender domain without customizing content, see [Project SMTP](/content/docs/user-management/project-smtp/index.html); the two features can be combined.

### Info

By default, this will work for Patient Users. If you want to process custom emails for Practitioner Users, the Practitioners must be [invited](/content/docs/api/project-admin/invite/index.html) as project scoped users. See [Project vs Server Scoped Users](/content/docs/user-management/project-vs-server-scoped-users/index.html) for more information.

### Key Steps

1. Setup reCAPTCHA (required for password reset emails, optional for welcome emails)
2. Create a "Reset Password" page in your application (required for password reset emails, optional for welcome emails)
3. Create a "Set Password" page in your application
4. Create a Medplum Bot that processes new `UserSecurityRequest` resources
5. Create a FHIR Subscription that connects `UserSecurityRequest` resources to the bot

## Setup reCAPTCHA

**Optional** reCAPTCHA is only required for Password Reset emails. reCAPTCHA is optional for Welcome emails.

Medplum requires reCAPTCHA for all unauthenticated API requests. "Reset Password" is necessarily unauthenticated, so you will need to setup reCAPTCHA first.

Visit the [reCAPTCHA website](https://www.google.com/recaptcha/about/) to get started. You will need to create a new reCAPTCHA v3 key. Make note of the "Site Key" and "Secret Key".

Once you have your "Site Key" and "Secret Key", you will need to configure your Medplum project. Go to [Projects](https://app.medplum.com/Project) and click "Edit...". Enter the "Site Key" and "Secret Key" in the "reCAPTCHA" section.

## Reset Password Page

**Optional** Reset Password Page is only required for Password Reset emails. Reset Password Page is optional for Welcome emails.

In your custom application, you will need a "Reset Password" page. This will be the page where users go to initiate the reset password flow. For a full example of a "Reset Password" page, check out the source to [`ResetPasswordPage.tsx`](https://github.com/medplum/medplum/blob/main/packages/app/src/ResetPasswordPage.tsx) for the Medplum App.

### Key Functions of the Page

- Initialize reCAPTCHA
- Prompts the user for `email`
- Sends the `email`, `projectId`, and `recaptchaToken` to the [/auth/resetpassword](/content/docs/api/auth/resetpassword/index.html) API endpoint

See the [`ResetPasswordPage.tsx`](https://github.com/medplum/medplum/blob/main/packages/app/src/ResetPasswordPage.tsx) for a full example.

## Set Password Page

In your custom application, you will need a "Set Password" page. This will be the page where users go to confirm their email address. For a full example of a "Set Password" page, check out the source to [`SetPasswordPage.tsx`](https://github.com/medplum/medplum/blob/main/packages/app/src/SetPasswordPage.tsx) for the Medplum App.

### Key Functions of the Page

- Receives `id` and `secret` from URL parameters
- Prompts the user for `password` and `confirmPassword`
- Verifies that `password` and `confirmPassword` match
- Sends the `id`, `secret`, and `password` to the [/auth/setpassword](/content/docs/api/auth/setpassword/index.html) API endpoint

## Password Change Request Bot

Create a Medplum Bot to handle new `UserSecurityRequest` resources. The bot will send a custom email message to the user.

### Tip

If you are new to Medplum Bots, you may want to read the [Bots](/content/docs/bots/index.html) documentation first.

This Bot will use `ProjectMembership` and `UserSecurityRequest` resources, so the Bot must be a "Project Admin" to access these resources.

### Note

You will also need the `email` project feature flag turned on to allow Bots to send emails. See [project feature flags](/content/docs/self-hosting/project-settings#project-feature-flags/index.html).

Here is a full example of a Bot that sends a custom email message:

```ts
import type { BotEvent, MedplumClient, ProfileResource } from '@medplum/core';

import { getDisplayString, getReferenceString } from '@medplum/core';

import type { ProjectMembership, Reference, UserSecurityRequest } from '@medplum/fhirtypes';

export async function handler(medplum: MedplumClient, event: BotEvent<UserSecurityRequest>): Promise<any> {

// This Bot executes on every new UserSecurityRequest resource.

const pcr = event.input;

const user = await medplum.readReference(pcr.user);

const membership = (await medplum.searchOne('ProjectMembership', {
    user: getReferenceString(user),
  })) as ProjectMembership;

const profile = await medplum.readReference(membership.profile as Reference<ProfileResource>);

const email = user.email as string;

const setPasswordUrl = `https://example.com/setpassword/${pcr.id}/${pcr.secret}`;

if (pcr.type === 'invite') {
    await medplum.sendEmail({
      to: email,
      subject: 'Welcome to Example Health!',
      text: [
        `Hello ${getDisplayString(profile)}`,
        '',
        'Please click on the following link to create your account:',
        '',
        setPasswordUrl,
        '',
        'Thank you,',
        'Example Health',
        '',
      ].join('\n'),
    });
  } else {
    await medplum.sendEmail({
      to: email,
      subject: 'Example Health Password Reset',
      text: [
        `Hello ${getDisplayString(profile)}`,
        '',
        'Someone requested to reset your Example Health password.',
        '',
        'To reset your password, please click on the following link:',
        '',
        setPasswordUrl,
        '',
        'If you received this in error, you can safely ignore it.',
        '',
        'Thank you,',
        'Example Health',
        '',
      ].join('\n'),
    });
  }

return true;
}
```

Create, save, and deploy your bot. Make note of the Bot ID.

## FHIR Subscription

Create a FHIR Subscription that connects `UserSecurityRequest` resources to the bot. The subscription will trigger the bot when a new `ProjectMembership` resource is created.

Go to [Subscriptions](https://app.medplum.com/Subscription) and click "New...".

Enter the following values:

- Status = `active`
- Reason = `New Password Change Request`
- Criteria = `UserSecurityRequest`
- Channel Type = `rest-hook`
- Channel Endpoint = `Bot/YOUR_BOT_ID`

## Testing

To test your custom welcome email, create a new user account. The user will receive a custom email message.

- [Setup reCAPTCHA](/content/docs/user-management/custom-emails#setup-recaptcha/index.html)
- [Reset Password Page](/content/docs/user-management/custom-emails#reset-password-page/index.html)
- [Set Password Page](/content/docs/user-management/custom-emails#set-password-page/index.html)
- [Password Change Request Bot](/content/docs/user-management/custom-emails#password-change-request-bot/index.html)
- [FHIR Subscription](/content/docs/user-management/custom-emails#fhir-subscription/index.html)
- [Testing](/content/docs/user-management/custom-emails#testing/index.html)
