Merge branch 'feature/new-registrations-digest' into 'develop'
New users digest email Closes #1514 See merge request pleroma/pleroma!2128
This commit is contained in:
commit
e0b2de6385
@ -72,6 +72,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
- User notification settings: Add `privacy_option` option.
|
- User notification settings: Add `privacy_option` option.
|
||||||
- Support for custom Elixir modules (such as MRF policies)
|
- Support for custom Elixir modules (such as MRF policies)
|
||||||
- User settings: Add _This account is a_ option.
|
- User settings: Add _This account is a_ option.
|
||||||
|
- A new users admin digest email
|
||||||
- OAuth: admin scopes support (relevant setting: `[:auth, :enforce_oauth_admin_scope_usage]`).
|
- OAuth: admin scopes support (relevant setting: `[:auth, :enforce_oauth_admin_scope_usage]`).
|
||||||
<details>
|
<details>
|
||||||
<summary>API Changes</summary>
|
<summary>API Changes</summary>
|
||||||
|
@ -480,13 +480,15 @@ config :pleroma, Oban,
|
|||||||
transmogrifier: 20,
|
transmogrifier: 20,
|
||||||
scheduled_activities: 10,
|
scheduled_activities: 10,
|
||||||
background: 5,
|
background: 5,
|
||||||
attachments_cleanup: 5
|
attachments_cleanup: 5,
|
||||||
|
new_users_digest: 1
|
||||||
],
|
],
|
||||||
crontab: [
|
crontab: [
|
||||||
{"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker},
|
{"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker},
|
||||||
{"0 * * * *", Pleroma.Workers.Cron.StatsWorker},
|
{"0 * * * *", Pleroma.Workers.Cron.StatsWorker},
|
||||||
{"* * * * *", Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker},
|
{"* * * * *", Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker},
|
||||||
{"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker}
|
{"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker},
|
||||||
|
{"0 0 * * *", Pleroma.Workers.Cron.NewUsersDigestWorker}
|
||||||
]
|
]
|
||||||
|
|
||||||
config :pleroma, :workers,
|
config :pleroma, :workers,
|
||||||
@ -560,6 +562,8 @@ config :pleroma, Pleroma.Emails.UserEmail,
|
|||||||
text_muted_color: "#b9b9ba"
|
text_muted_color: "#b9b9ba"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Emails.NewUsersDigestEmail, enabled: false
|
||||||
|
|
||||||
config :prometheus, Pleroma.Web.Endpoint.MetricsExporter, path: "/api/pleroma/app_metrics"
|
config :prometheus, Pleroma.Web.Endpoint.MetricsExporter, path: "/api/pleroma/app_metrics"
|
||||||
|
|
||||||
config :pleroma, Pleroma.ScheduledActivity,
|
config :pleroma, Pleroma.ScheduledActivity,
|
||||||
|
@ -2502,6 +2502,20 @@ config :pleroma, :config_description, [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
%{
|
||||||
|
group: :pleroma,
|
||||||
|
key: Pleroma.Emails.NewUsersDigestEmail,
|
||||||
|
type: :group,
|
||||||
|
description: "New users admin email digest",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :enabled,
|
||||||
|
type: :boolean,
|
||||||
|
description: "enables new users admin digest email when `true`",
|
||||||
|
suggestions: [false]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
%{
|
%{
|
||||||
group: :pleroma,
|
group: :pleroma,
|
||||||
key: :oauth2,
|
key: :oauth2,
|
||||||
|
@ -94,6 +94,8 @@ config :pleroma, Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.ClientMock
|
|||||||
|
|
||||||
config :pleroma, :modules, runtime_dir: "test/fixtures/modules"
|
config :pleroma, :modules, runtime_dir: "test/fixtures/modules"
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Emails.NewUsersDigestEmail, enabled: true
|
||||||
|
|
||||||
if File.exists?("./config/test.secret.exs") do
|
if File.exists?("./config/test.secret.exs") do
|
||||||
import_config "test.secret.exs"
|
import_config "test.secret.exs"
|
||||||
else
|
else
|
||||||
|
@ -501,6 +501,10 @@ Email notifications settings.
|
|||||||
- `:logo` - a path to a custom logo. Set it to `nil` to use the default Pleroma logo.
|
- `:logo` - a path to a custom logo. Set it to `nil` to use the default Pleroma logo.
|
||||||
- `:styling` - a map with color settings for email templates.
|
- `:styling` - a map with color settings for email templates.
|
||||||
|
|
||||||
|
### Pleroma.Emails.NewUsersDigestEmail
|
||||||
|
|
||||||
|
- `:enabled` - a boolean, enables new users admin digest email when `true`. Defaults to `false`.
|
||||||
|
|
||||||
## Background jobs
|
## Background jobs
|
||||||
|
|
||||||
### Oban
|
### Oban
|
||||||
|
32
lib/pleroma/emails/new_users_digest_email.ex
Normal file
32
lib/pleroma/emails/new_users_digest_email.ex
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Emails.NewUsersDigestEmail do
|
||||||
|
use Phoenix.Swoosh, view: Pleroma.Web.EmailView, layout: {Pleroma.Web.LayoutView, :email_styled}
|
||||||
|
|
||||||
|
defp instance_notify_email do
|
||||||
|
Pleroma.Config.get([:instance, :notify_email]) || Pleroma.Config.get([:instance, :email])
|
||||||
|
end
|
||||||
|
|
||||||
|
def new_users(to, users_and_statuses) do
|
||||||
|
instance_name = Pleroma.Config.get([:instance, :name])
|
||||||
|
styling = Pleroma.Config.get([Pleroma.Emails.UserEmail, :styling])
|
||||||
|
|
||||||
|
logo_url =
|
||||||
|
Pleroma.Web.Endpoint.url() <>
|
||||||
|
Pleroma.Config.get([:frontend_configurations, :pleroma_fe, :logo])
|
||||||
|
|
||||||
|
new()
|
||||||
|
|> to({to.name, to.email})
|
||||||
|
|> from({instance_name, instance_notify_email()})
|
||||||
|
|> subject("#{instance_name} New Users")
|
||||||
|
|> render_body("new_users_digest.html", %{
|
||||||
|
title: "New Users",
|
||||||
|
users_and_statuses: users_and_statuses,
|
||||||
|
instance: instance_name,
|
||||||
|
styling: styling,
|
||||||
|
logo_url: logo_url
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
158
lib/pleroma/web/templates/email/new_users_digest.html.eex
Normal file
158
lib/pleroma/web/templates/email/new_users_digest.html.eex
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
<%= for {user, total_statuses, latest_status} <- @users_and_statuses do %>
|
||||||
|
<%# user card START %>
|
||||||
|
<div style="background-color:transparent;">
|
||||||
|
<div class="block-grid mixed-two-up no-stack"
|
||||||
|
style="Margin: 0 auto; min-width: 320px; max-width: 590px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; background-color: <%= @styling.content_background_color%>;">
|
||||||
|
<div style="border-collapse: collapse;display: table;width: 100%;background-color:<%= @styling.content_background_color%>;">
|
||||||
|
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:transparent;"><tr><td align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:590px"><tr class="layout-full-width" style="background-color:<%= @styling.content_background_color%>"><![endif]-->
|
||||||
|
<!--[if (mso)|(IE)]><td align="center" width="147" style="background-color:<%= @styling.content_background_color%>;width:76px; border-top: 0px solid transparent; border-left: 0px solid transparent; border-bottom: 0px solid transparent; border-right: 0px solid transparent;" valign="top"><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 0px; padding-left: 20px; padding-top:5px; padding-bottom:5px;"><![endif]-->
|
||||||
|
<div class="col num3"
|
||||||
|
style="display: table-cell; vertical-align: top; max-width: 320px; min-width: 76px; width: 76px;">
|
||||||
|
<div style="width:100% !important;">
|
||||||
|
<!--[if (!mso)&(!IE)]><!-->
|
||||||
|
<div
|
||||||
|
style="border-top:0px solid transparent; border-left:0px solid transparent; border-bottom:0px solid transparent; border-right:0px solid transparent; padding-top:5px; padding-bottom:5px; padding-right: 0px; padding-left: 20px;">
|
||||||
|
<!--<![endif]-->
|
||||||
|
<div align="left" class="img-container left "
|
||||||
|
style="padding-right: 0px;padding-left: 0px;">
|
||||||
|
<!--[if mso]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr style="line-height:0px"><td style="padding-right: 0px;padding-left: 0px;" align="left"><![endif]--><img
|
||||||
|
alt="<%= user.name %>" border="0" class="left " src="<%= avatar_url(user) %>"
|
||||||
|
style="text-decoration: none; -ms-interpolation-mode: bicubic; border: 0; height: auto; width: 100%; max-width: 76px; display: block;"
|
||||||
|
title="<%= user.name %>" width="76" />
|
||||||
|
<!--[if mso]></td></tr></table><![endif]-->
|
||||||
|
</div>
|
||||||
|
<!--[if (!mso)&(!IE)]><!-->
|
||||||
|
</div>
|
||||||
|
<!--<![endif]-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--[if (mso)|(IE)]></td></tr></table><![endif]-->
|
||||||
|
<!--[if (mso)|(IE)]></td><td align="center" width="442" style="background-color:<%= @styling.content_background_color%>;width:442px; border-top: 0px solid transparent; border-left: 0px solid transparent; border-bottom: 0px solid transparent; border-right: 0px solid transparent;" valign="top"><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 0px; padding-left: 0px; padding-top:5px; padding-bottom:5px;"><![endif]-->
|
||||||
|
<div class="col num9"
|
||||||
|
style="display: table-cell; vertical-align: top; min-width: 320px; max-width: 441px; width: 442px;">
|
||||||
|
<div style="width:100% !important;">
|
||||||
|
<!--[if (!mso)&(!IE)]><!-->
|
||||||
|
<div
|
||||||
|
style="border-top:0px solid transparent; border-left:0px solid transparent; border-bottom:0px solid transparent; border-right:0px solid transparent; padding-top:5px; padding-bottom:5px; padding-right: 0px; padding-left: 0px;">
|
||||||
|
<!--<![endif]-->
|
||||||
|
<!--[if mso]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 10px; padding-left: 10px; padding-top: 10px; padding-bottom: 10px; font-family: Arial, sans-serif"><![endif]-->
|
||||||
|
<div
|
||||||
|
style="color:<%= @styling.text_color %>;font-family:Arial, 'Helvetica Neue', Helvetica, sans-serif;line-height:120%;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;">
|
||||||
|
<div
|
||||||
|
style="font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; font-size: 12px; line-height: 14px; color: <%= @styling.text_color %>;">
|
||||||
|
<p style="font-size: 14px; line-height: 19px; margin: 0;"><span
|
||||||
|
style="font-size: 16px; color: <%= @styling.text_color %>;"><%= user.name %></span></p>
|
||||||
|
<p style="font-size: 14px; line-height: 19px; margin: 0;"><span
|
||||||
|
style="font-size: 16px;"><%= link "@" <> user.nickname, style: "color: #{@styling.link_color};text-decoration: none;", to: admin_user_url(user) %></span></p>
|
||||||
|
<p style="font-size: 14px; line-height: 19px; margin: 0;"><span
|
||||||
|
style="font-size: 16px;">Total: <%= total_statuses %></span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--[if mso]></td></tr></table><![endif]-->
|
||||||
|
<!--[if (!mso)&(!IE)]><!-->
|
||||||
|
</div>
|
||||||
|
<!--<![endif]-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--[if (mso)|(IE)]></td></tr></table><![endif]-->
|
||||||
|
<!--[if (mso)|(IE)]></td></tr></table></td></tr></table><![endif]-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%# user card END %>
|
||||||
|
|
||||||
|
<%= if latest_status do %>
|
||||||
|
<div style="background-color:transparent;">
|
||||||
|
<div class="block-grid"
|
||||||
|
style="Margin: 0 auto; min-width: 320px; max-width: 590px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; background-color: <%= @styling.content_background_color%>;">
|
||||||
|
<div style="border-collapse: collapse;display: table;width: 100%;background-color:<%= @styling.content_background_color%>;">
|
||||||
|
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:transparent;"><tr><td align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:590px"><tr class="layout-full-width" style="background-color:<%= @styling.content_background_color%>"><![endif]-->
|
||||||
|
<!--[if (mso)|(IE)]><td align="center" width="590" style="background-color:<%= @styling.content_background_color%>;width:590px; border-top: 0px solid transparent; border-left: 0px solid transparent; border-bottom: 0px solid transparent; border-right: 0px solid transparent;" valign="top"><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 15px; padding-left: 15px; padding-top:5px; padding-bottom:5px;"><![endif]-->
|
||||||
|
<div class="col num12"
|
||||||
|
style="min-width: 320px; max-width: 590px; display: table-cell; vertical-align: top; width: 590px;">
|
||||||
|
<div style="width:100% !important;">
|
||||||
|
<!--[if (!mso)&(!IE)]><!-->
|
||||||
|
<div
|
||||||
|
style="border-top:0px solid transparent; border-left:0px solid transparent; border-bottom:0px solid transparent; border-right:0px solid transparent; padding-top:5px; padding-bottom:5px; padding-right: 15px; padding-left: 15px;">
|
||||||
|
<!--<![endif]-->
|
||||||
|
<!--[if mso]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 10px; padding-left: 10px; padding-top: 10px; padding-bottom: 10px; font-family: Arial, sans-serif"><![endif]-->
|
||||||
|
<div
|
||||||
|
style="color:<%= @styling.text_color %>;font-family:Arial, 'Helvetica Neue', Helvetica, sans-serif;line-height:120%;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;">
|
||||||
|
<div
|
||||||
|
style="font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; font-size: 12px; line-height: 14px; color: <%= @styling.text_color %>;">
|
||||||
|
<span style="font-size: 16px; line-height: 19px;"><%= raw latest_status.object.data["content"] %></span></div>
|
||||||
|
</div>
|
||||||
|
<!--[if mso]></td></tr></table><![endif]-->
|
||||||
|
<!--[if mso]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 10px; padding-left: 15px; padding-top: 10px; padding-bottom: 10px; font-family: Arial, sans-serif"><![endif]-->
|
||||||
|
<div
|
||||||
|
style="color:<%= @styling.text_muted_color %>;font-family:Arial, 'Helvetica Neue', Helvetica, sans-serif;line-height:120%;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:15px;">
|
||||||
|
<div
|
||||||
|
style="font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif; font-size: 12px; line-height: 14px; color: <%= @styling.text_muted_color %>;">
|
||||||
|
<p style="font-size: 14px; line-height: 16px; margin: 0;"><%= format_date latest_status.object.data["published"] %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--[if mso]></td></tr></table><![endif]-->
|
||||||
|
<!--[if (!mso)&(!IE)]><!-->
|
||||||
|
</div>
|
||||||
|
<!--<![endif]-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--[if (mso)|(IE)]></td></tr></table><![endif]-->
|
||||||
|
<!--[if (mso)|(IE)]></td></tr></table></td></tr></table><![endif]-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<%# divider start %>
|
||||||
|
<div style="background-color:transparent;">
|
||||||
|
<div class="block-grid"
|
||||||
|
style="Margin: 0 auto; min-width: 320px; max-width: 590px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; background-color: <%= @styling.content_background_color%>;">
|
||||||
|
<div style="border-collapse: collapse;display: table;width: 100%;background-color:<%= @styling.content_background_color%>;">
|
||||||
|
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:transparent;"><tr><td align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:590px"><tr class="layout-full-width" style="background-color:<%= @styling.content_background_color%>"><![endif]-->
|
||||||
|
<!--[if (mso)|(IE)]><td align="center" width="590" style="background-color:<%= @styling.content_background_color%>;width:590px; border-top: 0px solid transparent; border-left: 0px solid transparent; border-bottom: 0px solid transparent; border-right: 0px solid transparent;" valign="top"><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 0px; padding-left: 0px; padding-top:5px; padding-bottom:5px;"><![endif]-->
|
||||||
|
<div class="col num12"
|
||||||
|
style="min-width: 320px; max-width: 590px; display: table-cell; vertical-align: top; width: 590px;">
|
||||||
|
<div style="width:100% !important;">
|
||||||
|
<!--[if (!mso)&(!IE)]><!-->
|
||||||
|
<div
|
||||||
|
style="border-top:0px solid transparent; border-left:0px solid transparent; border-bottom:0px solid transparent; border-right:0px solid transparent; padding-top:5px; padding-bottom:5px; padding-right: 0px; padding-left: 0px;">
|
||||||
|
<!--<![endif]-->
|
||||||
|
<table border="0" cellpadding="0" cellspacing="0" class="divider" role="presentation"
|
||||||
|
style="table-layout: fixed; vertical-align: top; border-spacing: 0; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; min-width: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;"
|
||||||
|
valign="top" width="100%">
|
||||||
|
<tbody>
|
||||||
|
<tr style="vertical-align: top;" valign="top">
|
||||||
|
<td class="divider_inner"
|
||||||
|
style="word-break: break-word; vertical-align: top; min-width: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px;"
|
||||||
|
valign="top">
|
||||||
|
<table align="center" border="0" cellpadding="0" cellspacing="0" class="divider_content"
|
||||||
|
height="0" role="presentation"
|
||||||
|
style="table-layout: fixed; vertical-align: top; border-spacing: 0; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; border-top: 1px solid <%= @styling.text_color %>; height: 0px;"
|
||||||
|
valign="top" width="100%">
|
||||||
|
<tbody>
|
||||||
|
<tr style="vertical-align: top;" valign="top">
|
||||||
|
<td height="0"
|
||||||
|
style="word-break: break-word; vertical-align: top; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;"
|
||||||
|
valign="top"><span></span></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<!--[if (!mso)&(!IE)]><!-->
|
||||||
|
</div>
|
||||||
|
<!--<![endif]-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--[if (mso)|(IE)]></td></tr></table><![endif]-->
|
||||||
|
<!--[if (mso)|(IE)]></td></tr></table></td></tr></table><![endif]-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%# divider end %>
|
||||||
|
<%# user card END %>
|
||||||
|
<% end %>
|
193
lib/pleroma/web/templates/layout/email_styled.html.eex
Normal file
193
lib/pleroma/web/templates/layout/email_styled.html.eex
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
<!DOCTYPE html
|
||||||
|
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office"
|
||||||
|
xmlns:v="urn:schemas-microsoft-com:vml">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<!--[if gte mso 9]><xml><o:OfficeDocumentSettings><o:AllowPNG/><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml><![endif]-->
|
||||||
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
||||||
|
<meta content="width=device-width" name="viewport" />
|
||||||
|
<!--[if !mso]><!-->
|
||||||
|
<meta content="IE=edge" http-equiv="X-UA-Compatible" />
|
||||||
|
<!--<![endif]-->
|
||||||
|
<title><%= @email.subject %></title>
|
||||||
|
<!--[if !mso]><!-->
|
||||||
|
<!--<![endif]-->
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
|
||||||
|
color: <%= @styling.link_color %>;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table,
|
||||||
|
td,
|
||||||
|
tr {
|
||||||
|
vertical-align: top;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[x-apple-data-detectors=true] {
|
||||||
|
color: inherit !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style id="media-query" type="text/css">
|
||||||
|
@media (max-width: 610px) {
|
||||||
|
|
||||||
|
.block-grid,
|
||||||
|
.col {
|
||||||
|
min-width: 320px !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block-grid {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col>div {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-stack .col {
|
||||||
|
min-width: 0 !important;
|
||||||
|
display: table-cell !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-stack.two-up .col {
|
||||||
|
width: 50% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-stack .col.num4 {
|
||||||
|
width: 33% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-stack .col.num8 {
|
||||||
|
width: 66% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-stack .col.num4 {
|
||||||
|
width: 33% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-stack .col.num3 {
|
||||||
|
width: 25% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-stack .col.num6 {
|
||||||
|
width: 50% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-stack .col.num9 {
|
||||||
|
width: 75% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="clean-body" style="margin: 0; padding: 0; -webkit-text-size-adjust: 100%; background-color: <%= @styling.background_color %>;">
|
||||||
|
<!--[if IE]><div class="ie-browser"><![endif]-->
|
||||||
|
<table bgcolor="<%= @styling.background_color %>" cellpadding="0" cellspacing="0" class="nl-container" role="presentation"
|
||||||
|
style="table-layout: fixed; vertical-align: top; min-width: 320px; Margin: 0 auto; border-spacing: 0; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: <%= @styling.background_color %>; width: 100%;"
|
||||||
|
valign="top" width="100%">
|
||||||
|
<tbody>
|
||||||
|
<tr style="vertical-align: top;" valign="top">
|
||||||
|
<td style="word-break: break-word; vertical-align: top;" valign="top">
|
||||||
|
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td align="center" style="background-color:<%= @styling.background_color %>"><![endif]-->
|
||||||
|
|
||||||
|
<%# header %>
|
||||||
|
<div style="background-color:transparent;">
|
||||||
|
<div class="block-grid"
|
||||||
|
style="Margin: 0 auto; min-width: 320px; max-width: 590px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; background-color: <%= @styling.content_background_color%>;">
|
||||||
|
<div style="border-collapse: collapse;display: table;width: 100%;background-color:<%= @styling.content_background_color%>;">
|
||||||
|
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:transparent;"><tr><td align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:590px"><tr class="layout-full-width" style="background-color:<%= @styling.content_background_color%>"><![endif]-->
|
||||||
|
<!--[if (mso)|(IE)]><td align="center" width="590" style="background-color:<%= @styling.content_background_color%>;width:590px; border-top: 0px solid transparent; border-left: 0px solid transparent; border-bottom: 0px solid transparent; border-right: 0px solid transparent;" valign="top"><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 0px; padding-left: 0px; padding-top:5px; padding-bottom:5px;"><![endif]-->
|
||||||
|
<div class="col num12"
|
||||||
|
style="min-width: 320px; max-width: 590px; display: table-cell; vertical-align: top; width: 590px;">
|
||||||
|
<div style="width:100% !important;">
|
||||||
|
<!--[if (!mso)&(!IE)]><!-->
|
||||||
|
<div
|
||||||
|
style="border-top:0px solid transparent; border-left:0px solid transparent; border-bottom:0px solid transparent; border-right:0px solid transparent; padding-top:5px; padding-bottom:5px; padding-right: 0px; padding-left: 0px;">
|
||||||
|
<!--<![endif]-->
|
||||||
|
<div align="center" class="img-container center"
|
||||||
|
style="padding-right: 0px;padding-left: 0px;">
|
||||||
|
<!--[if mso]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr style="line-height:0px"><td style="padding-right: 0px;padding-left: 0px;" align="center"><![endif]--><img
|
||||||
|
align="center" alt="Image" border="0" class="center" src="<%= @logo_url %>"
|
||||||
|
style="text-decoration: none; -ms-interpolation-mode: bicubic; border: 0; height: 80px; width: auto; max-height: 80px; display: block;"
|
||||||
|
title="Image" height="80" />
|
||||||
|
<!--[if mso]></td></tr></table><![endif]-->
|
||||||
|
</div>
|
||||||
|
<!--[if (!mso)&(!IE)]><!-->
|
||||||
|
</div>
|
||||||
|
<!--<![endif]-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--[if (mso)|(IE)]></td></tr></table><![endif]-->
|
||||||
|
<!--[if (mso)|(IE)]></td></tr></table></td></tr></table><![endif]-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<%# title %>
|
||||||
|
<%= if @title do %>
|
||||||
|
<div style="background-color:transparent;">
|
||||||
|
<div class="block-grid"
|
||||||
|
style="Margin: 0 auto; min-width: 320px; max-width: 590px; overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; background-color: <%= @styling.content_background_color%>;">
|
||||||
|
<div style="border-collapse: collapse;display: table;width: 100%;background-color:<%= @styling.content_background_color%>;">
|
||||||
|
<!--[if (mso)|(IE)]><table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:transparent;"><tr><td align="center"><table cellpadding="0" cellspacing="0" border="0" style="width:590px"><tr class="layout-full-width" style="background-color:<%= @styling.content_background_color%>"><![endif]-->
|
||||||
|
<!--[if (mso)|(IE)]><td align="center" width="590" style="background-color:<%= @styling.content_background_color%>;width:590px; border-top: 0px solid transparent; border-left: 0px solid transparent; border-bottom: 0px solid transparent; border-right: 0px solid transparent;" valign="top"><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 0px; padding-left: 0px; padding-top:5px; padding-bottom:5px;"><![endif]-->
|
||||||
|
<div class="col num12"
|
||||||
|
style="min-width: 320px; max-width: 590px; display: table-cell; vertical-align: top; width: 590px;">
|
||||||
|
<div style="width:100% !important;">
|
||||||
|
<!--[if (!mso)&(!IE)]><!-->
|
||||||
|
<div
|
||||||
|
style="border-top:0px solid transparent; border-left:0px solid transparent; border-bottom:0px solid transparent; border-right:0px solid transparent; padding-top:5px; padding-bottom:5px; padding-right: 0px; padding-left: 0px;">
|
||||||
|
<!--<![endif]-->
|
||||||
|
<!--[if mso]><table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td style="padding-right: 10px; padding-left: 10px; padding-top: 10px; padding-bottom: 10px; font-family: Arial, sans-serif"><![endif]-->
|
||||||
|
<div
|
||||||
|
style="line-height:120%;padding-top:10px;padding-right:10px;padding-bottom:10px;padding-left:10px;">
|
||||||
|
<div
|
||||||
|
style="font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;line-height: 14px; color: <%= @styling.header_color %>;">
|
||||||
|
<p style="line-height: 36px; text-align: center; margin: 0;"><span
|
||||||
|
style="font-size: 30px; color: <%= @styling.header_color %>;"><%= @title %></span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--[if mso]></td></tr></table><![endif]-->
|
||||||
|
<!--[if (!mso)&(!IE)]><!-->
|
||||||
|
</div>
|
||||||
|
<!--<![endif]-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--[if (mso)|(IE)]></td></tr></table><![endif]-->
|
||||||
|
<!--[if (mso)|(IE)]></td></tr></table></td></tr></table><![endif]-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<%= render @view_module, @view_template, assigns %>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<!--[if (IE)]></div><![endif]-->
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -12,4 +12,8 @@ defmodule Pleroma.Web.EmailView do
|
|||||||
|> Timex.parse!("{ISO:Extended:Z}")
|
|> Timex.parse!("{ISO:Extended:Z}")
|
||||||
|> Timex.format!("{Mshort} {D}, {YYYY} {h24}:{m}")
|
|> Timex.format!("{Mshort} {D}, {YYYY} {h24}:{m}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def admin_user_url(%{id: id}) do
|
||||||
|
Pleroma.Web.Endpoint.url() <> "/pleroma/admin/#/users/" <> id
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
60
lib/pleroma/workers/cron/new_users_digest_worker.ex
Normal file
60
lib/pleroma/workers/cron/new_users_digest_worker.ex
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Workers.Cron.NewUsersDigestWorker do
|
||||||
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.Repo
|
||||||
|
alias Pleroma.User
|
||||||
|
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
use Pleroma.Workers.WorkerHelper, queue: "new_users_digest"
|
||||||
|
|
||||||
|
@impl Oban.Worker
|
||||||
|
def perform(_args, _job) do
|
||||||
|
if Pleroma.Config.get([Pleroma.Emails.NewUsersDigestEmail, :enabled]) do
|
||||||
|
today = NaiveDateTime.utc_now() |> Timex.beginning_of_day()
|
||||||
|
|
||||||
|
a_day_ago =
|
||||||
|
today
|
||||||
|
|> Timex.shift(days: -1)
|
||||||
|
|> Timex.beginning_of_day()
|
||||||
|
|
||||||
|
users_and_statuses =
|
||||||
|
%{
|
||||||
|
local: true,
|
||||||
|
order_by: :inserted_at
|
||||||
|
}
|
||||||
|
|> User.Query.build()
|
||||||
|
|> where([u], u.inserted_at >= ^a_day_ago and u.inserted_at < ^today)
|
||||||
|
|> Repo.all()
|
||||||
|
|> Enum.map(fn user ->
|
||||||
|
latest_status =
|
||||||
|
Activity
|
||||||
|
|> Activity.Queries.by_actor(user.ap_id)
|
||||||
|
|> Activity.Queries.by_type("Create")
|
||||||
|
|> Activity.with_preloaded_object()
|
||||||
|
|> order_by(desc: :inserted_at)
|
||||||
|
|> limit(1)
|
||||||
|
|> Repo.one()
|
||||||
|
|
||||||
|
total_statuses =
|
||||||
|
Activity
|
||||||
|
|> Activity.Queries.by_actor(user.ap_id)
|
||||||
|
|> Activity.Queries.by_type("Create")
|
||||||
|
|> Repo.aggregate(:count, :id)
|
||||||
|
|
||||||
|
{user, total_statuses, latest_status}
|
||||||
|
end)
|
||||||
|
|
||||||
|
if users_and_statuses != [] do
|
||||||
|
%{is_admin: true}
|
||||||
|
|> User.Query.build()
|
||||||
|
|> Repo.all()
|
||||||
|
|> Enum.map(&Pleroma.Emails.NewUsersDigestEmail.new_users(&1, users_and_statuses))
|
||||||
|
|> Enum.each(&Pleroma.Emails.Mailer.deliver/1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
32
test/workers/cron/new_users_digest_worker_test.exs
Normal file
32
test/workers/cron/new_users_digest_worker_test.exs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Workers.Cron.NewUsersDigestWorkerTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.Tests.ObanHelpers
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Workers.Cron.NewUsersDigestWorker
|
||||||
|
|
||||||
|
test "it sends new users digest emails" do
|
||||||
|
yesterday = NaiveDateTime.utc_now() |> Timex.shift(days: -1)
|
||||||
|
admin = insert(:user, %{is_admin: true})
|
||||||
|
user = insert(:user, %{inserted_at: yesterday})
|
||||||
|
user2 = insert(:user, %{inserted_at: yesterday})
|
||||||
|
CommonAPI.post(user, %{"status" => "cofe"})
|
||||||
|
|
||||||
|
NewUsersDigestWorker.perform(nil, nil)
|
||||||
|
ObanHelpers.perform_all()
|
||||||
|
|
||||||
|
assert_received {:email, email}
|
||||||
|
assert email.to == [{admin.name, admin.email}]
|
||||||
|
assert email.subject == "#{Pleroma.Config.get([:instance, :name])} New Users"
|
||||||
|
|
||||||
|
refute email.html_body =~ admin.nickname
|
||||||
|
assert email.html_body =~ user.nickname
|
||||||
|
assert email.html_body =~ user2.nickname
|
||||||
|
assert email.html_body =~ "cofe"
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user