diff --git a/.rubocop.yml b/.rubocop.yml index d857827..3c7e58f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,35 +1,174 @@ -inherit_from: - - https://dev.k.io/rubocop/rubocop.rails.yml +AllCops: + TargetRubyVersion: 3.0 + NewCops: enable + Exclude: + - "bin/*" + - "db/schema.rb" + # Fixes missing gem exception when running Rubocop on GitHub Actions. + - "vendor/bundle/**/*" +# Always use double quotes Style/StringLiterals: EnforcedStyle: double_quotes -Style/WordArray: +# We prefer arrays of symbols to look like an array of symbols. +# For example: [:one, :two, :three] as opposed to %i[one two three] +Style/SymbolArray: EnforcedStyle: brackets -Layout/LineLength: +# There should always be empty lines inside a class. For example +# +# class MyExample +# +# def some_method +# end +# +# end +Layout/EmptyLinesAroundClassBody: + EnforcedStyle: empty_lines + +# We want to keep attr_* definitions separated on their own lines, rather than +# all of them collapsed into a single attr_* call. The collapsed/grouped variant +# is harder to read, and harder to see what's been changed in diffs. +Style/AccessorGrouping: Enabled: false +# Blocks are slightly different to classes, in these cases there should +# not be new lines around the contents of the block. +# +# proc do +# # Do something +# end +Layout/EmptyLinesAroundBlockBody: + EnforcedStyle: no_empty_lines + +# Modules are the same as classes unless they're being used for namespacing +# purposes in which case there should not be new lines. +Layout/EmptyLinesAroundModuleBody: + EnforcedStyle: empty_lines_except_namespace + +# Space is required following -> when writing a lambda: +# +# somethign = -> (var) { block } +Layout/SpaceInLambdaLiteral: + EnforcedStyle: require_space + +Layout/FirstHashElementIndentation: + Enabled: false + +# We don't mind setting assignments in conditions so this has been disabled to +# allow `if something = something_else` without worrying about brackets. +Lint/AssignmentInCondition: + Enabled: false + +# Top level documentation is quite rare... +Style/Documentation: + Enabled: false + +# We want to allow inner slashes in a regexp to be used when using /xxx/ form. +Style/RegexpLiteral: + AllowInnerSlashes: true + +# Blocks of if statements are perfectly fine and usually more readable than +# putting everything onto a single line just because we can. +Style/IfUnlessModifier: + Enabled: false + +# We prefer assignments to happen within the condition rather than setting a +# variable to the result of a condition. +Style/ConditionalAssignment: + EnforcedStyle: assign_inside_condition + IncludeTernaryExpressions: false + +# Empty methods should not be compacted onto a single line +Style/EmptyMethod: + EnforcedStyle: expanded + +# As above, just flag them. +Lint/UnusedBlockArgument: + AutoCorrect: false + +# While we don't want to make heavy use of get_ or set_ methods we do often need +# to use these when we want to refer to actually getting or setting something +# (usually from another API). +Naming/AccessorMethodName: + Enabled: false + +# If we want a boolean called :true, we should be allowed that. These are likely +# not mistakes. +Lint/BooleanSymbol: + Enabled: false + +# Using block.map(&:upcase) is not always the neatest way to show something. For +# example if you have a block that just calls one thing, you don't want it +# collapsed. +# +# action do |user| +# user.delete +# end +# +# This should be action(&:delete) because it is not clear what is actually +# happening without the context of knowing what the inner variable should be +# called. +Style/SymbolProc: + Enabled: false + +# Allow a maxmium of 5 arguments and don't include keyword arguments +Metrics/ParameterLists: + Max: 5 + CountKeywordArgs: false + +# This cop checks for chaining of a block after another block that spans multiple lines. +Style/MultilineBlockChain: + Exclude: + - "spec/**/*.rb" + Metrics/AbcSize: Enabled: false +Style/FrozenStringLiteralComment: + Enabled: true + SafeAutoCorrect: true + +Naming/PredicateName: + Enabled: false + +Layout/LineLength: + # We want to reduce this back down to 120 but there are a fair number of offences + # of this which need addressing individually and carefully. + Max: 200 + +Metrics/PerceivedComplexity: + # As above, we want to enable this again in the future, but for now we'll just + # disable it entirely. + Enabled: false + +Metrics/CyclomaticComplexity: + # As above. + Enabled: false + +Metrics/MethodLength: + # As above. + Enabled: false + +Metrics/BlockNesting: + # As above. + Enabled: false + +Style/StringConcatenation: + Enabled: false + Metrics/BlockLength: Enabled: false Metrics/ClassLength: Enabled: false -Metrics/CyclomaticComplexity: - Enabled: false - -Metrics/MethodLength: - Enabled: false - Metrics/ModuleLength: Enabled: false -Metrics/PerceivedComplexity: +Lint/UnusedMethodArgument: Enabled: false -Lint/MissingSuper: +Style/SpecialGlobalVars: Enabled: false diff --git a/Gemfile b/Gemfile index ef6caaf..f5e76cf 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source "https://rubygems.org" gem "authie" gem "autoprefixer-rails" @@ -10,12 +12,12 @@ gem "clockwork" gem "dotenv-rails" gem "dynamic_form" gem "encrypto_signo" +gem "execjs", "~> 2.7", "< 2.8" gem "foreman" gem "gelf" gem "haml" gem "hashie" gem "highline", require: false -gem "execjs", '~> 2.7', "< 2.8" gem "jwt" gem "kaminari" gem "mail" @@ -28,8 +30,8 @@ gem "puma" gem "rails", "= 6.1.7.6" gem "resolv", "~> 0.2.1" gem "secure_headers" -gem 'sentry-rails' -gem 'sentry-ruby' +gem "sentry-rails" +gem "sentry-ruby" gem "turbolinks", "~> 5" group :development, :assets do diff --git a/Rakefile b/Rakefile index 9a5ea73..d2a78aa 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. diff --git a/api/authenticator.rb b/api/authenticator.rb index e42b863..a69b291 100644 --- a/api/authenticator.rb +++ b/api/authenticator.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + authenticator :server do friendly_name "Server Authenticator" header "X-Server-API-Key", "The API token for a server that you wish to authenticate with.", example: "f29a45f0d4e1744ebaee" diff --git a/api/controllers/messages_api_controller.rb b/api/controllers/messages_api_controller.rb index 96404ca..f76cb0d 100644 --- a/api/controllers/messages_api_controller.rb +++ b/api/controllers/messages_api_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + controller :messages do friendly_name "Messages API" description "This API allows you to access message details" @@ -12,7 +14,7 @@ controller :messages do action do begin message = identity.server.message(params.id) - rescue Postal::MessageDB::Message::NotFound => e + rescue Postal::MessageDB::Message::NotFound error "MessageNotFound", id: params.id end structure :message, message, return: true @@ -28,7 +30,7 @@ controller :messages do action do begin message = identity.server.message(params.id) - rescue Postal::MessageDB::Message::NotFound => e + rescue Postal::MessageDB::Message::NotFound error "MessageNotFound", id: params.id end message.deliveries.map do |d| diff --git a/api/controllers/send_api_controller.rb b/api/controllers/send_api_controller.rb index a51db10..c22935f 100644 --- a/api/controllers/send_api_controller.rb +++ b/api/controllers/send_api_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + controller :send do friendly_name "Send API" description "This API allows you to send messages" diff --git a/api/structures/delivery_api_structure.rb b/api/structures/delivery_api_structure.rb index d685f69..69cf82d 100644 --- a/api/structures/delivery_api_structure.rb +++ b/api/structures/delivery_api_structure.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + structure :delivery do basic :id basic :status diff --git a/api/structures/message_api_structure.rb b/api/structures/message_api_structure.rb index 5e97e5a..6cc3dcd 100644 --- a/api/structures/message_api_structure.rb +++ b/api/structures/message_api_structure.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + structure :message do basic :id basic :token @@ -5,9 +7,9 @@ structure :message do expansion(:status) do { status: o.status, - last_delivery_attempt: o.last_delivery_attempt ? o.last_delivery_attempt.to_f : nil, + last_delivery_attempt: o.last_delivery_attempt&.to_f, held: o.held, - hold_expiry: o.hold_expiry ? o.hold_expiry.to_f : nil + hold_expiry: o.hold_expiry&.to_f } end diff --git a/app/controllers/address_endpoints_controller.rb b/app/controllers/address_endpoints_controller.rb index bd5ce72..3d1f928 100644 --- a/app/controllers/address_endpoints_controller.rb +++ b/app/controllers/address_endpoints_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddressEndpointsController < ApplicationController include WithinOrganization diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 193a24b..3053575 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "authie/session" class ApplicationController < ActionController::Base @@ -46,11 +48,7 @@ class ApplicationController < ActionController::Base helper_method :page_title def redirect_to_with_return_to(url, *args) - if params[:return_to].blank? || !params[:return_to].starts_with?("/") - redirect_to url_with_return_to(url), *args - else - redirect_to url_with_return_to(url), *args - end + redirect_to url_with_return_to(url), *args end def set_timezone diff --git a/app/controllers/concerns/within_organization.rb b/app/controllers/concerns/within_organization.rb index 616d1c9..429a85b 100644 --- a/app/controllers/concerns/within_organization.rb +++ b/app/controllers/concerns/within_organization.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module WithinOrganization extend ActiveSupport::Concern diff --git a/app/controllers/credentials_controller.rb b/app/controllers/credentials_controller.rb index 736233e..c40fa89 100644 --- a/app/controllers/credentials_controller.rb +++ b/app/controllers/credentials_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CredentialsController < ApplicationController include WithinOrganization diff --git a/app/controllers/domains_controller.rb b/app/controllers/domains_controller.rb index c645944..f1ef258 100644 --- a/app/controllers/domains_controller.rb +++ b/app/controllers/domains_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class DomainsController < ApplicationController include WithinOrganization diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index 51d8bf0..29445d8 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class HelpController < ApplicationController include WithinOrganization diff --git a/app/controllers/http_endpoints_controller.rb b/app/controllers/http_endpoints_controller.rb index 5f8558d..56212f3 100644 --- a/app/controllers/http_endpoints_controller.rb +++ b/app/controllers/http_endpoints_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class HTTPEndpointsController < ApplicationController include WithinOrganization diff --git a/app/controllers/ip_addresses_controller.rb b/app/controllers/ip_addresses_controller.rb index fe00579..3e7bbb4 100644 --- a/app/controllers/ip_addresses_controller.rb +++ b/app/controllers/ip_addresses_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class IPAddressesController < ApplicationController before_action :admin_required diff --git a/app/controllers/ip_pool_rules_controller.rb b/app/controllers/ip_pool_rules_controller.rb index 043f004..566820a 100644 --- a/app/controllers/ip_pool_rules_controller.rb +++ b/app/controllers/ip_pool_rules_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class IPPoolRulesController < ApplicationController include WithinOrganization diff --git a/app/controllers/ip_pools_controller.rb b/app/controllers/ip_pools_controller.rb index d4476bf..106fae5 100644 --- a/app/controllers/ip_pools_controller.rb +++ b/app/controllers/ip_pools_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class IPPoolsController < ApplicationController before_action :admin_required @@ -31,7 +33,7 @@ class IPPoolsController < ApplicationController def destroy @ip_pool.destroy redirect_to_with_json :ip_pools, notice: "IP pool has been removed successfully." - rescue ActiveRecord::DeleteRestrictionError => e + rescue ActiveRecord::DeleteRestrictionError redirect_to_with_json [:edit, @ip_pool], alert: "IP pool cannot be removed because it still has associated addresses or servers." end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 1d267a9..6a6c2f1 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class MessagesController < ApplicationController include WithinOrganization @@ -186,7 +188,7 @@ class MessagesController < ApplicationController if qs[:before] begin options[:where][:timestamp][:less_than] = get_time_from_string(qs[:before]).to_f - rescue TimeUndetermined => e + rescue TimeUndetermined flash.now[:alert] = "Couldn't determine time for before from '#{qs[:before]}'" end end @@ -194,7 +196,7 @@ class MessagesController < ApplicationController if qs[:after] begin options[:where][:timestamp][:greater_than] = get_time_from_string(qs[:after]).to_f - rescue TimeUndetermined => e + rescue TimeUndetermined flash.now[:alert] = "Couldn't determine time for after from '#{qs[:after]}'" end end @@ -220,6 +222,7 @@ class MessagesController < ApplicationController time = Chronic.parse(string, context: :past) end rescue StandardError + time = nil end raise TimeUndetermined, "Couldn't determine a suitable time from '#{string}'" if time.nil? diff --git a/app/controllers/organization_ip_pools_controller.rb b/app/controllers/organization_ip_pools_controller.rb index ace1182..78f6740 100644 --- a/app/controllers/organization_ip_pools_controller.rb +++ b/app/controllers/organization_ip_pools_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class OrganizationIPPoolsController < ApplicationController include WithinOrganization diff --git a/app/controllers/organizations_controller.rb b/app/controllers/organizations_controller.rb index 8aaebc4..1e953fa 100644 --- a/app/controllers/organizations_controller.rb +++ b/app/controllers/organizations_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class OrganizationsController < ApplicationController before_action :admin_required, only: [:new, :create, :delete, :destroy] diff --git a/app/controllers/routes_controller.rb b/app/controllers/routes_controller.rb index e4c2eee..594b34b 100644 --- a/app/controllers/routes_controller.rb +++ b/app/controllers/routes_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class RoutesController < ApplicationController include WithinOrganization diff --git a/app/controllers/servers_controller.rb b/app/controllers/servers_controller.rb index 8e9626b..1058b53 100644 --- a/app/controllers/servers_controller.rb +++ b/app/controllers/servers_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ServersController < ApplicationController include WithinOrganization @@ -41,7 +43,12 @@ class ServersController < ApplicationController def update extra_params = [:spam_threshold, :spam_failure_threshold, :postmaster_address] - extra_params += [:send_limit, :allow_sender, :privacy_mode, :log_smtp_data, :outbound_spam_threshold, :message_retention_days, :raw_message_retention_days, :raw_message_retention_size] if current_user.admin? + + if current_user.admin? + extra_params += [:send_limit, :allow_sender, :privacy_mode, :log_smtp_data, :outbound_spam_threshold, + :message_retention_days, :raw_message_retention_days, :raw_message_retention_size] + end + if @server.update(safe_params(*extra_params)) redirect_to_with_json organization_server_path(organization, @server), notice: "Server settings have been updated" else diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 36385aa..e873d7d 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class SessionsController < ApplicationController layout "sub" @@ -8,7 +10,7 @@ class SessionsController < ApplicationController login(User.authenticate(params[:email_address], params[:password])) flash[:remember_login] = true redirect_to_with_return_to root_path - rescue Postal::Errors::AuthenticationError => e + rescue Postal::Errors::AuthenticationError flash.now[:alert] = "The credentials you've provided are incorrect. Please check and try again." render "new" end diff --git a/app/controllers/smtp_endpoints_controller.rb b/app/controllers/smtp_endpoints_controller.rb index cdefbcc..9659f26 100644 --- a/app/controllers/smtp_endpoints_controller.rb +++ b/app/controllers/smtp_endpoints_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class SMTPEndpointsController < ApplicationController include WithinOrganization diff --git a/app/controllers/track_domains_controller.rb b/app/controllers/track_domains_controller.rb index 31d11e2..b2a4f3e 100644 --- a/app/controllers/track_domains_controller.rb +++ b/app/controllers/track_domains_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class TrackDomainsController < ApplicationController include WithinOrganization diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 861c7ff..45d55ba 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class UserController < ApplicationController skip_before_action :login_required, only: [:new, :create, :join] @@ -69,7 +71,9 @@ class UserController < ApplicationController if @user.save if email_changed - redirect_to_with_json verify_path(return_to: settings_path), notice: "Your settings have been updated successfully. As you've changed, your e-mail address you'll need to verify it before you can continue." + redirect_to_with_json verify_path(return_to: settings_path), + notice: "Your settings have been updated successfully. As you've changed, your e-mail " \ + "address you'll need to verify it before you can continue." else redirect_to_with_json settings_path, notice: "Your settings have been updated successfully." end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 42dbbc8..4e3fb08 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class UsersController < ApplicationController before_action :admin_required diff --git a/app/controllers/webhooks_controller.rb b/app/controllers/webhooks_controller.rb index 6b949dc..0d76f5b 100644 --- a/app/controllers/webhooks_controller.rb +++ b/app/controllers/webhooks_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class WebhooksController < ApplicationController include WithinOrganization diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 0ddde9b..0e54e0d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ApplicationHelper def format_delivery_details(server, text) @@ -28,7 +30,7 @@ module ApplicationHelper server_domains = server.domains.verified.order(:name) unless server_domains.empty? s << "" - for domain in server_domains + server_domains.each do |domain| selected = domain == selected_domain ? "selected='selected'" : "" s << "" end @@ -38,7 +40,7 @@ module ApplicationHelper organization_domains = server.organization.domains.verified.order(:name) unless organization_domains.empty? s << "" - for domain in organization_domains + organization_domains.each do |domain| selected = domain == selected_domain ? "selected='selected'" : "" s << "" end @@ -54,7 +56,7 @@ module ApplicationHelper http_endpoints = server.http_endpoints.order(:name).to_a if http_endpoints.present? s << "" - for endpoint in http_endpoints + http_endpoints.each do |endpoint| value = "#{endpoint.class}##{endpoint.uuid}" selected = value == selected_value ? "selected='selected'" : "" s << "" @@ -65,7 +67,7 @@ module ApplicationHelper smtp_endpoints = server.smtp_endpoints.order(:name).to_a if smtp_endpoints.present? s << "" - for endpoint in smtp_endpoints + smtp_endpoints.each do |endpoint| value = "#{endpoint.class}##{endpoint.uuid}" selected = value == selected_value ? "selected='selected'" : "" s << "" @@ -76,7 +78,7 @@ module ApplicationHelper address_endpoints = server.address_endpoints.order(:address).to_a if address_endpoints.present? s << "" - for endpoint in address_endpoints + address_endpoints.each do |endpoint| value = "#{endpoint.class}##{endpoint.uuid}" selected = value == selected_value ? "selected='selected'" : "" s << "" diff --git a/app/jobs/action_deletion_job.rb b/app/jobs/action_deletion_job.rb index b39e877..e598a85 100644 --- a/app/jobs/action_deletion_job.rb +++ b/app/jobs/action_deletion_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ActionDeletionJob < Postal::Job def perform diff --git a/app/jobs/action_deletions_job.rb b/app/jobs/action_deletions_job.rb index ebdab73..f68b1d9 100644 --- a/app/jobs/action_deletions_job.rb +++ b/app/jobs/action_deletions_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ActionDeletionsJob < Postal::Job def perform diff --git a/app/jobs/check_all_dns_job.rb b/app/jobs/check_all_dns_job.rb index 29427c5..0393afa 100644 --- a/app/jobs/check_all_dns_job.rb +++ b/app/jobs/check_all_dns_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CheckAllDNSJob < Postal::Job def perform diff --git a/app/jobs/cleanup_authie_sessions_job.rb b/app/jobs/cleanup_authie_sessions_job.rb index 6beaa36..36a93d0 100644 --- a/app/jobs/cleanup_authie_sessions_job.rb +++ b/app/jobs/cleanup_authie_sessions_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "authie/session" class CleanupAuthieSessionsJob < Postal::Job diff --git a/app/jobs/expire_held_messages_job.rb b/app/jobs/expire_held_messages_job.rb index a65233f..e54d052 100644 --- a/app/jobs/expire_held_messages_job.rb +++ b/app/jobs/expire_held_messages_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ExpireHeldMessagesJob < Postal::Job def perform diff --git a/app/jobs/process_message_retention_job.rb b/app/jobs/process_message_retention_job.rb index d4ab415..35c3bf3 100644 --- a/app/jobs/process_message_retention_job.rb +++ b/app/jobs/process_message_retention_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ProcessMessageRetentionJob < Postal::Job def perform diff --git a/app/jobs/prune_suppression_lists_job.rb b/app/jobs/prune_suppression_lists_job.rb index 772b428..ece9db7 100644 --- a/app/jobs/prune_suppression_lists_job.rb +++ b/app/jobs/prune_suppression_lists_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class PruneSuppressionListsJob < Postal::Job def perform diff --git a/app/jobs/prune_webhook_requests_job.rb b/app/jobs/prune_webhook_requests_job.rb index 2b424cb..632bc4a 100644 --- a/app/jobs/prune_webhook_requests_job.rb +++ b/app/jobs/prune_webhook_requests_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class PruneWebhookRequestsJob < Postal::Job def perform diff --git a/app/jobs/requeue_webhooks_job.rb b/app/jobs/requeue_webhooks_job.rb index 21a4684..736f0b6 100644 --- a/app/jobs/requeue_webhooks_job.rb +++ b/app/jobs/requeue_webhooks_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class RequeueWebhooksJob < Postal::Job def perform diff --git a/app/jobs/send_notifications_job.rb b/app/jobs/send_notifications_job.rb index 9caf795..9d519c6 100644 --- a/app/jobs/send_notifications_job.rb +++ b/app/jobs/send_notifications_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class SendNotificationsJob < Postal::Job def perform diff --git a/app/jobs/send_webhook_job.rb b/app/jobs/send_webhook_job.rb index b0a3eab..8228563 100644 --- a/app/jobs/send_webhook_job.rb +++ b/app/jobs/send_webhook_job.rb @@ -1,16 +1,17 @@ +# frozen_string_literal: true + class SendWebhookJob < Postal::Job def perform if server = Server.find(params["server_id"]) new_items = {} - if params["payload"] - for key, value in params["payload"] - next unless key.to_s =~ /\A_(\w+)/ + params["payload"]&.each do |key, value| + next unless key.to_s =~ /\A_(\w+)/ - begin - new_items[::Regexp.last_match(1)] = server.message_db.message(value.to_i).webhook_hash - rescue Postal::MessageDB::Message::NotFound - end + begin + new_items[::Regexp.last_match(1)] = server.message_db.message(value.to_i).webhook_hash + rescue Postal::MessageDB::Message::NotFound + # No message found, don't do any replacement end end diff --git a/app/jobs/sleep_job.rb b/app/jobs/sleep_job.rb index 17da30c..9604b76 100644 --- a/app/jobs/sleep_job.rb +++ b/app/jobs/sleep_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class SleepJob < Postal::Job def perform diff --git a/app/jobs/tidy_raw_messages_job.rb b/app/jobs/tidy_raw_messages_job.rb index a9654e2..151188f 100644 --- a/app/jobs/tidy_raw_messages_job.rb +++ b/app/jobs/tidy_raw_messages_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class TidyRawMessagesJob < Postal::Job def perform diff --git a/app/jobs/unqueue_message_job.rb b/app/jobs/unqueue_message_job.rb index a382222..809ecfb 100644 --- a/app/jobs/unqueue_message_job.rb +++ b/app/jobs/unqueue_message_job.rb @@ -1,5 +1,8 @@ +# frozen_string_literal: true + class UnqueueMessageJob < Postal::Job + # rubocop:disable Layout/LineLength def perform if original_message = QueuedMessage.find_by_id(params["id"]) if original_message.acquire_lock @@ -91,11 +94,11 @@ class UnqueueMessageJob < Postal::Job log "#{log_prefix} Message is a bounce" original_messages = queued_message.message.original_messages unless original_messages.empty? - for original_message in queued_message.message.original_messages - queued_message.message.update(bounce_for_id: original_message.id, domain_id: original_message.domain_id) - queued_message.message.create_delivery("Processed", details: "This has been detected as a bounce message for .") - original_message.bounce!(queued_message.message) - log "#{log_prefix} Bounce linked with message #{original_message.id}" + queued_message.message.original_messages.each do |orig_msg| + queued_message.message.update(bounce_for_id: orig_msg.id, domain_id: orig_msg.domain_id) + queued_message.message.create_delivery("Processed", details: "This has been detected as a bounce message for .") + orig_msg.bounce!(queued_message.message) + log "#{log_prefix} Bounce linked with message #{orig_msg.id}" end queued_message.destroy next @@ -421,15 +424,17 @@ class UnqueueMessageJob < Postal::Job end rescue StandardError => e log "#{log_prefix} Internal error: #{e.class}: #{e.message}" - e.backtrace.each { |e| log("#{log_prefix} #{e}") } + e.backtrace.each { |line| log("#{log_prefix} #{line}") } queued_message.retry_later log "#{log_prefix} Queued message was unlocked" if defined?(Sentry) Sentry.capture_exception(e, extra: { job_id: self.id, server_id: queued_message.server_id, message_id: queued_message.message_id }) end - if queued_message.message - queued_message.message.create_delivery("Error", details: "An internal error occurred while sending this message. This message will be retried automatically. If this persists, contact support for assistance.", output: "#{e.class}: #{e.message}", log_id: "J-#{self.id}") - end + queued_message.message&.create_delivery("Error", + details: "An internal error occurred while sending " \ + "this message. This message will be retried " \ + "automatically.", + output: "#{e.class}: #{e.message}", log_id: "J-#{self.id}") end end @@ -446,9 +451,11 @@ class UnqueueMessageJob < Postal::Job nil end end + # rubocop:enable Layout/LineLength private + # rubocop:disable Naming/MemoizedInstanceVariableName def cached_sender(klass, *args) @sender ||= begin sender = klass.new(*args) @@ -456,5 +463,6 @@ class UnqueueMessageJob < Postal::Job sender end end + # rubocop:enable Naming/MemoizedInstanceVariableName end diff --git a/app/jobs/webhook_delivery_job.rb b/app/jobs/webhook_delivery_job.rb index d4217db..a7369f5 100644 --- a/app/jobs/webhook_delivery_job.rb +++ b/app/jobs/webhook_delivery_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class WebhookDeliveryJob < Postal::Job def perform diff --git a/app/mailers/app_mailer.rb b/app/mailers/app_mailer.rb index 61f366b..dca1d84 100644 --- a/app/mailers/app_mailer.rb +++ b/app/mailers/app_mailer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AppMailer < ApplicationMailer def verify_email_address(user) diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 75864cb..95b7f19 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ApplicationMailer < ActionMailer::Base default from: "#{Postal.smtp_from_name} <#{Postal.smtp_from_address}>" diff --git a/app/models/additional_route_endpoint.rb b/app/models/additional_route_endpoint.rb index 1282d9e..376cfa6 100644 --- a/app/models/additional_route_endpoint.rb +++ b/app/models/additional_route_endpoint.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: additional_route_endpoints @@ -35,9 +37,7 @@ class AdditionalRouteEndpoint < ApplicationRecord end def _endpoint=(value) - if value.blank? - self.endpoint = nil - elsif value =~ /\#/ + if value && value =~ /\#/ class_name, id = value.split("#", 2) unless Route::ENDPOINT_TYPES.include?(class_name) raise Postal::Error, "Invalid endpoint class name '#{class_name}'" diff --git a/app/models/address_endpoint.rb b/app/models/address_endpoint.rb index d1759ac..18de130 100644 --- a/app/models/address_endpoint.rb +++ b/app/models/address_endpoint.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: address_endpoints diff --git a/app/models/application_record.rb b/app/models/application_record.rb index 03c6a5b..aecc770 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ApplicationRecord < ActiveRecord::Base self.abstract_class = true diff --git a/app/models/concerns/has_authentication.rb b/app/models/concerns/has_authentication.rb index ec60b11..80a52ce 100644 --- a/app/models/concerns/has_authentication.rb +++ b/app/models/concerns/has_authentication.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module HasAuthentication extend ActiveSupport::Concern @@ -42,18 +44,4 @@ module HasAuthentication end -class Postal::Errors::AuthenticationError < Postal::Error - - attr_reader :error - - def initialize(error) - @error = error - end - - def to_s - "Authentication Failed: #{@error}" - end - -end - # -*- SkipSchemaAnnotations diff --git a/app/models/concerns/has_dns_checks.rb b/app/models/concerns/has_dns_checks.rb index 920980b..a4d6ec5 100644 --- a/app/models/concerns/has_dns_checks.rb +++ b/app/models/concerns/has_dns_checks.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + require "resolv" module HasDNSChecks def dns_ok? - spf_status == "OK" && dkim_status == "OK" && ["OK", "Missing"].include?(mx_status) && ["OK", "Missing"].include?(return_path_status) + spf_status == "OK" && dkim_status == "OK" && %w[OK Missing].include?(mx_status) && %w[OK Missing].include?(return_path_status) end def dns_checked? @@ -42,12 +44,12 @@ module HasDNSChecks def check_spf_record result = resolver.getresources(name, Resolv::DNS::Resource::IN::TXT) - spf_records = result.map(&:data).select { |d| d =~ /\Av=spf1/ } + spf_records = result.map(&:data).grep(/\Av=spf1/) if spf_records.empty? self.spf_status = "Missing" self.spf_error = "No SPF record exists for this domain" else - suitable_spf_records = spf_records.select { |d| d =~ /include:\s*#{Regexp.escape(Postal.config.dns.spf_include)}/ } + suitable_spf_records = spf_records.grep(/include:\s*#{Regexp.escape(Postal.config.dns.spf_include)}/) if suitable_spf_records.empty? self.spf_status = "Invalid" self.spf_error = "An SPF record exists but it doesn't include #{Postal.config.dns.spf_include}" diff --git a/app/models/concerns/has_message.rb b/app/models/concerns/has_message.rb index 97a02a0..99d4897 100644 --- a/app/models/concerns/has_message.rb +++ b/app/models/concerns/has_message.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module HasMessage def self.included(base) @@ -18,7 +20,7 @@ module HasMessage def include_message queued_messages = all.to_a server_ids = queued_messages.map(&:server_id).uniq - if server_ids.size == 0 + if server_ids.empty? return [] elsif server_ids.size > 1 raise Postal::Error, "'include_message' can only be used on collections of messages from the same server" diff --git a/app/models/concerns/has_soft_destroy.rb b/app/models/concerns/has_soft_destroy.rb index 7ad2865..55cfcaf 100644 --- a/app/models/concerns/has_soft_destroy.rb +++ b/app/models/concerns/has_soft_destroy.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module HasSoftDestroy def self.included(base) diff --git a/app/models/concerns/has_uuid.rb b/app/models/concerns/has_uuid.rb index a9b87a7..0c85bf7 100644 --- a/app/models/concerns/has_uuid.rb +++ b/app/models/concerns/has_uuid.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module HasUUID def self.included(base) diff --git a/app/models/credential.rb b/app/models/credential.rb index 1a774c0..18e3266 100644 --- a/app/models/credential.rb +++ b/app/models/credential.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: credentials @@ -21,7 +23,7 @@ class Credential < ApplicationRecord belongs_to :server - TYPES = ["SMTP", "API", "SMTP-IP"] + TYPES = %w[SMTP API SMTP-IP].freeze validates :key, presence: true, uniqueness: { case_sensitive: false } validates :type, inclusion: { in: TYPES } diff --git a/app/models/domain.rb b/app/models/domain.rb index 8c35bc5..4a845f8 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: domains @@ -42,15 +44,14 @@ class Domain < ApplicationRecord include HasDNSChecks - VERIFICATION_EMAIL_ALIASES = ["webmaster", "postmaster", "admin", "administrator", "hostmaster"] + VERIFICATION_EMAIL_ALIASES = %w[webmaster postmaster admin administrator hostmaster].freeze + VERIFICATION_METHODS = %w[DNS Email].freeze belongs_to :server, optional: true belongs_to :owner, optional: true, polymorphic: true has_many :routes, dependent: :destroy has_many :track_domains, dependent: :destroy - VERIFICATION_METHODS = ["DNS", "Email"] - validates :name, presence: true, format: { with: /\A[a-z0-9\-.]*\z/ }, uniqueness: { case_sensitive: false, scope: [:owner_type, :owner_id], message: "is already added" } validates :verification_method, inclusion: { in: VERIFICATION_METHODS } @@ -83,8 +84,8 @@ class Domain < ApplicationRecord def parent_domains parts = name.split(".") - parts[0, parts.size - 1].each_with_index.map do |p, i| - parts[i..-1].join(".") + parts[0, parts.size - 1].each_with_index.map do |_, i| + parts[i..].join(".") end end diff --git a/app/models/http_endpoint.rb b/app/models/http_endpoint.rb index b87266a..8cd9044 100644 --- a/app/models/http_endpoint.rb +++ b/app/models/http_endpoint.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: http_endpoints @@ -29,8 +31,8 @@ class HTTPEndpoint < ApplicationRecord has_many :routes, as: :endpoint has_many :additional_route_endpoints, dependent: :destroy, as: :endpoint - ENCODINGS = ["BodyAsJSON", "FormData"] - FORMATS = ["Hash", "RawMessage"] + ENCODINGS = %w[BodyAsJSON FormData].freeze + FORMATS = %w[Hash RawMessage].freeze before_destroy :update_routes diff --git a/app/models/incoming_message_prototype.rb b/app/models/incoming_message_prototype.rb index 8dee389..334df62 100644 --- a/app/models/incoming_message_prototype.rb +++ b/app/models/incoming_message_prototype.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class IncomingMessagePrototype attr_accessor :to @@ -22,13 +24,14 @@ class IncomingMessagePrototype end def route - @routes ||= if @to.present? - uname, domain = @to.split("@", 2) - uname, tag = uname.split("+", 2) - @server.routes.includes(:domain).where(domains: { name: domain }, name: uname).first - end + @route ||= if @to.present? + uname, domain = @to.split("@", 2) + uname, _tag = uname.split("+", 2) + @server.routes.includes(:domain).where(domains: { name: domain }, name: uname).first + end end + # rubocop:disable Lint/DuplicateMethods def attachments (@attachments || []).map do |attachment| { @@ -38,6 +41,7 @@ class IncomingMessagePrototype } end end + # rubocop:enable Lint/DuplicateMethods def create_messages if valid? diff --git a/app/models/ip_address.rb b/app/models/ip_address.rb index fd67e86..451c7a1 100644 --- a/app/models/ip_address.rb +++ b/app/models/ip_address.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: ip_addresses diff --git a/app/models/ip_pool.rb b/app/models/ip_pool.rb index 754d87c..7d118dc 100644 --- a/app/models/ip_pool.rb +++ b/app/models/ip_pool.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: ip_pools diff --git a/app/models/ip_pool_rule.rb b/app/models/ip_pool_rule.rb index 2f37ad4..8a85a6b 100644 --- a/app/models/ip_pool_rule.rb +++ b/app/models/ip_pool_rule.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: ip_pool_rules @@ -66,18 +68,22 @@ class IPPoolRule < ApplicationRecord errors.add :ip_pool_id, "must belong to the organization" end - def self.address_matches?(condition, address) - address = Postal::Helpers.strip_name_from_address(address) - if condition =~ /@/ - parts = address.split("@") - domain = parts.pop - uname = parts.join("@") - uname, = uname.split("+", 2) - condition == "#{uname}@#{domain}" - else - # Match as a domain - condition == address.split("@").last + class << self + + def address_matches?(condition, address) + address = Postal::Helpers.strip_name_from_address(address) + if condition =~ /@/ + parts = address.split("@") + domain = parts.pop + uname = parts.join("@") + uname, = uname.split("+", 2) + condition == "#{uname}@#{domain}" + else + # Match as a domain + condition == address.split("@").last + end end + end end diff --git a/app/models/organization.rb b/app/models/organization.rb index 1af7d7d..60841dc 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: organizations @@ -23,7 +25,7 @@ class Organization < ApplicationRecord - RESERVED_PERMALINKS = ["new", "edit", "remove", "delete", "destroy", "admin", "mail", "org", "server"] + RESERVED_PERMALINKS = %w[new edit remove delete destroy admin mail org server].freeze INITIAL_QUOTA = 10 INITIAL_SUPER_QUOTA = 10_000 @@ -48,7 +50,7 @@ class Organization < ApplicationRecord has_many :ip_pool_rules, dependent: :destroy, as: :owner after_create do - if pool = IPPool.default + if IPPool.default ip_pools << IPPool.default end end diff --git a/app/models/organization_ip_pool.rb b/app/models/organization_ip_pool.rb index 9db6f81..d0fefac 100644 --- a/app/models/organization_ip_pool.rb +++ b/app/models/organization_ip_pool.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: organization_ip_pools diff --git a/app/models/organization_user.rb b/app/models/organization_user.rb index 3f173da..d602a48 100644 --- a/app/models/organization_user.rb +++ b/app/models/organization_user.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: organization_users diff --git a/app/models/outgoing_message_prototype.rb b/app/models/outgoing_message_prototype.rb index c894917..7362f30 100644 --- a/app/models/outgoing_message_prototype.rb +++ b/app/models/outgoing_message_prototype.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "resolv" class OutgoingMessagePrototype @@ -47,13 +49,11 @@ class OutgoingMessagePrototype end def find_domain - @domain ||= begin - domain = @server.authenticated_domain_for_address(@from) - if @server.allow_sender? && domain.nil? - domain = @server.authenticated_domain_for_address(@sender) - end - domain || :none + domain = @server.authenticated_domain_for_address(@from) + if @server.allow_sender? && domain.nil? + domain = @server.authenticated_domain_for_address(@sender) end + domain || :none end def to_addresses @@ -93,6 +93,7 @@ class OutgoingMessagePrototype @errors || {} end + # rubocop:disable Lint/DuplicateMethods def attachments (@attachments || []).map do |attachment| { @@ -102,6 +103,7 @@ class OutgoingMessagePrototype } end end + # rubocop:enable Lint/DuplicateMethods def validate @errors = [] @@ -135,7 +137,7 @@ class OutgoingMessagePrototype end if attachments.present? - attachments.each_with_index do |attachment, index| + attachments.each do |attachment| if attachment[:name].blank? @errors << "AttachmentMissingName" unless @errors.include?("AttachmentMissingName") elsif attachment[:data].blank? diff --git a/app/models/queued_message.rb b/app/models/queued_message.rb index d0dc276..5fc413b 100644 --- a/app/models/queued_message.rb +++ b/app/models/queued_message.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: queued_messages diff --git a/app/models/route.rb b/app/models/route.rb index 8661d50..3ef415c 100644 --- a/app/models/route.rb +++ b/app/models/route.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: routes @@ -22,7 +24,9 @@ class Route < ApplicationRecord - MODES = ["Endpoint", "Accept", "Hold", "Bounce", "Reject"] + MODES = %w[Endpoint Accept Hold Bounce Reject].freeze + SPAM_MODES = %w[Mark Quarantine Fail].freeze + ENDPOINT_TYPES = %w[SMTPEndpoint HTTPEndpoint AddressEndpoint].freeze include HasUUID @@ -31,9 +35,6 @@ class Route < ApplicationRecord belongs_to :endpoint, polymorphic: true, optional: true has_many :additional_route_endpoints, dependent: :destroy - SPAM_MODES = ["Mark", "Quarantine", "Fail"] - ENDPOINT_TYPES = ["SMTPEndpoint", "HTTPEndpoint", "AddressEndpoint"] - validates :name, presence: true, format: /\A(([a-z0-9\-.]*)|(\*)|(__returnpath__))\z/ validates :spam_mode, inclusion: { in: SPAM_MODES } validates :endpoint, presence: { if: proc { mode == "Endpoint" } } @@ -115,7 +116,7 @@ class Route < ApplicationRecord if route.save seen << route.id else - route.errors.each do |field, message| + route.errors.each do |_, message| errors.add :base, message end raise ActiveRecord::RecordInvalid @@ -200,7 +201,7 @@ class Route < ApplicationRecord if route = Route.includes(:domain).where(domains: { name: domain.name }, name: name).where.not(id: id).first errors.add :name, "is configured on the #{route.server.full_permalink} mail server" end - elsif route = Route.where(name: "__returnpath__").where.not(id: id).exists? + elsif Route.where(name: "__returnpath__").where.not(id: id).exists? errors.add :base, "A return path route already exists for this server" end end @@ -218,12 +219,16 @@ class Route < ApplicationRecord errors.add :base, "Additional routes are not permitted unless the primary route is an actual endpoint" end - def self.find_by_name_and_domain(name, domain) - route = Route.includes(:domain).where(name: name, domains: { name: domain }).first - if route.nil? - route = Route.includes(:domain).where(name: "*", domains: { name: domain }).first + class << self + + def find_by_name_and_domain(name, domain) + route = Route.includes(:domain).where(name: name, domains: { name: domain }).first + if route.nil? + route = Route.includes(:domain).where(name: "*", domains: { name: domain }).first + end + route end - route + end end diff --git a/app/models/server.rb b/app/models/server.rb index 506ec48..557cdff 100644 --- a/app/models/server.rb +++ b/app/models/server.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: servers @@ -41,7 +43,8 @@ class Server < ApplicationRecord - RESERVED_PERMALINKS = ["new", "all", "search", "stats", "edit", "manage", "delete", "destroy", "remove"] + RESERVED_PERMALINKS = %w[new all search stats edit manage delete destroy remove].freeze + MODES = %w[Live Development].freeze include HasUUID include HasSoftDestroy @@ -62,8 +65,6 @@ class Server < ApplicationRecord has_many :track_domains, dependent: :destroy has_many :ip_pool_rules, dependent: :destroy, as: :owner - MODES = ["Live", "Development"] - random_string :token, type: :chars, length: 6, unique: true, upper_letters_only: true default_value :permalink, -> { name ? name.parameterize : nil } default_value :raw_message_retention_days, -> { 30 } @@ -155,11 +156,11 @@ class Server < ApplicationRecord time = Time.now.utc total_outgoing = 0.0 total_bounces = 0.0 - message_db.statistics.get(:daily, [:outgoing, :bounces], time, 30).each do |date, stat| + message_db.statistics.get(:daily, [:outgoing, :bounces], time, 30).each do |_, stat| total_outgoing += stat[:outgoing] total_bounces += stat[:bounces] end - total_outgoing == 0 ? 0 : (total_bounces / total_outgoing) * 100 + total_outgoing.zero? ? 0 : (total_bounces / total_outgoing) * 100 end end @@ -218,6 +219,10 @@ class Server < ApplicationRecord } end + # Return the domain which can be used to authenticate emails sent from the given e-mail address. + # + #  @param address [String] an e-mail address + # @return [Domain, nil] the domain to use for authentication def authenticated_domain_for_address(address) return nil if address.blank? @@ -226,16 +231,24 @@ class Server < ApplicationRecord return nil unless uname return nil unless domain_name - uname, = uname.split("+", 2) + # Find a verified domain which directly matches the domain name for the given address. + domain = Domain.verified + .order(owner_type: :desc) + .where("(owner_type = 'Organization' AND owner_id = ?) OR " \ + "(owner_type = 'Server' AND owner_id = ?)", organization_id, id) + .where(name: domain_name) + .first - # Check the server's domain - if domain = Domain.verified.order(owner_type: :desc).where("(owner_type = 'Organization' AND owner_id = ?) OR (owner_type = 'Server' AND owner_id = ?)", organization_id, id).where(name: domain_name).first - return domain - end + # If there is a matching domain, return it + return domain if domain - return unless any_domain = domains.verified.where(use_for_any: true).order(:name).first + # Otherwise, we need to look to see if there is a domain configured which can be used as the authenticated + # domain for any domain. This will look for domains directly within the server and return that. + any_domain = domains.verified.where(use_for_any: true).order(:name).first + return any_domain if any_domain - any_domain + # Return nil if we can't find anything suitable + nil end def find_authenticated_domain_from_headers(headers) diff --git a/app/models/smtp_endpoint.rb b/app/models/smtp_endpoint.rb index 5c0f094..b063f80 100644 --- a/app/models/smtp_endpoint.rb +++ b/app/models/smtp_endpoint.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: smtp_endpoints @@ -24,7 +26,7 @@ class SMTPEndpoint < ApplicationRecord has_many :routes, as: :endpoint has_many :additional_route_endpoints, dependent: :destroy, as: :endpoint - SSL_MODES = ["None", "Auto", "STARTTLS", "TLS"] + SSL_MODES = %w[None Auto STARTTLS TLS].freeze before_destroy :update_routes diff --git a/app/models/statistic.rb b/app/models/statistic.rb index 1a360f7..e344ba1 100644 --- a/app/models/statistic.rb +++ b/app/models/statistic.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: statistics diff --git a/app/models/track_domain.rb b/app/models/track_domain.rb index 7108a76..810b6ea 100644 --- a/app/models/track_domain.rb +++ b/app/models/track_domain.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: track_domains diff --git a/app/models/user.rb b/app/models/user.rb index ce111d1..b2831f3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: users diff --git a/app/models/user_invite.rb b/app/models/user_invite.rb index 35230df..2b8b4de 100644 --- a/app/models/user_invite.rb +++ b/app/models/user_invite.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: user_invites diff --git a/app/models/webhook.rb b/app/models/webhook.rb index e5b6989..a334632 100644 --- a/app/models/webhook.rb +++ b/app/models/webhook.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: webhooks diff --git a/app/models/webhook_event.rb b/app/models/webhook_event.rb index 81b7252..29295e7 100644 --- a/app/models/webhook_event.rb +++ b/app/models/webhook_event.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: webhook_events @@ -14,16 +16,16 @@ class WebhookEvent < ApplicationRecord - EVENTS = [ - "MessageSent", - "MessageDelayed", - "MessageDeliveryFailed", - "MessageHeld", - "MessageBounced", - "MessageLinkClicked", - "MessageLoaded", - "DomainDNSError" - ] + EVENTS = %w[ + MessageSent + MessageDelayed + MessageDeliveryFailed + MessageHeld + MessageBounced + MessageLinkClicked + MessageLoaded + DomainDNSError + ].freeze belongs_to :webhook diff --git a/app/models/webhook_request.rb b/app/models/webhook_request.rb index 5fc3043..97d4b6f 100644 --- a/app/models/webhook_request.rb +++ b/app/models/webhook_request.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: webhook_requests @@ -19,7 +21,7 @@ class WebhookRequest < ApplicationRecord include HasUUID - RETRIES = { 1 => 2.minutes, 2 => 3.minutes, 3 => 6.minutes, 4 => 10.minutes, 5 => 15.minutes } + RETRIES = { 1 => 2.minutes, 2 => 3.minutes, 3 => 6.minutes, 4 => 10.minutes, 5 => 15.minutes }.freeze belongs_to :server belongs_to :webhook, optional: true diff --git a/bin/rails b/bin/rails index efc0377..22f2d8d 100755 --- a/bin/rails +++ b/bin/rails @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + APP_PATH = File.expand_path("../config/application", __dir__) require_relative "../config/boot" require "rails/commands" diff --git a/bin/rake b/bin/rake index 4fbf10b..e436ea5 100755 --- a/bin/rake +++ b/bin/rake @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require_relative "../config/boot" require "rake" Rake.application.run diff --git a/bin/setup b/bin/setup index 37be32e..e413f40 100755 --- a/bin/setup +++ b/bin/setup @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require "pathname" require "fileutils" include FileUtils diff --git a/bin/update b/bin/update index db28935..998dede 100755 --- a/bin/update +++ b/bin/update @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require "pathname" require "fileutils" include FileUtils diff --git a/config.ru b/config.ru index 826d2c9..9f3cd86 100644 --- a/config.ru +++ b/config.ru @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file is used by Rack-based servers to start the application. require_relative "config/environment" diff --git a/config/application.rb b/config/application.rb index 3361592..d0fb313 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "boot" require "rails" @@ -30,7 +32,7 @@ module Postal config.eager_load_paths << Rails.root.join("lib") # Disable field_with_errors - config.action_view.field_error_proc = proc { |t, i| t } + config.action_view.field_error_proc = proc { |t, _| t } # Load the tracking server middleware require "postal/tracking_middleware" diff --git a/config/boot.rb b/config/boot.rb index 6a4545b..73db71c 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) $stdout.sync = true diff --git a/config/cron.rb b/config/cron.rb index b9def94..ab18723 100644 --- a/config/cron.rb +++ b/config/cron.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Clockwork configure do |config| diff --git a/config/environment.rb b/config/environment.rb index cac5315..7df99e8 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Load the Rails application. require_relative "application" diff --git a/config/environments/development.rb b/config/environments/development.rb index c3e7b0a..b13af62 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. diff --git a/config/environments/production.rb b/config/environments/production.rb index 8c12538..cca5f81 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -71,7 +73,7 @@ Rails.application.configure do # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') if ENV["RAILS_LOG_TO_STDOUT"].present? - logger = ActiveSupport::Logger.new(STDOUT) + logger = ActiveSupport::Logger.new($stdout) logger.formatter = config.log_formatter config.logger = ActiveSupport::TaggedLogging.new(logger) end diff --git a/config/environments/test.rb b/config/environments/test.rb index a3a92fb..f88be04 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb index 51639b6..315ac48 100644 --- a/config/initializers/application_controller_renderer.rb +++ b/config/initializers/application_controller_renderer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # ApplicationController.renderer.defaults.merge!( diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 0838ada..1be14d3 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb index 59385cd..d0f0d3b 100644 --- a/config/initializers/backtrace_silencers.rb +++ b/config/initializers/backtrace_silencers.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 5a6a32d..ee8dff9 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Specify a serializer for the signed and encrypted cookie jars. diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index 4a994e1..7a4f47b 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 0185b3b..da17573 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections @@ -12,7 +14,6 @@ # These inflection rules are supported but not enabled by default: ActiveSupport::Inflector.inflections(:en) do |inflect| - inflect.acronym "DKIM" inflect.acronym "HTTP" inflect.acronym "SMTP" diff --git a/config/initializers/mail_extensions.rb b/config/initializers/mail_extensions.rb index e51e364..c109fa7 100644 --- a/config/initializers/mail_extensions.rb +++ b/config/initializers/mail_extensions.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "mail" module Mail @@ -20,7 +22,7 @@ module Mail ## Extract plain text body of message def plain_body - if multipart? and text_part + if multipart? && text_part text_part.decoded elsif mime_type == "text/plain" || mime_type.nil? decoded @@ -29,7 +31,7 @@ module Mail ## Extract HTML text body of message def html_body - if multipart? and html_part + if multipart? && html_part html_part.decoded elsif mime_type == "text/html" decoded @@ -109,14 +111,16 @@ module Mail # Handle attached emails as attachments class AttachmentsList < Array + # rubocop:disable Lint/MissingSuper def initialize(parts_list) @parts_list = parts_list @content_disposition_type = "attachment" - parts_list.map do |p| - (p.parts.empty? and p.attachment?) ? p : p.attachments - end.flatten.compact.each { |a| self << a } - self + parts = parts_list.map do |p| + p.parts.empty? && p.attachment? ? p : p.attachments + end.flatten.compact + parts.each { |a| self << a } end + # rubocop:enable Lint/MissingSuper end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index dc18996..6e1d16f 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: diff --git a/config/initializers/new_framework_defaults.rb b/config/initializers/new_framework_defaults.rb index 761ff37..420535c 100644 --- a/config/initializers/new_framework_defaults.rb +++ b/config/initializers/new_framework_defaults.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # # This file contains migration options to ease your Rails 5.0 upgrade. diff --git a/config/initializers/postal.rb b/config/initializers/postal.rb index e5cfc9f..7c93a5c 100644 --- a/config/initializers/postal.rb +++ b/config/initializers/postal.rb @@ -1 +1,3 @@ +# frozen_string_literal: true + require "postal" diff --git a/config/initializers/record_key_for_dom.rb b/config/initializers/record_key_for_dom.rb index b9ff469..e0152c1 100644 --- a/config/initializers/record_key_for_dom.rb +++ b/config/initializers/record_key_for_dom.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ActionView module RecordIdentifier diff --git a/config/initializers/secret_key.rb b/config/initializers/secret_key.rb index b649767..d4f48f1 100644 --- a/config/initializers/secret_key.rb +++ b/config/initializers/secret_key.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + if Postal.config.rails&.secret_key Rails.application.secrets.secret_key_base = Postal.config.rails.secret_key else diff --git a/config/initializers/secure_headers.rb b/config/initializers/secure_headers.rb index 98422c8..71894cf 100644 --- a/config/initializers/secure_headers.rb +++ b/config/initializers/secure_headers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + SecureHeaders::Configuration.default do |config| config.hsts = SecureHeaders::OPT_OUT diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb index 22b6731..88d4588 100644 --- a/config/initializers/sentry.rb +++ b/config/initializers/sentry.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "postal/config" if Postal.config.general&.exception_url diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index d5ee351..51fd0d7 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. Rails.application.config.session_store :cookie_store, key: "_postal_session" diff --git a/config/initializers/smtp.rb b/config/initializers/smtp.rb index 9380825..a9a1de2 100644 --- a/config/initializers/smtp.rb +++ b/config/initializers/smtp.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "postal/config" if Postal.config&.smtp ActionMailer::Base.delivery_method = :smtp diff --git a/config/initializers/smtp_extensions.rb b/config/initializers/smtp_extensions.rb index 609560f..f6db89c 100644 --- a/config/initializers/smtp_extensions.rb +++ b/config/initializers/smtp_extensions.rb @@ -1,38 +1,42 @@ -class Net::SMTP::Response +# frozen_string_literal: true + +module Net + class SMTP + + attr_accessor :source_address + + def secure_socket? + @socket.io.is_a?(OpenSSL::SSL::SSLSocket) + end + + # + # We had an issue where a message was sent to a server and was greylisted. It returned + # a Net::SMTPUnknownError error. We then tried to send another message on the same + # connection after running `rset` the next message didn't raise any exceptions because + # net/smtp returns a '200 dummy reply code' and doesn't raise any exceptions. + # + def rset + @error_occurred = false + getok("RSET") + end + + def rset_errors + @error_occurred = false + end + + private + + def tcp_socket(address, port) + TCPSocket.open(address, port, source_address) + end + + class Response + + def message + @string + end + + end - def message - @string end - -end - -class Net::SMTP - - attr_accessor :source_address - - def secure_socket? - @socket.io.is_a?(OpenSSL::SSL::SSLSocket) - end - - # - # We had an issue where a message was sent to a server and was greylisted. It returned - # a Net::SMTPUnknownError error. We then tried to send another message on the same - # connection after running `rset` the next message didn't raise any exceptions because - # net/smtp returns a '200 dummy reply code' and doesn't raise any exceptions. - # - def rset - @error_occurred = false - getok("RSET") - end - - def rset_errors - @error_occurred = false - end - - private - - def tcp_socket(address, port) - TCPSocket.open(address, port, source_address) - end - end diff --git a/config/initializers/trusted_proxies.rb b/config/initializers/trusted_proxies.rb index c4317e6..59b1b85 100644 --- a/config/initializers/trusted_proxies.rb +++ b/config/initializers/trusted_proxies.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Rack class Request diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index bbfc396..2f3c0db 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which diff --git a/config/initializers/zeitwerk.rb b/config/initializers/zeitwerk.rb index 91562a1..518aba1 100644 --- a/config/initializers/zeitwerk.rb +++ b/config/initializers/zeitwerk.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + Rails.autoloaders.each do |autoloader| # Ignore the message DB migrations directory as it doesn't follow # Zeitwerk's conventions and is always loaded and executed in order. - autoloader.ignore(Rails.root.join('lib/postal/message_db/migrations')) + autoloader.ignore(Rails.root.join("lib/postal/message_db/migrations")) end diff --git a/config/puma.rb b/config/puma.rb index 98e3877..72aae6a 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require_relative "../lib/postal/config" threads_count = Postal.config.web_server&.max_threads&.to_i || 5 threads threads_count, threads_count diff --git a/config/routes.rb b/config/routes.rb index 48877e8..727ed2b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.routes.draw do scope "org/:org_permalink", as: "organization" do resources :domains, only: [:index, :new, :create, :destroy] do diff --git a/db/migrate/20161003195209_create_authie_sessions.authie.rb b/db/migrate/20161003195209_create_authie_sessions.authie.rb index 4b41180..1b6e990 100644 --- a/db/migrate/20161003195209_create_authie_sessions.authie.rb +++ b/db/migrate/20161003195209_create_authie_sessions.authie.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This migration comes from authie (originally 20141012174250) class CreateAuthieSessions < ActiveRecord::Migration diff --git a/db/migrate/20161003195210_add_indexes_to_authie_sessions.authie.rb b/db/migrate/20161003195210_add_indexes_to_authie_sessions.authie.rb index 38a25ee..8cb984e 100644 --- a/db/migrate/20161003195210_add_indexes_to_authie_sessions.authie.rb +++ b/db/migrate/20161003195210_add_indexes_to_authie_sessions.authie.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This migration comes from authie (originally 20141013115205) class AddIndexesToAuthieSessions < ActiveRecord::Migration diff --git a/db/migrate/20161003195211_add_parent_id_to_authie_sessions.authie.rb b/db/migrate/20161003195211_add_parent_id_to_authie_sessions.authie.rb index 674dff8..0bd5bd1 100644 --- a/db/migrate/20161003195211_add_parent_id_to_authie_sessions.authie.rb +++ b/db/migrate/20161003195211_add_parent_id_to_authie_sessions.authie.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This migration comes from authie (originally 20150109144120) class AddParentIdToAuthieSessions < ActiveRecord::Migration diff --git a/db/migrate/20161003195212_add_two_factor_auth_fields_to_authie.authie.rb b/db/migrate/20161003195212_add_two_factor_auth_fields_to_authie.authie.rb index f1204b1..9ae1f44 100644 --- a/db/migrate/20161003195212_add_two_factor_auth_fields_to_authie.authie.rb +++ b/db/migrate/20161003195212_add_two_factor_auth_fields_to_authie.authie.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This migration comes from authie (originally 20150305135400) class AddTwoFactorAuthFieldsToAuthie < ActiveRecord::Migration diff --git a/db/migrate/20170418200606_initial_schema.rb b/db/migrate/20170418200606_initial_schema.rb index 2d42ff1..76c3eb1 100644 --- a/db/migrate/20170418200606_initial_schema.rb +++ b/db/migrate/20170418200606_initial_schema.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class InitialSchema < ActiveRecord::Migration def up diff --git a/db/migrate/20170421195414_add_token_hashes_to_authie_sessions.authie.rb b/db/migrate/20170421195414_add_token_hashes_to_authie_sessions.authie.rb index fc23ed9..90baa7d 100644 --- a/db/migrate/20170421195414_add_token_hashes_to_authie_sessions.authie.rb +++ b/db/migrate/20170421195414_add_token_hashes_to_authie_sessions.authie.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This migration comes from authie (originally 20170417170000) class AddTokenHashesToAuthieSessions < ActiveRecord::Migration diff --git a/db/migrate/20170421195415_add_index_to_token_hashes_on_authie_sessions.authie.rb b/db/migrate/20170421195415_add_index_to_token_hashes_on_authie_sessions.authie.rb index 362c52a..7cb9b33 100644 --- a/db/migrate/20170421195415_add_index_to_token_hashes_on_authie_sessions.authie.rb +++ b/db/migrate/20170421195415_add_index_to_token_hashes_on_authie_sessions.authie.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This migration comes from authie (originally 20170421174100) class AddIndexToTokenHashesOnAuthieSessions < ActiveRecord::Migration diff --git a/db/migrate/20170428153353_remove_type_from_ip_pools.rb b/db/migrate/20170428153353_remove_type_from_ip_pools.rb index 40a9b18..3d02763 100644 --- a/db/migrate/20170428153353_remove_type_from_ip_pools.rb +++ b/db/migrate/20170428153353_remove_type_from_ip_pools.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class RemoveTypeFromIPPools < ActiveRecord::Migration[5.0] def change diff --git a/db/migrate/20180216114344_add_host_to_authie_sessions.authie.rb b/db/migrate/20180216114344_add_host_to_authie_sessions.authie.rb index df6bef7..179e4dc 100644 --- a/db/migrate/20180216114344_add_host_to_authie_sessions.authie.rb +++ b/db/migrate/20180216114344_add_host_to_authie_sessions.authie.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This migration comes from authie (originally 20180215152200) class AddHostToAuthieSessions < ActiveRecord::Migration[4.2] diff --git a/db/migrate/20200717083943_add_uuid_to_credentials.rb b/db/migrate/20200717083943_add_uuid_to_credentials.rb index efcb6d2..6aecd3b 100644 --- a/db/migrate/20200717083943_add_uuid_to_credentials.rb +++ b/db/migrate/20200717083943_add_uuid_to_credentials.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddUUIDToCredentials < ActiveRecord::Migration[5.2] def change diff --git a/db/migrate/20210727210551_add_priority_to_ip_addresses.rb b/db/migrate/20210727210551_add_priority_to_ip_addresses.rb index eae5cd7..85b792e 100644 --- a/db/migrate/20210727210551_add_priority_to_ip_addresses.rb +++ b/db/migrate/20210727210551_add_priority_to_ip_addresses.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddPriorityToIPAddresses < ActiveRecord::Migration[5.2] def change diff --git a/db/migrate/20240206173036_add_privacy_mode_to_servers.rb b/db/migrate/20240206173036_add_privacy_mode_to_servers.rb index 7757219..9bcd1d6 100644 --- a/db/migrate/20240206173036_add_privacy_mode_to_servers.rb +++ b/db/migrate/20240206173036_add_privacy_mode_to_servers.rb @@ -1,5 +1,9 @@ +# frozen_string_literal: true + class AddPrivacyModeToServers < ActiveRecord::Migration[6.1] + def change add_column :servers, :privacy_mode, :boolean, default: false end + end diff --git a/db/schema.rb b/db/schema.rb index a1b9e76..305d56b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. diff --git a/db/seeds.rb b/db/seeds.rb index e69de29..d2753df 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -0,0 +1,2 @@ +# frozen_string_literal: true +# Seeds go here... diff --git a/lib/postal.rb b/lib/postal.rb index b6f261b..4589dbe 100644 --- a/lib/postal.rb +++ b/lib/postal.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module Postal end diff --git a/lib/postal/app_logger.rb b/lib/postal/app_logger.rb index 4bac388..13fd044 100644 --- a/lib/postal/app_logger.rb +++ b/lib/postal/app_logger.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "logger" module Postal @@ -24,7 +26,7 @@ module Postal message end n.notify!(short_message: message_without_ansi, log_name: @log_name, facility: "postal", application_name: "postal", process_name: ENV.fetch("PROC_NAME", nil), pid: Process.pid) - rescue StandardError => e + rescue StandardError # Can't log this to GELF. Soz. end end @@ -43,8 +45,8 @@ module Postal class LogFormatter - TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%3N".freeze - COLORS = [32, 34, 35, 31, 32, 33] + TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%3N" + COLORS = [32, 34, 35, 31, 32, 33].freeze def call(severity, datetime, progname, msg) time = datetime.strftime(TIME_FORMAT) diff --git a/lib/postal/bounce_message.rb b/lib/postal/bounce_message.rb index 4c12a29..e5a98d0 100644 --- a/lib/postal/bounce_message.rb +++ b/lib/postal/bounce_message.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class BounceMessage diff --git a/lib/postal/config.rb b/lib/postal/config.rb index 3b9c9e4..6dd148d 100644 --- a/lib/postal/config.rb +++ b/lib/postal/config.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "erb" require "yaml" require "pathname" @@ -9,8 +11,10 @@ require_relative "version" module Postal + # rubocop:disable Lint/EmptyClass class Config end + # rubocop:enable Lint/EmptyClass def self.host @host ||= config.web.host || "localhost:5000" @@ -94,7 +98,7 @@ module Postal @loggers[name.to_sym] ||= begin require "postal/app_logger" if config.logging.stdout || ENV["LOG_TO_STDOUT"] - Postal::AppLogger.new(name, STDOUT) + Postal::AppLogger.new(name, $stdout) else FileUtils.mkdir_p(log_root) Postal::AppLogger.new(name, log_root.join("#{name}.log"), config.logging.max_log_files, config.logging.max_log_file_size.megabytes) diff --git a/lib/postal/countries.rb b/lib/postal/countries.rb deleted file mode 100644 index 0eeb4e3..0000000 --- a/lib/postal/countries.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Postal - module Countries - - NAMES = ["Afghanistan", "Aland Islands", "Albania", "Algeria", "American Samoa", "Andorra", "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia, Plurinational State of", "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", "Christmas Island", "Cocos (keeling) Islands", "Colombia", "Comoros", "Congo", "Congo, the Democratic Republic of the", "Cook Islands", "Costa Rica", "Cote D'ivoire", "Croatia", "Cuba", "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (malvinas)", "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia", "French Southern Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea", "Guinea-bissau", "Guyana", "Haiti", "Heard Island and Mcdonald Islands", "Holy See (Vatican City State)", "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran, Islamic Republic of", "Iraq", "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Korea, Democratic People's Republic of", "Korea, Republic of", "Kuwait", "Kyrgyzstan", "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libyan Arab Jamahiriya", "Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Macedonia, the Former Yugoslav Republic of", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia, Federated States of", "Moldova, Republic of", "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau", "Palestinian Territory, Occupied", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation", "Rwanda", "Saint Barthelemy", "Saint Helena, Ascension and Tristan Da Cunha", "Saint Kitts and Nevis", "Saint Lucia", "Saint Martin", "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic", "Taiwan", "Tajikistan", "Tanzania, United Republic of", "Thailand", "Timor-leste", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela, Bolivarian Republic of", "Viet Nam", "Virgin Islands, British", "Virgin Islands, U.S.", "Wallis and Futuna", "Western Sahara", "Yemen", "Zambia", "Zimbabwe"] - - end -end diff --git a/lib/postal/dkim_header.rb b/lib/postal/dkim_header.rb index 60f81d5..b2ba856 100644 --- a/lib/postal/dkim_header.rb +++ b/lib/postal/dkim_header.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class DKIMHeader @@ -32,7 +34,15 @@ module Postal def normalized_headers [].tap do |new_headers| - headers.select { |h| h.match(/^(from|sender|reply-to|subject|date|message-id|to|cc|mime-version|content-type|content-transfer-encoding|resent-to|resent-cc|resent-from|resent-sender|resent-message-id|in-reply-to|references|list-id|list-help|list-owner|list-unsubscribe|list-subscribe|list-post):/i) }.each do |h| + dkim_headers = headers.select do |h| + h.match(/ + ^( + from|sender|reply-to|subject|date|message-id|to|cc|mime-version|content-type|content-transfer-encoding| + resent-to|resent-cc|resent-from|resent-sender|resent-message-id|in-reply-to|references|list-id|list-help| + list-owner|list-unsubscribe|list-subscribe|list-post + ):/ix) + end + dkim_headers.each do |h| new_headers << normalize_header(h) end end diff --git a/lib/postal/error.rb b/lib/postal/error.rb index d00a423..7b42deb 100644 --- a/lib/postal/error.rb +++ b/lib/postal/error.rb @@ -1,9 +1,25 @@ -module Postal +# frozen_string_literal: true - module Errors - end +module Postal class Error < StandardError end + module Errors + class AuthenticationError < Error + + attr_reader :error + + def initialize(error) + super() + @error = error + end + + def to_s + "Authentication Failed: #{@error}" + end + + end + end + end diff --git a/lib/postal/helpers.rb b/lib/postal/helpers.rb index e4b7262..551e222 100644 --- a/lib/postal/helpers.rb +++ b/lib/postal/helpers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module Helpers diff --git a/lib/postal/http.rb b/lib/postal/http.rb index a3d1399..9f1dbb8 100644 --- a/lib/postal/http.rb +++ b/lib/postal/http.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "net/https" require "uri" @@ -15,7 +17,7 @@ module Postal def self.request(method, url, options = {}) options[:headers] ||= {} uri = URI.parse(url) - request = method.new((uri.path.length == 0 ? "/" : uri.path) + (uri.query ? "?" + uri.query : "")) + request = method.new((uri.path.empty? ? "/" : uri.path) + (uri.query ? "?" + uri.query : "")) options[:headers].each { |k, v| request.add_field k, v } if options[:username] || uri.user @@ -62,29 +64,29 @@ module Postal code: result.code.to_i, body: result.body, headers: result.to_hash, - secure: @ssl + secure: ssl } end - rescue OpenSSL::SSL::SSLError => e + rescue OpenSSL::SSL::SSLError { code: -3, body: "Invalid SSL certificate", headers: {}, - secure: @ssl + secure: ssl } rescue SocketError, Errno::ECONNRESET, EOFError, Errno::EINVAL, Errno::ENETUNREACH, Errno::EHOSTUNREACH, Errno::ECONNREFUSED => e { code: -2, body: e.message, headers: {}, - secure: @ssl + secure: ssl } - rescue Timeout::Error => e + rescue Timeout::Error { code: -1, body: "Timed out after #{timeout}s", headers: {}, - secure: @ssl + secure: ssl } end end diff --git a/lib/postal/http_sender.rb b/lib/postal/http_sender.rb index c6a23ee..0de927f 100644 --- a/lib/postal/http_sender.rb +++ b/lib/postal/http_sender.rb @@ -1,7 +1,10 @@ +# frozen_string_literal: true + module Postal class HTTPSender < Sender def initialize(endpoint, options = {}) + super() @endpoint = endpoint @options = options @log_id = Nifty::Utils::RandomString.generate(length: 8).upcase @@ -24,7 +27,7 @@ module Postal log "Sending request to #{@endpoint.url}" response = Postal::HTTP.post(@endpoint.url, request_options) - result.secure = !!response[:secure] + result.secure = !!response[:secure] # rubocop:disable Style/DoubleNegation result.details = "Received a #{response[:code]} from #{@endpoint.url}" log " -> Received: #{response[:code]}" if response[:body] @@ -38,7 +41,7 @@ module Postal # This is temporary. They might fix their server so it should soft fail. result.type = "SoftFail" result.retry = true - elsif response[:code] < 0 + elsif response[:code].negative? # Connection/SSL etc... errors result.type = "SoftFail" result.retry = true diff --git a/lib/postal/job.rb b/lib/postal/job.rb index 56b872e..32759cb 100644 --- a/lib/postal/job.rb +++ b/lib/postal/job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "nifty/utils/random_string" module Postal diff --git a/lib/postal/message_db.rb b/lib/postal/message_db.rb index dcc50bc..0d01c89 100644 --- a/lib/postal/message_db.rb +++ b/lib/postal/message_db.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB end diff --git a/lib/postal/message_db/click.rb b/lib/postal/message_db/click.rb index b476e4b..9a060ad 100644 --- a/lib/postal/message_db/click.rb +++ b/lib/postal/message_db/click.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB class Click diff --git a/lib/postal/message_db/connection_pool.rb b/lib/postal/message_db/connection_pool.rb index 579349c..d98e1ce 100644 --- a/lib/postal/message_db/connection_pool.rb +++ b/lib/postal/message_db/connection_pool.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB class ConnectionPool diff --git a/lib/postal/message_db/database.rb b/lib/postal/message_db/database.rb index ad9f26e..bdf0222 100644 --- a/lib/postal/message_db/database.rb +++ b/lib/postal/message_db/database.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB class Database @@ -144,7 +146,7 @@ module Postal # :count => Return a count of the results instead of the actual data # def select(table, options = {}) - sql_query = "SELECT" + sql_query = String.new("SELECT") if options[:count] sql_query << " COUNT(id) AS count" elsif options[:fields] @@ -158,7 +160,7 @@ module Postal end if options[:order] direction = (options[:direction] || "ASC").upcase - raise Postal::Error, "Invalid direction #{options[:direction]}" unless ["ASC", "DESC"].include?(direction) + raise Postal::Error, "Invalid direction #{options[:direction]}" unless %w[ASC DESC].include?(direction) sql_query << " ORDER BY `#{options[:order]}` #{direction}" end @@ -194,7 +196,7 @@ module Postal result[:records] = select(table, options.merge(limit: per_page, offset: offset)) result[:per_page] = per_page result[:total_pages], remainder = result[:total].divmod(per_page) - result[:total_pages] += 1 if remainder > 0 + result[:total_pages] += 1 if remainder.positive? result[:page] = page result end @@ -243,7 +245,7 @@ module Postal sql_query = "INSERT INTO `#{database_name}`.`#{table}`" sql_query << (" (" + keys.map { |k| "`#{k}`" }.join(", ") + ")") sql_query << " VALUES " - sql_query << values.map { |v| "(" + v.map { |v| escape(v) }.join(", ") + ")" }.join(", ") + sql_query << values.map { |v| "(" + v.map { |r| escape(r) }.join(", ") + ")" }.join(", ") query(sql_query) end end @@ -293,9 +295,7 @@ module Postal end def stringify_keys(hash) - hash.each_with_object({}) do |(key, value), hash| - hash[key.to_s] = value - end + hash.transform_keys(&:to_s) end def escape(value) @@ -304,9 +304,7 @@ module Postal "1" elsif value == false "0" - elsif value.nil? - "NULL" - elsif value.to_s.length == 0 + elsif value.nil? || value.to_s.empty? "NULL" else "'" + mysql.escape(value.to_s) + "'" @@ -331,7 +329,7 @@ module Postal id = Nifty::Utils::RandomString.generate(length: 6).upcase explain_result = ResultForExplainPrinter.new(connection.query("EXPLAIN #{query}")) slow_query_logger.info "[#{id}] EXPLAIN #{query}" - for line in ActiveRecord::ConnectionAdapters::MySQL::ExplainPrettyPrinter.new.pp(explain_result, time).split("\n") + ActiveRecord::ConnectionAdapters::MySQL::ExplainPrettyPrinter.new.pp(explain_result, time).split("\n").each do |line| slow_query_logger.info "[#{id}] " + line end end @@ -339,7 +337,7 @@ module Postal end def logger - defined?(Rails) ? Rails.logger : Logger.new(STDOUT) + defined?(Rails) ? Rails.logger : Logger.new($stdout) end def slow_query_logger @@ -363,16 +361,16 @@ module Postal "`#{key}` IN (#{escaped_values})" elsif value.is_a?(Hash) sql = [] - value.each do |operator, value| + value.each do |operator, inner_value| case operator when :less_than - sql << "`#{key}` < #{escape(value)}" + sql << "`#{key}` < #{escape(inner_value)}" when :greater_than - sql << "`#{key}` > #{escape(value)}" + sql << "`#{key}` > #{escape(inner_value)}" when :less_than_or_equal_to - sql << "`#{key}` <= #{escape(value)}" + sql << "`#{key}` <= #{escape(inner_value)}" when :greater_than_or_equal_to - sql << "`#{key}` >= #{escape(value)}" + sql << "`#{key}` >= #{escape(inner_value)}" end end sql.empty? ? "1=1" : sql.join(joiner) diff --git a/lib/postal/message_db/delivery.rb b/lib/postal/message_db/delivery.rb index f06c76b..177b7f9 100644 --- a/lib/postal/message_db/delivery.rb +++ b/lib/postal/message_db/delivery.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB class Delivery @@ -18,11 +20,15 @@ module Postal end def method_missing(name, value = nil, &block) - return unless @attributes.has_key?(name.to_s) + return unless @attributes.key?(name.to_s) @attributes[name.to_s] end + def respond_to_missing?(name) + @attributes.key?(name.to_s) + end + def timestamp @timestamp ||= @attributes["timestamp"] ? Time.zone.at(@attributes["timestamp"]) : nil end @@ -55,6 +61,7 @@ module Postal } end + # rubocop:disable Style/HashLikeCase def webhook_event @webhook_event ||= case status when "Sent" then "MessageSent" @@ -63,6 +70,7 @@ module Postal when "Held" then "MessageHeld" end end + # rubocop:enable Style/HashLikeCase end end diff --git a/lib/postal/message_db/live_stats.rb b/lib/postal/message_db/live_stats.rb index 1ed9547..9138cd3 100644 --- a/lib/postal/message_db/live_stats.rb +++ b/lib/postal/message_db/live_stats.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB class LiveStats @@ -30,7 +32,7 @@ module Postal raise Postal::Error, "You must provide at least one type to return" if options[:types].empty? time = minutes.minutes.ago.beginning_of_minute.utc.to_f - types = options[:types].map { |t| "#{@database.escape(t.to_s)}" }.join(", ") + types = options[:types].map { |t| @database.escape(t.to_s) }.join(", ") result = @database.query("SELECT SUM(count) as count FROM `#{@database.database_name}`.`live_stats` WHERE `type` IN (#{types}) AND timestamp > #{time}").first result["count"] || 0 end diff --git a/lib/postal/message_db/load.rb b/lib/postal/message_db/load.rb index a87df02..302fd3c 100644 --- a/lib/postal/message_db/load.rb +++ b/lib/postal/message_db/load.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB class Load diff --git a/lib/postal/message_db/message.rb b/lib/postal/message_db/message.rb index e54d77d..7222640 100644 --- a/lib/postal/message_db/message.rb +++ b/lib/postal/message_db/message.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB class Message @@ -176,13 +178,18 @@ module Postal #  Provide access to set and get acceptable attributes # def method_missing(name, value = nil, &block) - if @attributes.has_key?(name.to_s) + if @attributes.key?(name.to_s) @attributes[name.to_s] elsif name.to_s =~ /=\z/ @attributes[name.to_s.gsub("=", "").to_s] = value end end + def respond_to_missing?(name) + name = name.to_s.sub(/=\z/, "") + @attributes.key?(name.to_s) + end + # # Has this message been persisted to the database yet? # @@ -333,7 +340,7 @@ module Postal # Return the recipient domain for this message # def recipient_domain - rcpt_to ? rcpt_to.split("@").last : nil + rcpt_to&.split("@")&.last end # @@ -551,14 +558,14 @@ module Postal private def _update - @database.update("messages", @attributes.reject { |k, v| k == :id }, where: { id: @attributes["id"] }) + @database.update("messages", @attributes.except(:id), where: { id: @attributes["id"] }) end def _create self.timestamp = Time.now.to_f if timestamp.blank? self.status = "Pending" if status.blank? self.token = Nifty::Utils::RandomString.generate(length: 12) if token.blank? - last_id = @database.insert("messages", @attributes.reject { |k, v| k == :id }) + last_id = @database.insert("messages", @attributes.except(:id)) @attributes["id"] = last_id @database.statistics.increment_all(timestamp, scope) Statistic.global.increment!(:total_messages) diff --git a/lib/postal/message_db/migration.rb b/lib/postal/message_db/migration.rb index e209151..5664895 100644 --- a/lib/postal/message_db/migration.rb +++ b/lib/postal/message_db/migration.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB class Migration diff --git a/lib/postal/message_db/migrations/01_create_migrations.rb b/lib/postal/message_db/migrations/01_create_migrations.rb index af1358b..79f34d0 100644 --- a/lib/postal/message_db/migrations/01_create_migrations.rb +++ b/lib/postal/message_db/migrations/01_create_migrations.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/02_create_messages.rb b/lib/postal/message_db/migrations/02_create_messages.rb index 85d0086..051e6b7 100644 --- a/lib/postal/message_db/migrations/02_create_messages.rb +++ b/lib/postal/message_db/migrations/02_create_messages.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/03_create_deliveries.rb b/lib/postal/message_db/migrations/03_create_deliveries.rb index a1ff299..2f75c35 100644 --- a/lib/postal/message_db/migrations/03_create_deliveries.rb +++ b/lib/postal/message_db/migrations/03_create_deliveries.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/04_create_live_stats.rb b/lib/postal/message_db/migrations/04_create_live_stats.rb index 51824b8..9637e1b 100644 --- a/lib/postal/message_db/migrations/04_create_live_stats.rb +++ b/lib/postal/message_db/migrations/04_create_live_stats.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/05_create_raw_message_sizes.rb b/lib/postal/message_db/migrations/05_create_raw_message_sizes.rb index ecba2a0..e6b5939 100644 --- a/lib/postal/message_db/migrations/05_create_raw_message_sizes.rb +++ b/lib/postal/message_db/migrations/05_create_raw_message_sizes.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/06_create_clicks.rb b/lib/postal/message_db/migrations/06_create_clicks.rb index 19d8c66..27f867e 100644 --- a/lib/postal/message_db/migrations/06_create_clicks.rb +++ b/lib/postal/message_db/migrations/06_create_clicks.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/07_create_loads.rb b/lib/postal/message_db/migrations/07_create_loads.rb index 4ebfde3..a6e7e3d 100644 --- a/lib/postal/message_db/migrations/07_create_loads.rb +++ b/lib/postal/message_db/migrations/07_create_loads.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/08_create_stats.rb b/lib/postal/message_db/migrations/08_create_stats.rb index b31955d..1b532c6 100644 --- a/lib/postal/message_db/migrations/08_create_stats.rb +++ b/lib/postal/message_db/migrations/08_create_stats.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/09_create_links.rb b/lib/postal/message_db/migrations/09_create_links.rb index 96ddf4b..4d0d7fa 100644 --- a/lib/postal/message_db/migrations/09_create_links.rb +++ b/lib/postal/message_db/migrations/09_create_links.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/10_create_spam_checks.rb b/lib/postal/message_db/migrations/10_create_spam_checks.rb index 4e5f272..f180281 100644 --- a/lib/postal/message_db/migrations/10_create_spam_checks.rb +++ b/lib/postal/message_db/migrations/10_create_spam_checks.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/11_add_time_to_deliveries.rb b/lib/postal/message_db/migrations/11_add_time_to_deliveries.rb index f7fc4cc..d460b5f 100644 --- a/lib/postal/message_db/migrations/11_add_time_to_deliveries.rb +++ b/lib/postal/message_db/migrations/11_add_time_to_deliveries.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/12_add_hold_expiry.rb b/lib/postal/message_db/migrations/12_add_hold_expiry.rb index f7037ae..5541698 100644 --- a/lib/postal/message_db/migrations/12_add_hold_expiry.rb +++ b/lib/postal/message_db/migrations/12_add_hold_expiry.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/13_add_index_to_message_status.rb b/lib/postal/message_db/migrations/13_add_index_to_message_status.rb index 94034bf..8b3f056 100644 --- a/lib/postal/message_db/migrations/13_add_index_to_message_status.rb +++ b/lib/postal/message_db/migrations/13_add_index_to_message_status.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/14_create_suppressions.rb b/lib/postal/message_db/migrations/14_create_suppressions.rb index 79c272e..42b624e 100644 --- a/lib/postal/message_db/migrations/14_create_suppressions.rb +++ b/lib/postal/message_db/migrations/14_create_suppressions.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/15_create_webhook_requests.rb b/lib/postal/message_db/migrations/15_create_webhook_requests.rb index 90857aa..601dbc4 100644 --- a/lib/postal/message_db/migrations/15_create_webhook_requests.rb +++ b/lib/postal/message_db/migrations/15_create_webhook_requests.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/16_add_url_and_hook_to_webhooks.rb b/lib/postal/message_db/migrations/16_add_url_and_hook_to_webhooks.rb index 49e9ef3..f1df5a3 100644 --- a/lib/postal/message_db/migrations/16_add_url_and_hook_to_webhooks.rb +++ b/lib/postal/message_db/migrations/16_add_url_and_hook_to_webhooks.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/17_add_replaced_link_count_to_messages.rb b/lib/postal/message_db/migrations/17_add_replaced_link_count_to_messages.rb index df1075d..0d99d9a 100644 --- a/lib/postal/message_db/migrations/17_add_replaced_link_count_to_messages.rb +++ b/lib/postal/message_db/migrations/17_add_replaced_link_count_to_messages.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/18_add_endpoints_to_messages.rb b/lib/postal/message_db/migrations/18_add_endpoints_to_messages.rb index 9d872ce..87d286f 100644 --- a/lib/postal/message_db/migrations/18_add_endpoints_to_messages.rb +++ b/lib/postal/message_db/migrations/18_add_endpoints_to_messages.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/19_convert_database_to_utf8mb4.rb b/lib/postal/message_db/migrations/19_convert_database_to_utf8mb4.rb index b3d249c..20960a4 100644 --- a/lib/postal/message_db/migrations/19_convert_database_to_utf8mb4.rb +++ b/lib/postal/message_db/migrations/19_convert_database_to_utf8mb4.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/migrations/20_increase_links_url_size.rb b/lib/postal/message_db/migrations/20_increase_links_url_size.rb index 3ed4f78..eb31247 100644 --- a/lib/postal/message_db/migrations/20_increase_links_url_size.rb +++ b/lib/postal/message_db/migrations/20_increase_links_url_size.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB module Migrations diff --git a/lib/postal/message_db/provisioner.rb b/lib/postal/message_db/provisioner.rb index b6ca1cf..83271c0 100644 --- a/lib/postal/message_db/provisioner.rb +++ b/lib/postal/message_db/provisioner.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB class Provisioner @@ -68,9 +70,9 @@ module Postal # environment and can be quite dangerous in production. # def clean - ["clicks", "deliveries", "links", "live_stats", "loads", "messages", - "raw_message_sizes", "spam_checks", "stats_daily", "stats_hourly", - "stats_monthly", "stats_yearly", "suppressions", "webhook_requests"].each do |table| + %w[clicks deliveries links live_stats loads messages + raw_message_sizes spam_checks stats_daily stats_hourly + stats_monthly stats_yearly suppressions webhook_requests].each do |table| @database.query("TRUNCATE `#{@database.database_name}`.`#{table}`") end end diff --git a/lib/postal/message_db/statistics.rb b/lib/postal/message_db/statistics.rb index 37976e0..286bda3 100644 --- a/lib/postal/message_db/statistics.rb +++ b/lib/postal/message_db/statistics.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB class Statistics @@ -6,8 +8,8 @@ module Postal @database = database end - STATS_GAPS = { hourly: :hour, daily: :day, monthly: :month, yearly: :year } - COUNTERS = [:incoming, :outgoing, :spam, :bounces, :held] + STATS_GAPS = { hourly: :hour, daily: :day, monthly: :month, yearly: :year }.freeze + COUNTERS = [:incoming, :outgoing, :spam, :bounces, :held].freeze # # Increment an appropriate counter @@ -29,7 +31,7 @@ module Postal # Increment all stats counters # def increment_all(time, field) - STATS_GAPS.keys.each do |type| + STATS_GAPS.each_key do |type| increment_one(type, field, time) end end @@ -38,7 +40,7 @@ module Postal # Get a statistic (or statistics) # def get(type, counters, start_date = Time.now, quantity = 10) - date = start_date.utc + start_date = start_date.utc items = quantity.times.each_with_object({}) do |i, hash| hash[(start_date - i.send(STATS_GAPS[type])).send("beginning_of_#{STATS_GAPS[type]}").utc] = counters.each_with_object({}) do |c, h| h[c] = 0 diff --git a/lib/postal/message_db/suppression_list.rb b/lib/postal/message_db/suppression_list.rb index fe683d5..9858a07 100644 --- a/lib/postal/message_db/suppression_list.rb +++ b/lib/postal/message_db/suppression_list.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB class SuppressionList @@ -26,7 +28,7 @@ module Postal end def remove(type, address) - @database.delete("suppressions", where: { type: type, address: address }) > 0 + @database.delete("suppressions", where: { type: type, address: address }).positive? end def prune diff --git a/lib/postal/message_db/webhooks.rb b/lib/postal/message_db/webhooks.rb index 57855ee..cfe4bcd 100644 --- a/lib/postal/message_db/webhooks.rb +++ b/lib/postal/message_db/webhooks.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageDB class Webhooks diff --git a/lib/postal/message_inspection.rb b/lib/postal/message_inspection.rb index 402844e..125f594 100644 --- a/lib/postal/message_inspection.rb +++ b/lib/postal/message_inspection.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class MessageInspection diff --git a/lib/postal/message_inspector.rb b/lib/postal/message_inspector.rb index f522eb3..5eeadc8 100644 --- a/lib/postal/message_inspector.rb +++ b/lib/postal/message_inspector.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class MessageInspector diff --git a/lib/postal/message_inspectors.rb b/lib/postal/message_inspectors.rb index 7c083f1..8ddb584 100644 --- a/lib/postal/message_inspectors.rb +++ b/lib/postal/message_inspectors.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageInspectors end diff --git a/lib/postal/message_inspectors/clamav.rb b/lib/postal/message_inspectors/clamav.rb index 0890601..e16fc22 100644 --- a/lib/postal/message_inspectors/clamav.rb +++ b/lib/postal/message_inspectors/clamav.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageInspectors class Clamav < MessageInspector diff --git a/lib/postal/message_inspectors/rspamd.rb b/lib/postal/message_inspectors/rspamd.rb index f52db16..a1fce7a 100644 --- a/lib/postal/message_inspectors/rspamd.rb +++ b/lib/postal/message_inspectors/rspamd.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "net/http" module Postal @@ -12,7 +14,7 @@ module Postal response = JSON.parse(response.body) return unless response["symbols"].is_a?(Hash) - response["symbols"].values.each do |symbol| + response["symbols"].each_value do |symbol| next if symbol["description"].blank? inspection.spam_checks << SpamCheck.new(symbol["name"], symbol["score"], symbol["description"]) @@ -54,7 +56,7 @@ module Postal response = nil begin response = http.request(request) - rescue Exception => e + rescue StandardError => e logger.error "Error talking to rspamd: #{e.class} (#{e.message})" logger.error e.backtrace[0, 5] diff --git a/lib/postal/message_inspectors/spam_assassin.rb b/lib/postal/message_inspectors/spam_assassin.rb index 640d0dc..c3346bb 100644 --- a/lib/postal/message_inspectors/spam_assassin.rb +++ b/lib/postal/message_inspectors/spam_assassin.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module MessageInspectors class SpamAssassin < MessageInspector @@ -5,7 +7,7 @@ module Postal EXCLUSIONS = { outgoing: ["NO_RECEIVED", "NO_RELAYS", "ALL_TRUSTED", "FREEMAIL_FORGED_REPLYTO", "RDNS_DYNAMIC", "CK_HELO_GENERIC", /^SPF_/, /^HELO_/, /DKIM_/, /^RCVD_IN_/], incoming: [] - } + }.freeze def inspect_message(inspection) data = nil diff --git a/lib/postal/message_parser.rb b/lib/postal/message_parser.rb index 956e19f..386521b 100644 --- a/lib/postal/message_parser.rb +++ b/lib/postal/message_parser.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class MessageParser @@ -19,7 +21,7 @@ module Postal attr_reader :tracked_images def actioned? - @actioned || @tracked_links > 0 || @tracked_images > 0 + @actioned || @tracked_links.positive? || @tracked_images.positive? end def new_body @@ -61,15 +63,16 @@ module Postal def parse_parts(parts) parts.each do |part| - if part.content_type =~ /text\/html/ + case part.content_type + when /text\/html/ part.body = parse(part.body.decoded.dup, :html) part.content_transfer_encoding = nil part.charset = "UTF-8" - elsif part.content_type =~ /text\/plain/ + when /text\/plain/ part.body = parse(part.body.decoded.dup, :text) part.content_transfer_encoding = nil part.charset = "UTF-8" - elsif part.content_type =~ /multipart\/(alternative|related)/ + when /multipart\/(alternative|related)/ unless part.parts.empty? parse_parts(part.parts) end diff --git a/lib/postal/message_requeuer.rb b/lib/postal/message_requeuer.rb index ec4d2e3..a42732f 100644 --- a/lib/postal/message_requeuer.rb +++ b/lib/postal/message_requeuer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class MessageRequeuer diff --git a/lib/postal/mx_lookup.rb b/lib/postal/mx_lookup.rb index a859c04..21aa7eb 100644 --- a/lib/postal/mx_lookup.rb +++ b/lib/postal/mx_lookup.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class MXLookup diff --git a/lib/postal/query_string.rb b/lib/postal/query_string.rb index 9546baa..3ca28c0 100644 --- a/lib/postal/query_string.rb +++ b/lib/postal/query_string.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class QueryString @@ -6,12 +8,12 @@ module Postal end def [](value) - to_hash[value.to_s] + hash[value.to_s] end - delegate :empty?, to: :to_hash + delegate :empty?, to: :hash - def to_hash + def hash @hash ||= @string.scan(/([a-z]+):\s*(?:(\d{2,4}-\d{2}-\d{2}\s\d{2}:\d{2})|"(.*?)"|(.*?))(\s|\z)/).each_with_object({}) do |(key, date, string_with_spaces, value), hash| if date actual_value = date diff --git a/lib/postal/rabbit_mq.rb b/lib/postal/rabbit_mq.rb index 50ac3f9..2703cd5 100644 --- a/lib/postal/rabbit_mq.rb +++ b/lib/postal/rabbit_mq.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "postal/config" require "bunny" diff --git a/lib/postal/received_header.rb b/lib/postal/received_header.rb index 4afbaf2..a9bec15 100644 --- a/lib/postal/received_header.rb +++ b/lib/postal/received_header.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + module Postal class ReceivedHeader OUR_HOSTNAMES = { smtp: Postal.config.dns.smtp_server_hostname, http: Postal.config.web.host - } + }.freeze class << self diff --git a/lib/postal/reply_separator.rb b/lib/postal/reply_separator.rb index b27362e..30726bd 100644 --- a/lib/postal/reply_separator.rb +++ b/lib/postal/reply_separator.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class ReplySeparator @@ -13,13 +15,13 @@ module Postal /^>*\s*Sent from my.*/m, /^>*\s*=== Please reply above this line ===.*/m, /(^>.*\n?){10,}/ - ] + ].freeze def self.separate(text) return "" unless text.is_a?(String) text = text.gsub("\r", "") - stripped = "" + stripped = String.new RULES.each do |rule| text.gsub!(rule) do stripped = ::Regexp.last_match(0).to_s + "\n" + stripped diff --git a/lib/postal/rspec_helpers.rb b/lib/postal/rspec_helpers.rb index ddc875c..44fd0ab 100644 --- a/lib/postal/rspec_helpers.rb +++ b/lib/postal/rspec_helpers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module RspecHelpers diff --git a/lib/postal/send_result.rb b/lib/postal/send_result.rb index 251e075..af4c40a 100644 --- a/lib/postal/send_result.rb +++ b/lib/postal/send_result.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class SendResult diff --git a/lib/postal/sender.rb b/lib/postal/sender.rb index 7c4914a..ff5cd49 100644 --- a/lib/postal/sender.rb +++ b/lib/postal/sender.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class Sender diff --git a/lib/postal/smtp_sender.rb b/lib/postal/smtp_sender.rb index bd6121d..cc74b16 100644 --- a/lib/postal/smtp_sender.rb +++ b/lib/postal/smtp_sender.rb @@ -1,9 +1,12 @@ +# frozen_string_literal: true + require "resolv" module Postal class SMTPSender < Sender def initialize(domain, source_ip_address, options = {}) + super() @domain = domain @source_ip_address = source_ip_address @options = options @@ -62,8 +65,6 @@ module Postal smtp_client.enable_starttls(self.class.ssl_context_with_verify) when "TLS" smtp_client.enable_tls(self.class.ssl_context_with_verify) - else - # Nothing end smtp_client.start(@source_ip_address ? @source_ip_address.hostname : self.class.default_helo_hostname) @@ -141,9 +142,9 @@ module Postal mail_from = "#{message.server.token}@#{Postal.config.dns.return_path}" end if Postal.config.general.use_resent_sender_header - raw_message = "Resent-Sender: #{mail_from}\r\n" + message.raw_message + raw_message = "Resent-Sender: #{mail_from}\r\n" + message.raw_message else - raw_message = message.raw_message + raw_message = message.raw_message end tries = 0 begin @@ -250,39 +251,43 @@ module Postal records.first&.address&.to_s&.downcase end - def self.ssl_context_with_verify - @ssl_context_with_verify ||= begin - c = OpenSSL::SSL::SSLContext.new - c.verify_mode = OpenSSL::SSL::VERIFY_PEER - c.cert_store = OpenSSL::X509::Store.new - c.cert_store.set_default_paths - c + class << self + + def ssl_context_with_verify + @ssl_context_with_verify ||= begin + c = OpenSSL::SSL::SSLContext.new + c.verify_mode = OpenSSL::SSL::VERIFY_PEER + c.cert_store = OpenSSL::X509::Store.new + c.cert_store.set_default_paths + c + end end - end - def self.ssl_context_without_verify - @ssl_context_without_verify ||= begin - c = OpenSSL::SSL::SSLContext.new - c.verify_mode = OpenSSL::SSL::VERIFY_NONE - c + def ssl_context_without_verify + @ssl_context_without_verify ||= begin + c = OpenSSL::SSL::SSLContext.new + c.verify_mode = OpenSSL::SSL::VERIFY_NONE + c + end end - end - def self.default_helo_hostname - Postal.config.dns.helo_hostname || Postal.config.dns.smtp_server_hostname || "localhost" - end + def default_helo_hostname + Postal.config.dns.helo_hostname || Postal.config.dns.smtp_server_hostname || "localhost" + end - def self.relay_hosts - hosts = Postal.config.smtp_relays.map do |relay| - next unless relay.hostname.present? + def relay_hosts + hosts = Postal.config.smtp_relays.map do |relay| + next unless relay.hostname.present? + + { + hostname: relay.hostname, + port: relay.port, + ssl_mode: relay.ssl_mode + } + end.compact + hosts.empty? ? nil : hosts + end - { - hostname: relay.hostname, - port: relay.port, - ssl_mode: relay.ssl_mode - } - end.compact - hosts.empty? ? nil : hosts end end diff --git a/lib/postal/smtp_server.rb b/lib/postal/smtp_server.rb index ff56918..154ae62 100644 --- a/lib/postal/smtp_server.rb +++ b/lib/postal/smtp_server.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal module SMTPServer end diff --git a/lib/postal/smtp_server/client.rb b/lib/postal/smtp_server/client.rb index 7d93eb6..971995a 100644 --- a/lib/postal/smtp_server/client.rb +++ b/lib/postal/smtp_server/client.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "resolv" require "nifty/utils/random_string" @@ -6,7 +8,7 @@ module Postal class Client CRAM_MD5_DIGEST = OpenSSL::Digest.new("md5") - LOG_REDACTION_STRING = "[redacted]".freeze + LOG_REDACTION_STRING = "[redacted]" attr_reader :logging_enabled @@ -156,10 +158,10 @@ module Postal end def auth_plain(data) - handler = proc do |data| + handler = proc do |idata| @proc = nil - data = Base64.decode64(data) - parts = data.split("\0") + idata = Base64.decode64(idata) + parts = idata.split("\0") username = parts[-2] password = parts[-1] unless username && password @@ -180,13 +182,13 @@ module Postal end def auth_login(data) - password_handler = proc do |data| + password_handler = proc do |idata| @proc = nil - password = Base64.decode64(data) + password = Base64.decode64(idata) authenticate(password) end - username_handler = proc do |data| + username_handler = proc do @proc = password_handler @password_expected_next = true "334 UGFzc3dvcmQ6" # "Password:" @@ -215,9 +217,9 @@ module Postal challenge = Digest::SHA1.hexdigest(Time.now.to_i.to_s + rand(100_000).to_s) challenge = "<#{challenge[0, 20]}@#{Postal.config.dns.smtp_server_hostname}>" - handler = proc do |data| + handler = proc do |idata| @proc = nil - username, password = Base64.decode64(data).split(" ", 2).map { |a| a.chomp } + username, password = Base64.decode64(idata).split(" ", 2).map { |a| a.chomp } org_permlink, server_permalink = username.split(/[\/_]/, 2) server = ::Server.includes(:organization).where(organizations: { permalink: org_permlink }, permalink: server_permalink).first if server.nil? @@ -307,7 +309,7 @@ module Postal "550 Route does not accept incoming messages" else log "Added route #{route.id} to recipients (tag: #{tag.inspect})" - actual_rcpt_to = "#{route.name}" + (tag ? "+#{tag}" : "") + "@#{route.domain.name}" + actual_rcpt_to = "#{route.name}#{tag ? "+#{tag}" : ''}@#{route.domain.name}" @recipients << [:route, actual_rcpt_to, route.server, { route: route }] "250 OK" end @@ -355,12 +357,12 @@ module Postal end end - def data(data) + def data(_data) unless in_state(:rcpt_to_received) return "503 HELO/EHLO, MAIL FROM and RCPT TO before sending data" end - @data = "".force_encoding("BINARY") + @data = String.new.force_encoding("BINARY") @headers = {} @receiving_headers = true @@ -370,15 +372,15 @@ module Postal @data << "Received: #{received_header}\r\n" @headers["received"] = [received_header] - handler = proc do |data| - if data == "." + handler = proc do |idata| + if idata == "." @logging_enabled = true @proc = nil finished else - data = data.to_s.sub(/\A\.\./, ".") + idata = idata.to_s.sub(/\A\.\./, ".") - if @credential && @credential.server.log_smtp_data? + if @credential&.server&.log_smtp_data? # We want to log if enabled else log "Not logging further message data." @@ -386,20 +388,20 @@ module Postal end if @receiving_headers - if data.blank? + if idata.blank? @receiving_headers = false - elsif data.to_s =~ /^\s/ + elsif idata.to_s =~ /^\s/ # This is a continuation of a header if @header_key && @headers[@header_key.downcase] && @headers[@header_key.downcase].last - @headers[@header_key.downcase].last << data.to_s + @headers[@header_key.downcase].last << idata.to_s end else - @header_key, value = data.split(/:\s*/, 2) + @header_key, value = idata.split(/:\s*/, 2) @headers[@header_key.downcase] ||= [] @headers[@header_key.downcase] << value end end - @data << data + @data << idata @data << "\r\n" nil end @@ -413,10 +415,10 @@ module Postal if @data.bytesize > Postal.config.smtp_server.max_message_size.megabytes.to_i transaction_reset @state = :welcomed - return "552 Message too large (maximum size %dMB)" % Postal.config.smtp_server.max_message_size + return format("552 Message too large (maximum size %dMB)", Postal.config.smtp_server.max_message_size) end - if @headers["received"].select { |r| r =~ /by #{Postal.config.dns.smtp_server_hostname}/ }.count > 4 + if @headers["received"].grep(/by #{Postal.config.dns.smtp_server_hostname}/).count > 4 transaction_reset @state = :welcomed return "550 Loop detected" @@ -451,11 +453,11 @@ module Postal when :bounce if rp_route = server.routes.where(name: "__returnpath__").first # If there's a return path route, we can use this to create the message - rp_route.create_messages do |message| - message.rcpt_to = rcpt_to - message.mail_from = @mail_from - message.raw_message = @data - message.received_with_ssl = @tls + rp_route.create_messages do |msg| + msg.rcpt_to = rcpt_to + msg.mail_from = @mail_from + msg.raw_message = @data + msg.received_with_ssl = @tls end else # There's no return path route, we just need to insert the mesage diff --git a/lib/postal/smtp_server/server.rb b/lib/postal/smtp_server/server.rb index 5aae3fb..0ab056b 100644 --- a/lib/postal/smtp_server/server.rb +++ b/lib/postal/smtp_server/server.rb @@ -1,6 +1,9 @@ +# frozen_string_literal: true + require "ipaddr" require "nio" +# rubocop:disable Style/GlobalVars module Postal module SMTPServer class Server @@ -16,7 +19,7 @@ module Postal BasicSocket.do_not_reverse_lookup = true trap("USR1") do - STDOUT.puts "Received USR1 signal, respawning." + $stdout.puts "Received USR1 signal, respawning." fork do if ENV["APP_ROOT"] Dir.chdir(ENV["APP_ROOT"]) @@ -27,7 +30,7 @@ module Postal end trap("TERM") do - STDOUT.puts "Received TERM signal, shutting down." + $stdout.puts "Received TERM signal, shutting down." unlisten end end @@ -36,7 +39,7 @@ module Postal @ssl_context ||= begin ssl_context = OpenSSL::SSL::SSLContext.new ssl_context.cert = Postal.smtp_certificates[0] - ssl_context.extra_chain_cert = Postal.smtp_certificates[1..-1] + ssl_context.extra_chain_cert = Postal.smtp_certificates[1..] ssl_context.key = Postal.smtp_private_key ssl_context.ssl_version = Postal.config.smtp_server.ssl_version if Postal.config.smtp_server.ssl_version ssl_context.ciphers = Postal.config.smtp_server.tls_ciphers if Postal.config.smtp_server.tls_ciphers @@ -157,13 +160,11 @@ module Postal # The client is not negotiating a TLS handshake at this time begin # Read 10kiB of data at a time from the socket. + buffers[io] << io.readpartial(10_240) + # There is an extra step for SSL sockets - case io - when OpenSSL::SSL::SSLSocket - buffers[io] << io.readpartial(10_240) - buffers[io] << io.readpartial(10_240) while io.pending > 0 - else - buffers[io] << io.readpartial(10_240) + if io.is_a?(OpenSSL::SSL::SSLSocket) + buffers[io] << io.readpartial(10_240) while io.pending.positive? end rescue EOFError, Errno::ECONNRESET, Errno::ETIMEDOUT # Client went away @@ -186,10 +187,10 @@ module Postal next if result.nil? result = [result] unless result.is_a?(Array) - result.compact.each do |line| - client.log "\e[34m=> #{line.strip}\e[0m" + result.compact.each do |iline| + client.log "\e[34m=> #{iline.strip}\e[0m" begin - io.write(line.to_s + "\r\n") + io.write(iline.to_s + "\r\n") io.flush rescue Errno::ECONNRESET # Client disconnected before we could write response @@ -236,8 +237,8 @@ module Postal end logger.error "[#{client_id}] An error occurred while processing data from a client." logger.error "[#{client_id}] #{e.class}: #{e.message}" - e.backtrace.each do |line| - logger.error "[#{client_id}] #{line}" + e.backtrace.each do |iline| + logger.error "[#{client_id}] #{iline}" end # Close all IO and forget this client begin @@ -278,12 +279,14 @@ module Postal end # If we have been spawned to replace an existing processm shut down the # parent after listening. + # rubocop:disable Style/IdenticalConditionalBranches if ENV["SERVER_FD"] listen - kill_parent + kill_parent if ENV["SERVER_FD"] else listen end + # rubocop:enable Style/IdenticalConditionalBranches run_event_loop end @@ -296,3 +299,4 @@ module Postal end end end +# rubocop:enable Style/GlobalVars diff --git a/lib/postal/spam_check.rb b/lib/postal/spam_check.rb index b0ab968..61c1d71 100644 --- a/lib/postal/spam_check.rb +++ b/lib/postal/spam_check.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class SpamCheck diff --git a/lib/postal/tracking_middleware.rb b/lib/postal/tracking_middleware.rb index 3386b58..82a25a0 100644 --- a/lib/postal/tracking_middleware.rb +++ b/lib/postal/tracking_middleware.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class TrackingMiddleware @@ -85,8 +87,23 @@ module Postal time = Time.now.to_f if link["message_id"] message_db.update(:messages, { clicked: time }, where: { id: link["message_id"] }) - message_db.insert(:clicks, { message_id: link["message_id"], link_id: link["id"], ip_address: request.ip, user_agent: request.user_agent, timestamp: time }) - SendWebhookJob.queue(:main, server_id: message_db.server_id, event: "MessageLinkClicked", payload: { _message: link["message_id"], url: link["url"], token: link["token"], ip_address: request.ip, user_agent: request.user_agent }) + message_db.insert(:clicks, { + message_id: link["message_id"], + link_id: link["id"], + ip_address: request.ip, + user_agent: request.user_agent, + timestamp: time + }) + SendWebhookJob.queue(:main, + server_id: message_db.server_id, + event: "MessageLinkClicked", + payload: { + _message: link["message_id"], + url: link["url"], + token: link["token"], + ip_address: request.ip, + user_agent: request.user_agent + }) end [307, { "Location" => link["url"] }, ["Redirected to: #{link['url']}"]] diff --git a/lib/postal/user_creator.rb b/lib/postal/user_creator.rb index a8b32d0..27bb973 100644 --- a/lib/postal/user_creator.rb +++ b/lib/postal/user_creator.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "highline" module Postal @@ -16,18 +18,16 @@ module Postal user.password = cli.ask("Initial Password".ljust(20, " ") + ": ") { |value| value.echo = "*" } block.call(user) if block_given? + puts if user.save - puts puts "User has been created with e-mail address \e[32m#{user.email_address}\e[0m" - puts else - puts puts "\e[31mFailed to create user\e[0m" - for error in user.errors.full_messages + user.errors.full_messages.each do |error| puts " * #{error}" end - puts end + puts end end diff --git a/lib/postal/version.rb b/lib/postal/version.rb index 80d20d0..1e0c1ac 100644 --- a/lib/postal/version.rb +++ b/lib/postal/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal VERSION_PATH = File.expand_path("../../VERSION", __dir__) diff --git a/lib/postal/worker.rb b/lib/postal/worker.rb index e738841..7d5f858 100644 --- a/lib/postal/worker.rb +++ b/lib/postal/worker.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Postal class Worker @@ -33,7 +35,7 @@ module Postal logger.info "Job did not finish in a timely manner. Exiting" exit 0 end - if exit_checks == 0 + if exit_checks.zero? logger.info "Exit requested but job is running. Waiting for job to finish." end sleep 60 @@ -165,9 +167,9 @@ module Postal leave_queue("outgoing-#{id}") @ip_queues.delete(id) ip_addresses_to_clear = [] - @ip_to_id_mapping.each do |_ip, _id| - if id == _id - ip_addresses_to_clear << _ip + @ip_to_id_mapping.each do |iip, iid| + if id == iid + ip_addresses_to_clear << iip end end ip_addresses_to_clear.each { |ip| @ip_to_id_mapping.delete(ip) } @@ -193,21 +195,25 @@ module Postal self.class.logger end - def self.logger - Postal.logger_for(:worker) - end + class << self - def self.job_channel - @channel ||= Postal::RabbitMQ.create_channel - end + def logger + Postal.logger_for(:worker) + end - def self.job_queue(name) - @job_queues ||= {} - @job_queues[name] ||= job_channel.queue("deliver-jobs-#{name}", durable: true, arguments: { "x-message-ttl" => 60_000 }) - end + def job_channel + @job_channel ||= Postal::RabbitMQ.create_channel + end + + def job_queue(name) + @job_queues ||= {} + @job_queues[name] ||= job_channel.queue("deliver-jobs-#{name}", durable: true, arguments: { "x-message-ttl" => 60_000 }) + end + + def local_ip?(ip) + !!(ip =~ /\A(127\.|fe80:|::)/) + end - def self.local_ip?(ip) - !!(ip =~ /\A(127\.|fe80:|::)/) end end diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake index 1920150..948f883 100644 --- a/lib/tasks/auto_annotate_models.rake +++ b/lib/tasks/auto_annotate_models.rake @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # NOTE: only doing this in development as some production environments (Heroku) # NOTE: are sensitive to local FS writes, and besides -- it's just not proper # NOTE: to have a dev-mode tool do its thing in production. diff --git a/lib/tasks/postal.rake b/lib/tasks/postal.rake index 480f9f4..81770f6 100644 --- a/lib/tasks/postal.rake +++ b/lib/tasks/postal.rake @@ -1,3 +1,5 @@ +# frozen_string_literal: true + namespace :postal do desc "Start the cron worker" task cron: :environment do diff --git a/script/default_dkim_record.rb b/script/default_dkim_record.rb index 50c8a30..5444a38 100644 --- a/script/default_dkim_record.rb +++ b/script/default_dkim_record.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + require File.expand_path("../lib/postal/config", __dir__) puts Postal.rp_dkim_dns_record diff --git a/script/generate_initial_config.rb b/script/generate_initial_config.rb index 131b4cb..d3564c9 100755 --- a/script/generate_initial_config.rb +++ b/script/generate_initial_config.rb @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require File.expand_path("../lib/postal/config", __dir__) require "openssl" require "securerandom" diff --git a/script/insert-bounce.rb b/script/insert-bounce.rb index 81d4c2e..dfcf88b 100755 --- a/script/insert-bounce.rb +++ b/script/insert-bounce.rb @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true # This script will insert a message into your database that looks like a bounce # for a message that you specify. diff --git a/script/make_user.rb b/script/make_user.rb index 79db624..f5986c7 100755 --- a/script/make_user.rb +++ b/script/make_user.rb @@ -1,4 +1,6 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + trap("INT") do puts exit diff --git a/script/queue_size.rb b/script/queue_size.rb index d14a966..a9dec6b 100755 --- a/script/queue_size.rb +++ b/script/queue_size.rb @@ -1,7 +1,16 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require_relative "../lib/postal/config" require "mysql2" -client = Mysql2::Client.new(host: Postal.config.main_db.host, username: Postal.config.main_db.username, password: Postal.config.main_db.password, port: Postal.config.main_db.port, database: Postal.config.main_db.database) -result = client.query("SELECT COUNT(id) as size FROM `queued_messages` WHERE retry_after IS NULL OR retry_after <= ADDTIME(UTC_TIMESTAMP(), '30') AND locked_at IS NULL") +client = Mysql2::Client.new( + host: Postal.config.main_db.host, + username: Postal.config.main_db.username, + password: Postal.config.main_db.password, + port: Postal.config.main_db.port, + database: Postal.config.main_db.database +) +result = client.query("SELECT COUNT(id) as size FROM `queued_messages` WHERE retry_after IS NULL OR " \ + "retry_after <= ADDTIME(UTC_TIMESTAMP(), '30') AND locked_at IS NULL") puts result.to_a.first["size"] diff --git a/script/send-html-email.rb b/script/send_html_email.rb similarity index 79% rename from script/send-html-email.rb rename to script/send_html_email.rb index 564b0b0..9e8e4bb 100644 --- a/script/send-html-email.rb +++ b/script/send_html_email.rb @@ -3,8 +3,8 @@ # This script will automatically send an HTML email to the # SMTP server given. -require 'mail' -require 'net/smtp' +require "mail" +require "net/smtp" from = ARGV[0] to = ARGV[1] @@ -14,12 +14,11 @@ if from.nil? || to.nil? exit 1 end - mail = Mail.new mail.to = to mail.from = from -mail.subject = "A test email from #{Time.now.to_s}" -mail['X-Postal-Tag'] = 'send-html-email-script' +mail.subject = "A test email from #{Time.now}" +mail["X-Postal-Tag"] = "send-html-email-script" mail.text_part = Mail::Part.new do body <<~BODY Hello there. @@ -32,7 +31,7 @@ mail.text_part = Mail::Part.new do BODY end mail.html_part = Mail::Part.new do - content_type 'text/html; charset=UTF-8' + content_type "text/html; charset=UTF-8" body <<~BODY

