Merge develop
[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}} = notification, acc ->
107 new_mention = %{data: notification, from: Pleroma.User.get_by_ap_id(actor)}
108 %{acc | mentions: [new_mention | acc.mentions]}
109
110 %{activity: %{data: %{"type" => "Follow"}, actor: actor}} = notification, acc ->
111 new_follower = %{data: notification, from: Pleroma.User.get_by_ap_id(actor)}
112 %{acc | followers: [new_follower | acc.followers]}
113
114 _, acc ->
115 acc
116 end)
117
118 with [_ | _] = mentions <- new_notifications.mentions do
119 html_data = %{
120 instance: instance_name(),
121 user: user,
122 mentions: mentions,
123 followers: new_notifications.followers,
124 unsubscribe_link: unsubscribe_url(user, "digest")
125 }
126
127 new()
128 |> to(recipient(user))
129 |> from(sender())
130 |> subject("Your digest from #{instance_name()}")
131 |> render_body("digest.html", html_data)
132 else
133 _ ->
134 nil
135 end
136 end
137
138 @doc """
139 Generate unsubscribe link for given user and notifications type.
140 The link contains JWT token with the data, and subscription can be modified without
141 authorization.
142 """
143 @spec unsubscribe_url(Pleroma.User.t(), String.t()) :: String.t()
144 def unsubscribe_url(user, notifications_type) do
145 token =
146 %{"sub" => user.id, "act" => %{"unsubscribe" => notifications_type}, "exp" => false}
147 |> Pleroma.JWT.generate_and_sign!()
148 |> Base.encode64()
149
150 Router.Helpers.subscription_url(Pleroma.Web.Endpoint, :unsubscribe, token)
151 end
152 end