Skip to content

Commit 9ba333d

Browse files
authored
Merge branch 'master' into people-dropdown
2 parents c2c8dec + c29b93f commit 9ba333d

16 files changed

+260
-42
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
77
- Dashboard shows comparisons for all reports
88
- UTM Medium report and API shows (gclid) and (msclkid) for paid searches when no explicit utm medium present.
99
- Support for `case_sensitive: false` modifiers in Stats API V2 filters for case-insensitive searches.
10+
- Add text version to emails plausible/analytics#4674
1011

1112
### Removed
1213

Dockerfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ RUN mkdir /app
2020
WORKDIR /app
2121

2222
# install build dependencies
23-
RUN apk add --no-cache git nodejs yarn python3 npm ca-certificates wget gnupg make gcc libc-dev brotli && \
24-
npm install npm@latest -g
23+
RUN apk add --no-cache git nodejs yarn python3 npm ca-certificates wget gnupg make gcc libc-dev brotli
2524

2625
COPY mix.exs ./
2726
COPY mix.lock ./

assets/js/dashboard/query-dates.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ test.each([
9696
test.each([
9797
[
9898
{ period: 'custom', from: '2024-08-10', to: '2024-08-20' },
99-
'10 Aug - 20 Aug'
99+
'10 Aug - 20 Aug 24'
100100
],
101101
[{ period: 'realtime' }, 'Realtime']
102102
])(

lib/plausible/mailer.ex

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,21 @@ defmodule Plausible.Mailer do
22
use Bamboo.Mailer, otp_app: :plausible
33
require Logger
44

5-
@type result() :: :ok | {:error, :hard_bounce} | {:error, :unknown_error}
6-
7-
@spec send(Bamboo.Email.t()) :: result()
5+
@spec send(Bamboo.Email.t()) :: :ok | {:error, :unknown_error}
86
def send(email) do
9-
case deliver_now(email) do
10-
{:ok, _email} -> :ok
11-
{:ok, _email, _response} -> :ok
12-
{:error, error} -> handle_error(error)
13-
end
14-
end
15-
16-
defp handle_error(%{response: response}) when is_binary(response) do
17-
case Jason.decode(response) do
18-
{:ok, %{"ErrorCode" => 406}} ->
19-
{:error, :hard_bounce}
7+
try do
8+
deliver_now!(email)
9+
rescue
10+
e ->
11+
# this message is ignored by Sentry, only appears in logs
12+
log = "Failed to send e-mail:\n\n " <> Exception.format(:error, e, __STACKTRACE__)
13+
# Sentry report is built entirely from crash_reason
14+
crash_reason = {e, __STACKTRACE__}
2015

21-
{:ok, response} ->
22-
Logger.error("Failed to send e-mail", sentry: %{extra: %{response: inspect(response)}})
23-
{:error, :unknown_error}
24-
25-
{:error, _any} ->
26-
Logger.error("Failed to send e-mail", sentry: %{extra: %{response: inspect(response)}})
16+
Logger.error(log, crash_reason: crash_reason)
2717
{:error, :unknown_error}
18+
else
19+
_sent_email -> :ok
2820
end
2921
end
30-
31-
defp handle_error(error) do
32-
Logger.error("Failed to send e-mail", sentry: %{extra: %{response: inspect(error)}})
33-
{:error, :unknown_error}
34-
end
3522
end

lib/plausible/site/admin.ex

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ defmodule Plausible.SiteAdmin do
3434
from(r in query,
3535
as: :site,
3636
inner_join: o in assoc(r, :owner),
37-
preload: [owner: o, team: [team_memberships: :user]],
37+
inner_join: t in assoc(r, :team),
38+
preload: [owner: o, team: t, guest_memberships: [team_membership: :user]],
3839
or_where: ilike(r.domain, ^search_term),
3940
or_where: ilike(o.email, ^search_term),
4041
or_where: ilike(o.name, ^search_term),
@@ -193,8 +194,8 @@ defmodule Plausible.SiteAdmin do
193194
end
194195

195196
defp get_other_members(site) do
196-
site.team.team_memberships
197-
|> Enum.map(fn m -> m.user.email <> "(#{to_string(m.role)})" end)
197+
site.guest_memberships
198+
|> Enum.map(fn m -> m.team_membership.user.email <> "(#{member_role(m.role)})" end)
198199
|> Enum.join(", ")
199200
end
200201

@@ -208,4 +209,7 @@ defmodule Plausible.SiteAdmin do
208209

209210
def create_changeset(schema, attrs), do: Plausible.Site.crm_changeset(schema, attrs)
210211
def update_changeset(schema, attrs), do: Plausible.Site.crm_changeset(schema, attrs)
212+
213+
defp member_role(:editor), do: :admin
214+
defp member_role(other), do: other
211215
end

lib/plausible_web/email.ex

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
defmodule PlausibleWeb.Email do
22
use Plausible
3-
use Bamboo.Phoenix, view: PlausibleWeb.EmailView
3+
import Bamboo.Email
44
import Bamboo.PostmarkHelper
55

66
def mailer_email_from do
@@ -460,17 +460,71 @@ defmodule PlausibleWeb.Email do
460460
def base_email(), do: base_email(%{layout: "base_email.html"})
461461

462462
def base_email(%{layout: layout}) do
463-
mailer_from = Application.get_env(:plausible, :mailer_email)
464-
465463
new_email()
466464
|> put_param("TrackOpens", false)
467-
|> from(mailer_from)
465+
|> from(mailer_email_from())
468466
|> maybe_put_layout(layout)
469467
end
470468

471469
defp maybe_put_layout(email, nil), do: email
472470

473-
defp maybe_put_layout(email, layout) do
474-
put_html_layout(email, {PlausibleWeb.LayoutView, layout})
471+
defp maybe_put_layout(%{assigns: assigns} = email, layout) do
472+
%{email | assigns: Map.put(assigns, :layout, {PlausibleWeb.LayoutView, layout})}
473+
end
474+
475+
@doc false
476+
def render(email, template, assigns \\ []) do
477+
assigns = Map.merge(email.assigns, Map.new(assigns))
478+
html = Phoenix.View.render_to_string(PlausibleWeb.EmailView, template, assigns)
479+
email |> html_body(html) |> text_body(textify(html))
480+
end
481+
482+
defp textify(html) do
483+
Floki.parse_fragment!(html)
484+
|> traverse_and_textify()
485+
|> Floki.text()
486+
|> collapse_whitespace()
487+
end
488+
489+
defp traverse_and_textify([head | tail]) do
490+
[traverse_and_textify(head) | traverse_and_textify(tail)]
491+
end
492+
493+
defp traverse_and_textify(text) when is_binary(text) do
494+
String.replace(text, "\n", "\s")
495+
end
496+
497+
defp traverse_and_textify({"a" = tag, attrs, children}) do
498+
href = with {"href", href} <- List.keyfind(attrs, "href", 0), do: href
499+
children = traverse_and_textify(children)
500+
501+
if href do
502+
text = Floki.text(children)
503+
504+
if text == href do
505+
# avoids rendering "http://localhost:8000 (http://localhost:8000)" in base_email footer
506+
text
507+
else
508+
IO.iodata_to_binary([text, " (", href, ?)])
509+
end
510+
else
511+
{tag, attrs, children}
512+
end
513+
end
514+
515+
defp traverse_and_textify({tag, attrs, children}) do
516+
{tag, attrs, traverse_and_textify(children)}
517+
end
518+
519+
defp traverse_and_textify(other), do: other
520+
521+
defp collapse_whitespace(text) do
522+
text
523+
|> String.split("\n")
524+
|> Enum.map_join("\n", fn line ->
525+
line
526+
|> String.split(" ", trim: true)
527+
|> Enum.join(" ")
528+
end)
475529
end
476530
end

lib/workers/check_usage.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ defmodule Plausible.Workers.CheckUsage do
4343
inner_join: o in assoc(t, :owner),
4444
inner_lateral_join: s in subquery(Teams.last_subscription_join_query()),
4545
on: true,
46-
left_join: ep in assoc(t, :enterprise_plan),
46+
left_join: ep in Plausible.Billing.EnterprisePlan,
47+
on: ep.team_id == t.id and ep.paddle_plan_id == s.paddle_plan_id,
4748
where:
4849
s.status in [
4950
^Subscription.Status.active(),

mix.exs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ defmodule Plausible.MixProject do
6363
defp deps do
6464
[
6565
{:bamboo, "~> 2.3", override: true},
66-
{:bamboo_phoenix, "~> 1.0.0"},
6766
{:bamboo_postmark, git: "https://github.com/plausible/bamboo_postmark.git", branch: "main"},
6867
{:bamboo_smtp, "~> 4.1"},
6968
{:bamboo_mua, "~> 0.2.0"},

mix.lock

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"acceptor_pool": {:hex, :acceptor_pool, "1.0.0", "43c20d2acae35f0c2bcd64f9d2bde267e459f0f3fd23dab26485bf518c281b21", [:rebar3], [], "hexpm", "0cbcd83fdc8b9ad2eee2067ef8b91a14858a5883cb7cd800e6fcd5803e158788"},
33
"bamboo": {:hex, :bamboo, "2.3.0", "d2392a2cabe91edf488553d3c70638b532e8db7b76b84b0a39e3dfe492ffd6fc", [:mix], [{:hackney, ">= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.4 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "dd0037e68e108fd04d0e8773921512c940e35d981e097b5793543e3b2f9cd3f6"},
44
"bamboo_mua": {:hex, :bamboo_mua, "0.2.2", "c50cd41ef684155669e2d99d428fbb87e13797a80829a162b47d3c0a7f7e7ecd", [:mix], [{:bamboo, "~> 2.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:mail, "~> 0.3.0", [hex: :mail, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: false]}], "hexpm", "5fe6e3676640578c6fe8f040b34dda8991ebef8566c0601a984eb4771b85b11f"},
5-
"bamboo_phoenix": {:hex, :bamboo_phoenix, "1.0.0", "f3cc591ffb163ed0bf935d256f1f4645cd870cf436545601215745fb9cc9953f", [:mix], [{:bamboo, ">= 2.0.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.3.0", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "6db88fbb26019c84a47994bb2bd879c0887c29ce6c559bc6385fd54eb8b37dee"},
65
"bamboo_postmark": {:git, "https://github.com/plausible/bamboo_postmark.git", "5eac6dfdffacd273bd9aacdd3e494a600bb0b170", [branch: "main"]},
76
"bamboo_smtp": {:hex, :bamboo_smtp, "4.2.2", "e9f57a2300df9cb496c48751bd7668a86a2b89aa2e79ccaa34e0c46a5f64c3ae", [:mix], [{:bamboo, "~> 2.2.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:gen_smtp, "~> 1.2.0", [hex: :gen_smtp, repo: "hexpm", optional: false]}], "hexpm", "28cac2ec8adaae02aed663bf68163992891a3b44cfd7ada0bebe3e09bed7207f"},
87
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.1.0", "0b110a9a6c619b19a7f73fa3004aa11d6e719a67e672d1633dc36b6b2290a0f7", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2ad2acb5a8bc049e8d5aa267802631912bb80d5f4110a178ae7999e69dca1bf7"},

priv/ingest_repo/migrations/20241216133031_add_scroll_depth_to_imported_pages.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ defmodule Plausible.IngestRepo.Migrations.AddScrollDepthToImportedPages do
1515
execute """
1616
ALTER TABLE imported_pages
1717
#{@on_cluster}
18-
DROP COLUMN scroll_depth
18+
DROP COLUMN IF EXISTS scroll_depth
1919
"""
2020
end
2121
end

0 commit comments

Comments
 (0)