1
0
مراية لـ https://github.com/postalserver/postal.git تم المزامنة 2026-05-31 04:35:42 +00:00
الملفات
postal/lib/tracking_middleware.rb
Adam Cooke dca7f90b90 refactor(tracking): remove unused src image proxy
The /img/<server>/<message> endpoint accepted a src=<url> query
parameter and proxied the body of that URL back to the caller. Nothing
in the codebase ever produces a src= parameter — the parser only
inserts a plain tracking pixel and rewrites href links — so this branch
is dead code inherited from the original AppMail import.

Drop the src branch: requests with src now return 400. The no-src path
that serves the tracking pixel and records loads is unchanged, and a
spec covers both the pixel-serving path and the removed branch.
2026-04-24 22:24:18 +01:00

108 أسطر
3.2 KiB
Ruby

# frozen_string_literal: true
class TrackingMiddleware
TRACKING_PIXEL = File.read(Rails.root.join("app", "assets", "images", "tracking_pixel.png"))
def initialize(app = nil)
@app = app
end
def call(env)
unless env["HTTP_X_POSTAL_TRACK_HOST"].to_i == 1
return @app.call(env)
end
request = Rack::Request.new(env)
case request.path
when /\A\/img\/([a-z0-9-]+)\/([a-z0-9-]+)/i
server_token = ::Regexp.last_match(1)
message_token = ::Regexp.last_match(2)
dispatch_image_request(request, server_token, message_token)
when /\A\/([a-z0-9-]+)\/([a-z0-9-]+)/i
server_token = ::Regexp.last_match(1)
link_token = ::Regexp.last_match(2)
dispatch_redirect_request(request, server_token, link_token)
else
[200, {}, ["Hello."]]
end
end
private
def dispatch_image_request(request, server_token, message_token)
message_db = get_message_db_from_server_token(server_token)
if message_db.nil?
return [404, {}, ["Invalid Server Token"]]
end
begin
message = message_db.message(token: message_token)
message.create_load(request)
rescue Postal::MessageDB::Message::NotFound
# This message has been removed, we'll just continue to serve the image
rescue StandardError => e
# Somethign else went wrong. We don't want to stop the image loading though because
# this is our problem. Log this exception though.
Sentry.capture_exception(e) if defined?(Sentry)
end
if request.params["src"].nil?
headers = {}
headers["Content-Type"] = "image/png"
headers["Content-Length"] = TRACKING_PIXEL.bytesize.to_s
[200, headers, [TRACKING_PIXEL]]
else
[400, {}, ["Invalid/missing source image"]]
end
end
def dispatch_redirect_request(request, server_token, link_token)
message_db = get_message_db_from_server_token(server_token)
if message_db.nil?
return [404, {}, ["Invalid Server Token"]]
end
link = message_db.select(:links, where: { token: link_token }, limit: 1).first
if link.nil?
return [404, {}, ["Link not found"]]
end
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
})
begin
message_webhook_hash = message_db.message(link["message_id"]).webhook_hash
WebhookRequest.trigger(message_db.server, "MessageLinkClicked", {
message: message_webhook_hash,
url: link["url"],
token: link["token"],
ip_address: request.ip,
user_agent: request.user_agent
})
rescue Postal::MessageDB::Message::NotFound
# If we can't find the message that this link is associated with, we'll just ignore it
# and not trigger any webhooks.
end
end
[307, { "Location" => link["url"] }, ["Redirected to: #{link['url']}"]]
end
def get_message_db_from_server_token(token)
return unless server = ::Server.find_by_token(token)
server.message_db
end
end