Commit graph

162 commits

Author SHA1 Message Date
Kailash Nadh 13068ccce2 Fix broken bulk subscriber query. Closes #897. 2022-08-26 16:49:58 +05:30
Kailash Nadh bbbf28c5ce Create default tx template on upgrade. 2022-07-30 22:37:05 +05:30
Kailash Nadh bfc27def57 Fix regression of public subscriber page behaviour. 2022-07-30 20:11:59 +05:30
Kailash Nadh c84837f8cb Fix '&amp' encoding in tracked URLs before saving in the DB. Closes #844. 2022-07-11 23:18:08 +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 4de5d53fe4 Refactor upgrade schema to remove column default. 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 d3774d606a Make tx DB upgrade schema consistent with install schema. 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
Joe Paul 175770d8b8 fix: Use list append instead of indexing 2022-06-27 16:14:46 +05:30
Joe Paul a1df02b41c feat(postback): Add attachment, from email to postback body 2022-06-27 15:47:38 +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 fe5466dfda Remove test files committed accidentaly. 2022-05-10 11:00:45 +05:30
Kailash Nadh 959541f8ee Rename unsub query to match the core method name. 2022-05-08 14:45:45 +05:30
Kailash Nadh b94da621d7 Fix broken public link redirect. 2022-05-05 18:05:13 +05:30
Kailash Nadh 5fd4d7b44b Refactor paginated bounce query function to return DB total. 2022-05-03 10:50:33 +05:30
Kailash Nadh d2ef23d3fa Refactor paginated campaign query function to return DB total. 2022-05-03 10:50:33 +05:30
Kailash Nadh e303850584 Refactor paginated list query function to return DB total. 2022-05-03 10:50:33 +05:30
Kailash Nadh aa19771307 Refactor bounces package to remove db/queries dependency.
Instead of passing a DB/SQL statement references, instead pass a
callback that inserts a bounce into the DB via the `core` package.
2022-05-03 10:50:33 +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 89eca5f14b Changed email subject template from HTML to text. Fixes #785. 2022-05-03 10:41:46 +05:30
Kailash Nadh 7ea523db37
Merge pull request #727 from yatish27/fix_typos_in_comments
Fix typos
2022-04-03 11:39:07 +05:30
Kailash Nadh 73e4c1cf28 Fix POP mail parsing in multipart bounce e-mails.
This was originally authored by @stevesavanna in #707. This commit
contains changes and refactors that could not be pushed to the original PR.

Changes from #707

- Don't ignore bounce mails missing campaign / subscriber UUIDs. The
  original behaviour falls back to looking up subscribers by e-mail.
- Refactor repetetive header.get + regexp conditions per header into
  a simpler lookup map.
- Trim e-mail header values of `\r`.

Closes #707, #763

Co-authored-by: stevesavanna <steven@savannacorp.com>
2022-04-03 11:37:11 +05:30
Yatish Mehta 26483334c5 Fix typos 2022-03-20 11:17:29 -07:00
Gokul Menon 04c4552a9c Fixed typos 2022-02-28 14:19:50 +01:00
Kailash Nadh caa27f30cf
Merge pull request #699 from yatish27/fix_typos
Fix typos
2022-02-16 20:04:03 +05:30
Yatish Mehta 6c903239dd Fix typos 2022-02-13 08:54:39 -08:00
Yatish Mehta dc4e3a6780
Fix typo in manager.go 2022-02-12 23:03:41 -08:00
Kailash Nadh 0f6a0376da Add accurate realtime message rate counter.
The `rate` field `/api/campaigns/running/stats` returned was computed
based on the total time spent from the start of the campaign to the
current time. This meant that for large campaigns, if there were
pauses or slowdowns in between, the rate would be skewed heavily
making it useless to figure out the current send rate.

This commit introduces a realtime running rate counter in the campaign
manager that returns accurate (running) send rates for the last minute.

