From a8f147d0833078cc7b6655371daf2cc663b58ebb Mon Sep 17 00:00:00 2001 From: Felix Schneider Date: Mon, 18 May 2026 11:21:25 +0200 Subject: [PATCH] feat(notification): add support for public seerr logo in email (#3036) --- server/lib/notifications/agents/email.ts | 12 +++++++++++ server/lib/settings/index.ts | 2 ++ .../email/generatedpassword/html.pug | 9 +++++--- server/templates/email/media-issue/html.pug | 9 +++++--- server/templates/email/media-request/html.pug | 9 +++++--- server/templates/email/resetpassword/html.pug | 11 ++++++---- server/templates/email/test-email/html.pug | 9 +++++--- .../Notifications/NotificationsEmail.tsx | 21 +++++++++++++++++++ src/i18n/locale/en.json | 2 ++ 9 files changed, 68 insertions(+), 16 deletions(-) diff --git a/server/lib/notifications/agents/email.ts b/server/lib/notifications/agents/email.ts index 4a82b3943..4037aa6ad 100644 --- a/server/lib/notifications/agents/email.ts +++ b/server/lib/notifications/agents/email.ts @@ -16,6 +16,9 @@ import { Notification, shouldSendAdminNotification } from '..'; import type { NotificationAgent, NotificationPayload } from './agent'; import { BaseAgent } from './agent'; +const PUBLIC_LOGO_URL = + 'https://raw.githubusercontent.com/seerr-team/seerr/refs/heads/develop/public/logo_full.svg'; + const messages = defineMessages('notifications.agents.email', { issueType: '{type} issue', issue: 'issue', @@ -96,6 +99,12 @@ class EmailAgent const settings = getSettings(); const { applicationUrl, applicationTitle } = settings.main; const { embedPoster } = settings.notifications.agents.email; + const { usePublicLogo } = settings.notifications.agents.email.options; + const logoUrl = usePublicLogo + ? PUBLIC_LOGO_URL + : applicationUrl + ? `${applicationUrl}/logo_full.svg` + : undefined; if (type === Notification.TEST_NOTIFICATION) { return { @@ -107,6 +116,7 @@ class EmailAgent body: payload.message, applicationUrl, applicationTitle, + logoUrl, recipientName, recipientEmail, }, @@ -195,6 +205,7 @@ class EmailAgent : undefined, applicationUrl, applicationTitle, + logoUrl, recipientName, recipientEmail, }, @@ -263,6 +274,7 @@ class EmailAgent : undefined, applicationUrl, applicationTitle, + logoUrl, recipientName, recipientEmail, }, diff --git a/server/lib/settings/index.ts b/server/lib/settings/index.ts index bb287c8e0..c1124c22f 100644 --- a/server/lib/settings/index.ts +++ b/server/lib/settings/index.ts @@ -255,6 +255,7 @@ export interface NotificationAgentEmail extends NotificationAgentConfig { authPass?: string; allowSelfSigned: boolean; senderName: string; + usePublicLogo: boolean; pgpPrivateKey?: string; pgpPassword?: string; }; @@ -472,6 +473,7 @@ class Settings { requireTls: false, allowSelfSigned: false, senderName: 'Seerr', + usePublicLogo: false, }, }, discord: { diff --git a/server/templates/email/generatedpassword/html.pug b/server/templates/email/generatedpassword/html.pug index 1563c59b3..63bc51375 100644 --- a/server/templates/email/generatedpassword/html.pug +++ b/server/templates/email/generatedpassword/html.pug @@ -19,9 +19,12 @@ div(style='display: block; background-color: #111827; padding: 2.5rem 0;') table(style='margin: 0 auto; font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", Arial, sans-serif; color: #fff; font-size: 16px; width: 26rem;') tr td(style="text-align: center;") - if applicationUrl - a(href=applicationUrl style='margin: 0 1rem;') - img(src=applicationUrl +'/logo_full.png' style='width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') + if logoUrl + if applicationUrl + a(href=applicationUrl style='margin: 0 1rem;') + img(src=logoUrl style='width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') + else + img(src=logoUrl style='margin: 0 1rem; width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') else div(style='margin: 0 1rem 2.5rem; font-size: 3em; font-weight: 700;') | #{applicationTitle} diff --git a/server/templates/email/media-issue/html.pug b/server/templates/email/media-issue/html.pug index 1e34e835a..0f20e7517 100644 --- a/server/templates/email/media-issue/html.pug +++ b/server/templates/email/media-issue/html.pug @@ -19,9 +19,12 @@ div(style='display: block; background-color: #111827; padding: 2.5rem 0;') table(style='margin: 0 auto; font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", Arial, sans-serif; color: #fff; font-size: 16px; width: 26rem;') tr td(style="text-align: center;") - if applicationUrl - a(href=applicationUrl style='margin: 0 1rem;') - img(src=applicationUrl +'/logo_full.png' style='width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') + if logoUrl + if applicationUrl + a(href=applicationUrl style='margin: 0 1rem;') + img(src=logoUrl style='width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') + else + img(src=logoUrl style='margin: 0 1rem; width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') else div(style='margin: 0 1rem 2.5rem; font-size: 3em; font-weight: 700;') | #{applicationTitle} diff --git a/server/templates/email/media-request/html.pug b/server/templates/email/media-request/html.pug index bd7c9aa61..0e80287e7 100644 --- a/server/templates/email/media-request/html.pug +++ b/server/templates/email/media-request/html.pug @@ -19,9 +19,12 @@ div(style='display: block; background-color: #111827; padding: 2.5rem 0;') table(style='margin: 0 auto; font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", Arial, sans-serif; color: #fff; font-size: 16px; width: 26rem;') tr td(style="text-align: center;") - if applicationUrl - a(href=applicationUrl style='margin: 0 1rem;') - img(src=applicationUrl +'/logo_full.png' style='width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') + if logoUrl + if applicationUrl + a(href=applicationUrl style='margin: 0 1rem;') + img(src=logoUrl style='width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') + else + img(src=logoUrl style='margin: 0 1rem; width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') else div(style='margin: 0 1rem 2.5rem; font-size: 3em; font-weight: 700;') | #{applicationTitle} diff --git a/server/templates/email/resetpassword/html.pug b/server/templates/email/resetpassword/html.pug index 0b0b1fa04..e41cd6c5c 100644 --- a/server/templates/email/resetpassword/html.pug +++ b/server/templates/email/resetpassword/html.pug @@ -19,9 +19,12 @@ div(style='display: block; background-color: #111827; padding: 2.5rem 0;') table(style='margin: 0 auto; font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", Arial, sans-serif; color: #fff; font-size: 16px; width: 26rem;') tr td(style="text-align: center;") - if applicationUrl - a(href=applicationUrl style='margin: 0 1rem;') - img(src=applicationUrl +'/logo_full.png' style='width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') + if logoUrl + if applicationUrl + a(href=applicationUrl style='margin: 0 1rem;') + img(src=logoUrl style='width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') + else + img(src=logoUrl style='margin: 0 1rem; width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') else div(style='margin: 0 1rem 2.5rem; font-size: 3em; font-weight: 700;') | #{applicationTitle} @@ -46,4 +49,4 @@ div(style='display: block; background-color: #111827; padding: 2.5rem 0;') tr td(style='text-align: center;') div(style='margin: 1rem 1rem 0; font-size: 1.25em;') - | If you did not initiate this request, you may safely disregard this message. \ No newline at end of file + | If you did not initiate this request, you may safely disregard this message. diff --git a/server/templates/email/test-email/html.pug b/server/templates/email/test-email/html.pug index eb9fbe9bf..44e57f1be 100644 --- a/server/templates/email/test-email/html.pug +++ b/server/templates/email/test-email/html.pug @@ -19,9 +19,12 @@ div(style='display: block; background-color: #111827; padding: 2.5rem 0;') table(style='margin: 0 auto; font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", Arial, sans-serif; color: #fff; font-size: 16px; width: 26rem;') tr td(style="text-align: center;") - if applicationUrl - a(href=applicationUrl style='margin: 0 1rem;') - img(src=applicationUrl +'/logo_full.png' style='width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') + if logoUrl + if applicationUrl + a(href=applicationUrl style='margin: 0 1rem;') + img(src=logoUrl style='width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') + else + img(src=logoUrl style='margin: 0 1rem; width: 26rem; image-rendering: crisp-edges; image-rendering: -webkit-optimize-contrast;') else div(style='margin: 0 1rem 2.5rem; font-size: 3em; font-weight: 700;') | #{applicationTitle} diff --git a/src/components/Settings/Notifications/NotificationsEmail.tsx b/src/components/Settings/Notifications/NotificationsEmail.tsx index 077762b22..8076f510b 100644 --- a/src/components/Settings/Notifications/NotificationsEmail.tsx +++ b/src/components/Settings/Notifications/NotificationsEmail.tsx @@ -19,6 +19,9 @@ const messages = defineMessages('components.Settings.Notifications', { validationSmtpPortRequired: 'You must provide a valid port number', agentenabled: 'Enable Agent', embedPoster: 'Embed Poster', + usePublicLogo: 'Use public Seerr logo instead of instance logo', + usePublicLogoTip: + 'If your Seerr instance is not publicly accessible, enable this option so email clients outside your network can display the image. The image will be pulled from the public GitHub repository.', userEmailRequired: 'Require user email', emailsender: 'Sender Address', smtpHost: 'SMTP Host', @@ -134,6 +137,7 @@ const NotificationsEmail = () => { initialValues={{ enabled: data.enabled, embedPoster: data.embedPoster, + usePublicLogo: data.options.usePublicLogo, userEmailRequired: data.options.userEmailRequired, emailFrom: data.options.emailFrom, smtpHost: data.options.smtpHost, @@ -160,6 +164,7 @@ const NotificationsEmail = () => { embedPoster: values.embedPoster, options: { userEmailRequired: values.userEmailRequired, + usePublicLogo: values.usePublicLogo, emailFrom: values.emailFrom, smtpHost: values.smtpHost, smtpPort: Number(values.smtpPort), @@ -209,6 +214,7 @@ const NotificationsEmail = () => { enabled: true, embedPoster: values.embedPoster, options: { + usePublicLogo: values.usePublicLogo, emailFrom: values.emailFrom, smtpHost: values.smtpHost, smtpPort: Number(values.smtpPort), @@ -263,6 +269,21 @@ const NotificationsEmail = () => { +
+ +
+
+