Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract FoiAttachment::Dsn & restore functionality #8015

Merged
merged 2 commits into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 4 additions & 66 deletions app/models/foi_attachment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,76 +157,14 @@ def main_body_part?
self == incoming_message.get_main_body_text_part
end

# List of DSN codes taken from RFC 3463
# http://tools.ietf.org/html/rfc3463
DsnToMessage = {
'X.1.0' => 'Other address status',
'X.1.1' => 'Bad destination mailbox address',
'X.1.2' => 'Bad destination system address',
'X.1.3' => 'Bad destination mailbox address syntax',
'X.1.4' => 'Destination mailbox address ambiguous',
'X.1.5' => 'Destination mailbox address valid',
'X.1.6' => 'Mailbox has moved',
'X.1.7' => 'Bad sender\'s mailbox address syntax',
'X.1.8' => 'Bad sender\'s system address',
'X.2.0' => 'Other or undefined mailbox status',
'X.2.1' => 'Mailbox disabled, not accepting messages',
'X.2.2' => 'Mailbox full',
'X.2.3' => 'Message length exceeds administrative limit.',
'X.2.4' => 'Mailing list expansion problem',
'X.3.0' => 'Other or undefined mail system status',
'X.3.1' => 'Mail system full',
'X.3.2' => 'System not accepting network messages',
'X.3.3' => 'System not capable of selected features',
'X.3.4' => 'Message too big for system',
'X.4.0' => 'Other or undefined network or routing status',
'X.4.1' => 'No answer from host',
'X.4.2' => 'Bad connection',
'X.4.3' => 'Routing server failure',
'X.4.4' => 'Unable to route',
'X.4.5' => 'Network congestion',
'X.4.6' => 'Routing loop detected',
'X.4.7' => 'Delivery time expired',
'X.5.0' => 'Other or undefined protocol status',
'X.5.1' => 'Invalid command',
'X.5.2' => 'Syntax error',
'X.5.3' => 'Too many recipients',
'X.5.4' => 'Invalid command arguments',
'X.5.5' => 'Wrong protocol version',
'X.6.0' => 'Other or undefined media error',
'X.6.1' => 'Media not supported',
'X.6.2' => 'Conversion required and prohibited',
'X.6.3' => 'Conversion required but not supported',
'X.6.4' => 'Conversion with loss performed',
'X.6.5' => 'Conversion failed',
'X.7.0' => 'Other or undefined security status',
'X.7.1' => 'Delivery not authorized, message refused',
'X.7.2' => 'Mailing list expansion prohibited',
'X.7.3' => 'Security conversion required but not possible',
'X.7.4' => 'Security features not supported',
'X.7.5' => 'Cryptographic failure',
'X.7.6' => 'Cryptographic algorithm not supported',
'X.7.7' => 'Message integrity failure'
}

# Returns HTML, of extra comment to put by attachment
def extra_note
garethrees marked this conversation as resolved.
Show resolved Hide resolved
# For delivery status notification attachments, extract the status and
# look up what it means in the DSN table.
if @content_type == 'message/delivery-status'
return "" unless @body.match(/Status:\s+([0-9]+\.([0-9]+\.[0-9]+))\s+/)

dsn = $1
dsn_part = 'X.' + $2
return unless content_type == 'message/delivery-status'

dsn_message = ""
if DsnToMessage.include?(dsn_part)
dsn_message = " (" + DsnToMessage[dsn_part] + ")"
end
dsn = DeliveryStatusNotification.new(body)
return unless dsn.status && dsn.message

return "<br><em>DSN: " + dsn + dsn_message + "</em>"
end
""
"DSN: #{dsn.status} #{dsn.message}"
end

# Called by controller so old filenames still work
Expand Down
84 changes: 84 additions & 0 deletions app/models/foi_attachment/delivery_status_notification.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Parse DSN status code to provide a human readable summary message
class FoiAttachment::DeliveryStatusNotification
# List of DSN codes taken from RFC 3463
# http://tools.ietf.org/html/rfc3463
STATUS_TO_MESSAGE = {
'X.1.0' => 'Other address status',
'X.1.1' => 'Bad destination mailbox address',
'X.1.2' => 'Bad destination system address',
'X.1.3' => 'Bad destination mailbox address syntax',
'X.1.4' => 'Destination mailbox address ambiguous',
'X.1.5' => 'Destination mailbox address valid',
'X.1.6' => 'Mailbox has moved',
'X.1.7' => 'Bad sender\'s mailbox address syntax',
'X.1.8' => 'Bad sender\'s system address',
'X.2.0' => 'Other or undefined mailbox status',
'X.2.1' => 'Mailbox disabled, not accepting messages',
'X.2.2' => 'Mailbox full',
'X.2.3' => 'Message length exceeds administrative limit.',
'X.2.4' => 'Mailing list expansion problem',
'X.3.0' => 'Other or undefined mail system status',
'X.3.1' => 'Mail system full',
'X.3.2' => 'System not accepting network messages',
'X.3.3' => 'System not capable of selected features',
'X.3.4' => 'Message too big for system',
'X.4.0' => 'Other or undefined network or routing status',
'X.4.1' => 'No answer from host',
'X.4.2' => 'Bad connection',
'X.4.3' => 'Routing server failure',
'X.4.4' => 'Unable to route',
'X.4.5' => 'Network congestion',
'X.4.6' => 'Routing loop detected',
'X.4.7' => 'Delivery time expired',
'X.5.0' => 'Other or undefined protocol status',
'X.5.1' => 'Invalid command',
'X.5.2' => 'Syntax error',
'X.5.3' => 'Too many recipients',
'X.5.4' => 'Invalid command arguments',
'X.5.5' => 'Wrong protocol version',
'X.6.0' => 'Other or undefined media error',
'X.6.1' => 'Media not supported',
'X.6.2' => 'Conversion required and prohibited',
'X.6.3' => 'Conversion required but not supported',
'X.6.4' => 'Conversion with loss performed',
'X.6.5' => 'Conversion failed',
'X.7.0' => 'Other or undefined security status',
'X.7.1' => 'Delivery not authorized, message refused',
'X.7.2' => 'Mailing list expansion prohibited',
'X.7.3' => 'Security conversion required but not possible',
'X.7.4' => 'Security features not supported',
'X.7.5' => 'Cryptographic failure',
'X.7.6' => 'Cryptographic algorithm not supported',
'X.7.7' => 'Message integrity failure'
}.freeze