The `rate` field in the API now shows the live running rate and a
new `net_rate` field shows the rate from the beginning of the campaign.
2022-02-06 11:38:02 +05:30
Kailash Nadh 64d2c5aeb9 Add support for custom public S3 URLs. Closes #505. 2022-01-15 21:20:32 +05:30
Kailash Nadh 7955a4fa27 Fix media upload S3 IAM init blocking outside non-AWS environments.
- Update `simples3` to a version that supports IAM timeout.
- On IAM error, fall back to key/secret mode (although with empty creds)
  so that the app still starts.
2022-01-15 20:45:17 +05:30
Kailash Nadh e200ab0dab Add support for additional POP3 mail charsets. Closes #644. 2022-01-04 22:46:42 +05:30
Kailash Nadh e1d3dd4a65 Merge branch 'master' of github.com:knadh/listmonk 2022-01-04 22:33:58 +05:30
Kailash Nadh d8ed40422e Make tls_enabled key migratin idempotent. 2022-01-04 22:30:43 +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 dd061f56d4 Add support for direct SSL/TLS (non-STARTTLS) SMTP connections.
- Add support for TLS in `smtppool` (v0.4.0) and upgrade the lib.
- Change `tls_enabled: bool` in the settings table to string
  `tls_type: STARTTLS|TLS|none` and on the settings UI.
- Add DB migrations and schema changes to apply the field change.

Closes #504.
2022-01-03 19:28:36 +05:30
Rohan c003aec9c9 feat: switch from s3 POST to s3 put
This commit switches simples3 from issuing a POST to a PUT.

Ref #617
2021-12-29 15:13:23 +05:30
Kailash Nadh fabe06e339 Add support for custom CSS/JS in settings for admin and public pages.
This feature was originally authored by @sweetppro in PR #438.
However, since the PR ended up in an unclean state with
multiple master merges (instead of rebase) from the upstream, there are
several commits that are out of order and can can no longer be be
squashed for a clean feature merge.

This commit aggregates the changes from the original PR and applies the
following fixes on top of it.

- Add custom admin JS box to appearance UI.
- Refactor i18n language strings.
- Add handlers and migrations for the new `appearance.admin.custom_js`
  field.
- Fix migration version to `v2.1.0`
- Load custom appearance CSS/JS bytes into global constants during boot
  instead of making a DB call on every request.
- Fix and canonicalize URIs from `/api/custom*` to `/public/*.css`
  and `/admin/*.css`. Add proxy paths to yarn proxy config.
- Remove redundant HTTP handlers for different custom appearance files
  and refactor into a single handler `serveCustomApperance()`
- Fix content-type and UTF8 encoding headers for different file types.
- Fix incorrect registration of public facing custom CSS/JS handlers
  in the authenticated admin URI group.
- Fix merge conflicts in `Settings.vue`.
- Minor HTML and style fixes.
- Remove the `AppearanceEditor` component and use the existing
  `HTMLEditor` component instead.
- Add `language` prop to the `HTMLEditor` component.

Co-authored-by: SweetPPro <sweetppro@users.noreply.github.com>
2021-12-18 15:38:42 +05:30
Kailash Nadh 4cb5eb782f Fix settings form input validation.
- Fix settings UI form submit button.
- Validate upload URI. Closes #621.
2021-12-09 19:30:15 +05:30
Kailash Nadh a7fa97a214 Add scanning of full bounce email body for bounce headers. Closes #492. 2021-11-10 20:47:55 +05:30
Kailash Nadh 11010393d8 Add "passive" mode with --passive flag.
Every listmonk instance scans the DB periodically to look for
running campaigns to process. This made running multiple instances of
listmonk impractical as they would all pick up the same running
campaign and process them, resulting in duplicate e-mails.

