link-stack/packages/zammad-addon-hardening/src/config/initializers/transaction_notification_no_attachments.rb
2025-11-21 14:55:28 +01:00

79 lines
3.1 KiB
Ruby

# frozen_string_literal: true
# Monkey patch Transaction::Notification to prevent attachments from being
# included in ticket notification emails for security/privacy reasons.
#
# This overrides the send_notification_email method to always pass an empty
# attachments array instead of article.attachments_inline.
module TransactionNotificationNoAttachments
def send_notification_email(user:, ticket:, article:, changes:, current_user:, recipients_reason:)
template = case @item[:type]
when 'create'
'ticket_create'
when 'update'
'ticket_update'
when 'reminder_reached'
'ticket_reminder_reached'
when 'escalation'
'ticket_escalation'
when 'escalation_warning'
'ticket_escalation_warning'
when 'update.merged_into', 'update.received_merge'
'ticket_update_merged'
when 'update.reaction'
'ticket_article_update_reaction'
else
raise "unknown type for notification #{@item[:type]}"
end
# HARDENING: Always use empty attachments array to prevent leaking sensitive files
original_attachment_count = article&.attachments_inline&.count || 0
attachments = []
if original_attachment_count > 0
Rails.logger.info "[HARDENING] Stripped #{original_attachment_count} attachment(s) from notification email for ticket ##{ticket.id}"
end
NotificationFactory::Mailer.notification(
template: template,
user: user,
objects: {
ticket: ticket,
article: article,
recipient: user,
current_user: current_user,
changes: changes,
reason: recipients_reason[user.id],
},
message_id: "<notification.#{DateTime.current.to_fs(:number)}.#{ticket.id}.#{user.id}.#{SecureRandom.uuid}@#{Setting.get('fqdn')}>",
references: ticket.get_references,
main_object: ticket,
attachments: attachments,
)
Rails.logger.debug { "sent ticket email notification to agent (#{@item[:type]}/#{ticket.id}/#{user.email})" }
rescue Channel::DeliveryError => e
status_code = begin
e.original_error.response.status.to_i
rescue
raise e
end
if Transaction::Notification::SILENCABLE_SMTP_ERROR_CODES.any? { |elem| elem.include? status_code }
Rails.logger.info do
"could not send ticket email notification to agent (#{@item[:type]}/#{ticket.id}/#{user.email}) #{e.original_error}"
end
return
end
raise e
end
end
# Apply the monkey patch after Rails initialization when all classes are loaded
Rails.application.config.after_initialize do
Rails.logger.info '[HARDENING] Loading TransactionNotificationNoAttachments monkey patch...'
Transaction::Notification.prepend(TransactionNotificationNoAttachments)
Rails.logger.info '[HARDENING] TransactionNotificationNoAttachments monkey patch successfully applied - email attachments will be stripped from notifications'
end