1
0
مراية لـ https://github.com/postalserver/postal.git تم المزامنة 2025-12-01 05:43:04 +00:00

Add IP-based SMTP authentication (#1149)

هذا الالتزام موجود في:
Charlie Smurthwaite
2020-07-17 11:43:51 +01:00
ملتزم من قبل GitHub
الأصل 5c7802d218
التزام 9a3d568b27
9 ملفات معدلة مع 103 إضافات و14 حذوفات

عرض الملف

@@ -53,3 +53,21 @@ $ ->
$(element, $link.parent()).toggle()
false
toggleCredentialInputs = (type)->
$('[data-credential-key-type]').hide()
$('[data-credential-key-type] input').attr('disabled', true)
if type == 'SMTP-IP'
$('[data-credential-key-type=smtp-ip]').show()
$('[data-credential-key-type=smtp-ip] input').attr('disabled', false)
else
$('[data-credential-key-type=all]').show()
$(document).on 'change', 'select#credential_type', ->
value = $(this).val()
toggleCredentialInputs(value)
$(document).on 'turbolinks:load', ->
credentialTypeInput = $('select#credential_type')
if credentialTypeInput.length
toggleCredentialInputs(credentialTypeInput.val())

عرض الملف

@@ -95,6 +95,10 @@
background-color:$turquoise;
}
.label--credentialType-smtp_ip {
background-color:$orange;
}
.label--spamStatus-not_checked {
background:#aaa;
}

عرض الملف

@@ -3,7 +3,7 @@ class CredentialsController < ApplicationController
include WithinOrganization
before_action { @server = organization.servers.present.find_by_permalink!(params[:server_id]) }
before_action { params[:id] && @credential = @server.credentials.find_by_key!(params[:id]) }
before_action { params[:id] && @credential = @server.credentials.find_by_uuid!(params[:id]) }
def index
@credentials = @server.credentials.order(:name).to_a
@@ -14,7 +14,7 @@ class CredentialsController < ApplicationController
end
def create
@credential = @server.credentials.build(params.require(:credential).permit(:type, :name, :hold))
@credential = @server.credentials.build(params.require(:credential).permit(:type, :name, :key, :hold))
if @credential.save
redirect_to_with_json [organization, @server, :credentials]
else
@@ -23,7 +23,7 @@ class CredentialsController < ApplicationController
end
def update
if @credential.update(params.require(:credential).permit(:name, :hold))
if @credential.update(params.require(:credential).permit(:name, :key, :hold))
redirect_to_with_json [organization, @server, :credentials]
else
render_form_errors 'edit', @credential

عرض الملف

@@ -12,24 +12,37 @@
# created_at :datetime
# updated_at :datetime
# hold :boolean default(FALSE)
# uuid :string(255)
#
class Credential < ApplicationRecord
include HasUUID
belongs_to :server
TYPES = ['SMTP', 'API']
TYPES = ['SMTP', 'API', 'SMTP-IP']
validates :key, :presence => true, :uniqueness => true
validates :type, :inclusion => {:in => TYPES}
validates :name, :presence => true
random_string :key, :type => :chars, :length => 24, :unique => true
validate :validate_key_cannot_be_changed
validate :validate_key_for_smtp_ip
serialize :options, Hash
before_validation :generate_key
def generate_key
return if self.type == 'SMTP-IP'
return if self.persisted?
self.key = SecureRandomString.new(24)
end
def to_param
key
uuid
end
def use
@@ -54,4 +67,30 @@ class Credential < ApplicationRecord
Base64.encode64("\0XX\0#{self.key}").strip
end
def ipaddr
return unless type == 'SMTP-IP'
@ipaddr ||= IPAddr.new(self.key)
rescue IPAddr::InvalidAddressError
nil
end
private
def validate_key_cannot_be_changed
return if new_record?
return unless key_changed?
return if type == 'SMTP-IP'
errors.add :key, "cannot be changed"
end
def validate_key_for_smtp_ip
return unless type == 'SMTP-IP'
IPAddr.new(self.key.to_s)
rescue IPAddr::InvalidAddressError
errors.add :key, "must be a valid IPv4 or IPv6 address"
end
end

عرض الملف

@@ -15,14 +15,23 @@
%p.fieldSet__text
This is a friendly name so you can identify this credential later. You can enter anything
you want here, the more descriptive the better.
.fieldSet__field
.fieldSet__field{data: {credential_key_type: 'all'}}
= f.label :key, :class => 'fieldSet__label'
.fieldSet__input
= f.text_field :key, :readonly => true, :class => 'input input--text input--code', :placeholder => "Automatically generated", :tabindex => 1000, :value => (@credential.new_record? ? '' : @credential.key)
= f.text_field :key, :readonly => false, :class => 'input input--text input--code', :placeholder => "Automatically generated", :tabindex => 1000, :value => (@credential.new_record? ? '' : @credential.key)
%p.fieldSet__text
This is the unique key which will be used to authenticate any requests to the API or our SMTP servers.
This is the unique key which will be used to authenticate any requests to the API or the SMTP servers.
It will be generated randomly and cannot be changed. If you need a new token, you can create a new one and then
delete the old one when you're ready.
.fieldSet__field{data: {credential_key_type: 'smtp-ip'}}
= f.label :key, "Network", :class => 'fieldSet__label'
.fieldSet__input
= f.text_field :key, :class => 'input input--text input--code'
%p.fieldSet__text
This is the IP address or network that you wish to allow to authenticate to this mail server.
.fieldSet__field
= f.label :hold, :class => 'fieldSet__label'
.fieldSet__input

عرض الملف

@@ -23,7 +23,7 @@
%li.credentialList__item
= link_to [:edit, organization, @server, credential], :class => 'credentialList__link' do
.credentialList__type
%span.label{:class => "label--credentialType-#{credential.type.underscore}"}= credential.type
%span.label{:class => "label--credentialType-#{credential.type.underscore}"}= credential.type.split('-').last
.credentialList__properties
%p.credentialList__name
= credential.name

عرض الملف

@@ -0,0 +1,8 @@
class AddUUIDToCredentials < ActiveRecord::Migration[5.2]
def change
add_column :credentials, :uuid, :string
Credential.find_each do |c|
c.update_column(:uuid, SecureRandom.uuid)
end
end
end

عرض الملف

@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2018_02_16_114344) do
ActiveRecord::Schema.define(version: 2020_07_17_083943) do
create_table "additional_route_endpoints", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|
t.integer "route_id"
@@ -68,6 +68,7 @@ ActiveRecord::Schema.define(version: 2018_02_16_114344) do
t.datetime "created_at", precision: 6
t.datetime "updated_at", precision: 6
t.boolean "hold", default: false
t.string "uuid"
end
create_table "domains", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", force: :cascade do |t|

عرض الملف

@@ -312,10 +312,20 @@ module Postal
end
else
# This is unaccepted mail
# User is trying to relay but is not authenticated. Try to authenticate by IP address
@credential = Credential.where(:type => 'SMTP-IP').all.sort_by { |c| c.ipaddr&.prefix || 0 }.reverse.find do |credential|
credential.ipaddr.include?(@ip_address)
end
if @credential
# Retry with credential
@credential.use
rcpt_to(data)
else
'530 Authentication required'
end
end
end
def data(data)
unless in_state(:rcpt_to_received)