Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

179 рядки
5.5KB

  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. defmodule Pleroma.Emails.UserEmail do
  5. @moduledoc "User emails"
  6. use Phoenix.Swoosh, view: Pleroma.Web.EmailView, layout: {Pleroma.Web.LayoutView, :email}
  7. alias Pleroma.Config
  8. alias Pleroma.User
  9. alias Pleroma.Web.Endpoint
  10. alias Pleroma.Web.Router
  11. defp instance_name, do: Config.get([:instance, :name])
  12. defp sender do
  13. email = Config.get([:instance, :notify_email]) || Config.get([:instance, :email])
  14. {instance_name(), email}
  15. end
  16. defp recipient(email, nil), do: email
  17. defp recipient(email, name), do: {name, email}
  18. defp recipient(%User{} = user), do: recipient(user.email, user.name)
  19. def password_reset_email(user, token) when is_binary(token) do
  20. password_reset_url = Router.Helpers.reset_password_url(Endpoint, :reset, token)
  21. html_body = """
  22. <h3>Reset your password at #{instance_name()}</h3>
  23. <p>Someone has requested password change for your account at #{instance_name()}.</p>
  24. <p>If it was you, visit the following link to proceed: <a href="#{password_reset_url}">reset password</a>.</p>
  25. <p>If it was someone else, nothing to worry about: your data is secure and your password has not been changed.</p>
  26. """
  27. new()
  28. |> to(recipient(user))
  29. |> from(sender())
  30. |> subject("Password reset")
  31. |> html_body(html_body)
  32. end
  33. def user_invitation_email(
  34. user,
  35. %Pleroma.UserInviteToken{} = user_invite_token,
  36. to_email,
  37. to_name \\ nil
  38. ) do
  39. registration_url =
  40. Router.Helpers.redirect_url(
  41. Endpoint,
  42. :registration_page,
  43. user_invite_token.token
  44. )
  45. html_body = """
  46. <h3>You are invited to #{instance_name()}</h3>
  47. <p>#{user.name} invites you to join #{instance_name()}, an instance of Pleroma federated social networking platform.</p>
  48. <p>Click the following link to register: <a href="#{registration_url}">accept invitation</a>.</p>
  49. """
  50. new()
  51. |> to(recipient(to_email, to_name))
  52. |> from(sender())
  53. |> subject("Invitation to #{instance_name()}")
  54. |> html_body(html_body)
  55. end
  56. def account_confirmation_email(user) do
  57. confirmation_url =
  58. Router.Helpers.confirm_email_url(
  59. Endpoint,
  60. :confirm_email,
  61. user.id,
  62. to_string(user.confirmation_token)
  63. )
  64. html_body = """
  65. <h3>Welcome to #{instance_name()}!</h3>
  66. <p>Email confirmation is required to activate the account.</p>
  67. <p>Click the following link to proceed: <a href="#{confirmation_url}">activate your account</a>.</p>
  68. """
  69. new()
  70. |> to(recipient(user))
  71. |> from(sender())
  72. |> subject("#{instance_name()} account confirmation")
  73. |> html_body(html_body)
  74. end
  75. @doc """
  76. Email used in digest email notifications
  77. Includes Mentions and New Followers data
  78. If there are no mentions (even when new followers exist), the function will return nil
  79. """
  80. @spec digest_email(User.t()) :: Swoosh.Email.t() | nil
  81. def digest_email(user) do
  82. notifications = Pleroma.Notification.for_user_since(user, user.last_digest_emailed_at)
  83. mentions =
  84. notifications
  85. |> Enum.filter(&(&1.activity.data["type"] == "Create"))
  86. |> Enum.map(fn notification ->
  87. object = Pleroma.Object.normalize(notification.activity)
  88. object = update_in(object.data["content"], &format_links/1)
  89. %{
  90. data: notification,
  91. object: object,
  92. from: User.get_by_ap_id(notification.activity.actor)
  93. }
  94. end)
  95. followers =
  96. notifications
  97. |> Enum.filter(&(&1.activity.data["type"] == "Follow"))
  98. |> Enum.map(fn notification ->
  99. %{
  100. data: notification,
  101. object: Pleroma.Object.normalize(notification.activity),
  102. from: User.get_by_ap_id(notification.activity.actor)
  103. }
  104. end)
  105. unless Enum.empty?(mentions) do
  106. styling = Config.get([__MODULE__, :styling])
  107. logo = Config.get([__MODULE__, :logo])
  108. html_data = %{
  109. instance: instance_name(),
  110. user: user,
  111. mentions: mentions,
  112. followers: followers,
  113. unsubscribe_link: unsubscribe_url(user, "digest"),
  114. styling: styling
  115. }
  116. logo_path =
  117. if is_nil(logo) do
  118. Path.join(:code.priv_dir(:pleroma), "static/static/logo.png")
  119. else
  120. Path.join(Config.get([:instance, :static_dir]), logo)
  121. end
  122. new()
  123. |> to(recipient(user))
  124. |> from(sender())
  125. |> subject("Your digest from #{instance_name()}")
  126. |> put_layout(false)
  127. |> render_body("digest.html", html_data)
  128. |> attachment(Swoosh.Attachment.new(logo_path, filename: "logo.png", type: :inline))
  129. end
  130. end
  131. defp format_links(str) do
  132. re = ~r/<a.+href=['"].*>/iU
  133. %{link_color: color} = Config.get([__MODULE__, :styling])
  134. Regex.replace(re, str, fn link ->
  135. String.replace(link, "<a", "<a style=\"color: #{color};text-decoration: none;\"")
  136. end)
  137. end
  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(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. Router.Helpers.subscription_url(Endpoint, :unsubscribe, token)
  150. end
  151. end