From 652b2097add2710a85616b5c2af5ac65a7c72518 Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Tue, 17 Feb 2026 12:31:20 +0100 Subject: [PATCH 1/5] Translated using Weblate (Hebrew) Currently translated at 17.4% (71 of 407 strings) Translation: ntfy/Web app Translate-URL: https://hosted.weblate.org/projects/ntfy/web/he/ --- web/public/static/langs/he.json | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/web/public/static/langs/he.json b/web/public/static/langs/he.json index 4674c993..9e46e071 100644 --- a/web/public/static/langs/he.json +++ b/web/public/static/langs/he.json @@ -48,5 +48,26 @@ "notifications_none_for_topic_title": "לא קיבלת התראות בנושא הזה עדיין.", "notifications_none_for_topic_description": "כדי לשלוח התראות לנושא הזה, צריך לשלוח PUT או POST לכתובת הנושא הזה.", "notifications_none_for_any_title": "לא קיבלת התראות כלל.", - "notifications_no_subscriptions_title": "נראה שלא נרשמת למינויים עדיין." + "notifications_no_subscriptions_title": "נראה שלא נרשמת למינויים עדיין.", + "action_bar_toggle_mute": "השתקת/הפעלת התראות", + "action_bar_toggle_action_menu": "פתיחת/סגירת תפריט הפעולות", + "action_bar_profile_title": "פרופיל", + "action_bar_profile_settings": "הגדרות", + "action_bar_profile_logout": "יציאה", + "action_bar_sign_in": "כניסה", + "action_bar_sign_up": "הרשמה", + "message_bar_type_message": "כאן ניתן להקליד הודעה", + "message_bar_error_publishing": "שגיאה בפרסום ההתראה", + "message_bar_show_dialog": "הצגת חלונית פרסום", + "message_bar_publish": "פרסום הודעה", + "nav_topics_title": "נושאים שנרשמת אליהם", + "nav_button_all_notifications": "כל ההתראות", + "nav_button_account": "חשבון", + "nav_button_settings": "הגדרות", + "nav_button_documentation": "תיעוד", + "nav_button_publish_message": "פרסום התראה", + "nav_button_subscribe": "הרשמה לנושא", + "nav_button_muted": "התראות הושתקו", + "nav_button_connecting": "מתחבר", + "nav_upgrade_banner_label": "שדרוג ל־ntfy Pro" } From 046c0e8c793f1d00356254afa13732ce230af2ca Mon Sep 17 00:00:00 2001 From: Benjamin Kenawell Date: Wed, 18 Feb 2026 08:07:08 -0500 Subject: [PATCH 2/5] Add comment for zsh users in the terminal example Bash and Zsh terminals' history works slightly different. In bash, the current command is in the history already. In zsh, the history command does not have the currently running command in it. But it does set the HISTCMD variable to the entry number for the current command. So we can load the current command with `history "$HISTCMD"` in zsh and apply the same sed filter to get the same result as the bash `history | tail -n1` command. I think it makes more sense to leave this as a comment in the current example than to create a new example, since it otherwise works the exact same. I've added this to my workflow locally! --- docs/examples.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/examples.md b/docs/examples.md index 10bb014a..ee1de244 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -661,6 +661,8 @@ Add the following function and alias to your `.bashrc` or `.bash_profile`: local token=$(< ~/.ntfy_token) # Securely read the token local status_icon="$([ $exit_status -eq 0 ] && echo magic_wand || echo warning)" local last_command=$(history | tail -n1 | sed -e 's/^[[:space:]]*[0-9]\{1,\}[[:space:]]*//' -e 's/[;&|][[:space:]]*alert$//') + # for zsh users, use the same sed pattern but get the history differently. + # local last_command=$(history "$HISTCMD" | sed -e 's/^[[:space:]]*[0-9]\{1,\}[[:space:]]*//' -e 's/[;&|][[:space:]]*alert$//') curl -s -X POST "https://n.example.dev/alerts" \ -H "Authorization: Bearer $token" \ @@ -692,4 +694,4 @@ To test failure notifications: false; alert # Always fails (exit 1) ls --invalid; alert # Invalid option cat nonexistent_file; alert # File not found -``` \ No newline at end of file +``` From 28e85df36e10abc5d0b86fc98522724754ec81b1 Mon Sep 17 00:00:00 2001 From: PanderMusubi Date: Thu, 19 Feb 2026 15:47:49 +0100 Subject: [PATCH 3/5] add zabbix-ntfy to intergration doc --- docs/integrations.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/integrations.md b/docs/integrations.md index dd9b897f..a5a22530 100644 --- a/docs/integrations.md +++ b/docs/integrations.md @@ -185,6 +185,7 @@ I've added a ⭐ to projects or posts that have a significant following, or had - [Uptime Monitor](https://uptime-monitor.org) - Self-hosted, enterprise-grade uptime monitoring and alerting system (TS) - [send_to_ntfy_extension](https://github.com/TheDuffman85/send_to_ntfy_extension/) ⭐ - A browser extension to send the notifications to ntfy (JS) - [SIA-Server](https://github.com/ZebMcKayhan/SIA-Server) - A light weight, self-hosted notification Server for Honywell Galaxy Flex alarm systems (Python) +- [zabbix-ntfy](https://github.com/torgrimt/zabbix-ntfy) - Zabbix server Mediatype to add support for ntfy.sh services ## Blog + forum posts From 2e499389fc7068d73b8249d97ee7e28c6b2a86c6 Mon Sep 17 00:00:00 2001 From: Ivan Uzkikh Date: Sat, 21 Feb 2026 00:57:04 +0100 Subject: [PATCH 4/5] fix(smtp): preserve
line breaks in HTML emails HTML-only emails (e.g. from Synology DSM 7.3 Task Scheduler) use
tags for line breaks. The existing implementation passed the raw HTML body to bluemonday with AddSpaceWhenStrippingTag(true), which replaced every tag including
with a space, causing all content to appear on a single unreadable line. Fix: convert
tags to newlines before stripping HTML, so line break semantics are preserved in the notification body. Resolves the gap noted in #690 ("very sub-par" HTML support). --- server/smtp_server.go | 4 ++++ server/smtp_server_test.go | 41 ++++++++++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/server/smtp_server.go b/server/smtp_server.go index ee28efc2..02414d3b 100644 --- a/server/smtp_server.go +++ b/server/smtp_server.go @@ -33,6 +33,7 @@ var ( var ( onlySpacesRegex = regexp.MustCompile(`(?m)^\s+$`) consecutiveNewLinesRegex = regexp.MustCompile(`\n{3,}`) + htmlLineBreakRegex = regexp.MustCompile(`(?i)`) ) const ( @@ -327,6 +328,9 @@ func readHTMLMailBody(reader io.Reader, transferEncoding string) (string, error) if err != nil { return "", err } + // Convert
tags to newlines before stripping HTML, so that line breaks + // in HTML emails (e.g. from Synology DSM, and other appliances) are preserved. + body = htmlLineBreakRegex.ReplaceAllString(body, "\n") stripped := bluemonday. StrictPolicy(). AddSpaceWhenStrippingTag(true). diff --git a/server/smtp_server_test.go b/server/smtp_server_test.go index d4178a40..8b614819 100644 --- a/server/smtp_server_test.go +++ b/server/smtp_server_test.go @@ -694,7 +694,8 @@ home automation setup Now the light is on If you don't want to receive this message anymore, stop the push - services in your FRITZ!Box . + services in your FRITZ!Box . + Here you can see the active push services: "System > Push Service". This mail has ben sent by your FRITZ!Box automatically.` @@ -1354,9 +1355,11 @@ Congratulations! You have successfully set up the email notification on Synology s, c, conf, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) { require.Equal(t, "/synology", r.URL.Path) require.Equal(t, "[Synology NAS] Test Message from Litts_NAS", r.Header.Get("Title")) - actual := readAll(t, r.Body) - expected := `Congratulations! You have successfully set up the email notification on Synology_NAS. For further system configurations, please visit http://192.168.1.28:5000/, http://172.16.60.5:5000/. (If you cannot connect to the server, please contact the administrator.) From Synology_NAS` - require.Equal(t, expected, actual) + expected := "Congratulations! You have successfully set up the email notification on Synology_NAS.\n" + + "For further system configurations, please visit http://192.168.1.28:5000/, http://172.16.60.5:5000/.\n" + + "(If you cannot connect to the server, please contact the administrator.)\n\n" + + "From Synology_NAS" + require.Equal(t, expected, readAll(t, r.Body)) }) conf.SMTPServerDomain = "mydomain.me" conf.SMTPServerAddrPrefix = "" @@ -1365,6 +1368,36 @@ Congratulations! You have successfully set up the email notification on Synology writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued") } +func TestSmtpBackend_HTMLEmail_BrTagsPreserved(t *testing.T) { + email := `EHLO example.com +MAIL FROM: nas@example.com +RCPT TO: ntfy-alerts@ntfy.sh +DATA +Content-Type: text/html; charset=utf-8 +Content-Transfer-Encoding: 8bit +Subject: Task Scheduler: daily-backup + +Task Scheduler has completed a scheduled task.

