CHANGELOG.md
Rama main · réplica de lectura del repositorio original.
# Changelog
## Unreleased
## Version 0.40.2
> 🔒 Updated dependencies to address security advisories. Updating is recommended for all instances.
### Breaking Changes
- Unsubscribe links without a signature, which were used by Keila before v0.11.0, are no
longer supported
### Security
- Updated dependencies to address high-severity CVEs:
Bandit ([CVE-2026-116078](https://osv.dev/vulnerability/EEF-CVE-2026-116078)),
`phx_html` ([CVE-2026-117645](https://osv.dev/vulnerability/EEF-CVE-2026-117645)),
and `ssl_verify_fun` ([CVE-2026-117666](https://osv.dev/vulnerability/EEF-CVE-2026-117666))
- Changing the password now signs out all other sessions
### Changed
- API endpoints now limit page size to 1,000 entries
## Version 0.40.1
> 🔒 Fixes for several stored cross-site scripting vulnerabilities. Updating is recommended for all instances that allow untrusted users.
### Security
- Fixed several stored cross-site scripting vulnerabilities in forms and campaigns
- HMAC signatures of unsubscribe, double opt-in, and tracking links are now compared in constant time
### Added
- New error pages for 404 and 500 errors
### Improved
- Links in email previews now open in a new tab instead of navigating the preview
### Fixed
- Requests for missing entities (e.g. campaigns, contacts, forms) or user-facing links (e.g. unsubscribe or
double opt-in links with incorrect IDs or invalid signatures) now show the 404 page instead of an internal
server error
## Version 0.40.0
> 🇸🇪 Fully editable welcome and double opt-in emails, sortable form fields, Elixir 1.20, and a new Swedish translation
### Breaking Changes
- Keila now requires PostgreSQL 14 or newer
- The system mailer no longer uses opportunistic TLS. When `MAILER_SMTP_TLS_MODE` is unset or `auto`,
STARTTLS is now required on all ports except 465, where TLS is required. Set `MAILER_SMTP_TLS_MODE=none`
to disable TLS explicitly.
- Project SMTP senders now require an explicit TLS mode. Existing senders without one continue to work, but a
TLS mode must be selected when they are edited.
- Welcome and double opt-in emails of forms have moved to the new `welcome_email` and `double_opt_in_email`
objects in the forms API. The `template_id` property and the `settings.welcome_subject`,
`settings.welcome_markdown_body`, `settings.double_opt_in_subject`, and
`settings.double_opt_in_markdown_body` properties have been removed. Existing welcome and double opt-in
emails are migrated automatically.
### Security
- The Docker image is now based on Elixir 1.20 and Erlang/OTP 29, which includes fixes for several security
advisories in Erlang/OTP, among them two critical TLS certificate verification bypasses
- Updated dependencies to address further security advisories in Phoenix, Phoenix LiveView, Plug, Bandit,
Postgrex, Swoosh, Mint, HPAX, and Decimal
- Liquid `for` and `tablerow` loops over very large ranges can no longer exhaust server memory
### Added
- Welcome and double opt-in emails can now be edited with the full email editor
- Fields and the options of select fields in the form editor can now be reordered with drag and drop
- Data keys of custom form fields are now derived automatically from their field label
- New `MAILER_SMTP_VERIFY_SSL_HOST` and `MAILER_SMTP_CA_CERT` environment variables for disabling
certificate verification or trusting a custom CA for the system mailer
- The contacts list now shows when a contact was last updated; unsubscribed and unreachable contacts
are sorted by this date by default
- Added Swedish translation (thanks @rainersnookh)
### Improved
- The send and schedule dialogs now show the name of the selected segment (implements #574)
- Password resets now require a captcha
- System emails such as password resets and sender verifications are now sent via a background queue
- Added autocomplete hints to login, registration, and password forms as well as public forms (fixes #580,
thanks @vincenz1991 for reporting)
- Duplicate data keys for custom form fields now show an error (fixes #570)
- The forms API now enforces that forms must include a required email field and returns improved error
messages for invalid field settings
- Transactional messages without subject and template now return a validation error on `subject`
- TLS for SMTP senders and the system mailer now supports TLS 1.3
- Multi-column MJML sections with padding or borders now get correct column widths
- Updated Bulgarian translation (thanks @ramromcode)
### Fixed
- Fixed scheduler errors caused by Postgres subquery guarantees (fixes #585, thanks @castellinosviluppo for
reporting)
- Fixed a crash when adding options to a custom select field in the form editor
- Fixed content slots with blank content overriding the default content of templates
- Fixed a crash when rendering templates with missing content slots
- Email change verifications are now sent to the new email address
- Liquid comparisons with `blank` and `empty` now work correctly. Previously, `!= blank` and `!= empty` were
always true. Whitespace-only strings and `false` are now also treated as `blank`.
- SMTP senders created before connection security settings were introduced now use STARTTLS
- Campaign subjects are now properly escaped in the send and schedule dialogs
## Version 0.30.3
### Added
- Campaign ID is now available as `{{ campaign.id }}` in email templates (implements #559, thanks @Phobetor)
- New `MAILER_SMTP_TLS_MODE` and `MAILER_SMTP_AUTH_METHOD` environment variables for configuring TLS/STARTTLS and authentication method for the system mailer fixes #536 and #554, thanks @castellinosviluppo and @saz for reporting)
### Improved
- Shift+Enter now creates a line break instead of a new paragraph in the block editor
- Added cache for parsing Liquid templates, significantly improving campaign render performance, especially for campaigns with large HTML bodies
- Improved speed for many queries in large projects such as campaign stats and contact counts
### Fixed
- Deleting contacts by `external_id` from the API now works correctly (fixes #548, thanks @castellinosviluppo for reporting and @JoeJoeflyn for implementing)
- Fixed the *Resend verification email* button on the sender edit page
- Fixed MJML error messages caused by CRLF line breaks (fixes #567, thanks @Twilight-Computer for reporting)
## Version 0.30.2
### Added
- Added line-height setting for body text in Classic template style editor
- The status of a contact (active, unsubscribed, or unreachable) can now be changed manually on the contact edit page
- Contacts created via the API now trigger a *created* event the contact activity log (implements #429, thanks @lukoerfer for reporting)
### Fixed
- Added dedicated parser for extracting/filling content slots in MJML content slots, this fixes issues with MJML-specific elements that were being mangled by the HTML parser
## Version 0.30.1
### Fixed
- Add HTML option to campaign type dropdown in campaign settings
- Fixed a bug that caused an internal server error when creating new Block campaigns
- Fixed rendering errors when using self-closing MJML tags
- Fix gettext error with Block editor social media block
## Version 0.30.0
> MJML, HTML, and Plain-Text Templates, Content Slots, and Transactional Emails
### Breaking Changes
- In MJML campaigns, Liquid is now rendered before MJML. This means that
the previous convention of wrapping control-flow tags such as `{% if %}`
in `<mj-raw>` elements no longer works. This release automatically migrates
this pattern in existing campaigns to use the new `<keila-code>` element.
This new element can be placed at any level of an MJML template/campaign/message
and is removed cleanly before MJML is rendered.
### Added
- New API for sending and rendering transactional emails: one-off messages
can be sent with the `POST /messages` and previews rendered without sending
with `POST /messages/actions/render`.
- New API for managing templates.
- Added support for MJML, HTML and plain-text templates.
- Added content slots (`<keila-content>`) for MJML, HTML, and plain-text templates
which can be filled in the campaign editor and set via the API.
### Improved
- The MJML editor now allows scrolling the code editor independently from the preview and
has better autocomplete for MJML.
- Improved handling of image resizing in the Block Editor
- Improved handling of unsubscribe links in welcome and double-opt-in messages
- Improved validation of user-provided email addresses
- Added descriptions for API tags in the OpenAPI documentation
- Replaced the `tzdata` timezone database with `tz`, removing the need for
runtime timezone-data updates
- Replaced the HTTPoison HTTP client with Req
### Fixed
- Fixed a regression with linked images in Markdown campaigns
- Fixed a regression where `List-Unsubscribe` and `Precedence` headers were no
longer sent with delivered campaigns
- Fixed incorrect fuzzy translations (manual corrections for German and French,
machine translations for other languages)
## Version 0.20.1
> 🇧🇷 Brazilian Portuguese, pre-filled forms, and many fixes
### Added
- Added Brazilian Portuguese (pt-BR) translation (thanks @polesapart)
- Contact form fields can now be pre-populated using GET parameters
### Improved
- The send preview dialog can now be confirmed with the Enter/Return key
- App pages now set the HTML `lang` attribute based on the user's locale; forms don't set a `lang` attribute (thanks @marco-luigiano for reporting)
- Added database indices for `form_id`, `form_params_id`, and `sender_id` on the messages table for improved query performance
### Fixed
- Fixed recognition of language variants from request headers (e.g. `pt-BR`)
- Fixed a crash when using custom contact queries with fields not supported by the segment editor
- Fixed block editor image alignment in Outlook and uneven column gutters in block editor emails
- Fixed occasional exceptions in the block editor
- Fixed missing doctype when adding tracking links
- Fixed handling of single-image Markdown paragraphs
## Version 0.20.0
> 📮 New Email scheduler
### Added
- This version introduces a new email scheduler and migrates the `recipients` schema to
a more generic `messages`schema. This change makes sending large campaigns more performant
and will allow the introduction of transaction emails because records of sent messages no
longer have to be tied to a campaign or an existing contact.
### Improved
- When sending a message to the recipient of a campaign has failed, the number of failed
messages is now shown on the campaign analytics page
- Added Infomaniak and GMX to the list of known shared domains
### Fixed
- Fixed an issue where contacts could be marked as unreachable after a single soft bounce
## Version 0.19.1
> 🇮🇹 Italian translation, better Markdown performance, SMTP without auth, and many fixes
### Added
- Added Italian translation (thanks @energywave)
- Support for SMTP without password auth. Implements #491 (thanks @ghost1ndshell)
- Added `DISABLE_TZDATA_UPDATES` option to disable tzdata updates (thanks @sachabertschibfs)
- Image resizing in Block Editor & Markdown Editor
### Improved
- Significantly improved performance in Markdown editor. (thanks @roadriverrail for reporting)
- Campaign preview now updates when changing template in campaign settings
- Public archive pages are now rendered with campaign template
### Fixed
- Fixed some layout issues with column padding and font styles in Block Editor
- Fixed flickering images in Block Editor
- Fixed regression: Restored level 3 headings in Block Editor
- Fixed regression: Fixed error when creating shared senders (thanks @aj-foster)
## Version 0.19.0
> 👋 Welcome emails, Phoenix 1.7/LiveView 1.x upgrade, protected unsubscribe links, Bulgarian and Hungarian translations
### Added
- Welcome emails: You can now configure a welcome message for newly subscribed contacts in the form settings.
- Added protected unsubscribe and opt-in links: If an opt-in or unsubscribe link is clicked within three minutes of the email being sent, the associated action is only performed after an automatic JavaScript action or an additional click.
- Added text alignment settings to block editor
- Added Open button to forms index
- Added WebP image upload support (thanks @RohilPrajapati)
- Added Hungarian translation (thanks @trueqap)
- Added Bulgarian translation (thanks @ramromcode)
### Improved
- The Form editor now shows a preview of the Double Opt-In email and of the Welcome email
- The MJML editor toolbar is now sticky and remains visible when scrolling
- Improved handling of invalid email addresses
- Improved padding on forms
- Added additional known shared domains from Proton
- Upgraded to Phoenix 1.7 and LiveView 1.x
- Upgraded to Solid 1.2 which enables better Liquid error messages
### Fixed
- Fixed CSV import of files generated by Excel or Numbers
- Fixed an issue that sometimes made CSV imports appear stuck
- Fixed GenServer crash when exiting the contacts import page (thanks @katafrakt for reporting)
- `URL_PATH` is now respected when redirecting after login action (thanks @padjon and @Kptainflintt for reporting)
## Version 0.18.0
> Newsletter archives, interaction-based segmentation, many improvements and Keila en español!
### Added
- Added public archive links for campaigns
- Added ability to review sent campaigns
- Added `$empty` operator to Contact query language and segment editor
- Added segment filtering based on campaign interactions
- Added text color tool to Block Editor
- Added social media icons block to Block Editor (see #444)
- `success_url` in contact forms is now processed with Liquid, allowing personalized redirects
- Added support for `id_type` in API Contact deletion endpoint
- Preview emails are now prefixed with "[Preview]"
- Added Spanish translation (thanks @PedroMartpico)
- Added failure text and redirect URL options for double opt-in forms
### Improved
- Improved sender creation and editing experience
- Improved copy and paste functionality in the block editor
- Contacts are now marked as unreachable if delivery fails because they are invalid (thanks @henriqueberlesi)
- Contacts list now uses localized datetimes
- The `preview_text` of a campaign can now also be set via the API (thanks @samuelc92)
- Logs now include an ISO 8601 timestamp (thanks @samuelc92)
- Settings and send modals in the campaign editor can now be scrolled correctly
- Contact forms can now be embedded in Iframes
- TLS/SSL are now completely disabled when TLS mode is set to "none" in SMTP adapter
- Added message stream setting to Postmark adapter (thanks @codecat)
- New campaigns now use settings from the most recently sent campaign as defaults
### Fixed
- Fixed an issue where a contact that was already in the contact list would not receive the double opt-in email when trying to sign up again
- Template signature is now included in double opt-in emails
- Fixed issues with icon sizes in Safari
- Error message when root user failed to be created is now logged correctly
- Fixed logic and documentation of `DISABLE_UPDATE_CHECKS`
- When trying to access an auth URL as an authenticated user, the user is now correctly redirected to the project index page even if `URL_PATH` is set to a non-root path.
- Example data in .ods import template now uses correct straight quotes (thanks @individual-it)
- Upgraded Elixir and OTP have fixed previous SMTP adapter TLS issues
- Fixed exception in Mailings worker when contact has been deleted after recipient was created
## License Update
Keila continues to be licensed under the AGPLv3 license. However, going forward, all components that are only relevant for Keila Cloud (such as billing or the Send with Keila feature) are provided for informational purposes only and are not licensed under the terms of the AGPLv3 license. You can find more information in [extra/README.md](extra/README.md)
## Version 0.17.1
### Fixed
- Fixed error when launching the 0.17.0 release
## Version 0.17.0
👁️ Previews: Seeing is Believing
### Breaking Changes
- Keila now uses [Lexbor](https://github.com/lexbor/lexbor) instead of [Mochiweb](https://github.com/mochi/mochiweb) for parsing HTML.
Lexbor is faster and behaves much more like real-world browsers. Make sure to check your MJML templates to verify the change didn’t break anything.
The base template for Markdown and the Block Editor has been updated accordingly.
## Added
- Sending of campaign preview emails
- Unified and improved preview dialogs for all campaign types, including a switch for mobile/desktop view
- [Completely revamped API docs page](https://app.keila.io/api) and improved documentation
- `external_id` property for contacts
- `id_type` query param in contacts API to allow fetching/updating contacts by email address or external ID.
- API endpoints for managing and submitting forms, allowing for the creation of new contacts with double opt-in
## Changed
- Expanding the MJML editor now makes it take up the entire width of the UI
- Added forms, tracking, and unsubscribe links to robots.txt
## Fixed
- Fixed errors when custom form field labels were empty
- Block Editor no longer duplicates content when using copy and paste
- Deleting nested blocks in Block Editor works more reliably now
- API for delivering campaigns no longer returns a server error. Fixes #307
- Updated dev container dependencies to make sure they work with recent changes. Fixes #377 (thanks @henriqueberlesi)
## Version 0.16.1
🇫🇷♻️ Bonjour File Deletions!
## Added
- French translation (thanks @marc-bouvier for the translation and improving the translatability of Keila for other languages)
- Deletion of images in the upload interface (thanks @jrowah for implementing)
## Fixed
- The campaign update API endpoint now properly merges provided campaign settings with the existing settings
- Non-markdown default signature for plain text campaigns
- API Keys with no defined name no longer output the entire data structure upon creation (thanks @danilax86 for fixing)
## Version 0.16.0
🔄 Automatic Update Notifications
### Breaking Changes
- `MAILER_SMTP_FROM_EMAIL` is now used as the default for `MAILER_SMTP_USER` when only
`MAILER_SMTP_FROM_EMAIL` is set.
Before, the inverse was true (only `MAILER_SMTP_USER` needed to be set and was used
as the default for `MAILER_SMTP_FROM_EMAIL`).
This change was made to address the fact that the SMTP username might be confidential
and shouldn’t be accidentally exposed by using it as the FROM address in system emails.
If you are already setting both environment variables, you don’t need to change anything but if
you were only setting `MAILER_SMTP_USER`, you need to update your configuration.
Fixes #356 (thanks @kevinam99 for implementing)
### Added
- Information about new releases is now automatically fetched and displayed on a new "System info"
admin page. You can disable this by setting `DISABLE_UPDATE_CHECKS=true`.
- The log level can now be configured by setting `LOG_LEVEL` to `debug`, `info`, and `warning`.
Implements #360 (thanks @kevinam99)
- `mjml_body` and `html_body` are now included in the Campaign API responses
### Fixed
- Segment queries with the `$not` operator (e.g. `{"$not": {"data.foo": "bar"}}`)
now also correctly include entries where the queried data keys don't exist at all.
- Fixed possible exception when removing "Reply To" setting from sender settings.
- Fixed Campaign API docs to include `json_body` as a map instead of a string.
## Version 0.15.1
### Added
- Button for creating new users as admin (thanks @pmareke and @hellehata)
- Contacts can now re-subscribe or update their data by submitting a form again
(thanks @lislegaard for suggesting)
- Honeypot fields to block bot subscriptions
### Changed
- Limited `first_name` and `last_name` fields to 50 characters.
Implements #342 (thanks @lislegaard for suggesting)
### Fixed
- Updated broken tzdata library. Fixes #336. (thanks @VincentSC for reporting)
- Deletion of shared senders from the UI is now working.
Fixes #326 (thanks @bpivk for reporting)
## Version 0.15.0
### Added
- Support for MJML campaigns.
- Forms can now be configured to redirect users after successful submission and when double opt-in
is required.
- Forms can now be configured with a custom message when double opt-in is required
### Improved
- New email scheduler and rate limiter with significantly improved performance. (thanks @dompie
for supporting the development of this feature)
### Fixed
- Show correct state while campaign is being prepared for sending on stats page
- Marking custom checkboxes as *required* actually requires users to check them now.
Fixes #328. (thanks @cyberwuulf for reporting)
## Version 0.14.11
### Changed
- Increased database timeout when inserting recipients to 60 seconds
## Version 0.14.10
### Changed
- The analytics UI now shows a maximum of 20 links to avoid performance issues
with large campaigns and individualized links
## Version 0.14.9
### Fixed
- Enabled translation of system strings on public forms.
## Version 0.14.8
### Added
- Campaigns with type `block` and `json_body` can now be created via the API. Implements #300 (thanks @dompie for suggesting)
## Version 0.14.7
### Added
- Image blocks now allow the use of Liquid in `src` and other attributes.
Fixes #297 (thanks @dompie for reporting)
### Fixed
- Separators are now rendered more faithfully in the block editor
## Version 0.14.6
### Added
- Added PATCH and POST API endpoints for updating just the data field of a
contact
### Fixed
- Liquid tags are now correctly rendered in layout blocks in the Block Editor
(thanks @dompie for reporting)
- Fixed bug that caused "starts with" and "ends with" to be inverted in
segment editor (thanks @dompie for reporting)
## Version 0.14.5
### Changed
- Creating and updating contacts via the API now allows setting the `status`
field.
- Contacts list is now sorted in decending order by default
## Fixed
- Segments are now guaranteed to be initialized with a valid (empty) filter,
avoiding potential crashes with `nil` filters.
- `MAILER_SMTP_FROM_EMAIL` is now used for sending system emails again.
## Version 0.14.4
### Fixed
- Avoid potential partial merging of system sender config with user-configured senders
## Version 0.14.3
### Fixed
- Only support TLSv1.2 for STARTTLS SMTP Senders to avoid issues with
non-compliant TLSv1.3 implementation in OTP
## Version 0.14.2
### Improved
- Added new Gmail user agent to avoid tracking invalid clicks/opens
- Return to list of unsubscribed/unreachable contacts after delete action from
one of those pages. Implements #193 (thanks @digitalfredy for reporting)
- It's now possible to choose between the US and EU API endpoints for Mailgun senders (thanks @harryfear for reporting)
- Improvements to German translation (thanks @dompie)
### Fixed
- Clicking "Delete all" on the contacts list no longer causes a server error
when no contacts have been selected. Fixes #260 (thanks @CSDUMMI for reporting)
- Fixed connection errors when using SMTP senders with STARTTLS (thanks @beep and @CodeOfTim for reporting)
## Version 0.14.0
Custom signup form fields + contacts search 🔎
### Added
- Custom fields (text, checkbox, dropdown, tags, numbers) can now be added to
contact signup forms. Implements #135
- Search and sorting on contacts page
- Added buttons for inserting images, links, and buttons to plain Markdown
editor. Fixes #255 (thanks @lukaprincic for suggesting)
### Improved
- Errors in signup forms are displayed with a prominent red border and bold text
now.
### Fixed
- If the `status` column is present in a CSV import, only rows where this column
is set to "active" are imported. Fixes #253 (thanks @VZsI for reporting)
- Live preview in plain Markdown editor no longer disappears when switching to
rich editor and back.
- Fixed error when saving a contact with JSON data and a constraint error
## Version 0.13.1
### Fixed
- API Contact response now includes status field
- Fixed error when using custom email template for double opt-in emails
## Version 0.13.0
Double Opt-In ✅
### Added
- Added support for double opt-in/confirmed opt in.
Forms can now be configured to enable double opt-in to require new subscribers
to confirm their email address before they are added as contacts to the
project.
### Changed
- Updated Elixir to 1.15
- Translatable labels for first name and last name in form builder
- Refactored Form controller to separate config UI from public routes
- Refactored how form submissions are processed
- Refactored how Markdown campaigns are built
### Fixed
- Added support for additional JPEG variant (this avoids errors when uploading
previously unrecognized JPEG files)
## Version 0.12.8
### Added
- Added `MAILER_ENABLE_STARTTLS` option to configure a system mailer with STARTTLS (#247)
### Fixed
- API DELETE endpoints for campaigns, contacts, segments now return the
correct 204 response
## Version 0.12.7
### Added
- Added `MAILER_ENABLE_SSL` option to configure a system mailer with SSL/TLS
### Fixed
- Markdown campaigns now allow adding links to images (#245)
## Version 0.12.6
### Fixed
- Fixed SSL/TLS errors when sending emails with SMTP senders
- Fixed potential exception for image blocks without captions/urls
### Added
- CSV download for contacts and segments (#238 - thanks @katafrakt)
- Improved configuration form for SMTP senders with automatic port selection
depending on security mode
## Version 0.12.5
### Fixed
- Fixed crash when using data URLs in campaigns (#218 - thanks @katafrakt)
## Version 0.12.4
### Added
- Support for Captchas from [Friendly Captcha](https://friendlycaptcha.com/) (thanks @beeb)
### Changed
- Segments are now ordered alphabetically (#203 - thanks @panoramix360)
## Version 0.12.3
### Changed
- Failed campaign emails are now logged via `Logger.warning/1` instead of
`Logger.debug/1`.
## Version 0.12.2
### Fixed
- Email preview text is now actually included in emails
- Layout blocks now have a default 1:1 ratio, ensuring they are always rendered
correctly
## Version 0.12.1
New Campaign Block Editor 📝
### Added
- New block-style editor for building campaigns
- Multi-column layouts
- Headings, paragraphs, lists
- Images
- Buttons
- Blockquotes
- Spacers
- More styling options in the form editor (#185)
### Changed
- Changed base email template to [Cerberus Hybrid](https://www.cerberusemail.com/hybrid-responsive)
- Scheduled campaigns that could not be delivered are automatically un-scheduled
- Scrolling position in template and campaign previews is retained when changes are made
### Fixed
- Invalid signature markup no longer breaks the template editor (#119)
- Fixed error that caused uploaded images not to show up in upload modal (#186)
- Fixed some broken URLs when Keila is configured with `URL_PATH` (#189)
- Mailer port now defaults to `587` instead of `nil` (#182 - thanks @aej)
- Fixed bug that could cause the content of a Markdown campaign to be erased when changing the title (#188)
- Fixed bug that could cause the segment page to crash (#177)
## Version 0.11.2
### Changed
- Only hard bounces are shown as bounces on campaign statistics page
### Fixed
- Legacy IDs are now decoded correctly
## Version 0.11.1
Better Campaign Analytics 📈
### Added
- New Campaign Analytics page
- Improved Contact Activity Stream
- Separate lists for active/unsubscribed/unreachable contacts
- Improved handling and logging of campaign delivery errors
- Bot detection in campaign open tracking (#164 - thanks @panoramix360)
- New API endpoint to list Senders (#147)
- Added support for Postmark senders (thanks @aej)
### Changed
- Improved compatibility with SMTP servers by relaxing `gen_smtp` SSL/TLS settings
- Upgraded to Elixir 1.14
- Ugraded to Tailwind 3
- Added success hint when copying API key to clipboard
### Fixed
- Fixed error when no user content dir is set (#171)
- Fixed error when CSRF is enabled for forms (#167)
- **Breaking:** Hashids now use configurable salt. Read more on [keila.io](https://www.keila.io/updates/breaking-hashid-update)
## Version 0.10.0
Image Uploads, Rate Limits, Do-not-track Campaigns 🖼️
### Added
- Image Uploads
- Do-not-track option for campaigns
- Liquid templating support in campaign subjects
- First interface translation added: German
- Rate limits for Senders and Shared Senders (thanks @gbottari & @panoramix360!)
- Allow configuring `FROM` email address for system emails
- Shared local sender for testing/development
- Improved styling: New spacer block and additional styling for signatures
- Configurable FROM email address for system emails
### Changed
- Updated LiveView to 0.17
- Images in the WYSIWYG editor can now be modified on double-click
- Easier configuration of public-facing Keila URLs
### Fixed
- API keys don’t expire anymore
- Fixed some typos (thanks @kianmeng!)
- Liquid tags can be used as link targets now
## Version 0.9.0
Campaign Data, Improved WYSIWYG editor 💽
### Added
- Campaign data feature
- Automatic recognition of Markdown in WYSIWYG editor
- New *Code* button in WYSIWYG editor with Liquid template examples
- Highlighting of Liquid tags in WYSIWYG editor
- Pretty-printing of embedded form HTML
- Support for Dev Containers
### Changed
- Updated JS dependencies
- Added size constraint to contact data field (8 KB per contact)
- Simplified UI for campaign editor with settings moved to modal
- Link click statistics are now displayed live while campaign is sending
### Fixed
- Use full URL for embedded form action attribute
## Version 0.8.0
API for Contacts & Campaigns, Better Imports, UX Improvements 🧑💻
### Added
- API for managing Contacts, Campaigns, Segments
- Swagger UI for API at `/api`
- Improved contact import with support for custom data and upserts
- Notifications when leaving pages with unsaved data
- Added `DB_ENABLE_SSL` configuration option
### Changed
- Updated Oban and Jason dependencies
### Fixed
- Segments with custom data fields can now be edited after saving
- Error display in campaigns without sender no longer keeps reloading page
## Version 0.7.1
### Fixed
- Fixed error when creating new segments
## Version 0.7.0
### Added
- Contact segmentation
- Support for custom contact data
- Allow deletion of sent campaigns
### Changed
- Improved UI design
- Moved all templates from leex/eex to heex
- Improved Core querying API
### Fixed
- Fixed exception when processing unhandled SES webhooks
## Version 0.6.2
### Added
- Configuration option to run Keila in a subdirectory
- Login-as feature for admins
- Gzip compression of assets
### Changed
- Upgraded to Phoenix 1.6
- Upgraded various dependencies, including Ecto
- Replaced Webpack with esbuild
## Version 0.6.1
### Fixed
- Default contact status is now *subscribed*
## Version 0.6.0
Contact Activity Log & Bounce Handling 🗒️
### Changed
- Upon unsubscribing, contacts are no longer deleted from the database
### Added
- Contact activity log
- Contact dashboard with subscriber numbers
- Support for Configuration Sets for AWS SES
- Automatic handling of bounces and complaints for AWS SES
## Version 0.5.4
### Changed
- Removed password placeholder texts
### Fixed
- Dockerfile and sample docker-compose configuration are now compatible
## Version 0.5.3
### Added
- Template now fully compatible with Outlook and Windows Mail
### Fixed
- Fixed broken CSV template downloads
- Improved template display in WYSIWG editor
## Version 0.5.2
### Fixed
- Fixed broken styling on non-authenticated routes
## Version 0.5.1
### Added
- Improved onboarding experience with empty states for all views
### Changed
- Improved dark app design
- Stricter code-checks in CI
### Fixed
- Default template is now displayed correctly in campaign editor
- Paddle webhooks now have improved idempotency
## Version 0.5.0
### Added
- Added click/open tracking for campaign emails
- `Precedence: Bulk` header now included in all campaign emails
- Implemented per-instance `SharedSenders`
- Implemented Shared Senders for AWS SES
- Added account and account credits for organizing users and implementing quotas
- Added subscription plans for app.keila.io
### Changed
- Updated to Elixir 1.12
### Fixed
- Removed email preview text from Cerberus
## Version 0.4.0 🎨
Template customization & UI improvements
### Added
- Template editor for customizing Markdown campaign styles
### Changed
- Improved index pages for forms, templates, and campaigns
- Updated dependencies, using upstream of `Swoosh` again
### Fixed
- Fixed broken template download links in production
## Version 0.3.0
Scheduling campaigns & WYSIWYG editor ⏲️
### Added
- Campaigns can now be scheduled to be sent automatically
- WYSIWYG editor for Markdown campaigns
- Local sender for testing in development mode
### Fixed
- Formatted dates in local timezone now used on campaign overview page
- Removed default email preview text
## Version 0.2.2
## Fixed
- Fixed crash when starting release
## Version 0.2.1
### Fixed
- TailwindCSS styles are now pruned, massively reducing CSS size
- Default admin user is created correctly when `KEILA_USER` is not specified
- Fixed crash when starting release
## Version 0.2.0
Simplified deployments ⚙️
### Added
- Improved deployment workflow with automatic migrations
- Automatic creation of root user
- Admin panel with simple user management
### Fixed
- Campaigns can no longer be sent twice
## Version 0.1.0
First official release of Keila 🚀
### Added
This first release implements the most important features to make Keila a
viable tool for managing newsletters.
- Editor for plain text + Markdown campaigns
- Sending campaigns with SMTP, SES, Sendgrid, Mailgun
- Signup forms and form editor
- Contact import
- One-click unsubscription