JasonKing-inline_attachment 0.3.7 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/README +50 -61
  2. data/lib/inline_attachment.rb +46 -74
  3. metadata +2 -3
data/README CHANGED
@@ -3,77 +3,66 @@
3
3
  This package adds full support for embedding inline images into your HTML emails
4
4
  through ActionMailer.
5
5
 
6
- It is created from a Rails patch #2179 (found at http://dev.rubyonrails.org/ticket/2179).
7
-
8
- The goal of this gem is to remove the need for manual patching.
9
-
10
6
  == Installation
11
7
 
12
8
  To perform a system wide installation:
13
9
 
14
- <tt>gem install inline_attachment</tt>
10
+ <tt>gem source -a http://gems.github.com</tt>
11
+ <tt>gem install JasonKing-inline_attachment</tt>
15
12
 
16
13
  To use inline_attachment in your project, add the following line to your project's
17
14
  config/environment.rb:
18
15
 
19
- <tt>require 'inline_attachment'</tt>
16
+ <tt>config.gem 'inline_attachment'</tt>
20
17
 
21
18
 
22
19
  == Usage
23
20
 
24
- ==== Embed Images Manually
25
-
26
- The code to add inline attachments into your HTML emails is pretty simple:
27
-
28
- @cid = Time.now.to_f.to_s + "foobar.png@domain.com"
29
-
30
- inline_attachment :content_type => "image/png",
31
- :body => File.read("#{RAILS_ROOT}/public/images/foobar.png"),
32
- :filename => "foobar.png",
33
- :cid => "<#{@cid}>"
34
-
35
- Note that the above code should go into your ActionMailer.
36
-
37
- The instance variable @cid is the unique identifier your MIME email will be using to
38
- locate the attached image. All you have to do is then pass it over to your email
39
- template, and display it like so:
40
-
41
- <img src="cid:<%= @cid %>" alt="Foo Bar" />
42
-
43
- ==== Embed Images Automatically
44
-
45
- As of version 0.2.0, Inline Attachment automatically embeds any images found within
46
- your ActionMailer templates. There is no longer any extra code required when adding images
47
- into your mail templates. Though, you must use rails image_tag helper when displaying
48
- images within your mailer views.
49
-
50
- With version 0.3.0, you are now able to embed images into nested parts by specifying
51
- a part container to place the attached images into. For example:
52
-
53
- class Notifier < ActionMailer::Base
54
- def images
55
- recipients "test@test.com"
56
- from "test@test.com"
57
- subject "Test"
58
- content_type "multipart/alternative"
59
-
60
- part "text/plain" do |p|
61
- p.body = render_message("images.text.plain.rhtml", {})
62
- p.content_disposition = ""
63
- p.transfer_encoding = "7bit"
64
- p.charset = "ISO-8859-15"
65
- end
66
-
67
- part "multipart/related" do |p|
68
- p.parts << ActionMailer::Part.new(
69
- :content_type => "text/html", :body => render_message("images.text.html.rhtml", :part_container => p),
70
- :disposition => "",
71
- :charset => "ISO-8859-15",
72
- :transfer_encoding => "7bit"
73
- )
74
- end
75
- end
21
+ I've rewritten most of Edmond's great work in this version. I now override
22
+ path_to_image instead of image_tag because a big reason for all the Rails2
23
+ breakages was because image_tag was basically reproduced in previous versions,
24
+ so broke when that method changed.
25
+
26
+ Now we override the very simple path_to_image, and most importantly we really
27
+ just add our own stuff for ActionMailer templates, and resort to the existing
28
+ code for everything else.
29
+
30
+ I've also integrated in with the new implicit multipart stuff. So now, there is
31
+ so little code required!
32
+
33
+
34
+ class Notifier < ActionMailer::Base
35
+ def signup
36
+ recipients %q{"Testing IA" <testing@handle.it>}
37
+ from %q{"Mr Tester" <tester@handle.it>}
38
+ subject "Here's a funky test"
39
+ end
76
40
  end