This commit adds a `--passive` flag to the binary that runs listmonk
in a "passive" mode where campaign processing is disabled. This allows
multiple instances of listmonk to be run to handle different kinds of
requests if there is a requirement (scale/traffic?). It is important
to note that there should only be one non-passive instance running at
any given time. If distributed campaign processing is ever considered,
this will change.
2021-10-29 14:40:22 +05:30
Kailash Nadh b46ab6d3a9 Fallback to default S3 URL on empty media upload URL in settings. 2021-10-04 22:20:24 +05:30
Kailash Nadh 7aa850824c Add explicit public-read ACL to public S3 uploads. Closes #496. 2021-10-02 17:12:31 +05:30
Kailash Nadh 3ffd88f0df Remove obsolete bounce routines from manager package. 2021-09-26 18:57:25 +05:30
Kailash Nadh 7aee36eab1 Add support for blocklisting e-mail domains.
E-mails in the domain blocklist are disallowed on the admin UI, public
subscription forms, API, and in the bulk importer.

- Add blocklist setting that takes a list of multi-line domains on the
  Settings -> Privacy UI.
- Refactor e-mail validation in subimporter to add blocklist checking
  centrally.
- Add Cypress testr testing domain blocklist behaviour on admin
  and non-admin views.

Closes #336.
2021-09-25 15:39:09 +05:30
Kailash Nadh e71115db26 Add option to toggle sending opt-in confirmation. Closes #363. 2021-09-25 10:38:13 +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 fd8f5a96c9 Add missing bounce_type to v2 migration. 2021-09-17 20:18:53 +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 81d183b808 Fix incorrect date in bounce insert 2021-08-22 15:46:37 +05:30
Kailash Nadh d6d1883587 Add custom S3 backend support (eg: Minio) to media uploads
- Introduce a new S3 backend URL on the settings UI
- Add DB migration to populate S3 URL for existing S3 settings
- Refactor and fix URL formatting

Closes #139
2021-08-15 16:09:00 +05:30
Kailash Nadh 923b882f05 Add migration to remove obsolete subscribers.campaigns field 2021-08-14 17:23:05 +05:30
Kailash Nadh cce5cff539 Fix bounce upgrade schema 2021-08-14 17:00:11 +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 5988ea36cb Sanitize media upload filenames. Closes #397. 2021-06-19 17:11:27 +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 931e467b25 Fixes campaign test messages not including unsub headers.
Campaign messages are handled by `manager` whereas test messages
were being pushed directly into a messenger skipping some campaign
related routines such as the addition of list unsub headers.

This commit exposes a new function `manager.PushCampaignMessage()`
that accepts arbitrary campaign messages that then pass through
the standard campaign message workers, thus getting the missing unsub
headers. This closes #360.

In addition, this removes the superfluous `CampaignMessage.Render()`
function which had to be mandatorily called always and makes it
implicit in `manager.NewCampaignMessage()`.
2021-05-21 23:35:08 +05:30
Kailash Nadh 95a81d17ce Add option on UI to toggle update checks.
Closes #326
2021-05-16 16:54: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 1e59d53135 Add markdown support to campaign content. 2021-04-14 12:26:09 +05:30
Tamal Saha 40aaa2694d Use github.com/Masterminds/sprig/v3
Signed-off-by: Tamal Saha <tamal@appscode.com>
2021-04-11 03:00:48 -07:00
Tamal Saha b060c751ce Bundle sprig template functions
Signed-off-by: Tamal Saha <tamal@appscode.com>
2021-04-11 15:07:10 +05:30
TomBoss 50549f3bfe
Adding Safe templating function for keeping HTML comment
Closes #270
According to https://stackoverflow.com/questions/34348072/go-html-comments-are-not-rendered
2021-02-15 13:33:47 +01:00
Kailash Nadh b6dcf2c841 Merge branch 'i18n' 2021-02-07 12:06:06 +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
Joe Paul 8867f771d4 fix: Stop tickers 2021-01-27 12:58:17 +05:30
Kailash Nadh 4bfdda9b91 Load a default (en) language underneath the selected language.
The default language (en) is loaded first and the selected
language is loaded on top of it so that missing translation keys
in the selected language will have the original English strings
available on the UI.
2021-01-26 21:59:27 +05:30
Kailash Nadh 05928d57b1 Fix default campaign template not being setup on first install.
This was a ridiculous miss, where on first time installation, the
well designed default e-mail template was never installed in the
DB! I never spotted this because my local dev setup, and
surprisingly, nobody ever complained that the default campaign
template was a blank slate with no styles.
2021-01-24 12:49:52 +05:30
Kailash Nadh 027261793f Add support for rate limiting messages with a sliding window.
Certain SMTP hosts limit the total number of messages that can be
sent within a window, for instance, X / 24 hours. The concurrency
and message rate controls can only limit that to a max of
1 messages / second, without a global cap.

