diff --git a/plugins/send_email/controllers/send_email_plugin_admin_controller.rb b/plugins/send_email/controllers/send_email_plugin_admin_controller.rb new file mode 100644 index 0000000..94ab9fc --- /dev/null +++ b/plugins/send_email/controllers/send_email_plugin_admin_controller.rb @@ -0,0 +1,16 @@ +class SendEmailPluginAdminController < PluginsController + append_view_path File.join(File.dirname(__FILE__) + '/../views') + + def index + @environment = environment + if request.post? + if environment.update_attributes(params[:environment]) + session[:notice] = _('Configurations was saved') + redirect_to :controller => 'plugins' + else + session[:notice] = _('Configurations could not be saved') + end + end + end + +end diff --git a/plugins/send_email/controllers/send_email_plugin_base_controller.rb b/plugins/send_email/controllers/send_email_plugin_base_controller.rb new file mode 100644 index 0000000..c45aaee --- /dev/null +++ b/plugins/send_email/controllers/send_email_plugin_base_controller.rb @@ -0,0 +1,31 @@ +module SendEmailPluginBaseController + def deliver + if request.post? + @context_url = profile ? profile.url : {:host => environment.default_hostname, :controller => 'home'} + @mail = SendEmailPlugin::Mail.new( + :from => environment.contact_email, + :to => params[:to], + :message => params[:message], + :environment => environment, + :params => params.dup + ) + @mail.subject = params[:subject] unless params[:subject].blank? + if @mail.valid? + SendEmailPlugin::Sender.deliver_mail(request.referer, @context_url, @mail) + if request.xhr? + render :text => _('Message sent') + else + render :action => 'success' + end + else + if request.xhr? + render_dialog_error_messages :mail + else + render :action => 'fail' + end + end + else + render_access_denied + end + end +end diff --git a/plugins/send_email/controllers/send_email_plugin_environment_controller.rb b/plugins/send_email/controllers/send_email_plugin_environment_controller.rb new file mode 100644 index 0000000..e5043e0 --- /dev/null +++ b/plugins/send_email/controllers/send_email_plugin_environment_controller.rb @@ -0,0 +1,4 @@ +class SendEmailPluginEnvironmentController < ApplicationController + append_view_path File.join(File.dirname(__FILE__) + '/../views') + include SendEmailPluginBaseController +end diff --git a/plugins/send_email/controllers/send_email_plugin_profile_controller.rb b/plugins/send_email/controllers/send_email_plugin_profile_controller.rb new file mode 100644 index 0000000..70beffd --- /dev/null +++ b/plugins/send_email/controllers/send_email_plugin_profile_controller.rb @@ -0,0 +1,4 @@ +class SendEmailPluginProfileController < ProfileController + append_view_path File.join(File.dirname(__FILE__) + '/../views') + include SendEmailPluginBaseController +end diff --git a/plugins/send_email/db/migrate/20110804180047_add_send_email_plugin_config_to_environment.rb b/plugins/send_email/db/migrate/20110804180047_add_send_email_plugin_config_to_environment.rb new file mode 100644 index 0000000..19cbf26 --- /dev/null +++ b/plugins/send_email/db/migrate/20110804180047_add_send_email_plugin_config_to_environment.rb @@ -0,0 +1,9 @@ +class AddSendEmailPluginConfigToEnvironment < ActiveRecord::Migration + def self.up + add_column :environments, :send_email_plugin_allow_to, :text + end + + def self.down + remove_column :environments, :send_email_plugin_allow_to + end +end diff --git a/plugins/send_email/doc/send_email.textile b/plugins/send_email/doc/send_email.textile new file mode 100644 index 0000000..2b842ac --- /dev/null +++ b/plugins/send_email/doc/send_email.textile @@ -0,0 +1,61 @@ +h1. SendEmailPlugin + +Allows to send e-mails through an e-mail form. + +h2. Usage + +* Create a HTML form using RawHTMLBlock or RawHTMLArticle that invokes the {sendemail} action +* Add a "to" and "message" field and a submit button +* Make sure to fill in allowed 'to' addresses in plugin settings + +h2. HTML form + +h3. Form action + +You should use {sendemail} macro as form action, it will be expanded as: + +* */profile/<identifier>/plugins/send_email/deliver* in profile context +* */plugin/send_email/deliver* in environment context + +h3. 'Subject' field + +Subject of message. + +(default: 'New mail') + +h3. 'Message' field + +Body of message. + +(required) + +h3. 'To' field + +Target address. Accepts multiple addresses separated by comma. + +(required) + +h3. extra fields + +Each other params in HTML form will compose message body in a format "key: value" + +h2. Options + +h3. Using ajax + +Ajax is supported using #ajax-form as id of HTML form. + +Example: + +
++ + +h2. Info + +This plugin was inspired by "Foswiki SendEmailPlugin":http://foswiki.org/Extensions/SendEmailPlugin diff --git a/plugins/send_email/lib/send_email_plugin.rb b/plugins/send_email/lib/send_email_plugin.rb new file mode 100644 index 0000000..639f2fe --- /dev/null +++ b/plugins/send_email/lib/send_email_plugin.rb @@ -0,0 +1,23 @@ +class SendEmailPlugin < Noosfero::Plugin + + def self.plugin_name + "SendEmailPlugin" + end + + def self.plugin_description + _("A plugin that allows sending e-mails via HTML forms.") + end + + def stylesheet? + true + end + + def parse_content(raw_content) + if context.profile + raw_content.gsub(/\{sendemail\}/, "/profile/#{context.profile.identifier}/plugins/send_email/deliver") + else + raw_content.gsub(/\{sendemail\}/, '/plugin/send_email/deliver') + end + end + +end diff --git a/plugins/send_email/lib/send_email_plugin/mail.rb b/plugins/send_email/lib/send_email_plugin/mail.rb new file mode 100644 index 0000000..b3a4f9e --- /dev/null +++ b/plugins/send_email/lib/send_email_plugin/mail.rb @@ -0,0 +1,42 @@ +class SendEmailPlugin::Mail < ActiveRecord::Base #WithoutTable + + N_('Subject'); N_('Message'); N_('To'); N_('From') + tableless :columns => [ + [:from, :string], + [:to, :string], + [:subject, :string, _('New mail')], + [:message, :string], + [:params, :hash, {}], + ] + attr_accessor :environment + + validates_presence_of :environment + validates_presence_of :to, :message + + def validate + if to_as_list.any? do |value| + if value !~ Noosfero::Constants::EMAIL_FORMAT + self.errors.add(:to, _("%{fn} '%s' isn't a valid e-mail address") % value) + end + end + else + allowed_emails = environment ? environment.send_email_plugin_allow_to.to_s.gsub(/\s+/, '').split(/,/) : [] + if to_as_list.any? do |value| + if !allowed_emails.include?(value) + self.errors.add(:to, _("%{fn} '%s' address is not allowed (see SendEmailPlugin config)") % value) + end + end + end + end + end + + def params=(value = {}) + [:action, :controller, :to, :message, :subject, :from].each{|k| value.delete(k)} + self[:params] = value + end + + def to_as_list + to && to.split(/,/) || [] + end + +end diff --git a/plugins/send_email/lib/send_email_plugin/sender.rb b/plugins/send_email/lib/send_email_plugin/sender.rb new file mode 100644 index 0000000..6f69c06 --- /dev/null +++ b/plugins/send_email/lib/send_email_plugin/sender.rb @@ -0,0 +1,13 @@ +class SendEmailPlugin::Sender < Noosfero::Plugin::MailerBase + prepend_view_path(SendEmailPlugin.root_path+'/views') + + def mail(referer, url, mail) + recipients mail.to + from mail.from + subject "[#{mail.environment.name}] #{mail.subject}" + body :message => mail.message, + :referer => referer, + :context_url => url, + :params => mail.params + end +end diff --git a/plugins/send_email/public/style.css b/plugins/send_email/public/style.css new file mode 100644 index 0000000..2c0060f --- /dev/null +++ b/plugins/send_email/public/style.css @@ -0,0 +1,22 @@ +.sendemail-plugin-message-sent { + width: 100%; + background-color: #F0F0F0; + border: 1px solid #CFCFCF; +} +.sendemail-plugin-message-sent td { + border: 0; +} +.sendemail-plugin-message-sent tr:hover, +.sendemail-plugin-message-sent td:hover, +.sendemail-plugin-message-sent tr:hover td { + background-color: auto; +} +.sendemail-plugin-message-sent pre { + margin: 0 auto; +} +.sendemail-plugin-message-sent td { + vertical-align: top; +} +.sendemail-plugin-message-sent .value { + width: 100%; +} diff --git a/plugins/send_email/test/features/send_email_plugin.feature b/plugins/send_email/test/features/send_email_plugin.feature new file mode 100644 index 0000000..36b97a9 --- /dev/null +++ b/plugins/send_email/test/features/send_email_plugin.feature @@ -0,0 +1,41 @@ +Feature: send_email_plugin + + Background: + Given the following users + | login | name | + | joaosilva | Joao Silva | + And I am logged in as "joaosilva" + + Scenario: expand macro in article content + Given plugin SendEmailPlugin is enabled on environment + And the following articles + | owner | name | body | + | joaosilva | sample-article | URL path to {sendemail} action | + When I go to /joaosilva/sample-article + Then I should see "URL path to /profile/joaosilva/plugins/send_email/deliver action" + + Scenario: expand macro in block content + Given plugin SendEmailPlugin is enabled on environment + And the following blocks + | owner | type | html | + | joaosilva | RawHTMLBlock | URL path to {sendemail} action | + When I go to Joao Silva's homepage + Then I should see "URL path to /profile/joaosilva/plugins/send_email/deliver action" + + Scenario: as admin I can configure plugin + Given I am logged in as admin + When I go to the environment control panel + And I follow "Enable/disable plugins" + Then I should see "SendEmailPlugin" linking to "/admin/plugin/send_email" + + Scenario: configure plugin to allow emails to john@example.com + Given I am logged in as admin + And I go to the environment control panel + And I follow "Enable/disable plugins" + When I follow "SendEmailPlugin" + Then I should not see "john@example.com" + When I fill in "E-Mail addresses you want to allow to send" with "john@example.com" + And I press "Save" + Then I should be on /admin/plugins + When I follow "SendEmailPlugin" + Then I should see "john@example.com" diff --git a/plugins/send_email/test/functional/send_email_plugin_admin_controller_test.rb b/plugins/send_email/test/functional/send_email_plugin_admin_controller_test.rb new file mode 100644 index 0000000..c999038 --- /dev/null +++ b/plugins/send_email/test/functional/send_email_plugin_admin_controller_test.rb @@ -0,0 +1,37 @@ +require File.dirname(__FILE__) + '/../../../../test/test_helper' +require File.dirname(__FILE__) + '/../../controllers/send_email_plugin_admin_controller' + +# Re-raise errors caught by the controller. +class SendEmailPluginAdminController; def rescue_action(e) raise e end; end + +class SendEmailPluginAdminControllerTest < Test::Unit::TestCase + + def setup + @controller = SendEmailPluginAdminController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @admin = create_user('adminplug').person + @environment = @admin.environment + @environment.add_admin(@admin) + end + + should 'deny access to guests and redirect to login' do + get :index + assert_response :redirect + assert_redirected_to :controller => 'account', :action => 'login' + end + + should 'allow access to admin' do + login_as @admin.identifier + get :index + assert_response :success + end + + should 'deny access to ordinary users' do + @user = create_user('normaluser').person + login_as @user.identifier + get :index + assert_response 403 + end + +end diff --git a/plugins/send_email/test/functional/send_email_plugin_base_controller_test.rb b/plugins/send_email/test/functional/send_email_plugin_base_controller_test.rb new file mode 100644 index 0000000..eed1687 --- /dev/null +++ b/plugins/send_email/test/functional/send_email_plugin_base_controller_test.rb @@ -0,0 +1,81 @@ +require File.dirname(__FILE__) + '/../../../../test/test_helper' +require File.dirname(__FILE__) + '/../../controllers/send_email_plugin_profile_controller' + +# Re-raise errors caught by the controller. +class SendEmailPluginProfileController; def rescue_action(e) raise e end; end + +def run_common_tests + should 'not deliver emails via GET requests' do + get :deliver, @extra_args + assert_response 403 # forbidden + end + + should 'deliver emails only via POST requests' do + post :deliver, @extra_args + assert_response :success + end + + should 'render fail template if could not deliver mail' do + post :deliver, @extra_args + assert_template 'fail' + end + + should 'render success template after deliver mail' do + SendEmailPlugin::Mail.any_instance.stubs(:valid?).returns(true) + post :deliver, @extra_args.merge(:to => 'john@example.com', :message => 'Hi john') + assert_template 'success' + end + + should 'render dialog error if could not deliver mail by ajax request' do + xhr :post, :deliver, @extra_args + assert_template '_dialog_error_messages' + end + + should 'render success message after deliver mail by ajax request' do + SendEmailPlugin::Mail.any_instance.stubs(:valid?).returns(true) + xhr :post, :deliver, @extra_args.merge(:to => 'john@example.com', :message => 'Hi john') + assert_equal 'Message sent', @response.body + end + + should 'deliver mail' do + Environment.any_instance.stubs(:send_email_plugin_allow_to).returns('john@example.com') + assert_difference ActionMailer::Base.deliveries, :size do + post :deliver, @extra_args.merge(:to => 'john@example.com', :message => 'Hi john') + end + end + + should 'deliver mail with nondefault subject' do + Environment.any_instance.stubs(:send_email_plugin_allow_to).returns('john@example.com') + post :deliver, @extra_args.merge(:to => 'john@example.com', :message => 'Hi john', :subject => 'Hello john') + assert_equal '[Colivre.net] Hello john', ActionMailer::Base.deliveries.first.subject + end +end + +class SendEmailPluginProfileControllerTest < Test::Unit::TestCase + def setup + @controller = SendEmailPluginProfileController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + ActionMailer::Base.delivery_method = :test + ActionMailer::Base.perform_deliveries = true + ActionMailer::Base.deliveries = [] + community = fast_create(Community) + @extra_args = {:profile => community.identifier} + end + + run_common_tests() +end + +class SendEmailPluginEnvironmentControllerTest < Test::Unit::TestCase + def setup + @controller = SendEmailPluginEnvironmentController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + ActionMailer::Base.delivery_method = :test + ActionMailer::Base.perform_deliveries = true + ActionMailer::Base.deliveries = [] + @extra_args = {} + end + + run_common_tests() +end diff --git a/plugins/send_email/test/unit/send_email_plugin_mail_test.rb b/plugins/send_email/test/unit/send_email_plugin_mail_test.rb new file mode 100644 index 0000000..e1730e8 --- /dev/null +++ b/plugins/send_email/test/unit/send_email_plugin_mail_test.rb @@ -0,0 +1,63 @@ +require File.dirname(__FILE__) + '/../../../../test/test_helper' + +class SendEmailPluginMailTest < Test::Unit::TestCase + + def setup + @environment = mock() + @environment.stubs(:send_email_plugin_allow_to).returns('john@example.com, someone@example.com, someother@example.com') + end + + should 'instance a valid object with fields to be fired in mail' do + mail = SendEmailPlugin::Mail.new(:subject => 'Hi', :message => 'Hi john', :to => 'john@example.com', :environment => @environment) + assert mail.valid? + end + + should 'requires to field' do + mail = SendEmailPlugin::Mail.new(:subject => 'Hi', :message => 'Hi john', :environment => @environment) + assert !mail.valid? + end + + should 'require message field' do + mail = SendEmailPlugin::Mail.new(:subject => 'Hi', :to => 'john@example.com', :environment => @environment) + assert !mail.valid? + end + + should 'require environment field' do + mail = SendEmailPlugin::Mail.new(:subject => 'Hi', :to => 'john@example.com', :message => 'Hi john') + assert !mail.valid? + end + + should 'have a default subject' do + mail = SendEmailPlugin::Mail.new + assert_equal 'New mail', mail.subject + end + + should 'not accept invalid email address' do + mail = SendEmailPlugin::Mail.new(:subject => 'Hi', :message => 'Hi john', :to => 'invalid-mail-address', :environment => @environment) + assert !mail.valid? + end + + should 'not accept email that is not in allowed address list' do + mail = SendEmailPlugin::Mail.new(:subject => 'Hi', :message => 'Hi john', :to => 'unknow@example.com', :environment => @environment) + assert !mail.valid? + end + + should 'discard some keys on set params hash' do + mail = SendEmailPlugin::Mail.new(:params => {:action => 1, :controller => 2, :to => 3, :message => 4, :subject => 5, :age => 6}) + [:action, :controller, :to, :message, :subject].each do |k| + assert !mail.params.include?(k) + end + assert mail.params.include?(:age) + end + + should "accept multiple 'to' emails" do + mail = SendEmailPlugin::Mail.new(:subject => 'Hi', :message => 'Hi john', :to => 'john@example.com,someother@example.com', :environment => @environment) + assert mail.valid? + end + + should "invalid if just one listed in 'to' list was not allowed" do + mail = SendEmailPlugin::Mail.new(:subject => 'Hi', :message => 'Hi john', :to => 'john@example.com,notallowed@example.com,someother@example.com', :environment => @environment) + assert !mail.valid? + end + +end diff --git a/plugins/send_email/test/unit/send_email_plugin_sender_test.rb b/plugins/send_email/test/unit/send_email_plugin_sender_test.rb new file mode 100644 index 0000000..6b5f86a --- /dev/null +++ b/plugins/send_email/test/unit/send_email_plugin_sender_test.rb @@ -0,0 +1,35 @@ +require File.dirname(__FILE__) + '/../../../../test/test_helper' + +class SendEmailPluginSenderTest < Test::Unit::TestCase + + def setup + ActionMailer::Base.delivery_method = :test + ActionMailer::Base.perform_deliveries = true + ActionMailer::Base.deliveries = [] + @environment = mock() + @environment.stubs(:contact_email).returns('noreply@localhost') + @environment.stubs(:default_hostname).returns('localhost') + @environment.stubs(:name).returns('Noosfero') + @environment.stubs(:send_email_plugin_allow_to).returns('john@example.com, someone@example.com, someother@example.com') + @mail = SendEmailPlugin::Mail.new(:subject => 'Hi', :message => 'Hi john', :to => 'john@example.com', :from => 'noreply@localhost', :environment => @environment) + end + + should 'be able to deliver mail' do + response = SendEmailPlugin::Sender.deliver_mail("http://localhost/contact", 'http//profile', @mail) + assert_equal 'noreply@localhost', response.from.to_s + assert_equal "[Noosfero] #{@mail.subject}", response.subject + end + + should 'deliver mail to john@example.com' do + response = SendEmailPlugin::Sender.deliver_mail("http://localhost/contact", 'http//profile', @mail) + assert_equal ['john@example.com'], response.to + end + + should 'add each key value pair to message body' do + @mail.params = {:param1 => 'value1', :param2 => 'value2'} + response = SendEmailPlugin::Sender.deliver_mail("http://localhost/contact", 'http//profile', @mail) + assert_match /param1.+value1/m, response.body + assert_match /param2.+value2/m, response.body + end + +end diff --git a/plugins/send_email/test/unit/send_email_plugin_test.rb b/plugins/send_email/test/unit/send_email_plugin_test.rb new file mode 100644 index 0000000..6bcbc4d --- /dev/null +++ b/plugins/send_email/test/unit/send_email_plugin_test.rb @@ -0,0 +1,29 @@ +require File.dirname(__FILE__) + '/../../../../test/test_helper' + +class SendEmailPluginTest < Test::Unit::TestCase + + def setup + @plugin = SendEmailPlugin.new + @context = mock() + @plugin.context = @context + end + + should 'return true to stylesheet?' do + assert @plugin.stylesheet? + end + + should 'have admin controller' do + assert SendEmailPlugin.has_admin_url? + end + + should 'expand macro in parse_content event' do + @plugin.context.stubs(:profile).returns(nil) + assert_match /plugin\/send_email\/deliver/, @plugin.parse_content("expand this macro {sendemail}") + end + + should 'expand macro in parse_content event on profile context' do + @plugin.context.stubs(:profile).returns(fast_create(Community)) + assert_match /profile\/#{@plugin.context.profile.identifier}\/plugins\/send_email\/deliver/, @plugin.parse_content("expand this macro {sendemail}") + end + +end diff --git a/plugins/send_email/views/send_email_plugin/sender/mail.rhtml b/plugins/send_email/views/send_email_plugin/sender/mail.rhtml new file mode 100644 index 0000000..251f4a8 --- /dev/null +++ b/plugins/send_email/views/send_email_plugin/sender/mail.rhtml @@ -0,0 +1,8 @@ +<%= _('Contact from %s') % @referer %> + +<%= word_wrap(@message || @mail.message) %> +<% (@params || @mail.params).each_pair do |key, value| %> +<%= key %>: <%= word_wrap(value) %> +<% end %> +--- +<%= url_for @context_url %> diff --git a/plugins/send_email/views/send_email_plugin_admin/index.rhtml b/plugins/send_email/views/send_email_plugin_admin/index.rhtml new file mode 100644 index 0000000..9bb2a14 --- /dev/null +++ b/plugins/send_email/views/send_email_plugin_admin/index.rhtml @@ -0,0 +1,9 @@ +
<%= button :back, _('Back'), :back %>
diff --git a/plugins/send_email/views/send_email_plugin_environment b/plugins/send_email/views/send_email_plugin_environment new file mode 120000 index 0000000..8ccfd60 --- /dev/null +++ b/plugins/send_email/views/send_email_plugin_environment @@ -0,0 +1 @@ +send_email_plugin_base \ No newline at end of file diff --git a/plugins/send_email/views/send_email_plugin_profile b/plugins/send_email/views/send_email_plugin_profile new file mode 120000 index 0000000..8ccfd60 --- /dev/null +++ b/plugins/send_email/views/send_email_plugin_profile @@ -0,0 +1 @@ +send_email_plugin_base \ No newline at end of file -- libgit2 0.21.2