Commit graph

111 commits

Author SHA1 Message Date
Kailash Nadh 8e3e1b9af8 Change naive ILIKE search to full text (unindexed) on lists and campaigns. Closes #1058. 2022-11-27 23:01:15 +05:30
Kailash Nadh 1e90feecaf Show send_at on archive page for scheduled campaigns. Closes #1036. 2022-11-18 23:12:53 +05:30
Kailash Nadh eaaca05f36 Fix archive template selection in campaign creation query. 2022-11-10 23:30:53 +05:30
Kailash Nadh 9add728b08 WIP: Add support for publishing campaigns to publish archives. 2022-11-10 23:30:11 +05:30
Romain 6d3ae4cc73
Add subscription created_at, updated_at when listing subscribers list (#1018) 2022-11-09 21:40:11 +05:30
Kailash Nadh 879bff854e Update subscription date on public unsubscribe. Closes #915. 2022-11-01 21:46:07 +05:30
Kailash Nadh ef1f84ee7c Add new description field to lists. Closes #925. 2022-11-01 21:04:35 +05:30
Kailash Nadh 3b0083190e Add ability for subscribers to manage preferences on the unsub form.
- Ability to change name.
- Ability to unsubscribe from individual lists.
- Toggle option to enable this in Admin Settings -> Privacy.

Closes #455.
2022-10-29 15:23:28 +05:30
Kailash Nadh c38100427d Add arbitrary meta field to media. Closes #938.
- Add new `meta` JSONB field to `media` table.
- Start storing image width and height as meta with media uploads.
2022-10-02 23:04:51 +05:30
Kailash Nadh 6d820f4f6e Add maintenance options.
- Add new maintenance UI with options to garbage collect (delete)
  orphan subscriber and analytics records.
2022-09-03 14:58:25 +05:30
Kailash Nadh b497f52ae7 Merge branch 'fix-analytics' 2022-07-30 20:12:11 +05:30
Kailash Nadh bfc27def57 Fix regression of public subscriber page behaviour. 2022-07-30 20:11:59 +05:30
Kailash Nadh 3550d5453d Fix incorrect analytics count. Closes #712. 2022-07-30 19:01:20 +05:30
Kailash Nadh e99c8ed86b Disable template type updation after creation to prevent breaking of campaign relations. 2022-07-09 10:36:12 +05:30
Kailash Nadh 2dcac57cba Fix tx template delete query. 2022-07-09 10:36:12 +05:30
Kailash Nadh 463e92d1e1 Add transactional (tx) messaging capability.
This commit adds a new API `POST /api/tx` that sends an ad-hoc message
to a subscriber based on a pre-defined transactional template. This is
a large commit that adds the following:

- New campaign / tx template types on the UI. tx templates have an
  additional subject field.
- New fields `type` and `subject` to the templates table.
- Refactor template CRUD operations and models.
- Refactor template func assignment in manager.
- Add pre-compiled template caching to manager runtime.
- Pre-compile all tx templates into memory on program boot to avoid
  expensive template compilation on ad-hoc tx messages.
2022-07-09 10:36:12 +05:30
Kailash Nadh 59c9441b3b Fix subscriber create query to not ignore duplicate e-mail error.
Trying to insert a pre-existing e-mail on POST /api/subscribers
now return a 409 Conflict error.

Closes #718
2022-05-11 21:40:31 +05:30
Kailash Nadh 959541f8ee Rename unsub query to match the core method name. 2022-05-08 14:45:45 +05:30
Kailash Nadh b5cd9498b1 Refactore all CRUD functions to a new core package.
This is a long pending refactor. All the DB, query, CRUD, and related
logic scattered across HTTP handlers are now moved into a central
`core` package with clean, abstracted methods, decoupling HTTP
handlers from executing direct DB queries and other business logic.

eg: `core.CreateList()`, `core.GetLists()` etc.

- Remove obsolete subscriber methods.
- Move optin hook queries to core.
- Move campaign methods to `core`.
- Move all campaign methods to `core`.
- Move public page functions to `core`.
- Move all template functions to `core`.
- Move media and settings function to `core`.
- Move handler middleware functions to `core`.
- Move all bounce functions to `core`.
- Move all dashboard functions to `core`.
- Fix GetLists() not honouring type
- Fix unwrapped JSON responses.
- Clean up obsolete pre-core util function.
- Replace SQL array null check with cardinality check.
- Fix missing validations in `core` queries.
- Remove superfluous deps on internal `subimporter`.
- Add dashboard functions to `core`.
- Fix broken domain ban check.
- Fix broken subscriber check middleware.
- Remove redundant error handling.
- Remove obsolete functions.
- Remove obsolete structs.
- Remove obsolete queries and DB functions.
- Document the `core` package.
2022-05-03 10:50:29 +05:30
Kailash Nadh ef643a14a3 Add ability to export select subscriber ids.
- Add `id=[]` query param to `/api/subscribers/export` API.
- Add UI export prompt.
- Add Cypress tests.

Closes #739
2022-03-19 13:44:23 +05:30
Kailash Nadh 1b163d1895 Fix next-subscribers batch query for a ~210x speedup.
It was observed that the next-campaign-subscribers query on an instance
with ~9 million subscribers had slowed down significantly. Fetching
a batch of 5k subscribers was taking around ~25 seconds.

After multiple hours of debugging and trial and errors, it turned out
that Postgres was doing very poor query planning on JOINs with CTEs
because of the dynamic cardinality of some CTEs (even with just 1 row).
Afer rewriting the query and adding a hack to overcome the CTE
cardinality issue, the same query now takes a few milliseconds,
a speed up of several orders of magnitude.
2022-02-05 22:41:43 +05:30
Kailash Nadh 48ef3dcb14 Support status in bulk subscriber list update API. Closes #604. 2022-02-05 00:03:28 +05:30
Kailash Nadh da30d4688e Add subscriber status counts to the lists UI.
- Change `query-lists` query to aggregate the subscriber count by
  status (confirmed, unsubscribed etc.) and expose them under a new
  `subscriber_statuses: {}` field in the `GET /lists` API.
- Display the statuses and counts in the lists table on the UI.

Closes #616
2022-02-03 00:03:31 +05:30
Kailash Nadh 2614b072f2 Refactor campaign analytics to show unique / non-unique data.
The analytics page showed non-unique counts for views and clicks which
was misleading and source of confusion: #522, #561, #571, #676, #680
This commit changes this behaviour to pull unique views and clicks when
individual subscriber tracking is turned on in settings, and non-unique
counts when it is turned off (as `subscriber_id` in `campaign_views`
and `link_clicks` will be NULL, rendering unique queries dysfunctional).

This commit changes the stats SQL queries to use string interpolation
to either to SELECT `*` or `DISTINCT subscriber_id` on app boot based
on the setting in the DB. This involves significant changes to how
queries are read and prepared on init.

- Refactor `initQueries()` to `readQueries()` and `prepareQueries()`.
- Read queries first before preparing.
- Load settings from the DB using the read settings query.
- Prepare queries next. Use the privacy setting from the DB to apply
  string interpolation to the analytics queries to pull
  unique/non-unique before preparing the queries.

On the UI:
- Show a note on the analytics page about unique/non-unique counts.
- Hide the % donut charts on the analytics page in non-unique mode.

Closes #676, closes #680
2022-02-01 23:40:03 +05:30
Kailash Nadh d0b32b95c1 Allow unsubscribed users to re-subscribe. Closes #588 2022-01-30 23:08:39 +05:30
Kailash Nadh 583dab4bc6 Add support for per-campaign custom headers.
- Add new `headers[]` column to the campain table.
- Add new headers box to the campaign UI that takes a JSON array of
  custom headers like the headers on the SMTP settings UI.
- Headers are added to e-mails and messenger postback webhooks.
- Add cypress tests.

Closes #514.
2022-01-04 22:27:40 +05:30
Kailash Nadh ca128df49a Add support for searching lists + search UI. Closes #618. 2021-12-09 21:34:38 +05:30
Kailash Nadh 3386de40c7 Fix GET /subscribers calls not accepting multiple list_ids.
Closes #585
2021-11-29 20:38:57 +05:30
Kailash Nadh 5bfbe15c24 Fix campaign template preview not working without saving. Closes #553. 2021-10-31 11:49:43 +05:30
Kailash Nadh e0bf1f1b77 Fix broken Cypress tests.
- DOM / UI / JS spaghetti state management is just ...
2021-09-25 18:05:15 +05:30
Kailash Nadh 71fd71d18c Refactor individual subscriber edit view.
- Add route /lists/:id URI to load subscriber edit modal.
- Make list name open the edit popup to be consistent with all other
  table views.
- Refactor get-lists query to make single list look up faster.
2021-09-19 13:27:14 +05:30
Kailash Nadh 8733b205a0 Refactor SQL schema and queries for performance improvements.
- Add indexes.
- Refactor dashboard charts and view/click count queries.
  (~10x speed bump on a setup of 7mn subscribers and 80mn views)
- Refactor get subscriber queries.
  (~10x speed bump on 7mn subscribers)
- Make subscriber UI issue an equality query for email seach strings.
2021-09-18 17:25:08 +05:30
Kailash Nadh 9302dfbd56 Add missing id (pkey) to analytics tables for faster queries 2021-09-17 20:11:45 +05:30
Kailash Nadh 3d0031b207 Add campaign analytics APIs and UI 2021-09-17 18:45:35 +05:30
Kailash Nadh 158ea9fad2 Fix bounce action only triggering on n+1st bounce. 2021-08-22 15:42:54 +05:30
Kailash Nadh 1ae98699e7 Add support for bounce processing.
- Blocklist or unsubscribe subscribers based on a bounce threshold
- Add /bounces UI for viewing bounces and in the subscriber view
- Add settings UI for managing bounce settings
- Add support for scanning POP3 bounce mailboxes
- Add a generic webhook for posting custom bounces at /webhooks/bounce
- Add SES bounce webhook support at /webhooks/services/ses
- Add Sendgrid bounce webhook support at /webhooks/services/sendgrid
2021-08-14 15:35:29 +05:30
Kailash Nadh e6566189ed Add preconfirm_subscriptions to subscriber update. Closes #426. 2021-08-02 19:23:46 +05:30
Kailash Nadh fb48477aa7 Fix SQL expressions breaking subscriber export. Closes #408 2021-07-25 22:42:54 +05:30
Kailash Nadh 868fae6ac2 Refactor subsbscription status option on the import page.
- Refactor subimporter New*() funcs to take opt structs.
- Refactor and simplify Vue code.
- Remove redundant i18n entries and use existing ones.
- Remove redundant subimporter constants and use existing ones.

- Consider 'overwrite' option for subscription status as well.
- Write Cypress integration tests for the new feature.
2021-06-06 17:33:23 +05:30
Russ Smith 7ca08f0a36 Adding a subscription status option to the import.
Ref #168
2021-06-06 17:33:23 +05:30
Kailash Nadh 3d26366620 Fix pagination query.
- Fix '?per_page=all' not working inconditional LIMIT queries.
- Fetch all lists on the UI for list dropdowns everywhere.
2021-06-04 19:47:55 +05:30
Kailash Nadh ad0a0e0841 Add preconfirm_subscriptions=true/falsenew subs API.
Sending th optional flag as `trunue` in the POST /api/subscrirs
body will skip sending opt-iconfirmation e-mails to subscribers
and mark list subscriptions in the request a`confirmed`.
2021-04-17 13:34:37 +05:30
Kailash Nadh 708d0e0b00 Fix re-submission of public form e-mails not registering 2021-04-15 21:53:36 +05:30
Kailash Nadh e8ad7a9adc Fix subscriber attribs update API.
Change the behaviour where not passing attribs to the update API
overwrites the attribs with empty values. This commit changes the
behaviour so that in the absence of the attribs field in the
subscriber API, the existing value in the DB is retained.
2021-03-10 21:20:26 +05:30
Kailash Nadh 2f6bd05ca0 Fix the optin-in, form re-subscribe behaviour.
If a user is already subscribed to an optin list but hasn't
confirmed, subscribing using the same e-mail id from the public
form now re-sends the optin e-mail while also showing an
appropriate message on the frontend rather than just saying
"subscribed successfully".

https://github.com/knadh/listmonk/issues/266
https://github.com/knadh/listmonk/issues/264
2021-02-13 17:55:10 +05:30
Kailash Nadh 2235d30063 Add a new public page for end users to subscribe to public lists.
In addition to generating HTML forms for selected public lists,
the form page now shows a URL (/subscription/form) that can be
publicly shared to solicit subscriptions. The page lists all
public lists in the database. This page can be disabled on the
Settings UI.
2021-01-31 16:19:39 +05:30
Kailash Nadh 68afd61024 Add support for alternate plaintext body for e-mails.
This commit removes the Go html2text lib that would automatically
convert all HTML messages to plaintext and add them as the alt
text body to outgoing e-mails. This lib also had memory leak
issues with certain kinds of HTML templates.

A new UI field for optionally adding an alt plaintext body to
a campaign is added. On enabling, it converts the HTML message in
the campaign editor into plaintext (using the textversionjs lib).

This introduces breaking changes in the campaigns table schema,
model, and template compilation.
2021-01-30 18:49:47 +05:30
Kailash Nadh ec1c4f30ed Add subscriber export feature 2021-01-23 18:23:29 +05:30
Kailash Nadh 62182ab979 Refactor get-lists query for speed 2020-11-21 17:29:24 +05:30
Kailash Nadh 684c64ced1 Fix SQL ORDER BY compatibility issue in Postgres 12/13.
- Fix for `pq: SELECT DISTINCT ON expressions must match
  initial ORDER BY expressions` in Postgres 13.
2020-11-08 16:02:11 +05:30