77
-
78
- You can see that we passed in the variable :part_container => p into the body of the nested part.
79
- This needs to be done so that the images are embedded into the part that they are used in.
41
+
42
+ # Oh yeah baby! Read it and weep! So how's this work? Well, you'll need
43
+ # your templates named properly - see the `Multipart email` section of the
44
+ # ActionMailer::Base docs.
45
+
46
+ # signup.text.plain.erb
47
+ Your username is: <%= @username %>
48
+
49
+ # signup.text.html.erb
50
+ <html><head><title>Signup Notification</title></head><body>
51
+ <%= image_tag "logo.png" %>
52
+ <p>Your username is: <%=h @username %>
53
+ </body></html>
54
+
55
+
56
+ That's it! InlineAttachment will look for
57
+ "#{RAILS_ROOT}/public/images/logo.png" and will do the right thing and embed it
58
+ inline into the HTML version of the email. ActionMailer will do the right thing
59
+ and offer the recipient both the text/plain and text/html parts as alternatives.
60
+
61
+
62
+ Note, that you should still be able to use this in the 0.3.0 way if you have
63
+ code that uses that. But there were a lot of alternatives, and the examples in
64
+ here didn't show a crucial step of shuffling the parts around to be sure that
65
+ the image parts came after the html.
66
+
67
+ You can also do the old "manual" method if you want.
68
+
@@ -1,4 +1,5 @@
1
1
  TMail::HeaderField::FNAME_TO_CLASS.delete('content-id')
2
+ CID_NAME = 'Content-Id'
2
3
 
3
4
  module ActionMailer
4
5
  module PartContainer
@@ -8,59 +9,40 @@ module ActionMailer
8
9
  params = { :disposition => "inline",
9
10
  :transfer_encoding => "base64" }.merge(params)
10
11
  params[:headers] ||= {}
11
- params[:headers]['Content-ID'] = params[:cid]
12
+ params[:headers][CID_NAME] = params[:cid]
12
13
  part(params, &block)
13
14
  end
14
15
  end
15
16
 
16
- class Part
17
- def to_mail(defaults)
18
- part = TMail::Mail.new
19
-
20
- if @parts.empty?
21
- part.content_transfer_encoding = transfer_encoding || "quoted-printable"
22
- case (transfer_encoding || "").downcase
23
- when "base64" then
24
- part.body = TMail::Base64.folding_encode(body)
25
- when "quoted-printable"
26
- part.body = [Utils.normalize_new_lines(body)].pack("M*")
27
- else
28
- part.body = body
17
+ class Base
18
+ alias_method :ia_original_create_mail, :create_mail
19
+ def create_mail
20
+ # sniff out inline html parts with inline images and wrap them up in a
21
+ # multipart/related mime part
22
+ got_inlines = false
23
+ related_parts = []
24
+ for_deletion = []
25
+ @parts.each_with_index do |p,i|
26
+ logger.debug "Considering #{i}"
27
+ if p.content_disposition == 'inline' && p.content_type =~ %r{^image/}i && p.headers[CID_NAME]
28
+ logger.debug "Just adding [#{i}] to the list\n#{p.filename}"
29
+ for_deletion << i
30
+ related_parts << p
31
+ got_inlines = true
29
32
  end
30
33
 
