immich-app/immich · error · BadRequestException
Failed to verify SMTP configuration
Error message
Failed to verify SMTP configuration
What it means
Thrown by NotificationService.sendTestEmail when emailRepository.verifySmtp(dto.transport) rejects. It is a BadRequestException with the original SMTP error attached via { cause }, so NestJS responds with HTTP 400 and the cause is preserved in logs. The SMTP verification opens a real connection to the configured transport before any email is rendered or sent.
Source
Thrown at server/src/services/notification.service.ts:254
await this.jobRepository.queue({ name: JobName.NotifyAlbumInvite, data: { id, recipientId: userId, senderName } });
}
@OnEvent({ name: 'SessionDelete' })
onSessionDelete({ sessionId }: ArgOf<'SessionDelete'>) {
// after the response is sent
setTimeout(() => this.websocketRepository.clientSend('on_session_delete', sessionId, sessionId), 500);
}
async sendTestEmail(id: string, dto: SystemConfigSmtpDto, tempTemplate?: string) {
const user = await this.userRepository.get(id, { withDeleted: false });
if (!user) {
throw new Error('User not found');
}
try {
await this.emailRepository.verifySmtp(dto.transport);
} catch (error) {
throw new BadRequestException('Failed to verify SMTP configuration', { cause: error });
}
const { server } = await this.getConfig({ withCache: false });
const { html, text } = await this.emailRepository.renderEmail({
template: EmailTemplate.TEST_EMAIL,
data: {
baseUrl: getExternalDomain(server),
displayName: user.name,
},
customTemplate: tempTemplate!,
});
const { messageId } = await this.emailRepository.sendEmail({
to: user.email,
subject: 'Test email from Immich',
html,
text,
from: dto.from,
replyTo: dto.replyTo || dto.from,View on GitHub (pinned to 199723261c)
Solutions
- Check the `cause` field on the exception: it carries the upstream nodemailer error (EAUTH, ECONNECTION, EENVELOPE, etc.).
- Verify host, port, and security setting (e.g. 465 with 'tls', 587 with 'starttls') against the provider's docs.
- Confirm outbound network access and DNS resolution from the immich-server container.
- Use provider-specific credentials (e.g. a Gmail App Password, not the account password).
- Test the same transport with swaks or nodemailer directly from the host to isolate immich vs SMTP server issues.
Example fix
// before
try {
await this.emailRepository.verifySmtp(dto.transport);
} catch (error) {
throw new BadRequestException('Failed to verify SMTP configuration', { cause: error });
}
// after (surface the upstream code so callers can branch)
try {
await this.emailRepository.verifySmtp(dto.transport);
} catch (error) {
throw new BadRequestException(`Failed to verify SMTP configuration: ${error.code ?? error.message}`, { cause: error });
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: open a throwaway SMTP connection before persisting the config.
try {
await emailRepository.verifySmtp(dto.transport);
} catch (e) {
// report the upstream code (EAUTH, ECONNECTION, ...) to the user
return { ok: false, code: e.code, message: e.message };
} Type guard
import { isIPv4 } from 'node:net';
const isLikelyValidTransport = (t: SmtpTransport): boolean =>
!!t.host && (typeof t.port === 'number' && t.port > 0 && t.port < 65536);
if (!isLikelyValidTransport(dto.transport)) { /* reject early */ } Try / catch
try {
await notificationService.sendTestEmail(id, dto);
} catch (e) {
if (e instanceof BadRequestException && /SMTP/.test(e.message)) {
const upstream = (e as any).cause; // nodemailer error
// surface upstream.code to the operator
}
throw e;
} Prevention
- Test SMTP credentials with swaks/nodemailer from the same host before entering them in Immich.
- Use provider app passwords for OAuth-enabled providers (Gmail, Microsoft).
- Whitelist the immich-server container's outbound IP on your SMTP relay.
- Read the `cause` field to distinguish auth (EAUTH) vs network (ECONNECTION) failures.
When it happens
Trigger: POST /system/preferences/notifications/test with a SystemConfigSmtpDto whose transport.host/port/username/password/security are wrong, unreachable, or whose credentials are rejected by the SMTP server.
Common situations: Typo in host/port, firewall blocking outbound SMTP (port 25/465/587), wrong auth credentials, STARTTLS vs SSL mismatch, self-signed cert rejected, Gmail requiring an app password, or the SMTP host not resolvable in the container's DNS.
Related errors
- Failed to verify SMTP configuration
- Invalid SMTP configuration
- User not found
- User not found
- Notification not found
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/7e22376730343de8.
Report an issue: GitHub.