mirror of
https://github.com/immich-app/immich.git
synced 2025-01-19 18:26:46 +01:00
9ac2ac2fcb
* feat(web): test email button * openapi * UI button * Show notification * pr feedback * remove jobs * send email directly from repository and add feedback * avoid sending many emails * linter * pr feedback * lint * lint * lint
95 lines
2.9 KiB
TypeScript
95 lines
2.9 KiB
TypeScript
import { Inject, Injectable } from '@nestjs/common';
|
|
import { render } from '@react-email/render';
|
|
import { createTransport } from 'nodemailer';
|
|
import React from 'react';
|
|
import { AlbumInviteEmail } from 'src/emails/album-invite.email';
|
|
import { AlbumUpdateEmail } from 'src/emails/album-update.email';
|
|
import { TestEmail } from 'src/emails/test.email';
|
|
import { WelcomeEmail } from 'src/emails/welcome.email';
|
|
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
|
import {
|
|
EmailRenderRequest,
|
|
EmailTemplate,
|
|
INotificationRepository,
|
|
SendEmailOptions,
|
|
SendEmailResponse,
|
|
SmtpOptions,
|
|
} from 'src/interfaces/notification.interface';
|
|
import { Instrumentation } from 'src/utils/instrumentation';
|
|
|
|
@Instrumentation()
|
|
@Injectable()
|
|
export class NotificationRepository implements INotificationRepository {
|
|
constructor(@Inject(ILoggerRepository) private logger: ILoggerRepository) {
|
|
this.logger.setContext(NotificationRepository.name);
|
|
}
|
|
|
|
verifySmtp(options: SmtpOptions): Promise<true> {
|
|
const transport = this.createTransport(options);
|
|
try {
|
|
return transport.verify();
|
|
} finally {
|
|
transport.close();
|
|
}
|
|
}
|
|
|
|
renderEmail(request: EmailRenderRequest): { html: string; text: string } {
|
|
const component = this.render(request);
|
|
const html = render(component, { pretty: true });
|
|
const text = render(component, { plainText: true });
|
|
return { html, text };
|
|
}
|
|
|
|
sendEmail({ to, from, subject, html, text, smtp, imageAttachments }: SendEmailOptions): Promise<SendEmailResponse> {
|
|
this.logger.debug(`Sending email to ${to} with subject: ${subject}`);
|
|
const transport = this.createTransport(smtp);
|
|
|
|
const attachments = imageAttachments?.map((attachment) => ({
|
|
filename: attachment.filename,
|
|
path: attachment.path,
|
|
cid: attachment.cid,
|
|
}));
|
|
|
|
try {
|
|
return transport.sendMail({ to, from, subject, html, text, attachments });
|
|
} finally {
|
|
transport.close();
|
|
}
|
|
}
|
|
|
|
private render({ template, data }: EmailRenderRequest): React.FunctionComponentElement<any> {
|
|
switch (template) {
|
|
case EmailTemplate.TEST_EMAIL: {
|
|
return React.createElement(TestEmail, data);
|
|
}
|
|
|
|
case EmailTemplate.WELCOME: {
|
|
return React.createElement(WelcomeEmail, data);
|
|
}
|
|
|
|
case EmailTemplate.ALBUM_INVITE: {
|
|
return React.createElement(AlbumInviteEmail, data);
|
|
}
|
|
|
|
case EmailTemplate.ALBUM_UPDATE: {
|
|
return React.createElement(AlbumUpdateEmail, data);
|
|
}
|
|
}
|
|
}
|
|
|
|
private createTransport(options: SmtpOptions) {
|
|
return createTransport({
|
|
host: options.host,
|
|
port: options.port,
|
|
tls: { rejectUnauthorized: !options.ignoreCert },
|
|
auth:
|
|
options.username || options.password
|
|
? {
|
|
user: options.username,
|
|
pass: options.password,
|
|
}
|
|
: undefined,
|
|
connectionTimeout: 5000,
|
|
});
|
|
}
|
|
}
|