immich/server/src/services/notification-admin.service.spec.ts
Clement Martin 95889a69c9
feat(server): Option to configure SMTPS transport (#22833)
* feat(server): Option to configure SMTPS transport

This commit adds a boolean option in the SMTP transport configuration to
enable the so-called "secure" mode. What it does is use SMTP over TLS
instead of relying on the more common STARTTLS option over plain SMTP.

* Add missing field in dto

* Add missing field

* Use a switch instead of text field

* Add field in spec

* chore: regen open-api

---------

Co-authored-by: Jason Rasmussen <jason@rasm.me>
2025-10-17 10:21:27 +00:00

112 lines
4.2 KiB
TypeScript

import { defaults, SystemConfig } from 'src/config';
import { EmailTemplate } from 'src/repositories/email.repository';
import { NotificationService } from 'src/services/notification.service';
import { userStub } from 'test/fixtures/user.stub';
import { newTestService, ServiceMocks } from 'test/utils';
const smtpTransport = Object.freeze<SystemConfig>({
...defaults,
notifications: {
smtp: {
...defaults.notifications.smtp,
enabled: true,
transport: {
ignoreCert: false,
host: 'localhost',
port: 587,
secure: false,
username: 'test',
password: 'test',
},
},
},
});
describe(NotificationService.name, () => {
let sut: NotificationService;
let mocks: ServiceMocks;
beforeEach(() => {
({ sut, mocks } = newTestService(NotificationService));
});
it('should work', () => {
expect(sut).toBeDefined();
});
describe('sendTestEmail', () => {
it('should throw error if user could not be found', async () => {
await expect(sut.sendTestEmail('', smtpTransport.notifications.smtp)).rejects.toThrow('User not found');
});
it('should throw error if smtp validation fails', async () => {
mocks.user.get.mockResolvedValue(userStub.admin);
mocks.email.verifySmtp.mockRejectedValue('');
await expect(sut.sendTestEmail('', smtpTransport.notifications.smtp)).rejects.toThrow(
'Failed to verify SMTP configuration',
);
});
it('should send email to default domain', async () => {
mocks.user.get.mockResolvedValue(userStub.admin);
mocks.email.verifySmtp.mockResolvedValue(true);
mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' });
mocks.email.sendEmail.mockResolvedValue({ messageId: 'message-1', response: '' });
await expect(sut.sendTestEmail('', smtpTransport.notifications.smtp)).resolves.not.toThrow();
expect(mocks.email.renderEmail).toHaveBeenCalledWith({
template: EmailTemplate.TEST_EMAIL,
data: { baseUrl: 'https://my.immich.app', displayName: userStub.admin.name },
});
expect(mocks.email.sendEmail).toHaveBeenCalledWith(
expect.objectContaining({
subject: 'Test email from Immich',
smtp: smtpTransport.notifications.smtp.transport,
}),
);
});
it('should send email to external domain', async () => {
mocks.user.get.mockResolvedValue(userStub.admin);
mocks.email.verifySmtp.mockResolvedValue(true);
mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' });
mocks.systemMetadata.get.mockResolvedValue({ server: { externalDomain: 'https://demo.immich.app' } });
mocks.email.sendEmail.mockResolvedValue({ messageId: 'message-1', response: '' });
await expect(sut.sendTestEmail('', smtpTransport.notifications.smtp)).resolves.not.toThrow();
expect(mocks.email.renderEmail).toHaveBeenCalledWith({
template: EmailTemplate.TEST_EMAIL,
data: { baseUrl: 'https://demo.immich.app', displayName: userStub.admin.name },
});
expect(mocks.email.sendEmail).toHaveBeenCalledWith(
expect.objectContaining({
subject: 'Test email from Immich',
smtp: smtpTransport.notifications.smtp.transport,
}),
);
});
it('should send email with replyTo', async () => {
mocks.user.get.mockResolvedValue(userStub.admin);
mocks.email.verifySmtp.mockResolvedValue(true);
mocks.email.renderEmail.mockResolvedValue({ html: '', text: '' });
mocks.email.sendEmail.mockResolvedValue({ messageId: 'message-1', response: '' });
await expect(
sut.sendTestEmail('', { ...smtpTransport.notifications.smtp, replyTo: 'demo@immich.app' }),
).resolves.not.toThrow();
expect(mocks.email.renderEmail).toHaveBeenCalledWith({
template: EmailTemplate.TEST_EMAIL,
data: { baseUrl: 'https://my.immich.app', displayName: userStub.admin.name },
});
expect(mocks.email.sendEmail).toHaveBeenCalledWith(
expect.objectContaining({
subject: 'Test email from Immich',
smtp: smtpTransport.notifications.smtp.transport,
replyTo: 'demo@immich.app',
}),
);
});
});
});