Task: daily-backup
Start time: Mon, 01 Jan 2026 02:00:00 +0000
Stop time: Mon, 01 Jan 2024 02:03:00 +0000
Current status: 0 (Normal)
Standard output/error:
OK

From MyNAS +. +` + s, c, _, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) { + require.Equal(t, "/alerts", r.URL.Path) + require.Equal(t, "Task Scheduler: daily-backup", r.Header.Get("Title")) + expected := "Task Scheduler has completed a scheduled task.\n\n" + + "Task: daily-backup\n" + + "Start time: Mon, 01 Jan 2026 02:00:00 +0000\n" + + "Stop time: Mon, 01 Jan 2024 02:03:00 +0000\n" + + "Current status: 0 (Normal)\n" + + "Standard output/error:\n" + + "OK\n\n" + + "From MyNAS" + require.Equal(t, expected, readAll(t, r.Body)) + }) + defer s.Close() + defer c.Close() + writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued") +} + func TestSmtpBackend_PlaintextWithToken(t *testing.T) { email := `EHLO example.com MAIL FROM: phil@example.com From 4e22e7f4c80bf3c40a25772b70d2baa7af2c0d50 Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Sat, 21 Feb 2026 09:58:52 -0500 Subject: [PATCH 5/5] Release notes --- docs/releases.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/releases.md b/docs/releases.md index f291bea2..919b75b7 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1698,6 +1698,12 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release ## Not released yet +### ntfy server v2.18.x (UNRELEASED) + +**Bug fixes + maintenance:** + +* Preserve `
` line breaks in HTML-only emails received via SMTP ([#690](https://github.com/binwiederhier/ntfy/issues/690), [#1620](https://github.com/binwiederhier/ntfy/pull/1620), thanks to [@uzkikh](https://github.com/uzkikh) for the fix and to [@teastrainer](https://github.com/teastrainer) for reporting) + ### ntfy Android v1.23.x (UNRELEASED) **Features:**