@ -1,9 +1,16 @@
# Mailer
# Mail Services
## `MailService`
The `MailService` and its implementation in `HandlebarsMailService` has been deprecated in favor of the `Mailer` implementation.
New emails should be implemented using [MJML ](../../MailTemplates/README.md ) and the `Mailer` .
## `Mailer`
The Mailer feature provides a structured, type-safe approach to sending emails in the Bitwarden server application. It
The Mailer feature provides a structured, type-safe approach to sending emails in the Bitwarden server application. It
uses Handlebars templates to render both HTML and plain text email content.
uses Handlebars templates to render both HTML and plain text email content.
## Architecture
### Architecture
The Mailer system consists of four main components:
The Mailer system consists of four main components:
@ -12,7 +19,7 @@ The Mailer system consists of four main components:
3. **BaseMailView** - Abstract base class for email template view models
3. **BaseMailView** - Abstract base class for email template view models
4. **IMailRenderer** - Internal interface for rendering templates (implemented by `HandlebarMailRenderer` )
4. **IMailRenderer** - Internal interface for rendering templates (implemented by `HandlebarMailRenderer` )
## How To Use
### How To Use
1. Define a view model that inherits from `BaseMailView` with properties for template data
1. Define a view model that inherits from `BaseMailView` with properties for template data
2. Create Handlebars templates (`.html.hbs` and `.text.hbs` ) as embedded resources, preferably using the MJML pipeline,
2. Create Handlebars templates (`.html.hbs` and `.text.hbs` ) as embedded resources, preferably using the MJML pipeline,
@ -20,9 +27,9 @@ The Mailer system consists of four main components:
3. Define an email class that inherits from `BaseMail<TView>` with metadata like subject
3. Define an email class that inherits from `BaseMail<TView>` with metadata like subject
4. Use `IMailer.SendEmail()` to render and send the email
4. Use `IMailer.SendEmail()` to render and send the email
## Creating a New Email
### Creating a New Email
### Step 1: Define the Email & View Model
#### Step 1: Define the Email & View Model
Create a class that inherits from `BaseMailView` :
Create a class that inherits from `BaseMailView` :
@ -43,7 +50,7 @@ public class WelcomeEmail : BaseMail<WelcomeEmailView>
}
}
```
```
### Step 2: Create Handlebars Templates
#### Step 2: Create Handlebars Templates
Create two template files as embedded resources next to your view model. **Important** : The file names must be located
Create two template files as embedded resources next to your view model. **Important** : The file names must be located
directly next to the `ViewClass` and match the name of the view.
directly next to the `ViewClass` and match the name of the view.
@ -80,7 +87,7 @@ Activate your account: {{ ActivationUrl }}
< / ItemGroup >
< / ItemGroup >
```
```
### Step 3: Send the Email
#### Step 3: Send the Email
Inject `IMailer` and send the email, this may be done in a service, command or some other application layer.
Inject `IMailer` and send the email, this may be done in a service, command or some other application layer.
@ -111,9 +118,9 @@ public class SomeService
}
}
```
```
## Advanced Features
### Advanced Features
### Multiple Recipients
#### Multiple Recipients
Send to multiple recipients by providing multiple email addresses:
Send to multiple recipients by providing multiple email addresses:
@ -125,7 +132,7 @@ var mail = new WelcomeEmail
};
};
```
```
### Bypass Suppression List
#### Bypass Suppression List
For critical emails like account recovery or email OTP, you can bypass the suppression list:
For critical emails like account recovery or email OTP, you can bypass the suppression list:
@ -139,7 +146,7 @@ public class PasswordResetEmail : BaseMail<PasswordResetEmailView>
**Warning**: Only use `IgnoreSuppressList = true` for critical account recovery or authentication emails.
**Warning**: Only use `IgnoreSuppressList = true` for critical account recovery or authentication emails.
### Email Categories
#### Email Categories
Optionally categorize emails for processing at the upstream email delivery service:
Optionally categorize emails for processing at the upstream email delivery service:
@ -151,7 +158,7 @@ public class MarketingEmail : BaseMail<MarketingEmailView>
}
}
```
```
## Built-in View Properties
### Built-in View Properties
All view models inherit from `BaseMailView` , which provides:
All view models inherit from `BaseMailView` , which provides:
@ -162,7 +169,7 @@ All view models inherit from `BaseMailView`, which provides:
< footer > © {{ CurrentYear }} Bitwarden Inc.< / footer >
< footer > © {{ CurrentYear }} Bitwarden Inc.< / footer >
```
```
## Template Naming Convention
### Template Naming Convention
Templates must follow this naming convention:
Templates must follow this naming convention:
@ -193,8 +200,14 @@ services.TryAddSingleton<IMailRenderer, HandlebarMailRenderer>();
services.TryAddSingleton< IMailer , Mailer > ();
services.TryAddSingleton< IMailer , Mailer > ();
```
```
## Performance Notes
### Performance Notes
- **Template caching** - `HandlebarMailRenderer` automatically caches compiled templates
- **Template caching** - `HandlebarMailRenderer` automatically caches compiled templates
- **Lazy initialization** - Handlebars is initialized only when first needed
- **Lazy initialization** - Handlebars is initialized only when first needed
- **Thread-safe** - The renderer is thread-safe for concurrent email rendering
- **Thread-safe** - The renderer is thread-safe for concurrent email rendering
# Overriding email templates from disk
The mail services support loading the mail template from disk. This is intended to be used by self-hosted customers who want to modify their email appearance. These overrides are not intended to be used during local development, as any changes there would not be reflected in the templates used in a normal deployment configuration.
Any customer using this override has worked with Bitwarden support on an approved implementation and has acknowledged that they are responsible for reacting to any changes made to the templates as a part of the Bitwarden development process. This includes, but is not limited to, changes in Handlebars property names, removal of properties from the `ViewModel` classes, and changes in template names. **Bitwarden is not responsible for maintaining backward compatibility between releases in order to support any overridden emails.**