31
- # Always set the content_type after setting the body and or parts
32
-
33
- # CHANGE: treat attachments and inline files the same
34
- if content_disposition == "attachment" || ((content_disposition == "inline") && filename)
35
- part.set_content_type(content_type || defaults.content_type, nil,
36
- squish("charset" => nil, "name" => filename))
37
- else
38
- part.set_content_type(content_type || defaults.content_type, nil,
39
- "charset" => (charset || defaults.charset))
40
- end
41
-
42
- part.set_content_disposition(content_disposition, squish("filename" => filename)) unless content_disposition.blank?
43
- headers.each {|k,v| part[k] = v }
44
- # END CHANGE
45
-
46
- else
47
- if String === body
48
- part = TMail::Mail.new
49
- part.body = body
50
- part.set_content_type content_type, nil, { "charset" => charset }
51
- part.set_content_disposition "inline"
52
- m.parts << part
34
+ if got_inlines && p.content_type =~ %r{text/html}i
35
+ @parts[i] = ActionMailer::Part.new( :content_type => "multipart/related" )
36
+ @parts[i].parts << p
37
+ related_parts.each do |rp|
38
+ @parts[i].parts << rp
39
+ end
40
+ got_inlines = false
41
+ related_parts = []
53
42
  end
54
-
55
- @parts.each do |p|
56
- prt = (TMail::Mail === p ? p : p.to_mail(defaults))
57
- part.parts << prt
58
- end
59
-
60
- part.set_content_type(content_type, nil, { "charset" => charset }) if content_type =~ /multipart/
61
43
  end
62
-
63
- part
44
+ for_deletion.sort{|a,b|b<=>a}.each {|i|@parts.delete_at(i)}
45
+ ia_original_create_mail
64
46
  end
65
47
  end
66
48
  end
@@ -68,39 +50,29 @@ end
68
50
  module ActionView
69
51
  module Helpers #:nodoc:
70
52
  module AssetTagHelper
71
- def image_tag(source, options = {})
72
- options.symbolize_keys!
73
-
53
+ alias_method :ia_original_path_to_image, :path_to_image
54
+ def path_to_image(source)
74
55
  @part_container ||= @controller
75
-
76
56
  if @part_container.is_a?(ActionMailer::Base) or @part_container.is_a?(ActionMailer::Part)
77
- file_path = "#{RAILS_ROOT}/public#{image_path(source).split('?').first}"
78
- basename = File.basename(file_path)
79
- ext = basename.split('.').last
80
- cid = Time.now.to_f.to_s + "#{basename}@inline_attachment"
81
- file = File.open(file_path, 'rb')
82
-
83
- @part_container.inline_attachment(:content_type => "image/#{ext}",
84
- :body => file.read,
85
- :filename => basename,
86
- :cid => "<#{cid}>",
87
- :disposition => "inline")
88
-
89
- options[:src] = "cid:#{cid}"
90
- options[:alt] = basename.split('.').first.capitalize
91
- else
92
- options[:src] = image_path(source)
93
- options[:alt] ||= File.basename(options[:src], '.*').split('.').first.capitalize
94
- end
95
-
96
- if options[:size]
97
- options[:width], options[:height] = options[:size].split("x") if options[:size] =~ %r{^\d+x\d+$}
98
- options.delete(:size)
99
- end
57
+ file_path = "#{RAILS_ROOT}/public#{ia_original_path_to_image(source).split('?').first}"
58
+
59
+ if File.exists?(file_path)
60
+ basename = File.basename(file_path)
61
+ ext = basename.split('.').last
62
+ cid = Time.now.to_f.to_s + "#{basename}@inline_attachment"
63
+ file = File.open(file_path, 'rb')
100
64
 
101
- tag("img", options)
65
+ @part_container.inline_attachment(:content_type => "image/#{ext}",
66
+ :body => file.read,
67
+ :filename => basename,
68
+ :cid => "<#{cid}>",
69
+ :disposition => "inline")
70
+
71
+ return "cid:#{cid}"
72
+ end
73
+ end
74
+ return ia_original_path_to_image(source)
102
75
  end
103
76
  end
104
77
  end
105
78
  end
106
-
metadata CHANGED
@@ -1,16 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: JasonKing-inline_attachment
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.7
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason King
8
- - Edmond Leung
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
11
 
13
- date: 2009-01-31 00:00:00 -08:00
12
+ date: 2009-02-01 00:00:00 -08:00
14
13
  default_executable:
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency