Skip to content

Commit

Permalink
Adding inline attachment support
Browse files Browse the repository at this point in the history
  • Loading branch information
mikel committed Jun 8, 2010
1 parent cc8fafd commit ba9a684
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rdoc
@@ -1,3 +1,7 @@
== Tue Jun 8 01:55:21 UTC 2010 Mikel Lindsaar <mikel@rubyx.com>

* Added inline attachment support to mail (mikel)

== Mon Jun 7 18:00:39 UTC 2010 Mikel Lindsaar <mikel@rubyx.com>

* Updating versioning so we only have one source, VERSION.yml (mikel)
Expand Down
4 changes: 2 additions & 2 deletions VERSION.yml
@@ -1,5 +1,5 @@
---
:patch: 2
:patch: 3
:major: 2
:build:
:build: 0
:minor: 2
8 changes: 7 additions & 1 deletion lib/mail/attachments_list.rb
Expand Up @@ -3,6 +3,7 @@ class AttachmentsList < Array

def initialize(parts_list)
@parts_list = parts_list
@content_disposition_type = 'attachment'
parts_list.map { |p|
if p.content_type == "message/rfc822"
Mail.new(p.body).attachments
Expand All @@ -15,6 +16,11 @@ def initialize(parts_list)
self
end

def inline
@content_disposition_type = 'inline'
self
end

# Returns the attachment by filename or at index.
#
# mail.attachments['test.png'] = File.read('test.png')
Expand All @@ -33,7 +39,7 @@ def [](index_value)
def []=(name, value)
default_values = { :content_type => "#{set_mime_type(name)}; filename=\"#{name}\"",
:content_transfer_encoding => "#{guess_encoding}",
:content_disposition => "attachment; filename=\"#{name}\"" }
:content_disposition => "#{@content_disposition_type}; filename=\"#{name}\"" }

if value.is_a?(Hash)

Expand Down
3 changes: 2 additions & 1 deletion lib/mail/message.rb
Expand Up @@ -1644,6 +1644,7 @@ def convert_to_multipart
# ready to send
def ready_to_send!
identify_and_set_transfer_encoding
parts.sort!([ "text/plain", "text/enriched", "text/html", "multipart/alternative" ])
parts.each do |part|
part.transport_encoding = transport_encoding
part.ready_to_send!
Expand Down Expand Up @@ -1695,7 +1696,7 @@ def read
end

def decode_body
body.decoded
body.decoded
end

# Returns true if this part is an attachment
Expand Down
8 changes: 8 additions & 0 deletions lib/mail/part.rb
Expand Up @@ -29,6 +29,14 @@ def cid
uri_escape(unbracket(content_id))
end

def url
"cid:#{cid}"
end

def inline?
header[:content_disposition].disposition_type == 'inline' if header[:content_disposition]
end

def add_required_fields
add_content_id unless has_content_id?
super
Expand Down
24 changes: 24 additions & 0 deletions spec/mail/attachments_list_spec.rb
Expand Up @@ -134,6 +134,30 @@ def check_decoded(actual, expected)

end

describe "inline attachments" do

it "should set the content_disposition to inline or attachment as appropriate" do
mail = Mail.new
mail.attachments['test.pdf'] = File.read(fixture('attachments', 'test.pdf'))
mail.attachments['test.pdf'].content_disposition.should == 'attachment; filename=test.pdf'
mail.attachments.inline['test.png'] = File.read(fixture('attachments', 'test.png'))
mail.attachments.inline['test.png'].content_disposition.should == 'inline; filename=test.png'
end

it "should return a cid" do
mail = Mail.new
mail.attachments.inline['test.png'] = File.read(fixture('attachments', 'test.png'))
mail.attachments['test.png'].url.should == "cid:#{mail.attachments['test.png'].cid}"
end

it "should respond true to inline?" do
mail = Mail.new
mail.attachments.inline['test.png'] = File.read(fixture('attachments', 'test.png'))
mail.attachments['test.png'].should be_inline
end

end

describe "getting the content ID from an inline attachment" do

before(:each) do
Expand Down
17 changes: 17 additions & 0 deletions spec/mail/message_spec.rb
Expand Up @@ -1406,4 +1406,21 @@ def self.delivering_email(mail)
mail[:from].encoded.should == "From: =?UTF-8?B?Rm9vIMOhw6vDtCDDrsO8?= <extended@example.net>\r\n"
end
end

describe "ordering messages" do
it "should put all attachments as the last item" do
mail = Mail.new
mail.attachments['image.png'] = "\302\302\302\302"
p = Mail::Part.new(:content_type => 'multipart/alternative')
p.add_part(Mail::Part.new(:content_type => 'text/html', :body => 'HTML TEXT'))
p.add_part(Mail::Part.new(:content_type => 'text/plain', :body => 'PLAIN TEXT'))
mail.add_part(p)
mail.encoded
mail.parts[0].mime_type.should == "multipart/alternative"
mail.parts[0].parts[0].mime_type.should == "text/plain"
mail.parts[0].parts[1].mime_type.should == "text/html"
mail.parts[1].mime_type.should == "image/png"
end
end

end
10 changes: 10 additions & 0 deletions spec/mail/part_spec.rb
Expand Up @@ -28,6 +28,7 @@
part.inline_content_id.should == "thisis@acontentid"
end


it "should URL escape its inline content_id" do
part = Mail::Part.new do
content_id "<thi%%sis@acontentid>"
Expand All @@ -45,6 +46,15 @@
part.inline_content_id.should_not be_nil
end

it "should respond correctly to inline?" do
part = Mail::Part.new(:content_disposition => 'attachment')
part.should_not be_inline

part = Mail::Part.new(:content_disposition => 'inline')
part.should be_inline
end


describe "parts that have a missing header" do
it "should not try to init a header if there is none" do
part =<<PARTEND
Expand Down

0 comments on commit ba9a684

Please sign in to comment.