feat(server): email notifications (#8447)
* feat(server): add `react-mail` as mail template engine and `nodemailer` * feat(server): add `smtp` related configs to `SystemConfig` * feat(web): add page for SMTP settings * feat(server): add `react-email.adapter` This adapter render the React-Email into HTML and plain/text email. The output is set as the body of the email. * feat(server): add `MailRepository` and `MailService` Allow to use the NestJS-modules-mailer module to send SMTP emails. This is the base transport for the `NotificationRepository` * feat(server): register the job dispatcher and Job for async email This allows to queue email sending jobs for the `EmailService`. * feat(server): add `NotificationRepository` and `NotificationService` This act as a middleware to properly route the notification to the right transport. As POC I've only implemented a simple SMTP transport. * feat(server): add `welcome` email template * feat(server): add the first notification on `createUser` in `UserService` This trigger an event for the `NotificationRepository` that once processes by using the global config and per-user config will carry the payload to the right notification transport. * chore: clean up * chore: clean up web * fix: type errors" * fix package lock * fix mail sending, option to ignore certs * chore: open api * chore: clean up * remove unused import * feat: email feature flag * chore: remove unused interface * small styling --------- Co-authored-by: Jason Rasmussen <jrasm91@gmail.com> Co-authored-by: Daniel Dietzler <mail@ddietzler.dev> Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
@@ -46,6 +46,11 @@ void main() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// JobStatusDto notifications
|
||||
test('to test the property `notifications`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// JobStatusDto search
|
||||
test('to test the property `search`', () async {
|
||||
// TODO
|
||||
|
||||
+5
@@ -31,6 +31,11 @@ void main() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool notify
|
||||
test('to test the property `notify`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String password
|
||||
test('to test the property `password`', () async {
|
||||
// TODO
|
||||
|
||||
@@ -21,6 +21,11 @@ void main() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool email
|
||||
test('to test the property `email`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool facialRecognition
|
||||
test('to test the property `facialRecognition`', () async {
|
||||
// TODO
|
||||
|
||||
+5
@@ -56,6 +56,11 @@ void main() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// SystemConfigNotificationsDto notifications
|
||||
test('to test the property `notifications`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// SystemConfigOAuthDto oauth
|
||||
test('to test the property `oauth`', () async {
|
||||
// TODO
|
||||
|
||||
@@ -41,6 +41,11 @@ void main() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// JobSettingsDto notifications
|
||||
test('to test the property `notifications`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// JobSettingsDto search
|
||||
test('to test the property `search`', () async {
|
||||
// TODO
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for SystemConfigNotificationsDto
|
||||
void main() {
|
||||
// final instance = SystemConfigNotificationsDto();
|
||||
|
||||
group('test SystemConfigNotificationsDto', () {
|
||||
// SystemConfigSmtpDto smtp
|
||||
test('to test the property `smtp`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for SystemConfigSmtpDto
|
||||
void main() {
|
||||
// final instance = SystemConfigSmtpDto();
|
||||
|
||||
group('test SystemConfigSmtpDto', () {
|
||||
// bool enabled
|
||||
test('to test the property `enabled`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String from
|
||||
test('to test the property `from`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String replyTo
|
||||
test('to test the property `replyTo`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// SystemConfigSmtpTransportDto transport
|
||||
test('to test the property `transport`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||
//
|
||||
// @dart=2.12
|
||||
|
||||
// ignore_for_file: unused_element, unused_import
|
||||
// ignore_for_file: always_put_required_named_parameters_first
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
|
||||
import 'package:openapi/api.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
// tests for SystemConfigSmtpTransportDto
|
||||
void main() {
|
||||
// final instance = SystemConfigSmtpTransportDto();
|
||||
|
||||
group('test SystemConfigSmtpTransportDto', () {
|
||||
// String host
|
||||
test('to test the property `host`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// bool ignoreCert
|
||||
test('to test the property `ignoreCert`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String password
|
||||
test('to test the property `password`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// num port
|
||||
test('to test the property `port`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String username
|
||||
test('to test the property `username`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user