Hello there

This is an example email. It doesn't do all that much.

@@ -41,9 +40,9 @@ mail.html_part = Mail::Part.new do BODY end -#puts mail.to_s +# puts mail.to_s -Net::SMTP.start('127.0.0.1', 2525) do |smtp| +Net::SMTP.start("127.0.0.1", 2525) do |smtp| smtp.send_message mail.to_s, mail.from.first, mail.to.first end diff --git a/script/test_app_smtp.rb b/script/test_app_smtp.rb index a7b009d..466865c 100755 --- a/script/test_app_smtp.rb +++ b/script/test_app_smtp.rb @@ -1,10 +1,12 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + trap("INT") do puts exit end -if ARGV[0].nil? || !(ARGV[0] =~ /@/) +if ARGV[0].nil? || ARGV[0] !~ /@/ puts "usage: postal test-app-smtp [email address]" exit 1 end @@ -17,6 +19,8 @@ begin end puts "\e[32mMessage has been sent successfully.\e[0m" +rescue Timeout::Error + puts "Sending timed out" rescue StandardError => e puts "\e[31mMessage was not delivered successfully to SMTP server.\e[0m" puts "Error: #{e.class} (#{e.message})" @@ -26,6 +30,4 @@ rescue StandardError => e puts " SMTP Username: #{Postal.config.smtp.username}" puts " SMTP Password: #{Postal.config.smtp.password}" puts -rescue Timeout::Error - puts "Sending timed out" end diff --git a/script/version.rb b/script/version.rb index 0bd3a3c..c8db897 100755 --- a/script/version.rb +++ b/script/version.rb @@ -1,3 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require File.expand_path("../lib/postal/version", __dir__) puts Postal.version diff --git a/script/worker.rb b/script/worker.rb index 3642577..121f5ce 100755 --- a/script/worker.rb +++ b/script/worker.rb @@ -1,3 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + require_relative "../config/environment" Postal::Worker.new([:main]).work diff --git a/spec/app/models/organization_spec.rb b/spec/app/models/organization_spec.rb index bde3f5e..2340af4 100644 --- a/spec/app/models/organization_spec.rb +++ b/spec/app/models/organization_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rails_helper" describe Organization do diff --git a/spec/app/models/outgoing_message_prototype_spec.rb b/spec/app/models/outgoing_message_prototype_spec.rb index ff71716..01c3d57 100644 --- a/spec/app/models/outgoing_message_prototype_spec.rb +++ b/spec/app/models/outgoing_message_prototype_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rails_helper" describe OutgoingMessagePrototype do diff --git a/spec/app/models/server_spec.rb b/spec/app/models/server_spec.rb index 049dfff..f871408 100644 --- a/spec/app/models/server_spec.rb +++ b/spec/app/models/server_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rails_helper" describe Server do diff --git a/spec/app/models/user_spec.rb b/spec/app/models/user_spec.rb index f955561..ca9366b 100644 --- a/spec/app/models/user_spec.rb +++ b/spec/app/models/user_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rails_helper" describe User do diff --git a/spec/factories/domain_factory.rb b/spec/factories/domain_factory.rb index 0a61d55..e128497 100644 --- a/spec/factories/domain_factory.rb +++ b/spec/factories/domain_factory.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: domains diff --git a/spec/factories/organization_factory.rb b/spec/factories/organization_factory.rb index 843c0f4..937a33d 100644 --- a/spec/factories/organization_factory.rb +++ b/spec/factories/organization_factory.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: organizations diff --git a/spec/factories/server_factory.rb b/spec/factories/server_factory.rb index 3397cd2..bd8c74e 100644 --- a/spec/factories/server_factory.rb +++ b/spec/factories/server_factory.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: servers diff --git a/spec/factories/track_domain_factory.rb b/spec/factories/track_domain_factory.rb index 64a7d62..836af3f 100644 --- a/spec/factories/track_domain_factory.rb +++ b/spec/factories/track_domain_factory.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: track_domains diff --git a/spec/factories/user_factory.rb b/spec/factories/user_factory.rb index a4a0f02..0337349 100644 --- a/spec/factories/user_factory.rb +++ b/spec/factories/user_factory.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # == Schema Information # # Table name: users diff --git a/spec/lib/postal/dkim_header_spec.rb b/spec/lib/postal/dkim_header_spec.rb index b2e5390..0342e15 100644 --- a/spec/lib/postal/dkim_header_spec.rb +++ b/spec/lib/postal/dkim_header_spec.rb @@ -7,7 +7,7 @@ describe Postal::DKIMHeader do Dir[examples].each do |path| contents = File.read(path) frontmatter, email = contents.split(/^---\n/m, 2) - frontmatter = YAML.load(frontmatter) + frontmatter = YAML.safe_load(frontmatter) email.strip it "works with #{path.split('/').last}" do mocked_time = Time.at(frontmatter["time"].to_i) diff --git a/spec/lib/postal/message_db/connection_pool_spec.rb b/spec/lib/postal/message_db/connection_pool_spec.rb index 73760e0..cbc730b 100644 --- a/spec/lib/postal/message_db/connection_pool_spec.rb +++ b/spec/lib/postal/message_db/connection_pool_spec.rb @@ -1,11 +1,12 @@ +# frozen_string_literal: true + require "rails_helper" describe Postal::MessageDB::ConnectionPool do - subject(:pool) { described_class.new } - describe '#use' do - it 'yields a connection' do + describe "#use" do + it "yields a connection" do counter = 0 pool.use do |connection| expect(connection).to be_a Mysql2::Client @@ -14,7 +15,7 @@ describe Postal::MessageDB::ConnectionPool do expect(counter).to eq 1 end - it 'checks in a connection after the block has executed' do + it "checks in a connection after the block has executed" do connection = nil pool.use do |c| expect(pool.connections).to be_empty @@ -23,16 +24,16 @@ describe Postal::MessageDB::ConnectionPool do expect(pool.connections).to eq [connection] end - it 'checks in a connection if theres an error in the block' do + it "checks in a connection if theres an error in the block" do expect do - pool.use do |c| + pool.use do raise StandardError end end.to raise_error StandardError expect(pool.connections).to match [kind_of(Mysql2::Client)] end - it 'does not check in connections when there is a connection error' do + it "does not check in connections when there is a connection error" do expect do pool.use do raise Mysql2::Error, "lost connection to server" @@ -41,5 +42,4 @@ describe Postal::MessageDB::ConnectionPool do expect(pool.connections).to eq [] end end - end diff --git a/spec/lib/postal/message_db/database_spec.rb b/spec/lib/postal/message_db/database_spec.rb index 00995e1..0e2639f 100644 --- a/spec/lib/postal/message_db/database_spec.rb +++ b/spec/lib/postal/message_db/database_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rails_helper" describe Postal::MessageDB::Database do diff --git a/spec/lib/postal/message_parser_spec.rb b/spec/lib/postal/message_parser_spec.rb index c47a229..3d94cef 100644 --- a/spec/lib/postal/message_parser_spec.rb +++ b/spec/lib/postal/message_parser_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "rails_helper" describe Postal::MessageParser do @@ -15,7 +17,7 @@ describe Postal::MessageParser do it "should replace links in messages" do with_global_server do |server| message = create_plain_text_message(server, "Hello world! http://github.com/atech/postal", "test@example.com") - track_domain = create(:track_domain, server: server, domain: message.domain) + create(:track_domain, server: server, domain: message.domain) parser = Postal::MessageParser.new(message) expect(parser.actioned?).to be true expect(parser.new_body).to match(/^Hello world! https:\/\/click\.#{message.domain.name}/) diff --git a/spec/lib/postal/query_string_spec.rb b/spec/lib/postal/query_string_spec.rb index 1e34488..6be6283 100644 --- a/spec/lib/postal/query_string_spec.rb +++ b/spec/lib/postal/query_string_spec.rb @@ -1,42 +1,44 @@ +# frozen_string_literal: true + require "rails_helper" describe Postal::QueryString do it "should work with a single item" do qs = Postal::QueryString.new("to: test@example.com") - expect(qs.to_hash["to"]).to eq "test@example.com" + expect(qs.hash["to"]).to eq "test@example.com" end it "should work with a multiple items" do qs = Postal::QueryString.new("to: test@example.com from: another@example.com") - expect(qs.to_hash["to"]).to eq "test@example.com" - expect(qs.to_hash["from"]).to eq "another@example.com" + expect(qs.hash["to"]).to eq "test@example.com" + expect(qs.hash["from"]).to eq "another@example.com" end it "should not require a space after the field name" do qs = Postal::QueryString.new("to:test@example.com from:another@example.com") - expect(qs.to_hash["to"]).to eq "test@example.com" - expect(qs.to_hash["from"]).to eq "another@example.com" + expect(qs.hash["to"]).to eq "test@example.com" + expect(qs.hash["from"]).to eq "another@example.com" end it "should return nil when it receives blank" do qs = Postal::QueryString.new("to:[blank]") - expect(qs.to_hash["to"]).to eq nil + expect(qs.hash["to"]).to eq nil end it "should handle dates with spaces" do qs = Postal::QueryString.new("date: 2017-02-12 15:20") - expect(qs.to_hash["date"]).to eq("2017-02-12 15:20") + expect(qs.hash["date"]).to eq("2017-02-12 15:20") end it "should return an array for multiple items" do qs = Postal::QueryString.new("to: test@example.com to: another@example.com") - expect(qs.to_hash["to"]).to be_a(Array) - expect(qs.to_hash["to"][0]).to eq "test@example.com" - expect(qs.to_hash["to"][1]).to eq "another@example.com" + expect(qs.hash["to"]).to be_a(Array) + expect(qs.hash["to"][0]).to eq "test@example.com" + expect(qs.hash["to"][1]).to eq "another@example.com" end it "should work with a z in the string" do qs = Postal::QueryString.new("to: testaz@example.com") - expect(qs.to_hash["to"]).to eq "testaz@example.com" + expect(qs.hash["to"]).to eq "testaz@example.com" end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index b4de236..2e10886 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + ENV["POSTAL_ENV"] = "test" require File.expand_path("../config/environment", __dir__) @@ -9,7 +11,6 @@ require "database_cleaner" DatabaseCleaner.allow_remote_database_url = true ActiveRecord::Base.logger = Logger.new("/dev/null") -FACTORIES_EXCLUDED_FROM_LINT = [] Dir[File.expand_path("factories/*.rb", __dir__)].each { |f| require f } ActiveRecord::Migration.maintain_test_schema! @@ -24,7 +25,7 @@ RSpec.configure do |config| # the rest of the suite. begin DatabaseCleaner.start - FactoryBot.lint(FactoryBot.factories.select { |f| !FACTORIES_EXCLUDED_FROM_LINT.include?(f.name.to_sym) }) + FactoryBot.lint ensure DatabaseCleaner.clean end @@ -33,7 +34,10 @@ RSpec.configure do |config| # Because the mail databases don't use any transactions, all data left in the # database will be left there unless removed. DatabaseCleaner.start + + # rubocop:disable Lint/ConstantDefinitionInBlock GLOBAL_SERVER = FactoryBot.create(:server, provision_database: true) + # rubocop:enable Lint/ConstantDefinitionInBlock end config.after(:suite) do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a4e3954..64bf63e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + RSpec.configure do |config| config.color = true