From d433372bf3c6d97cceffdfdf3c2d17281db8f149 Mon Sep 17 00:00:00 2001 From: "Brian D. Burns" Date: Mon, 25 Mar 2013 18:07:19 -0400 Subject: [PATCH] use a single `encryption` option to specify STARTTLS or SSL/TLS --- lib/backup/notifier/mail.rb | 138 ++++++++++++++++++++++-------------- spec/notifier/mail_spec.rb | 92 +++++++++++++++++++----- templates/cli/notifier/mail | 2 +- 3 files changed, 157 insertions(+), 75 deletions(-) diff --git a/lib/backup/notifier/mail.rb b/lib/backup/notifier/mail.rb index 815e7a62b..8586e5b43 100644 --- a/lib/backup/notifier/mail.rb +++ b/lib/backup/notifier/mail.rb @@ -10,106 +10,131 @@ class Mail < Base ## # Mail delivery method to be used by the Mail gem. + # # Supported methods: # - # `:smtp` [::Mail::SMTP] (default) - # : Settings used only by this method: - # : `address`, `port`, `domain`, `user_name`, `password` - # : `authentication`, `enable_starttls_auto`, `openssl_verify_mode` + # [:smtp - ::Mail::SMTP (default)] + # Settings used by this method: + # {#address}, {#port}, {#domain}, {#user_name}, {#password}, + # {#authentication}, {#encryption}, {#openssl_verify_mode} # - # `:sendmail` [::Mail::Sendmail] - # : Settings used only by this method: - # : `sendmail`, `sendmail_args` + # [:sendmail - ::Mail::Sendmail] + # Settings used by this method: + # {#sendmail}, {#sendmail_args} # - # `:exim` [::Mail::Exim] - # : Settings used only by this method: - # : `exim`, `exim_args` + # [:exim - ::Mail::Exim] + # Settings used by this method: + # {#exim}, {#exim_args} # - # `:file` [::Mail::FileDelivery] - # : Settings used only by this method: - # : `mail_folder` + # [:file - ::Mail::FileDelivery] + # Settings used by this method: + # {#mail_folder} # attr_accessor :delivery_method ## - # Sender and Receiver email addresses - # Examples: - # sender - my.email.address@gmail.com - # receiver - your.email.address@gmail.com - attr_accessor :from, :to + # Sender Email Address + attr_accessor :from + + ## + # Receiver Email Address + attr_accessor :to ## - # The address to use - # Example: smtp.gmail.com + # SMTP Server Address attr_accessor :address ## - # The port to connect to - # Example: 587 + # SMTP Server Port attr_accessor :port ## # Your domain (if applicable) - # Example: mydomain.com attr_accessor :domain ## - # Username and Password (sender email's credentials) - # Examples: - # user_name - meskyanichi - # password - my_secret_password - attr_accessor :user_name, :password + # SMTP Server Username (sender email's credentials) + attr_accessor :user_name + + ## + # SMTP Server Password (sender email's credentials) + attr_accessor :password ## # Authentication type - # Example: plain + # + # Acceptable values: +:plain+, +:login+, +:cram_md5+ attr_accessor :authentication ## - # Automatically set TLS - # Example: true - attr_accessor :enable_starttls_auto + # Set the method of encryption to be used for the +SMTP+ connection. + # + # [:none (default)] + # No encryption will be used. + # + # [:starttls] + # Use +STARTTLS+ to upgrade the connection to a +SSL/TLS+ connection. + # + # [:tls or :ssl] + # Use a +SSL/TLS+ connection. + attr_accessor :encryption + + attr_deprecate :enable_starttls_auto, :version => '3.2.0', + :message => "Use #encryption instead.\n" + + 'e.g. mail.encryption = :starttls', + :action => lambda {|klass, val| + klass.encryption = val ? :starttls : :none + } ## # OpenSSL Verify Mode - # Example: none - Only use this option for a self-signed and/or wildcard certificate + # + # Valid modes: +:none+, +:peer+, +:client_once+, +:fail_if_no_peer_cert+ + # See +OpenSSL::SSL+ for details. + # + # Use +:none+ for a self-signed and/or wildcard certificate attr_accessor :openssl_verify_mode ## - # Automatically set SSL - # Example: true - attr_accessor :ssl - - ## + # Path to `sendmail` (if needed) + # # When using the `:sendmail` `delivery_method` option, - # this may be used to specify the absolute path to `sendmail` (if needed) + # this may be used to specify the absolute path to `sendmail` + # # Example: '/usr/sbin/sendmail' attr_accessor :sendmail ## # Optional arguments to pass to `sendmail` + # # Note that this will override the defaults set by the Mail gem (currently: '-i -t') # So, if set here, be sure to set all the arguments you require. + # # Example: '-i -t -X/tmp/traffic.log' attr_accessor :sendmail_args ## + # Path to `exim` (if needed) + # # When using the `:exim` `delivery_method` option, - # this may be used to specify the absolute path to `exim` (if needed) + # this may be used to specify the absolute path to `exim` + # # Example: '/usr/sbin/exim' attr_accessor :exim ## # Optional arguments to pass to `exim` + # # Note that this will override the defaults set by the Mail gem (currently: '-i -t') # So, if set here, be sure to set all the arguments you require. + # # Example: '-i -t -X/tmp/traffic.log' attr_accessor :exim_args ## # Folder where mail will be kept when using the `:file` `delivery_method` option. + # # Default location is '$HOME/Backup/emails' - # Example: '/tmp/test-mails' attr_accessor :mail_folder def initialize(model, &block) @@ -122,22 +147,23 @@ def initialize(model, &block) ## # Notify the user of the backup operation results. + # # `status` indicates one of the following: # - # `:success` - # : The backup completed successfully. - # : Notification will be sent if `on_success` was set to `true` + # [:success] + # The backup completed successfully. + # Notification will be sent if `on_success` was set to `true` # - # `:warning` - # : The backup completed successfully, but warnings were logged - # : Notification will be sent, including a copy of the current - # : backup log, if `on_warning` was set to `true` + # [:warning] + # The backup completed successfully, but warnings were logged + # Notification will be sent, including a copy of the current + # backup log, if `on_warning` was set to `true` # - # `:failure` - # : The backup operation failed. - # : Notification will be sent, including the Exception which caused - # : the failure, the Exception's backtrace, a copy of the current - # : backup log and other information if `on_failure` was set to `true` + # [:failure] + # The backup operation failed. + # Notification will be sent, including the Exception which caused + # the failure, the Exception's backtrace, a copy of the current + # backup log and other information if `on_failure` was set to `true` # def notify!(status) name, send_log = @@ -178,9 +204,11 @@ def new_email :user_name => @user_name, :password => @password, :authentication => @authentication, - :enable_starttls_auto => @enable_starttls_auto, + :enable_starttls_auto => @encryption == :starttls, :openssl_verify_mode => @openssl_verify_mode, - :ssl => @ssl } + :ssl => @encryption == :ssl, + :tls => @encryption == :tls + } when 'sendmail' opts = {} opts.merge!(:location => File.expand_path(@sendmail)) if @sendmail diff --git a/spec/notifier/mail_spec.rb b/spec/notifier/mail_spec.rb index a64911801..7b3471a8b 100644 --- a/spec/notifier/mail_spec.rb +++ b/spec/notifier/mail_spec.rb @@ -15,7 +15,7 @@ mail.user_name = 'user' mail.password = 'secret' mail.authentication = 'plain' - mail.enable_starttls_auto = true + mail.encryption = :starttls mail.sendmail = '/path/to/sendmail' mail.sendmail_args = '-i -t -X/tmp/traffic.log' @@ -26,23 +26,9 @@ end end - it 'should be a subclass of Notifier::Base' do - Backup::Notifier::Mail. - superclass.should == Backup::Notifier::Base - end - describe '#initialize' do after { Backup::Notifier::Mail.clear_defaults! } - it 'should load pre-configured defaults through Base' do - Backup::Notifier::Mail.any_instance.expects(:load_defaults!) - notifier - end - - it 'should pass the model reference to Base' do - notifier.instance_variable_get(:@model).should == model - end - context 'when no pre-configured defaults have been set' do it 'should use the values given' do notifier.delivery_method.should == :smtp @@ -54,7 +40,7 @@ notifier.user_name.should == 'user' notifier.password.should == 'secret' notifier.authentication.should == 'plain' - notifier.enable_starttls_auto.should == true + notifier.encryption.should == :starttls notifier.sendmail.should == '/path/to/sendmail' notifier.sendmail_args.should == '-i -t -X/tmp/traffic.log' @@ -79,7 +65,7 @@ notifier.user_name.should be_nil notifier.password.should be_nil notifier.authentication.should be_nil - notifier.enable_starttls_auto.should be_nil + notifier.encryption.should be_nil notifier.sendmail.should be_nil notifier.sendmail_args.should be_nil @@ -115,7 +101,7 @@ notifier.user_name.should be_nil notifier.password.should be_nil notifier.authentication.should be_nil - notifier.enable_starttls_auto.should be_nil + notifier.encryption.should be_nil notifier.sendmail.should be_nil notifier.sendmail_args.should be_nil @@ -247,8 +233,26 @@ settings[:user_name].should == 'user' settings[:password].should == 'secret' settings[:authentication].should == 'plain' - settings[:enable_starttls_auto].should == true + settings[:enable_starttls_auto].should be(true) settings[:openssl_verify_mode].should be_nil + settings[:ssl].should be(false) + settings[:tls].should be(false) + end + + it 'should properly set other encryption settings' do + notifier.encryption = :ssl + email = notifier.send(:new_email) + settings = email.delivery_method.settings + settings[:enable_starttls_auto].should be(false) + settings[:ssl].should be(true) + settings[:tls].should be(false) + + notifier.encryption = :tls + email = notifier.send(:new_email) + settings = email.delivery_method.settings + settings[:enable_starttls_auto].should be(false) + settings[:ssl].should be(false) + settings[:tls].should be(true) end end @@ -309,4 +313,54 @@ end end # describe '#new_email' + describe 'deprecations' do + + describe '#enable_starttls_auto' do + before do + Backup::Logger.expects(:warn).with {|err| + err.should be_an_instance_of Backup::Errors::ConfigurationError + err.message.should match( + /Use #encryption instead/ + ) + } + end + + context 'when set directly' do + it 'warns and transfers true value' do + notifier = Backup::Notifier::Mail.new(model) do |mail| + mail.enable_starttls_auto = true + end + notifier.encryption.should == :starttls + end + + it 'warns and transfers false value' do + notifier = Backup::Notifier::Mail.new(model) do |mail| + mail.enable_starttls_auto = false + end + notifier.encryption.should == :none + end + end + + context 'when set as a default' do + after { Backup::Notifier::Mail.clear_defaults! } + + it 'warns and transfers true value' do + Backup::Notifier::Mail.defaults do |mail| + mail.enable_starttls_auto = true + end + notifier = Backup::Notifier::Mail.new(model) + notifier.encryption.should == :starttls + end + + it 'warns and transfers false value' do + Backup::Notifier::Mail.defaults do |mail| + mail.enable_starttls_auto = false + end + notifier = Backup::Notifier::Mail.new(model) + notifier.encryption.should == :none + end + end + end # describe '#enable_starttls_auto' + + end # describe 'deprecations' end diff --git a/templates/cli/notifier/mail b/templates/cli/notifier/mail index aab7d8ef2..c6365fc69 100644 --- a/templates/cli/notifier/mail +++ b/templates/cli/notifier/mail @@ -18,5 +18,5 @@ mail.user_name = "sender@email.com" mail.password = "my_password" mail.authentication = "plain" - mail.enable_starttls_auto = true + mail.encryption = :starttls end