Fix conflict
[akkoma] / lib / pleroma / emails / user_email.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Emails.UserEmail do
6 @moduledoc "User emails"
7
8 use Phoenix.Swoosh, view: Pleroma.Web.EmailView, layout: {Pleroma.Web.LayoutView, :email}
9
10 alias Pleroma.Web.Endpoint
11 alias Pleroma.Web.Router
12
13 defp instance_config, do: Pleroma.Config.get(:instance)
14
15 defp instance_name, do: instance_config()[:name]
16
17 defp sender do
18 email = Keyword.get(instance_config(), :notify_email, instance_config()[:email])
19 {instance_name(), email}
20 end
21
22 defp recipient(email, nil), do: email
23 defp recipient(email, name), do: {name, email}
24 defp recipient(%Pleroma.User{} = user), do: recipient(user.email, user.name)
25
26 def password_reset_email(user, password_reset_token) when is_binary(password_reset_token) do
27 password_reset_url =
28 Router.Helpers.util_url(
29 Endpoint,
30 :show_password_reset,
31 password_reset_token
32 )
33
34 html_body = """
35 <h3>Reset your password at #{instance_name()}</h3>
36 <p>Someone has requested password change for your account at #{instance_name()}.</p>
37 <p>If it was you, visit the following link to proceed: <a href="#{password_reset_url}">reset password</a>.</p>
38 <p>If it was someone else, nothing to worry about: your data is secure and your password has not been changed.</p>
39 """
40
41 new()
42 |> to(recipient(user))
43 |> from(sender())
44 |> subject("Password reset")
45 |> html_body(html_body)
46 end
47
48 def user_invitation_email(
49 user,
50 %Pleroma.UserInviteToken{} = user_invite_token,
51 to_email,
52 to_name \\ nil
53 ) do
54 registration_url =
55 Router.Helpers.redirect_url(
56 Endpoint,
57 :registration_page,
58 user_invite_token.token
59 )
60
61 html_body = """
62 <h3>You are invited to #{instance_name()}</h3>
63 <p>#{user.name} invites you to join #{instance_name()}, an instance of Pleroma federated social networking platform.</p>
64 <p>Click the following link to register: <a href="#{registration_url}">accept invitation</a>.</p>
65 """
66
67 new()
68 |> to(recipient(to_email, to_name))
69 |> from(sender())
70 |> subject("Invitation to #{instance_name()}")
71 |> html_body(html_body)
72 end
73
74 def account_confirmation_email(user) do
75 confirmation_url =
76 Router.Helpers.confirm_email_url(
77 Endpoint,
78 :confirm_email,
79 user.id,
80 to_string(user.info.confirmation_token)
81 )
82
83 html_body = """
84 <h3>Welcome to #{instance_name()}!</h3>
85 <p>Email confirmation is required to activate the account.</p>
86 <p>Click the following link to proceed: <a href="#{confirmation_url}">activate your account</a>.</p>
87 """
88
89 new()
90 |> to(recipient(user))
91 |> from(sender())
92 |> subject("#{instance_name()} account confirmation")
93 |> html_body(html_body)
94 end
95
96 @doc """
97 Email used in digest email notifications
98 Includes Mentions and New Followers data
99 If there are no mentions (even when new followers exist), the function will return nil
100 """
101 @spec digest_email(Pleroma.User.t()) :: Swoosh.Email.t() | nil
102 def digest_email(user) do
103 new_notifications =
104 Pleroma.Notification.for_user_since(user, user.last_digest_emailed_at)
105 |> Enum.reduce(%{followers: [], mentions: []}, fn
106 %{activity: %{data: %{"type" => "Create"}, actor: actor} = activity} = notification,
107 acc ->
108 new_mention = %{
109 data: notification,
110 object: Pleroma.Object.normalize(activity),
111 from: Pleroma.User.get_by_ap_id(actor)
112 }
113
114 %{acc | mentions: [new_mention | acc.mentions]}
115
116 %{activity: %{data: %{"type" => "Follow"}, actor: actor} = activity} = notification,
117 acc ->
118 new_follower = %{
119 data: notification,
120 object: Pleroma.Object.normalize(activity),
121 from: Pleroma.User.get_by_ap_id(actor)
122 }
123
124 %{acc | followers: [new_follower | acc.followers]}
125
126 _, acc ->
127 acc
128 end)
129
130 with [_ | _] = mentions <- new_notifications.mentions do
131 html_data = %{
132 instance: instance_name(),
133 user: user,
134 mentions: mentions,
135 followers: new_notifications.followers,
136 unsubscribe_link: unsubscribe_url(user, "digest")
137 }
138
139 new()
140 |> to(recipient(user))
141 |> from(sender())
142 |> subject("Your digest from #{instance_name()}")
143 |> render_body("digest.html", html_data)
144 else
145 _ ->
146 nil
147 end
148 end
149
150 @doc """
151 Generate unsubscribe link for given user and notifications type.
152 The link contains JWT token with the data, and subscription can be modified without
153 authorization.
154 """
155 @spec unsubscribe_url(Pleroma.User.t(), String.t()) :: String.t()
156 def unsubscribe_url(user, notifications_type) do
157 token =
158 %{"sub" => user.id, "act" => %{"unsubscribe" => notifications_type}, "exp" => false}
159 |> Pleroma.JWT.generate_and_sign!()
160 |> Base.encode64()
161
162 Router.Helpers.subscription_url(Pleroma.Web.Endpoint, :unsubscribe, token)
163 end
164 end