- Add new `attribs` field to the DB.
- New `Attributes` JSON text input in the campaign editor UI.
- Introduces the new `{{ Campaign.Attribs.$key}}` syntax in campaign body.
Closes#2059
This addresses the specific security scenario described here:
https://github.com/knadh/listmonk/security/advisories/GHSA-jmr4-p576-v565
Although it cannot mitigate a lower ranking user with campaign/template
permissions adding arbitrary scripts to templates that render in various
places including the public archive page.
- Add missing zh-TW translations
- Fix zh-TW placeholder inconsistencies
- Replace Chinese placeholders {名稱} with English {name}
- Add proper spacing around placeholders for consistency
- Use Taiwan Chinese terminology in zh-TW
- Replace 文件 (China) with 檔案 (Taiwan) for 'file'
- Replace 文本編輯器 with 文字編輯器 for 'text editor'
- Ensures proper Taiwan localization throughout
- Change 'Campaigns' from 廣告 (advertisement) to 活動 (campaign/activity)
- Fix 'Opt-in to' translation to proper Chinese 訂閱
- Improve 'Publish' translation from 發送 (send) to 發布 (publish)
- Fix 'running' from 發送中 (sending) to 執行中 (running)
- Improve 'Orphans' explanation to proper Chinese
- Fix 'Blocklist' verb form to 加入黑名單
- Add missing space in subscriber count placeholder
* Add env var support for static-dir and i18n-dir flags.
LISTMONK_static_dir and LISTMONK_i18n_dir now work as environment
variables, allowing custom static file paths without modifying
the command line in docker-compose.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix env var mapping: only convert underscore to hyphen for top-level keys.
Nested config keys like db.ssl_mode keep underscores.
Top-level CLI flags like static-dir get underscore->hyphen conversion.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add a new vacuum setting option on the UI in Admin -> Settings -> Maintenance.
- Also refactor frontend (lock-and-wait-for-restart) login on settings into
the global vue instance so that it can be reused across contexts.
Settings.vue and Maintenance.vue both now use it to wait for the backend
to restart.
This patch introduces the long pending requirement of being able to send messages
to arbitrary recipients via the `/api/tx` endpoint without them having to be
subscribers in the database.
It maintains backwards compatibility and introduces just one new field,
`subscriber_mode` to the `/api/tx` endpoint.
- `default` - Recipients must exist as subscribers in the database.
Pass either `subscriber_emails` or `subscriber_ids`. |
- `fallback` - Only accepts `subscriber_emails` and looks up subscribers in the
database. If not found, sends the message to the e-mail anyway.
In the template, apart from `{{ .Subscriber.Email }}`, other
subscriber fields such as `.Name`. will be empty.
Use `{{ Tx.Data.* }}` instead. |
- `external` - Sends to the given `subscriber_emails` without subscriber lookup
in the database. In the template, apart from
`{{ .Subscriber.Email }}`, other subscriber fields such as
`.Name`. will be empty. Use `{{ Tx.Data.* }}` instead. |
- Like subscribers, select one-or more or 'all' items and delete them
on the lists and campaigns UIs.
- New `DELETE /api/lists` and `DELETE /api/campaigns` endpoints that
take one or more `id` params or a single `query` param.
This patch adds a new `status` field (active, archived) to the lists table and
an 'Archived?' toggle on the UI that allows a list to be marked as archived.
This hides the lists from the lists page, campaigns list selection, list roles,
and public forms. A new "View archived lists" link on the lists UI allows
viewing the list of archived lists.
This is useful to hide/declutter lists by archiving historical, temporary lists
etc. This is largely a UX value addition.
Closes#2613.
Prior to this patch, when a new campaign was created, the `to send` count of
subscribers was counted from the subscriptions and added to the campaign to be
displayed on the frontend. However, this had several issues:
- On large databases, the count can be extremely slow, slowing down campaign
creation.
- The count was purely cosmetic. When a campaign starts, it's recounted (for real)
anyway.
- The count was also inaccurate. Changing the list on a campaign, or changes to
the subscribers in a list never updated the count on the campaign, rendering
it wholly incorrect sometimes.
Closes#2431.
The media UI was calling getSettings(), which requires the `settings:get`
permission to get the uploader type, which creates a bad permission dependecy.
This patch removes this dependecy and instead exposes the media provider
via `/api/config` (`serverConfig` in the frontend).
Fixes#2747.