FEATURE: Add hooks for email poller plugins (#21384)
While we are unable to support OAUTH2 with pop3 (due to upstream dependency ruby/net-pop#16), we are adding the support for mail pollers plugin. Doing so, it would be possible to write a plugin which then uses other ways (microsoft graph sdk for example) to poll emails from a mailbox. The idea is that a plugin would define a class which inherits from Email::Poller and defines a poll_mailbox static method which returns an array of strings. Then the plugin could call register_mail_poller(<class_name>) to have it registered. All the configuration (oauth2 tokens, email, etc) could be managed by sitesettings defined in the plugin.
This commit is contained in:
parent
52894b9d7c
commit
56718504ac
|
@ -12,6 +12,12 @@ module Jobs
|
|||
def execute(args)
|
||||
@args = args
|
||||
poll_pop3 if should_poll?
|
||||
|
||||
DiscoursePluginRegistry.mail_pollers.each do |poller|
|
||||
return if !poller.enabled?
|
||||
|
||||
poller.poll_mailbox(method(:process_popmail))
|
||||
end
|
||||
end
|
||||
|
||||
def should_poll?
|
||||
|
|
|
@ -115,7 +115,8 @@ class SiteSetting < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def self.email_polling_enabled?
|
||||
SiteSetting.manual_polling_enabled? || SiteSetting.pop3_polling_enabled?
|
||||
SiteSetting.manual_polling_enabled? || SiteSetting.pop3_polling_enabled? ||
|
||||
DiscoursePluginRegistry.mail_pollers.any?(&:enabled?)
|
||||
end
|
||||
|
||||
def self.blocked_attachment_content_types_regex
|
||||
|
|
|
@ -2457,7 +2457,7 @@ en:
|
|||
pop3_polling_password_is_empty: "You must set a 'pop3 polling password' before enabling POP3 polling."
|
||||
pop3_polling_authentication_failed: "POP3 authentication failed. Please verify your pop3 credentials."
|
||||
reply_by_email_address_is_empty: "You must set a 'reply by email address' before enabling reply by email."
|
||||
email_polling_disabled: "You must enable either manual or POP3 polling before enabling reply by email."
|
||||
email_polling_disabled: "You must enable either manual, POP3 polling or have a custom mail poller enabled before enabling reply by email."
|
||||
user_locale_not_enabled: "You must first enable 'allow user locale' before enabling this setting."
|
||||
personal_message_enabled_groups_invalid: "You must specify at least one group for this setting. If you do not want anyone except staff to send PMs, choose the staff group."
|
||||
invalid_regex: "Regex is invalid or not allowed."
|
||||
|
|
|
@ -72,6 +72,7 @@ class DiscoursePluginRegistry
|
|||
define_register :seedfu_filter, Set
|
||||
define_register :demon_processes, Set
|
||||
define_register :groups_callback_for_users_search_controller_action, Hash
|
||||
define_register :mail_pollers, Set
|
||||
|
||||
define_filtered_register :staff_user_custom_fields
|
||||
define_filtered_register :public_user_custom_fields
|
||||
|
@ -119,6 +120,10 @@ class DiscoursePluginRegistry
|
|||
self.auth_providers << auth_provider
|
||||
end
|
||||
|
||||
def self.register_mail_poller(mail_poller)
|
||||
self.mail_pollers << mail_poller
|
||||
end
|
||||
|
||||
def register_js(filename, options = {})
|
||||
# If we have a server side option, add that too.
|
||||
self.class.javascripts << filename
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Email
|
||||
class Poller
|
||||
# To be implemented by concrete classes.
|
||||
# This function takes as input a function that processes the incoming email.
|
||||
# The function passed as argument should take as an argument the MIME string of the email.
|
||||
# An example of function to pass is `process_popmail` in `app/jobs/scheduled/poll_mailbox.rb`
|
||||
def poll_mailbox(process_cb)
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Child class can override this
|
||||
def enabled?
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
|
@ -647,6 +647,11 @@ class Plugin::Instance
|
|||
end
|
||||
end
|
||||
|
||||
def register_email_poller(poller)
|
||||
plugin = self
|
||||
DiscoursePluginRegistry.register_mail_poller(poller) if plugin.enabled?
|
||||
end
|
||||
|
||||
def register_asset(file, opts = nil)
|
||||
raise <<~ERROR if file.end_with?(".hbs", ".handlebars")
|
||||
[#{name}] Handlebars templates can no longer be included via `register_asset`.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
require "email/poller"
|
||||
|
||||
RSpec.describe Jobs::PollMailbox do
|
||||
let(:poller) { Jobs::PollMailbox.new }
|
||||
|
@ -175,4 +176,45 @@ RSpec.describe Jobs::PollMailbox do
|
|||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "poller plugin" do
|
||||
let(:poller_plugin) do
|
||||
Class
|
||||
.new(described_class) do
|
||||
def set_enabled(e)
|
||||
@enabled = e
|
||||
end
|
||||
|
||||
def enabled?
|
||||
@enabled
|
||||
end
|
||||
|
||||
def poll_mailbox(process_cb)
|
||||
process_cb.call(file_from_fixtures("original_message.eml", "emails"))
|
||||
end
|
||||
end
|
||||
.new
|
||||
end
|
||||
|
||||
let(:plugin) { Plugin::Instance.new }
|
||||
|
||||
before(:each) { plugin.register_email_poller(poller_plugin) }
|
||||
|
||||
after(:each) do
|
||||
Discourse.plugins.delete plugin
|
||||
DiscoursePluginRegistry.reset!
|
||||
end
|
||||
|
||||
it "doesn't call process method when plugin is not active" do
|
||||
poller_plugin.set_enabled(false)
|
||||
poller.expects(:process_popmail).never
|
||||
poller.execute({})
|
||||
end
|
||||
|
||||
it "calls process method when plugin is active" do
|
||||
poller_plugin.set_enabled(true)
|
||||
poller.expects(:process_popmail).once
|
||||
poller.execute({})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -98,6 +98,13 @@ RSpec.describe DiscoursePluginRegistry do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#mail_pollers" do
|
||||
it "defaults to an empty Set" do
|
||||
registry.reset!
|
||||
expect(registry.mail_pollers).to eq(Set.new)
|
||||
end
|
||||
end
|
||||
|
||||
describe ".register_html_builder" do
|
||||
it "can register and build html" do
|
||||
DiscoursePluginRegistry.register_html_builder(:my_html) { "<b>my html</b>" }
|
||||
|
|
Loading…
Reference in New Issue