Merge branch 'feature/new-registrations-digest' into 'develop'
authorlain <lain@soykaf.club>
Thu, 20 Feb 2020 11:58:37 +0000 (11:58 +0000)
committerlain <lain@soykaf.club>
Thu, 20 Feb 2020 11:58:37 +0000 (11:58 +0000)
New users digest email

Closes #1514

See merge request pleroma/pleroma!2128

CHANGELOG.md
config/config.exs
config/description.exs
config/test.exs
docs/configuration/cheatsheet.md
lib/pleroma/emails/new_users_digest_email.ex [new file with mode: 0644]
lib/pleroma/web/templates/email/new_users_digest.html.eex [new file with mode: 0644]
lib/pleroma/web/templates/layout/email_styled.html.eex [new file with mode: 0644]
lib/pleroma/web/views/email_view.ex
lib/pleroma/workers/cron/new_users_digest_worker.ex [new file with mode: 0644]
test/workers/cron/new_users_digest_worker_test.exs [new file with mode: 0644]

index 3e838983b4b4393e26f0ae8ae27a90e685c7acbb..ce0f584cba9342aa223d2ae7aaf0a8c2e1d6965c 100644 (file)
@@ -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.
 - Support for custom Elixir modules (such as MRF policies)
 - 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]`).
 <details>
   <summary>API Changes</summary>
index ccc0c4e525b99b79a08a2c64e8fd6761ac8ff59f..664572cf31bc65460666ed889a4aeb9642ad411c 100644 (file)
@@ -480,13 +480,15 @@ config :pleroma, Oban,
     transmogrifier: 20,
     scheduled_activities: 10,
     background: 5,
-    attachments_cleanup: 5
+    attachments_cleanup: 5,
+    new_users_digest: 1
   ],
   crontab: [
     {"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker},
     {"0 * * * *", Pleroma.Workers.Cron.StatsWorker},
     {"* * * * *", 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,
@@ -560,6 +562,8 @@ config :pleroma, Pleroma.Emails.UserEmail,
     text_muted_color: "#b9b9ba"
   }
 
+config :pleroma, Pleroma.Emails.NewUsersDigestEmail, enabled: false
+
 config :prometheus, Pleroma.Web.Endpoint.MetricsExporter, path: "/api/pleroma/app_metrics"
 
 config :pleroma, Pleroma.ScheduledActivity,
index 0c0f4af3cc6bcb4d7c48af4b32833f6a775428ac..53d980c83a8800eec2e518c578c2fdc3aa8e63fb 100644 (file)
@@ -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,
     key: :oauth2,
index 078c462051e67ac1861e17c4d71d76945f3f9379..6bea0938061cc7afa07e64923ed342808fd482c9 100644 (file)
@@ -94,6 +94,8 @@ config :pleroma, Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.ClientMock
 
 config :pleroma, :modules, runtime_dir: "test/fixtures/modules"
 
+config :pleroma, Pleroma.Emails.NewUsersDigestEmail, enabled: true
+
 if File.exists?("./config/test.secret.exs") do
   import_config "test.secret.exs"
 else
index 2bd9359832254b662c78224e81b1b78bdc393ba0..c9559fe858286ab4dc9c3e7d0c5dba319cc52626 100644 (file)
@@ -501,6 +501,10 @@ Email notifications settings.
 - `: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.
 
+### Pleroma.Emails.NewUsersDigestEmail
+
+- `:enabled` - a boolean, enables new users admin digest email when `true`. Defaults to `false`.
+
 ## Background jobs
 
 ### Oban
diff --git a/lib/pleroma/emails/new_users_digest_email.ex b/lib/pleroma/emails/new_users_digest_email.ex
new file mode 100644 (file)
index 0000000..7d16b80
--- /dev/null
@@ -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
diff --git a/lib/pleroma/web/templates/email/new_users_digest.html.eex b/lib/pleroma/web/templates/email/new_users_digest.html.eex
new file mode 100644 (file)
index 0000000..40d9b83
--- /dev/null
@@ -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 %>
diff --git a/lib/pleroma/web/templates/layout/email_styled.html.eex b/lib/pleroma/web/templates/layout/email_styled.html.eex
new file mode 100644 (file)
index 0000000..ca2caaf
--- /dev/null
@@ -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>
index b506a234b636f4d2a204448eb11ef984c271d449..6b0fbe61ee2348a7f138a29cbbea1c340d919a0b 100644 (file)
@@ -12,4 +12,8 @@ defmodule Pleroma.Web.EmailView do
     |> Timex.parse!("{ISO:Extended:Z}")
     |> Timex.format!("{Mshort} {D}, {YYYY} {h24}:{m}")
   end
+
+  def admin_user_url(%{id: id}) do
+    Pleroma.Web.Endpoint.url() <> "/pleroma/admin/#/users/" <> id
+  end
 end
diff --git a/lib/pleroma/workers/cron/new_users_digest_worker.ex b/lib/pleroma/workers/cron/new_users_digest_worker.ex
new file mode 100644 (file)
index 0000000..951c2c0
--- /dev/null
@@ -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
diff --git a/test/workers/cron/new_users_digest_worker_test.exs b/test/workers/cron/new_users_digest_worker_test.exs
new file mode 100644 (file)
index 0000000..2f439c1
--- /dev/null
@@ -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