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

refactor: refactor log use within SMTP server

Additionally adds logging when authentication is required but not provided.

closes #2794
closes #2791
هذا الالتزام موجود في:
Adam Cooke
2024-03-04 17:16:52 +00:00
الأصل 0d3eccb368
التزام cae4b63599
2 ملفات معدلة مع 41 إضافات و40 حذوفات

عرض الملف

@@ -50,8 +50,8 @@ module SMTPServer
@headers = nil @headers = nil
end end
def id def trace_id
@id ||= Nifty::Utils::RandomString.generate(length: 6).upcase @trace_id ||= SecureRandom.alphanumeric(8).upcase
end end
def handle(data) def handle(data)
@@ -59,21 +59,21 @@ module SMTPServer
@cr_present = true @cr_present = true
data = data.chop # remove last character (\r) data = data.chop # remove last character (\r)
else else
Postal.logger.debug("\e[33m WARN: Detected line with invalid line ending (missing <CR>)\e[0m", id: id) # This doesn't use `logger` because that will be nil when logging is disabled
# and we always want to log this.
Postal.logger&.warn("Detected line with invalid line ending (missing <CR>)", trace_id: trace_id)
@cr_present = false @cr_present = false
end end
Postal.logger.tagged(id: id) do if @state == :preauth
if @state == :preauth return proxy(data)
return proxy(data) end
end
log "\e[32m<= #{sanitize_input_for_log(data.strip)}\e[0m" logger&.debug "\e[32m<= #{sanitize_input_for_log(data.strip)}\e[0m"
if @proc if @proc
@proc.call(data) @proc.call(data)
else else
handle_command(data) handle_command(data)
end
end end
ensure ensure
@previous_cr_present = @cr_present @previous_cr_present = @cr_present
@@ -109,10 +109,10 @@ module SMTPServer
end end
end end
def log(text) def logger
return false unless @logging_enabled return nil unless @logging_enabled
Postal.logger.debug(text, id: id) @logger ||= Postal.logger.create_tagged_logger(trace_id: trace_id)
end end
private private
@@ -122,7 +122,7 @@ module SMTPServer
@ip_address = m[2] @ip_address = m[2]
check_ip_address check_ip_address
@state = :welcome @state = :welcome
log "\e[35m Client identified as #{@ip_address}\e[0m" logger&.debug "\e[35mClient identified as #{@ip_address}\e[0m"
increment_command_count("PROXY") increment_command_count("PROXY")
"220 #{Postal::Config.postal.smtp_hostname} ESMTP Postal/#{id}" "220 #{Postal::Config.postal.smtp_hostname} ESMTP Postal/#{id}"
else else
@@ -236,7 +236,7 @@ module SMTPServer
@credential.use @credential.use
"235 Granted for #{@credential.server.organization.permalink}/#{@credential.server.permalink}" "235 Granted for #{@credential.server.organization.permalink}/#{@credential.server.permalink}"
else else
log "\e[33m WARN: AUTH failure for #{@ip_address}\e[0m" logger&.warn "Authentication failure for #{@ip_address}"
increment_error_count("invalid-credentials") increment_error_count("invalid-credentials")
"535 Invalid credential" "535 Invalid credential"
end end
@@ -254,7 +254,7 @@ module SMTPServer
org_permlink, server_permalink = username.split(/[\/_]/, 2) org_permlink, server_permalink = username.split(/[\/_]/, 2)
server = ::Server.includes(:organization).where(organizations: { permalink: org_permlink }, permalink: server_permalink).first server = ::Server.includes(:organization).where(organizations: { permalink: org_permlink }, permalink: server_permalink).first
if server.nil? if server.nil?
log "\e[33m WARN: AUTH failure for #{@ip_address}\e[0m" logger&.warn "Authentication failure for #{@ip_address}"
increment_error_count("invalid-credentials") increment_error_count("invalid-credentials")
next "535 Denied" next "535 Denied"
end end
@@ -271,7 +271,7 @@ module SMTPServer
end end
if grant.nil? if grant.nil?
log "\e[33m WARN: AUTH failure for #{@ip_address}\e[0m" logger&.warn "Authentication failure for #{@ip_address}"
increment_error_count("invalid-credentials") increment_error_count("invalid-credentials")
next "535 Denied" next "535 Denied"
end end
@@ -332,7 +332,7 @@ module SMTPServer
increment_error_count("server-suspended") increment_error_count("server-suspended")
"535 Mail server has been suspended" "535 Mail server has been suspended"
else else
log "Added bounce on server #{server.id}" logger&.debug "Added bounce on server #{server.id}"
@recipients << [:bounce, rcpt_to, server] @recipients << [:bounce, rcpt_to, server]
"250 OK" "250 OK"
end end
@@ -352,7 +352,7 @@ module SMTPServer
increment_error_count("route-rejected") increment_error_count("route-rejected")
"550 Route does not accept incoming messages" "550 Route does not accept incoming messages"
else else
log "Added route #{route.id} to recipients (tag: #{tag.inspect})" logger&.debug "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 }] @recipients << [:route, actual_rcpt_to, route.server, { route: route }]
"250 OK" "250 OK"
@@ -368,7 +368,7 @@ module SMTPServer
increment_error_count("server-suspended") increment_error_count("server-suspended")
"535 Mail server has been suspended" "535 Mail server has been suspended"
else else
log "Added external address '#{rcpt_to}'" logger&.debug "Added external address '#{rcpt_to}'"
@recipients << [:credential, rcpt_to, @credential.server] @recipients << [:credential, rcpt_to, @credential.server]
"250 OK" "250 OK"
end end
@@ -383,7 +383,7 @@ module SMTPServer
increment_error_count("route-rejection") increment_error_count("route-rejection")
"550 Route does not accept incoming messages" "550 Route does not accept incoming messages"
else else
log "Added route #{route.id} to recipients (tag: #{tag.inspect})" logger&.debug "Added route #{route.id} to recipients (tag: #{tag.inspect})"
@recipients << [:route, rcpt_to, route.server, { route: route }] @recipients << [:route, rcpt_to, route.server, { route: route }]
"250 OK" "250 OK"
end end
@@ -400,6 +400,7 @@ module SMTPServer
rcpt_to(data) rcpt_to(data)
else else
increment_error_count("authentication-required") increment_error_count("authentication-required")
logger&.warn "Authentication failure for #{@ip_address}"
"530 Authentication required" "530 Authentication required"
end end
end end
@@ -432,7 +433,7 @@ module SMTPServer
if @credential&.server&.log_smtp_data? if @credential&.server&.log_smtp_data?
# We want to log if enabled # We want to log if enabled
else else
log "Not logging further message data." logger&.debug "Not logging further message data."
@logging_enabled = false @logging_enabled = false
end end

