-
Notifications
You must be signed in to change notification settings - Fork 444
Auto dispatch emails #4167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Auto dispatch emails #4167
Changes from 3 commits
393c392
6adc148
97e974e
db67ff6
a6c003f
5cdfa6e
aeec33c
f35a328
fca92e2
a8cb1e4
5869d0c
7c36c7f
2690ad9
407c779
f5c91e9
173bf36
399f849
5ef9324
83ee73b
e1bb879
0e77f8a
603ac11
3e3e7ff
09d02ad
d707311
6543105
25107c9
f18159b
7f47d87
6eb6ce2
bf2a54a
2a425a0
58e3141
e55c7d0
212f97a
be7ff8f
7399282
2d5095a
5c9380d
24d2e1b
007b0ca
2639a0b
f6c2463
73b6fac
d87b99e
07932dd
587fa42
06ad4e6
a091abb
2329383
e3590b0
de46b88
1413ebf
69b34c8
89d9941
60119bd
b06d971
51c937b
51f2597
2f95af5
6eca4aa
5ec786e
fa269f6
0c0eb0b
e58245f
1102cbb
610e817
9c55cfd
b1df096
e36ed96
7067c83
cf701a2
f298e0c
756abf8
1aa621a
6b2ab9f
0317710
4a5b968
b04b4db
4392053
386807d
781e880
1249431
f9c0ee4
b460a1d
79efb56
69541a1
7894451
750a525
cf813d5
c1c9e43
8e26760
3ffbdc2
7c9f17d
331e371
2c4464d
3e58510
172c675
76ebff4
3ec3dea
bc08be5
e53f6c1
f9490ff
f8815c4
3ee69e5
dd682da
60643ad
06178d9
9df7cd5
527ba42
e22d75e
2aca8a3
81a7d90
be68594
18e612f
9e403aa
890422f
9013d91
3513d76
d371eb2
2a675ca
de6fab9
182d4f7
29c57da
bc9b00b
9463305
90f925e
86f4d71
7b38c23
e9ffc2a
2f01930
60fec69
a94a492
a80d492
d586a54
d9afd89
eee0c5b
cbb6e5b
0ef01b7
ed098c2
d31980c
0678bd2
f17032d
5cd83f7
3b26d8f
5bb9e3a
8c49dbb
ed4e9a9
9ce18bc
f5b71f0
fde3d3f
c8d25b0
e7c87fb
f13d1df
19d7af7
e47b4a5
419b095
05fa4d2
fd4eb52
d1327ed
859352a
ea26d71
92b6bcb
e5b203c
f7ba47e
ad0a8cc
e0f7ab0
f016290
7b22ab5
34a75e9
75d5126
e0fafd5
2eb93fe
bcb0a68
97ab987
1cfc108
589dc83
06d5f0b
80cc733
1b19bf7
895c51b
0348d1c
45712f2
3b1f85b
5168257
47d026f
93c026f
c323323
a36aac4
93595ab
de3e567
f78539e
1e4604a
00d9b3e
672dc3d
9c06011
7ae87e6
a1efced
ecbd92f
5a6917e
6161835
ce87b7a
d8fed62
2a4723f
3945a5d
a43a2ea
6cafe4b
024eac9
4574946
9458919
480e23d
896f804
66e195e
689dd4e
b1d760a
fab5059
6076c22
011f41b
3c469b6
b2b87b7
1eb31bc
8f9371b
395d3ce
f7133b7
bbfe21a
6ca5046
9c0c70d
edbd0ea
6fda534
cdc277f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| class SendPushCreatedEmailJob < ApplicationJob | ||
| queue_as :default | ||
|
|
||
| def perform(push) | ||
| return if push.notify_emails_to.blank? | ||
|
|
||
| PushCreatedMailer.with(record: push).notify.deliver_now | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| class PushCreatedMailer < ApplicationMailer | ||
| def notify | ||
| @push = params[:record] | ||
| locale = @push.notify_emails_to_locale.presence | ||
| I18n.with_locale(locale || I18n.default_locale) do | ||
| @secret_url = secret_url_for_push(@push, locale: locale) | ||
| @subject = "#{Settings.brand&.title || "Password Pusher"} #{_("has sent you a push")}" | ||
| mail( | ||
| to: parse_emails(@push.notify_emails_to), | ||
| subject: @subject | ||
| ) | ||
| end | ||
|
LukasMalyszko marked this conversation as resolved.
|
||
| end | ||
|
|
||
| private | ||
|
|
||
| def parse_emails(raw) | ||
| raw.to_s.split(",").map(&:strip).reject(&:blank?) | ||
|
LukasMalyszko marked this conversation as resolved.
Outdated
|
||
| end | ||
|
|
||
| def secret_url_for_push(push, locale: nil) | ||
| raw_url = if push.retrieval_step | ||
| preliminary_push_url(push) | ||
| else | ||
| push_url(push) | ||
| end | ||
| base = raw_url.split("?").first | ||
| if locale.present? && Array(Settings.enabled_language_codes).include?(locale.to_s) | ||
|
LukasMalyszko marked this conversation as resolved.
Outdated
|
||
| base += "?locale=#{locale}" | ||
| end | ||
|
LukasMalyszko marked this conversation as resolved.
|
||
| base = base.gsub(/http/i, "https") if ENV.key?("FORCE_SSL") | ||
|
LukasMalyszko marked this conversation as resolved.
Outdated
|
||
| base | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Pwpush | ||
| module NotifyEmailsTo | ||
| extend ActiveSupport::Concern | ||
|
|
||
| included do | ||
| validates :notify_emails_to, multiple_emails: true, allow_blank: true | ||
|
LukasMalyszko marked this conversation as resolved.
Outdated
|
||
| end | ||
|
|
||
| # Enqueue job to send creation email if notify_emails_to is present. | ||
| def send_creation_emails | ||
| return if notify_emails_to.blank? | ||
|
|
||
| if Rails.env.development? | ||
| SendPushCreatedEmailJob.perform_now(self) | ||
| else | ||
| SendPushCreatedEmailJob.perform_later(self) | ||
| end | ||
|
LukasMalyszko marked this conversation as resolved.
Outdated
|
||
| end | ||
|
LukasMalyszko marked this conversation as resolved.
Outdated
|
||
| end | ||
| end | ||
|
LukasMalyszko marked this conversation as resolved.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| # Validates comma-separated email addresses: format, max 5, no duplicates. | ||
| class MultipleEmailsValidator < ActiveModel::EachValidator | ||
| EMAIL_REGEX = /\A[^@\s]+@[^@\s]+\.[^@\s]+\z/ | ||
| MAX_EMAILS = 5 | ||
|
|
||
| def validate_each(record, attribute, value) | ||
| return if value.blank? | ||
|
|
||
| emails = value.to_s.split(",").map(&:strip).reject(&:blank?) | ||
|
|
||
| if emails.size > MAX_EMAILS | ||
| record.errors.add(attribute, "You can enter at most %{count} email addresses", count: MAX_EMAILS) | ||
| end | ||
|
|
||
| if emails.size != emails.uniq.size | ||
|
LukasMalyszko marked this conversation as resolved.
Outdated
|
||
| record.errors.add(attribute, "Duplicate email addresses are not allowed") | ||
| end | ||
|
|
||
| invalid = emails.reject { |e| e.match?(EMAIL_REGEX) } | ||
| unless invalid.empty? | ||
| record.errors.add(attribute, "%{list} are invalid email addresses", list: invalid.join(", ")) | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| <h1><%= Settings.brand.title %> <%= _('has sent you a push') %></h1> | ||
|
LukasMalyszko marked this conversation as resolved.
Outdated
|
||
|
|
||
| <p> | ||
| <%= _('Use the link below to view the shared content. The link will expire after a certain number of views or time.') %> | ||
| </p> | ||
|
|
||
| <p> | ||
| <%= link_to _('View the secret'), @secret_url %> | ||
| </p> | ||
|
|
||
| <p class="text-muted small"> | ||
| <%= _('Or copy and paste this URL into your browser') %> | ||
| </p> | ||
| <pre><%= @secret_url %></pre> | ||
|
|
||
| <%= render 'shared/email_footer' %> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| <%= Settings.brand.title %> <%= _('has sent you a push') %> | ||
|
LukasMalyszko marked this conversation as resolved.
Outdated
|
||
|
|
||
| <%= _('Use the link below to view the shared content. The link will expire after a certain number of views or time.') %> | ||
|
|
||
| <%= _('View the secret') %>: <%= @secret_url %> | ||
|
|
||
| <%= _('Or copy and paste this URL into your browser') %>: <%= @secret_url %> | ||
|
|
||
| -- | ||
| <%= Settings.brand.title %> | ||
| <%= Settings.brand.tagline %> | ||
|
LukasMalyszko marked this conversation as resolved.
Outdated
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <% unless action_name == 'edit' %> | ||
| <div class='row mb-3'> | ||
| <div class='col'> | ||
| <div class="input-group"> | ||
| <span class="input-group-text"><%= _('Email notification recipients') %></span> | ||
| <%= f.text_field(:notify_emails_to, { class: "form-control", | ||
| placeholder: _('Enter email addresses separated by commas'), | ||
| autocomplete: "off" }) %> | ||
| </div> | ||
| <div class="form-text"><%= _('Enter email addresses separated by commas') %></div> | ||
| </div> | ||
| </div> | ||
| <% end %> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| <% unless action_name == 'edit' %> | ||
| <div class='row mb-3'> | ||
| <div class='col'> | ||
| <div class="input-group"> | ||
| <span class="input-group-text"><%= _('Email notification language') %></span> | ||
| <%= f.select(:notify_emails_to_locale, | ||
| options_for_select([["", ""]] + language_options_for_select, f.object.notify_emails_to_locale), | ||
| {}, | ||
| { class: "form-select" }) %> | ||
| </div> | ||
| <div class="form-text"><%= _('Select the language of the email notification') %></div> | ||
| </div> | ||
| </div> | ||
| <% end %> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| class AddNotifyEmailsToPushes < ActiveRecord::Migration[8.1] | ||
| def change | ||
| add_column :pushes, :notify_emails_to, :text | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These fields should be encrypted like in Pro:
Then in the concern, we set Double check the Pro implementation and the OSS implementation. They should be as similar as possible.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added like in PRO |
||
| add_column :pushes, :notify_emails_to_locale, :string | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -181,4 +181,59 @@ def push_url(push) | |
| assert qr.html_safe? | ||
| assert qr.is_a?(ActiveSupport::SafeBuffer) | ||
| end | ||
|
|
||
| # Test smtp_configured? method | ||
| test "smtp_configured? is false in test environment" do | ||
| assert_equal "test", Rails.env | ||
| assert_not smtp_configured? | ||
| end | ||
|
|
||
| test "smtp_configured? is true in development environment" do | ||
| env = env_inquirer("development") | ||
| Rails.stub(:env, env) do | ||
| assert smtp_configured? | ||
| end | ||
| end | ||
|
|
||
| test "smtp_configured? in production is true when Settings.mail has smtp_address" do | ||
| env = env_inquirer("production") | ||
| Rails.stub(:env, env) do | ||
| Settings.stub(:mail, OpenStruct.new(smtp_address: "smtp.example.com")) do | ||
| assert smtp_configured? | ||
| end | ||
| end | ||
| end | ||
|
|
||
| test "smtp_configured? in production is false when Settings.mail has no smtp_address" do | ||
| env = env_inquirer("production") | ||
| Rails.stub(:env, env) do | ||
| Settings.stub(:mail, OpenStruct.new(smtp_address: nil)) do | ||
| assert_not smtp_configured? | ||
| end | ||
| end | ||
| end | ||
|
|
||
| test "smtp_configured? in production is false when Settings.mail is nil" do | ||
| env = env_inquirer("production") | ||
| Rails.stub(:env, env) do | ||
| Settings.stub(:mail, nil) do | ||
| assert_not smtp_configured? | ||
| end | ||
| end | ||
| end | ||
|
|
||
| test "smtp_configured? in production is false when smtp_address is empty string" do | ||
| env = env_inquirer("production") | ||
| Rails.stub(:env, env) do | ||
| Settings.stub(:mail, OpenStruct.new(smtp_address: "")) do | ||
| assert_not smtp_configured? | ||
| end | ||
| end | ||
| end | ||
|
|
||
| private | ||
|
|
||
| def env_inquirer(name) | ||
| ActiveSupport::StringInquirer.new(name) | ||
| end | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Re-evaluate - even in tests user_signed_in? should be provided by devise. |
||
| end | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it was redundant so removed