JasonKing-InlineAttachment 0.3.3
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.
- data/README +79 -0
- data/lib/inline_attachment.rb +117 -0
- data/lib/tmail_content_id.rb +40 -0
- metadata +65 -0
data/README
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
= Inline Attachment
|
2
|
+
|
3
|
+
This package adds full support for embedding inline images into your HTML emails
|
4
|
+
through ActionMailer.
|
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
|
+
== Installation
|
11
|
+
|
12
|
+
To perform a system wide installation:
|
13
|
+
|
14
|
+
<tt>gem install inline_attachment</tt>
|
15
|
+
|
16
|
+
To use inline_attachment in your project, add the following line to your project's
|
17
|
+
config/environment.rb:
|
18
|
+
|
19
|
+
<tt>require 'inline_attachment'</tt>
|
20
|
+
|
21
|
+
|
22
|
+
== Usage
|
23
|
+
|
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
|
76
|
+
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.
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module ActionMailer
|
2
|
+
module PartContainer
|
3
|
+
# Add an inline attachment to a multipart message.
|
4
|
+
def inline_attachment(params, &block)
|
5
|
+
params = { :content_type => params } if String === params
|
6
|
+
params = { :disposition => "inline",
|
7
|
+
:transfer_encoding => "base64" }.merge(params)
|
8
|
+
params[:headers] ||= {}
|
9
|
+
params[:headers]['Content-ID'] = params[:cid]
|
10
|
+
part(params, &block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Part
|
15
|
+
def to_mail(defaults)
|
16
|
+
part = TMail::Mail.new
|
17
|
+
|
18
|
+
if @parts.empty?
|
19
|
+
part.content_transfer_encoding = transfer_encoding || "quoted-printable"
|
20
|
+
case (transfer_encoding || "").downcase
|
21
|
+
when "base64" then
|
22
|
+
part.body = TMail::Base64.folding_encode(body)
|
23
|
+
when "quoted-printable"
|
24
|
+
part.body = [Utils.normalize_new_lines(body)].pack("M*")
|
25
|
+
else
|
26
|
+
part.body = body
|
27
|
+
end
|
28
|
+
|
29
|
+
# Always set the content_type after setting the body and or parts
|
30
|
+
|
31
|
+
# CHANGE: treat attachments and inline files the same
|
32
|
+
if content_disposition == "attachment" || ((content_disposition == "inline") && filename)
|
33
|
+
part.set_content_type(content_type || defaults.content_type, nil,
|
34
|
+
squish("charset" => nil, "name" => filename))
|
35
|
+
else
|
36
|
+
part.set_content_type(content_type || defaults.content_type, nil,
|
37
|
+
"charset" => (charset || defaults.charset))
|
38
|
+
end
|
39
|
+
|
40
|
+
part.set_content_disposition(content_disposition, squish("filename" => filename)) unless content_disposition.blank?
|
41
|
+
headers.each {|k,v| part[k] = v }
|
42
|
+
# END CHANGE
|
43
|
+
|
44
|
+
else
|
45
|
+
if String === body
|
46
|
+
part = TMail::Mail.new
|
47
|
+
part.body = body
|
48
|
+
part.set_content_type content_type, nil, { "charset" => charset }
|
49
|
+
part.set_content_disposition "inline"
|
50
|
+
m.parts << part
|
51
|
+
end
|
52
|
+
|
53
|
+
@parts.each do |p|
|
54
|
+
prt = (TMail::Mail === p ? p : p.to_mail(defaults))
|
55
|
+
part.parts << prt
|
56
|
+
end
|
57
|
+
|
58
|
+
part.set_content_type(content_type, nil, { "charset" => charset }) if content_type =~ /multipart/
|
59
|
+
end
|
60
|
+
|
61
|
+
part
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
module ActionView
|
67
|
+
module Helpers #:nodoc:
|
68
|
+
module AssetTagHelper
|
69
|
+
def image_tag(source, options = {})
|
70
|
+
options.symbolize_keys!
|
71
|
+
|
72
|
+
@part_container ||= @controller
|
73
|
+
|
74
|
+
if @part_container.is_a?(ActionMailer::Base) or @part_container.is_a?(ActionMailer::Part)
|
75
|
+
file_path = "#{RAILS_ROOT}/public#{image_path(source).split('?').first}"
|
76
|
+
basename = File.basename(file_path, '.*')
|
77
|
+
ext = basename.split('.').last
|
78
|
+
cid = Time.now.to_f.to_s + "#{basename}@inline_attachment"
|
79
|
+
file = File.open(file_path, 'rb')
|
80
|
+
|
81
|
+
@part_container.inline_attachment(:content_type => "image/#{ext}",
|
82
|
+
:body => file.read,
|
83
|
+
:filename => basename,
|
84
|
+
:cid => "<#{cid}>",
|
85
|
+
:disposition => "inline")
|
86
|
+
|
87
|
+
options[:src] = "cid:#{cid}"
|
88
|
+
options[:alt] = basename.split('.').first.capitalize
|
89
|
+
else
|
90
|
+
options[:src] = image_path(source)
|
91
|
+
options[:alt] ||= File.basename(options[:src], '.*').split('.').first.capitalize
|
92
|
+
end
|
93
|
+
|
94
|
+
if options[:size]
|
95
|
+
options[:width], options[:height] = options[:size].split("x") if options[:size] =~ %r{^\d+x\d+$}
|
96
|
+
options.delete(:size)
|
97
|
+
end
|
98
|
+
|
99
|
+
tag("img", options)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class DummyClass
|
106
|
+
def relative_url_root
|
107
|
+
""
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
module ActionMailer #:nodoc:
|
112
|
+
class Base
|
113
|
+
def request
|
114
|
+
DummyClass.new
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module TMail
|
2
|
+
|
3
|
+
class HeaderField # redefine
|
4
|
+
|
5
|
+
FNAME_TO_CLASS = {
|
6
|
+
'date' => DateTimeHeader,
|
7
|
+
'resent-date' => DateTimeHeader,
|
8
|
+
'to' => AddressHeader,
|
9
|
+
'cc' => AddressHeader,
|
10
|
+
'bcc' => AddressHeader,
|
11
|
+
'from' => AddressHeader,
|
12
|
+
'reply-to' => AddressHeader,
|
13
|
+
'resent-to' => AddressHeader,
|
14
|
+
'resent-cc' => AddressHeader,
|
15
|
+
'resent-bcc' => AddressHeader,
|
16
|
+
'resent-from' => AddressHeader,
|
17
|
+
'resent-reply-to' => AddressHeader,
|
18
|
+
'sender' => SingleAddressHeader,
|
19
|
+
'resent-sender' => SingleAddressHeader,
|
20
|
+
'return-path' => ReturnPathHeader,
|
21
|
+
'message-id' => MessageIdHeader,
|
22
|
+
'resent-message-id' => MessageIdHeader,
|
23
|
+
'in-reply-to' => ReferencesHeader,
|
24
|
+
'received' => ReceivedHeader,
|
25
|
+
'references' => ReferencesHeader,
|
26
|
+
'keywords' => KeywordsHeader,
|
27
|
+
'encrypted' => EncryptedHeader,
|
28
|
+
'mime-version' => MimeVersionHeader,
|
29
|
+
'content-type' => ContentTypeHeader,
|
30
|
+
'content-transfer-encoding' => ContentTransferEncodingHeader,
|
31
|
+
'content-disposition' => ContentDispositionHeader,
|
32
|
+
# 'content-id' => MessageIdHeader,
|
33
|
+
'subject' => UnstructuredHeader,
|
34
|
+
'comments' => UnstructuredHeader,
|
35
|
+
'content-description' => UnstructuredHeader
|
36
|
+
}
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: JasonKing-InlineAttachment
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jason King
|
8
|
+
- Edmond Leung
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-01-31 00:00:00 -08:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: mime-types
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "1.15"
|
24
|
+
version:
|
25
|
+
description:
|
26
|
+
email: jk@handle.it
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files: []
|
32
|
+
|
33
|
+
files:
|
34
|
+
- README
|
35
|
+
- lib/inline_attachment.rb
|
36
|
+
- lib/tmail_content_id.rb
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: http://github.com/JasonKing/inline_attachment
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options:
|
41
|
+
- --inline-source
|
42
|
+
- --charset=UTF-8
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
version:
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 1.2.0
|
61
|
+
signing_key:
|
62
|
+
specification_version: 2
|
63
|
+
summary: Makes image_tag in an ActionMailer template embed the images in the emails
|
64
|
+
test_files: []
|
65
|
+
|