مراية لـ
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
هذا الالتزام موجود في:
@@ -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,
|
||||||
|
|||||||
المرجع في مشكلة جديدة
حظر مستخدم