def initialize(body)
@body = body
end

def status
@status ||= status!
end

def message
STATUS_TO_MESSAGE[status_part]
end

private

attr_reader :body

def status!
@status = match ? match[1] : nil
end

def status_part
return '' unless match

'X.' + match[2]
end

def match
body.match(/Status:\s+([0-9]+\.([0-9]+\.[0-9]+))\s+/)
end
end
5 changes: 4 additions & 1 deletion app/views/request/_attachments.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
<% if a.has_body_as_html? && incoming_message.info_request.prominence(:decorate => true).is_public? %>
<%= link_to "View as HTML", attachment_path(a, :html => true) %>
<% end %>
<%= a.extra_note %>

<% if note = a.extra_note %>
<em><%= note %></em>
<% end %>
</p>
<% end %>
<% end %>
Expand Down
1 change: 1 addition & 0 deletions doc/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Highlighted Features

* Restore delivery status notification attachment note (Gareth Rees)
* Allow `InfoRequest` to be categorised (Graeme Porteous)
* Replace public body categories with generalised categories (Graeme Porteous)
* Add admin links to and from batch request show action (Graeme Porteous)
Expand Down
11 changes: 11 additions & 0 deletions spec/factories/foi_attchments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,19 @@
body { 'hereisthetext' }
filename { 'attachment.txt' }
end

factory :pdf_attachment do
content_type { 'application/pdf' }
filename { 'interesting.pdf' }
body { load_file_fixture('interesting.pdf') }
end

factory :rtf_attachment do
content_type { 'application/rtf' }
filename { 'interesting.rtf' }
body { load_file_fixture('interesting.rtf') }
end

factory :html_attachment do
content_type { 'text/html' }
filename { 'interesting.html' }
Expand All @@ -51,11 +54,19 @@
Mail::Utilities.to_crlf(load_file_fixture('interesting.html'))
}
end

factory :jpeg_attachment do
content_type { 'image/jpeg' }
filename { 'interesting.jpg' }
body { 'someimage' }
end

factory :delivery_status_notification_attachment do
content_type { 'message/delivery-status' }
filename { 'attachment.delivery_status' }
body { load_file_fixture('attachment.delivery_status') }
end

factory :unknown_attachment do
content_type { 'application/unknown' }
filename { 'interesting.spc' }
Expand Down
10 changes: 10 additions & 0 deletions spec/fixtures/files/attachment.delivery_status
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
X-Symantec-Messaging-Gateway-Queue-ID: EE/CD-06721-9C109DE4
X-Symantec-Messaging-Gateway-Sender: rfc822; [email protected]
Reporting-MTA: dns; gov.example.com
Arrival-Date: Sat, 03 Dec 2011 04:50:17 +0000

Final-Recipient: rfc822; [email protected]
Status: 4.4.0
Action: delayed
Last-Attempt-Date: Sat, 03 Dec 2011 04:50:17 +0000
Diagnostic-Code: smtp; 421 4.4.0 [internal] no MXs for this domain could be reached at this time
47 changes: 47 additions & 0 deletions spec/models/foi_attachment/delivery_status_notification_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require 'spec_helper'

RSpec.describe FoiAttachment::DeliveryStatusNotification do
let(:valid_status_body) do
<<~EOF
Action: failed
Status: 5.4.1
EOF
end

let(:invalid_status_body) do
<<~EOF
Action: failed
Status: invalid
EOF
end

describe '#status' do
subject { dsn.status }
let(:dsn) { described_class.new(body) }

context 'with a valid status' do
let(:body) { valid_status_body }
it { is_expected.to eq('5.4.1') }
end

context 'with an invalid status' do
let(:body) { invalid_status_body }
it { is_expected.to be_nil }
end
end

describe '#message' do
subject { dsn.message }
let(:dsn) { described_class.new(body) }

context 'with a valid status' do
let(:body) { valid_status_body }
it { is_expected.to eq('No answer from host') }
end

context 'with an invalid status' do
let(:body) { invalid_status_body }
it { is_expected.to be_nil }
end
end
end
21 changes: 21 additions & 0 deletions spec/models/foi_attachment_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -374,4 +374,25 @@
it { is_expected.to be_nil }
end
end

describe '#extra_note' do
subject { foi_attachment.extra_note }

context 'with a delivery status notification' do
let(:foi_attachment) do
FactoryBot.create(:delivery_status_notification_attachment)
end

let(:note) do
'DSN: 4.4.0 Other or undefined network or routing status'
end

it { is_expected.to eq(note) }
end

context 'with any other content type' do
let(:foi_attachment) { FactoryBot.build(:rtf_attachment) }
it { is_expected.to be_nil }
end
end
end