عرض الملف

@@ -117,17 +117,17 @@ module SMTPServer
# client's IP later. Delay the welcome process. # client's IP later. Delay the welcome process.
client = Client.new(nil) client = Client.new(nil)
if Postal::Config.smtp_server.log_connections? if Postal::Config.smtp_server.log_connections?
logger.debug "[#{client.id}] \e[35m Connection opened from #{new_io.remote_address.ip_address}\e[0m" client.logger&.debug "Connection opened from #{new_io.remote_address.ip_address}"
end end
else else
# We're not using the proxy protocol so we already know the client's IP # We're not using the proxy protocol so we already know the client's IP
client = Client.new(new_io.remote_address.ip_address) client = Client.new(new_io.remote_address.ip_address)
if Postal::Config.smtp_server.log_connections? if Postal::Config.smtp_server.log_connections?
logger.debug "[#{client.id}] \e[35m Connection opened from #{new_io.remote_address.ip_address}\e[0m" client.logger&.debug "Connection opened from #{new_io.remote_address.ip_address}"
end end
# We know who the client is, welcome them. # We know who the client is, welcome them.
client.log "\e[35m Client identified as #{new_io.remote_address.ip_address}\e[0m" client.logger&.debug "Client identified as #{new_io.remote_address.ip_address}"
new_io.print("220 #{Postal::Config.postal.smtp_hostname} ESMTP Postal/#{client.id}") new_io.print("220 #{Postal::Config.postal.smtp_hostname} ESMTP Postal/#{client.trace_id}")
end end
# Register the client and its socket with nio4r # Register the client and its socket with nio4r
monitor = @io_selector.register(new_io, :r) monitor = @io_selector.register(new_io, :r)
@@ -135,8 +135,8 @@ module SMTPServer
rescue StandardError => e rescue StandardError => e
# If something goes wrong, log as appropriate and disconnect the client # If something goes wrong, log as appropriate and disconnect the client
if defined?(Sentry) if defined?(Sentry)
Sentry.capture_exception(e, extra: { log_id: begin Sentry.capture_exception(e, extra: { trace_id: begin
client.id client.trace_id
rescue StandardError rescue StandardError
nil nil
end }) end })
@@ -175,7 +175,7 @@ module SMTPServer
# We will try again later # We will try again later
next next
rescue OpenSSL::SSL::SSLError => e rescue OpenSSL::SSL::SSLError => e
client.log "SSL Negotiation Failed: #{e.message}" client.logger&.debug "SSL Negotiation Failed: #{e.message}"
eof = true eof = true
end end
else else
@@ -205,7 +205,7 @@ module SMTPServer
result = [result] unless result.is_a?(Array) result = [result] unless result.is_a?(Array)
result.compact.each do |iline| result.compact.each do |iline|
client.log "\e[34m=> #{iline.strip}\e[0m" client.logger&.debug "\e[34m=> #{iline.strip}"
begin begin
io.write(iline.to_s + "\r\n") io.write(iline.to_s + "\r\n")
io.flush io.flush
@@ -232,7 +232,7 @@ module SMTPServer
# Has the client requested we close the connection? # Has the client requested we close the connection?
if client.finished? || eof if client.finished? || eof
client.log "\e[35m Connection closed\e[0m" client.logger&.debug "Connection closed"
# Deregister the socket and close it # Deregister the socket and close it
@io_selector.deregister(io) @io_selector.deregister(io)
buffers.delete(io) buffers.delete(io)
@@ -244,18 +244,18 @@ module SMTPServer
end end
rescue StandardError => e rescue StandardError => e
# Something went wrong, log as appropriate # Something went wrong, log as appropriate
client_id = client ? client.id : "------" client_id = client ? client.trace_id : "------"
if defined?(Sentry) if defined?(Sentry)
Sentry.capture_exception(e, extra: { log_id: begin Sentry.capture_exception(e, extra: { trace_id: begin
client.id client&.trace_id
rescue StandardError rescue StandardError
nil nil
end }) end })
end end
logger.error "[#{client_id}] An error occurred while processing data from a client." logger.error "An error occurred while processing data from a client.", trace_id: client_id
logger.error "[#{client_id}] #{e.class}: #{e.message}" logger.error "#{e.class}: #{e.message}", trace_id: client_id
e.backtrace.each do |iline| e.backtrace.each do |iline|
logger.error "[#{client_id}] #{iline}" logger.error iline, trace_id: client_id
end end
increment_prometheus_counter :postal_smtp_server_exceptions_total, increment_prometheus_counter :postal_smtp_server_exceptions_total,