This commit introduces a simple sliding window rate limit feature
that counts the number of messages sent in a specific window, and
upon reaching that limit, waits for the window to reset before
any more messages are pushed out globally across any number of
campaigns.

Context: https://github.com/knadh/listmonk/issues/119
2021-01-24 12:19:26 +05:30
Kailash Nadh ee4fb7182f Refactor i18n name and fix the L() function in public HTML templates 2021-01-23 19:34:30 +05:30
Kailash Nadh 4cd5e6ebeb Refactor and remove placeholder i18n func 2021-01-23 18:54:33 +05:30
Kailash Nadh 3498a727f5 WIP: Add i18n support 2021-01-17 20:59:01 +05:30
Kailash Nadh a0b36bb01b Log subscriber UUID in message send errors 2020-10-24 14:24:22 +05:30
Kailash Nadh a1aeba22bb Fix invalid link click registrations
The link_clicks.link_id table was NULLable incorrectly. Links that
do not exist should not register a tracking entry. Fix the query
and also update the schema + migration (breaking table change).
2020-10-24 14:03:37 +05:30
Kailash Nadh 966954d8f4 Refactor log view UI into a component. 2020-10-24 11:42:28 +05:30
Kailash Nadh 2e361c7371 Add v0.8.0 DB migrations. 2020-10-18 21:10:47 +05:30
Kailash Nadh 1b279478fb Make individual subscriber tracking optional.
A new toggle switch in Settings -> Privacy, which is off by
default, allows campaign views (pixel) and link clicks to function
without registering the subscriber ID against view and click
events, anonymising tracking. When off, the subscriber UUIDs in
view and link tracking URLs are removed, anonymising subscriber
information from HTTP logs as well.
2020-10-18 17:49:46 +05:30
Vivek R 86c618981f fix: use mail.ParseAddress to validate email instead of custom regex
According to [RFC6532](https://tools.ietf.org/html/rfc6532) unicode characters are supported in email address but the in-built custom regex was only validating ASCII characters.
2020-10-16 01:06:18 +05:30
Kailash Nadh 8dbe30cd26 Add new 'Logs' page to the UI to view stdout logs 2020-10-10 23:55:54 +05:30
Kailash Nadh 6cf43ea674 Add generic HTTP postback Messenger support.
This is a major feature that builds upon the `Messenger` interface
that has been in listmonk since its inception (with SMTP as the only
messenger). This commit introduces a new Messenger implementation, an
HTTP "postback", that can post campaign messages as a standard JSON
payload to arbitrary HTTP servers. These servers can in turn push them
to FCM, SMS, or any or any such upstream, enabling listmonk to be a
generic campaign messenger for any type of communication, not just
e-mails.

Postback HTTP endpoints can be defined in settings and they can be
selected on campaigns.
2020-10-10 18:52:08 +05:30
Kailash Nadh b822955ac9 Add BasicAuth to admin endpoints.
This removes the Nginx dependency for protecting admin pages.
BasicAuth is configured in config.toml. This is a "temporary"
setup until a full fledged auth mechanism is added.
2020-08-08 13:11:49 +05:30
Kailash Nadh 7ed07550ff Fix minor inconsistencies in settings.
- Add missing `app.root_url` key in migration.
- Register `/settings` handler in the backend.
- Add dummy dots in secret fields on the UI for visibility.
2020-08-07 19:28:23 +05:30
Kailash Nadh 5fb7c6cfb0 Add support for automatic, idempotent DB migrations
- On boot, the app now checks if the DB version matches its
  expected version and refuses to start if there are pending
  migrations to be run.
- The new `--upgrade` flag runs data migrations from the last
  recorded migration (in the settings table) to the latest one
  in the binary.
- Migrations are DB/arbitrary logic functions in .go files in
  internal/migrations.
- All migration functions are idempotent.
2020-08-03 19:02:23 +05:30
Kailash Nadh ec097909db Add support for List-Unsubscribe header.
- Added as a setting in the settings UI.
- Refactor Messenger.Push() method to accept messenger.Message{}
  instead of a growing number of positional arguments.
2020-08-01 17:54:51 +05:30
Kailash Nadh 8c0804ba9f Refactor blacklist to blocklist 2020-08-01 16:45:29 +05:30
Kailash Nadh 942eb7c3d8 Add settings UI and "hot reload" support to the app.
This is a major breaking change that moves away from having the
entire app configuration in external TOML files to settings being
in the database with a UI to update them dynamically.

The app loads all config into memory (app settings, SMTP conf)
on boot. "Hot" replacing them is complex and it's a fair tradeoff
to instead just restart the application as it is practically
instant.

A new `settings` table stores arbitrary string keys with a JSONB
value field which happens to support arbitrary types. After every
settings update, the app gracefully releases all resources
(HTTP server, DB pool, SMTP pool etc.) and restarts itself,
occupying the same PID. If there are any running campaigns, the
auto-restart doesn't happen and the user is prompted to invoke
it manually with a one-click button once all running campaigns
have been paused.
2020-07-21 00:23:57 +05:30
Kailash Nadh c2613d1030 Fix ticker leak in campaign manager message push 2020-07-06 20:29:19 +05:30
Kailash Nadh fd044f4cb6 Minor refactor to campaign manager.
- Remove external invocation of worker goroutines into Run()
- Split Run() into smaller functions.
2020-07-06 20:22:57 +05:30
Kailash Nadh 61f8fae50d Add 'overwrite?' option to bulk import.
- Fix minor UI inconsitency on import states.
- Minor refactor to importer initialisation.
2020-07-05 21:35:17 +05:30
Kailash Nadh 79dd916d09 Make DB pull batch size in campaign manager configurable 2020-07-05 19:48:39 +05:30
Kailash Nadh b45a2a0f89 Fix incorrect record count in the importer 2020-07-05 19:39:42 +05:30
Kailash Nadh 64d44707c2 Add {{ templating }} support to e-mail subjects 2020-07-05 18:39:24 +05:30
Kailash Nadh 24192a327f Refactor and fix media uploads.
- Fix path related issues in filesystem and S3.
- Add checks for S3 "/" path prefix.
- Add support for custom S3 domain names.
- Remove obsolete `width` and `height` columns from media table (breaking)
- Add `provider` field to media table (breaking)
2020-07-05 17:35:05 +05:30
Kailash Nadh 7a467a5a3b Add support for custom e-mail headers per SMTP server 2020-05-31 21:16:56 +05:30
Kailash Nadh 18329ff052 Add TLS to SMTP config 2020-05-17 21:07:48 +05:30
Kailash Nadh abddcb9a03 Remove redundant SMTP LOGIN auth implementation 2020-05-16 23:38:19 +05:30
Kailash Nadh 9d3ca357f6 Integrate new SMTP pool lib 2020-05-16 23:25:37 +05:30
Kailash Nadh e58b2fa669 Fix typo 2020-05-11 21:00:06 +05:30