Add "Your backup is ready" email
[akkoma] / lib / pleroma / emails / user_email.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 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.Config
11 alias Pleroma.User
12 alias Pleroma.Web.Endpoint
13 alias Pleroma.Web.Router
14
15 import Pleroma.Config.Helpers, only: [instance_name: 0, sender: 0]
16
17 defp recipient(email, nil), do: email
18 defp recipient(email, name), do: {name, email}
19 defp recipient(%User{} = user), do: recipient(user.email, user.name)
20
21 @spec welcome(User.t(), map()) :: Swoosh.Email.t()
22 def welcome(user, opts \\ %{}) do
23 new()
24 |> to(recipient(user))
25 |> from(Map.get(opts, :sender, sender()))
26 |> subject(Map.get(opts, :subject, "Welcome to #{instance_name()}!"))
27 |> html_body(Map.get(opts, :html, "Welcome to #{instance_name()}!"))
28 |> text_body(Map.get(opts, :text, "Welcome to #{instance_name()}!"))
29 end
30
31 def password_reset_email(user, token) when is_binary(token) do
32 password_reset_url = Router.Helpers.reset_password_url(Endpoint, :reset, token)
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.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(User.t()) :: Swoosh.Email.t() | nil
102 def digest_email(user) do
103 notifications = Pleroma.Notification.for_user_since(user, user.last_digest_emailed_at)
104
105 mentions =
106 notifications
107 |> Enum.filter(&(&1.activity.data["type"] == "Create"))
108 |> Enum.map(fn notification ->
109 object = Pleroma.Object.normalize(notification.activity)
110
111 if not is_nil(object) do
112 object = update_in(object.data["content"], &format_links/1)
113
114 %{
115 data: notification,
116 object: object,
117 from: User.get_by_ap_id(notification.activity.actor)
118 }
119 end
120 end)
121 |> Enum.filter(& &1)
122
123 followers =
124 notifications
125 |> Enum.filter(&(&1.activity.data["type"] == "Follow"))
126 |> Enum.map(fn notification ->
127 from = User.get_by_ap_id(notification.activity.actor)
128
129 if not is_nil(from) do
130 %{
131 data: notification,
132 object: Pleroma.Object.normalize(notification.activity),
133 from: User.get_by_ap_id(notification.activity.actor)
134 }
135 end
136 end)
137 |> Enum.filter(& &1)
138
139 unless Enum.empty?(mentions) do
140 styling = Config.get([__MODULE__, :styling])
141 logo = Config.get([__MODULE__, :logo])
142
143 html_data = %{
144 instance: instance_name(),
145 user: user,
146 mentions: mentions,
147 followers: followers,
148 unsubscribe_link: unsubscribe_url(user, "digest"),
149 styling: styling
150 }
151
152 logo_path =
153 if is_nil(logo) do
154 Path.join(:code.priv_dir(:pleroma), "static/static/logo.png")
155 else
156 Path.join(Config.get([:instance, :static_dir]), logo)
157 end
158
159 new()
160 |> to(recipient(user))
161 |> from(sender())
162 |> subject("Your digest from #{instance_name()}")
163 |> put_layout(false)
164 |> render_body("digest.html", html_data)
165 |> attachment(Swoosh.Attachment.new(logo_path, filename: "logo.png", type: :inline))
166 end
167 end
168
169 defp format_links(str) do
170 re = ~r/<a.+href=['"].*>/iU
171 %{link_color: color} = Config.get([__MODULE__, :styling])
172
173 Regex.replace(re, str, fn link ->
174 String.replace(link, "<a", "<a style=\"color: #{color};text-decoration: none;\"")
175 end)
176 end
177
178 @doc """
179 Generate unsubscribe link for given user and notifications type.
180 The link contains JWT token with the data, and subscription can be modified without
181 authorization.
182 """
183 @spec unsubscribe_url(User.t(), String.t()) :: String.t()
184 def unsubscribe_url(user, notifications_type) do
185 token =
186 %{"sub" => user.id, "act" => %{"unsubscribe" => notifications_type}, "exp" => false}
187 |> Pleroma.JWT.generate_and_sign!()
188 |> Base.encode64()
189
190 Router.Helpers.subscription_url(Endpoint, :unsubscribe, token)
191 end
192
193 def backup_is_ready_email(backup) do
194 %{user: user} = Pleroma.Repo.preload(backup, :user)
195 download_url = Pleroma.Web.PleromaAPI.BackupView.download_url(backup)
196
197 html_body = """
198 <p>You requested a full backup of your Pleroma account. It's ready for download:</p>
199 <p><a href="#{download_url}"></a></p>
200 """
201
202 new()
203 |> to(recipient(user))
204 |> from(sender())
205 |> subject("Your account archive is ready")
206 |> html_body(html_body)
207 end
208 end