ruby-gmail 0.0.8 → 0.0.9

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/History.txt CHANGED
@@ -1,4 +1,10 @@
1
- === 0.0.8 / 2009/12-23
1
+ === 0.0.9 / 2010-04-17
2
+
3
+ * 1 bugfix
4
+
5
+ * Fixed content-transfer-encoding when sending email
6
+
7
+ === 0.0.8 / 2009-12-23
2
8
 
3
9
  * 1 bugfix
4
10
 
data/Manifest.txt CHANGED
@@ -6,6 +6,7 @@ lib/gmail.rb
6
6
  lib/ietf/rfc2045.rb
7
7
  lib/ietf/rfc822.rb
8
8
  lib/mime/entity.rb
9
+ lib/mime/entity_tmail.rb
9
10
  lib/mime/message.rb
10
11
  lib/smtp_tls.rb
11
12
  Manifest.txt
data/README.markdown CHANGED
@@ -12,7 +12,8 @@ Extra thanks for specific feature contributions from:
12
12
 
13
13
  * [Justin Perkins](http://github.com/justinperkins)
14
14
  * [Mikkel Malmberg](http://github.com/mikker)
15
-
15
+ * [Julien Blanchard](http://github.com/julienXX)
16
+ * [Federico Galassi](http://github.com/fgalassi)
16
17
 
17
18
  ## Description
18
19
 
@@ -74,11 +75,11 @@ A Rubyesque interface to Gmail, with all the tools you'll need. Search, read and
74
75
  * ruby
75
76
  * net/smtp
76
77
  * net/imap
77
- * shared-mime-info rubygem
78
+ * shared-mime-info rubygem (for MIME-detection when attaching files)
78
79
 
79
80
  ## Install
80
81
 
81
- sudo gem install ruby-gmail -s http://gemcutter.org
82
+ gem install ruby-gmail
82
83
 
83
84
  ## License
84
85
 
data/Rakefile CHANGED
@@ -10,3 +10,21 @@ Hoe.spec 'ruby-gmail' do
10
10
  self.url = "http://dcparker.github.com/ruby-gmail"
11
11
  self.post_install_message = "\n\033[34mIf ruby-gmail saves you TWO hours of work, want to compensate me for, like, a half-hour?\nSupport me in making new and better gems:\033[0m \033[31;4mhttp://pledgie.com/campaigns/7087\033[0m\n\n"
12
12
  end
13
+
14
+ begin
15
+ require 'jeweler'
16
+ Jeweler::Tasks.new do |gem|
17
+ gem.name = "ruby-gmail"
18
+ gem.summary = %Q{A Rubyesque interface to Gmail, with all the tools you'll need.}
19
+ gem.description = %Q{A Rubyesque interface to Gmail, with all the tools you'll need. Search, read and send multipart emails; archive, mark as read/unread, delete emails; and manage labels.}
20
+ gem.email = "gems@behindlogic.com"
21
+ gem.homepage = "http://dcparker.github.com/ruby-gmail"
22
+ gem.authors = ["BehindLogic"]
23
+ gem.post_install_message = "\n\033[34mIf ruby-gmail saves you TWO hours of work, want to compensate me for, like, a half-hour?\nSupport me in making new and better gems:\033[0m \033[31;4mhttp://pledgie.com/campaigns/7087\033[0m\n\n"
24
+ gem.add_dependency('shared-mime-info', '>= 0')
25
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
26
+ end
27
+ Jeweler::GemcutterTasks.new
28
+ rescue LoadError
29
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
30
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.9
data/lib/gmail.rb CHANGED
@@ -3,7 +3,7 @@ require 'net/smtp'
3
3
  require 'smtp_tls'
4
4
 
5
5
  class Gmail
6
- VERSION = '0.0.8'
6
+ VERSION = '0.0.9'
7
7
 
8
8
  class NoLabel < RuntimeError; end
9
9
 
@@ -53,6 +53,14 @@ class Gmail
53
53
  imap.create(name)
54
54
  end
55
55
 
56
+ # List the available labels
57
+ def labels
58
+ (@imap.list("", "%") + @imap.list("[Gmail]/", "%")).inject([]) do |lables,label|
59
+ label[:name].each_line { |l| labels << l }
60
+ labels
61
+ end
62
+ end
63
+
56
64
  def in_mailbox(mailbox, &block)
57
65
  raise ArgumentError, "Must provide a code block" unless block_given?
58
66
  mailbox_stack << mailbox
@@ -80,7 +88,7 @@ class Gmail
80
88
  block.call(lambda {|to, body|
81
89
  from = meta.username
82
90
  puts "Sending from #{from} to #{to}:\n#{body}"
83
- smtp.send_message(body, from, to)
91
+ smtp.send_message(body.to_s, from, to)
84
92
  })
85
93
  puts "SMTP closing."
86
94
  end
data/lib/ietf/rfc2045.rb CHANGED
@@ -4,7 +4,7 @@ module IETF
4
4
  def self.parse_rfc2045_from(raw)
5
5
  headers, raw = IETF::RFC822.parse_rfc822_from(raw)
6
6
 
7
- if headers['content-type'] =~ /multipart\/(\w+); boundary=([\"\']?)(.*)\2?/
7
+ if headers['content-type'] =~ /multipart\/(\w+); boundary=([\"\'])(.*)\2/ || headers['content-type'] =~ /multipart\/(\w+); boundary(=)(.*)$/
8
8
  content = {}
9
9
  content[:type] = $1
10
10
  content[:boundary] = $3
data/lib/mime/entity.rb CHANGED
@@ -11,11 +11,11 @@ module MIME
11
11
  end
12
12
  class Entity
13
13
  def initialize(one=nil,two=nil)
14
- if one.is_a?(Hash) || two.is_a?(Hash)
14
+ if one.is_a?(Hash) || two.is_a?(Hash) # Intent is to generate a message from parameters
15
15
  @headers = one.is_a?(Hash) ? one : two
16
16
  set_content one if one.is_a?(String)
17
17
  @encoding = 'quoted-printable' unless encoding
18
- elsif one.is_a?(String)
18
+ elsif one.is_a?(String) # Intent is to parse a message body
19
19
  @raw = one.gsub(/\r/,'').gsub(/\n/, "\r\n") # normalizes end-of-line characters
20
20
  from_parsed(IETF::RFC2045.parse_rfc2045_from(@raw))
21
21
  end
@@ -150,7 +150,7 @@ module MIME
150
150
  # Renders this data structure into a string, encoded
151
151
  def to_s
152
152
  multipart_boundary # initialize the boundary if necessary
153
- headers.inject('') {|a,(k,v)| a << "#{MIME.capitalize_header(k)}: #{v}\r\n"} + "\r\n" + if content.is_a?(Array)
153
+ {'charset' => 'utf-8', 'content-transfer-encoding' => @encoding}.merge(headers).inject('') {|a,(k,v)| a << "#{MIME.capitalize_header(k)}: #{v}\r\n"} + "\r\n" + if content.is_a?(Array)
154
154
  "\r\n--#{multipart_boundary}\r\n" + content.collect {|part| part.to_s }.join("\r\n--#{multipart_boundary}\r\n") + "\r\n--#{multipart_boundary}--\r\n"
155
155
  else
156
156
  content.to_s
@@ -0,0 +1,217 @@
1
+ require 'tmail'
2
+ require 'ietf/rfc2045'
3
+ String::ALPHANUMERIC_CHARACTERS = ('a'..'z').to_a + ('A'..'Z').to_a unless defined? String::ALPHANUMERIC_CHARACTERS
4
+ def String.random(size)
5
+ length = String::ALPHANUMERIC_CHARACTERS.length
6
+ (0...size).collect { String::ALPHANUMERIC_CHARACTERS[Kernel.rand(length)] }.join
7
+ end
8
+
9
+ module MIME
10
+ def self.capitalize_header(header_name)
11
+ header_name.gsub(/^(\w)/) {|m| m.capitalize}.gsub(/-(\w)/) {|n| '-' + n[1].chr.capitalize}
12
+ end
13
+ class Entity
14
+ def initialize(one=nil,two=nil)
15
+ if one.is_a?(Hash) || two.is_a?(Hash) # Intent is to generate a message from parameters
16
+ @headers = one.is_a?(Hash) ? one : two
17
+ set_content one if one.is_a?(String)
18
+ @encoding = 'quoted-printable' unless encoding
19
+ elsif one.is_a?(String) # Intent is to parse a message body
20
+ @raw = one.gsub(/\r/,'').gsub(/\n/, "\r\n") # normalizes end-of-line characters
21
+ @tmail = TMail::Mail.parse(@raw)
22
+ from_tmail(@tmail)
23
+ elsif one.is_a?(TMail::Mail)
24
+ @tmail = one
25
+ from_tmail(@tmail)
26
+ end
27
+ end
28
+
29
+ def inspect
30
+ "<#{self.class.name}##{object_id} Headers:{#{headers.collect {|k,v| "#{k}=#{v}"}.join(' ')}} content:#{multipart? ? 'multipart' : 'flat'}>"
31
+ end
32
+
33
+ # This means we have a structure from IETF::RFC2045.
34
+ # Entity is: [headers, content], while content may be an array of Entities.
35
+ # Or, {:type, :boundary, :content}
36
+ def from_parsed(parsed)
37
+ case parsed
38
+ when Array
39
+ if parsed[0].is_a?(Hash) && (parsed[1].is_a?(Hash) || parsed[1].is_a?(String))
40
+ @headers = parsed[0]
41
+ @content = parsed[1].is_a?(Hash) ? parsed[1][:content].collect {|p| Entity.new.from_parsed(p)} : parsed[1]
42
+ if parsed[1].is_a?(Hash)
43
+ @multipart_type = parsed[1][:type]
44
+ @multipart_boundary = parsed[1][:boundary]
45
+ raise "IETF PARSING FAIL! (empty boundary)" if @multipart_boundary == ''
46
+ end
47
+ else
48
+ raise "IETF PARSING FAIL! ('A' structure)"
49
+ end
50
+ return self
51
+ when Hash
52
+ if parsed.has_key?(:type) && parsed.has_key?(:boundary) && parsed.has_key?(:content)
53
+ @content = parsed[:content].is_a?(Array) ? parsed[:content].collect {|p| Entity.new.from_parsed(p)} : parsed[:content]
54
+ else
55
+ raise "IETF PARSING FAIL! ('H' structure)"
56
+ end
57
+ return self
58
+ end
59
+ raise ArgumentError, "Must pass in either: [an array with two elements: headers(hash) and content(string or array)] OR [a hash containing :type, :boundary, and :content(being the former or a string)]"
60
+ end
61
+ def from_tmail(tmail)
62
+ raise ArgumentError, "Expecting a TMail::Mail object." unless tmail.is_a?(TMail::Mail)
63
+ @headers ||= Hash.new {|h,k| @tmail.header[k].to_s }
64
+ if multipart?
65
+ @content = @tmail.parts.collect { |tpart| Entity.new.from_tmail(tpart) }
66
+ else
67
+ set_content @tmail.body # TMail has already decoded it, but we need it still encoded
68
+ end
69
+ end
70
+
71
+ ##############
72
+ # ATTRIBUTES #
73
+
74
+ # An Entity has Headers.
75
+ def headers
76
+ @headers ||= {}
77
+ end
78
+ # An Entity has Content.
79
+ # IF the Content-Type is a multipart type,
80
+ # the content will be one or more Entities.
81
+ attr_reader :content, :multipart_type
82
+
83
+ #################
84
+ # Macro Methods #
85
+
86
+ def multipart?
87
+ return @tmail.multipart? if @tmail
88
+ !!(headers['content-type'] =~ /multipart\//) if headers['content-type']
89
+ end
90
+ def multipart_type
91
+ if headers['content-type'] =~ /multipart\/(\w+)/
92
+ $1
93
+ end if headers['content-type']
94
+ end
95
+ # Auto-generates a boundary if one doesn't yet exist.
96
+ def multipart_boundary
97
+ return nil unless multipart?
98
+ unless @multipart_boundary ||= (@tmail && @tmail.header['content-type'] ? @tmail.header['content-type'].params['boundary'] : nil)
99
+ # Content-Type: multipart/mixed; boundary=000e0cd28d1282f4ba04788017e5
100
+ @multipart_boundary = String.random(25)
101
+ headers['content-type'] = "multipart/#{multipart_type}; boundary=#{@multipart_boundary}"
102
+ @multipart_boundary
103
+ end
104
+ @multipart_boundary
105
+ end
106
+ def attachment?
107
+ @tmail.disposition_is_attachment? || headers['content-disposition'] =~ /^form-data;.* filename=[\"\']?[^\"\']+[\"\']?/ if headers['content-disposition']
108
+ end
109
+ alias :file? :attachment?
110
+ def part_filename
111
+ # Content-Disposition: attachment; filename="summary.txt"
112
+ if headers['content-disposition'] =~ /; filename=[\"\']?([^\"\']+)/
113
+ $1
114
+ end if headers['content-disposition']
115
+ end
116
+
117
+ def encoding
118
+ @encoding ||= headers['content-transfer-encoding'] || nil
119
+ end
120
+ # Re-encodes content if necessary when a new encoding is set
121
+ def encoding=(new_encoding)
122
+ raw_content = decoded_content # nil if multipart
123
+ @encoding = new_encoding
124
+ set_content(raw_content) if raw_content # skips if multipart
125
+ @encoding
126
+ end
127
+ alias :set_encoding :encoding=
128
+
129
+ def find_part(options)
130
+ find_parts(options,true).first
131
+ end
132
+ def find_parts(options,find_only_one=false)
133
+ parts = []
134
+ return nil unless (options[:content_type] && headers['content-type']) || (options[:content_disposition] && headers['content-disposition'])
135
+ # Do I match your search?
136
+ iam = true
137
+ iam = false if options[:content_type] && headers['content-type'] !~ /^#{options[:content_type]}(?=;|$)/
138
+ iam = false if options[:content_disposition] && headers['content-disposition'] !~ /^#{options[:content_disposition]}(?=;|$)/
139
+ parts << self if iam
140
+ return parts unless parts.empty?
141
+ # Do any of my children match your search?
142
+ content.each do |part|
143
+ parts.concat part.find_parts(options,find_only_one)
144
+ return parts if !parts.empty? && find_only_one
145
+ end if multipart?
146
+ return parts
147
+ end
148
+
149
+ def save_to_file(path=nil)
150
+ filename = path if path && !File.exists?(path) # If path doesn't exist, assume it's a filename
151
+ filename ||= path + '/' + part_filename if path && attachment? # If path does exist, and we're saving an attachment, use the attachment filename
152
+ filename ||= (attachment? ? part_filename : path) # If there is no path and we're saving an attachment, use the attachment filename; otherwise use path (whether it is present or not)
153
+ filename ||= '.' # No path supplied, and not saving an attachment. We'll just save it in the current directory.
154
+ if File.directory?(filename)
155
+ i = 0
156
+ begin
157
+ i += 1
158
+ filename = filename + "/attachment-#{i}"
159
+ end until !File.exists(filename)
160
+ end
161
+ # After all that trouble to get a filename to save to...
162
+ File.open(filename, 'w') do |file|
163
+ file << decoded_content
164
+ end
165
+ end
166
+
167
+ ##########################
168
+ # CONVERTING / RENDERING #
169
+
170
+ # Renders this data structure into a string, encoded
171
+ def to_s
172
+ multipart_boundary # initialize the boundary if necessary, so it will be included in the headers
173
+ headers.inject('') {|a,(k,v)| a << "#{MIME.capitalize_header(k)}: #{v}\r\n"} + "\r\n" + if content.is_a?(Array)
174
+ "\r\n--#{multipart_boundary}\r\n" + content.collect {|part| part.to_s }.join("\r\n--#{multipart_boundary}\r\n") + "\r\n--#{multipart_boundary}--\r\n"
175
+ else
176
+ content.to_s
177
+ end
178
+ end
179
+
180
+ # Converts this data structure into a string, but decoded if necessary
181
+ def decoded_content
182
+ return nil if @content.is_a?(Array)
183
+ case encoding.to_s.downcase
184
+ when 'quoted-printable'
185
+ @content.unpack('M')[0]
186
+ when 'base64'
187
+ @content.unpack('m')[0]
188
+ # when '7bit'
189
+ # # should get this 7bit encoding done too...
190
+ else
191
+ @content
192
+ end
193
+ end
194
+
195
+ # You can set new content, and it will be saved in encoded form.
196
+ def set_content(raw)
197
+ @content = raw.is_a?(Array) ? raw :
198
+ case encoding.to_s.downcase
199
+ when 'quoted-printable'
200
+ [raw].pack('M')
201
+ when 'base64'
202
+ [raw].pack('m')
203
+ else
204
+ raw
205
+ end
206
+ end
207
+ alias :content= :set_content
208
+
209
+ private
210
+ def transfer_to(other)
211
+ other.instance_variable_set(:@content, @content.dup) if @content
212
+ other.headers.clear
213
+ other.headers.merge!(Hash[*headers.dup.select {|k,v| k =~ /content/}.flatten])
214
+ end
215
+
216
+ end
217
+ end
data/lib/mime/message.rb CHANGED
@@ -1,5 +1,4 @@
1
- require 'mime/entity'
2
- require 'shared-mime-info'
1
+ require 'mime/entity_tmail'
3
2
  module MIME
4
3
  # A Message is really a MIME::Entity,
5
4
  # but should be used for the outermost Entity, because
@@ -52,6 +51,7 @@ module MIME
52
51
  short_filename = filename.match(/([^\\\/]+)$/)[1]
53
52
 
54
53
  # Generate the attachment piece
54
+ require 'shared-mime-info'
55
55
  attachment = Entity.new(
56
56
  'content-type' => MIME.check(filename).type + "; \r\n name=\"#{short_filename}\"",
57
57
  'content-disposition' => "attachment; \r\n filename=\"#{short_filename}\"",
@@ -61,10 +61,10 @@ module MIME
61
61
 
62
62
  # Enclose in a top-level multipart/mixed
63
63
  if multipart? && multipart_type == 'mixed'
64
- # If already enclosed, all we have to do is add the attachment part
64
+ # If we're already dealing with a mixed multipart, all we have to do is add the attachment part
65
65
  (@content ||= []) << attachment
66
66
  else
67
- # If there is no content, add a little message about the attachment(s).
67
+ # If there is no content yet, add a little message about the attachment(s).
68
68
  set_content 'See attachment(s)' if @content.nil?
69
69
  # Generate the new top-level multipart, transferring what is here already into a child object
70
70
  new_content = Entity.new
@@ -72,7 +72,7 @@ module MIME
72
72
  transfer_to(new_content)
73
73
  headers.reject! {|k,v| k =~ /content/}
74
74
  headers['content-type'] = 'multipart/mixed'
75
- headers.delete 'content-transfer-encoding' # because now it's useless.
75
+ headers.delete 'content-transfer-encoding' # because we don't need a transfer-encoding on a multipart package.
76
76
  @content = [new_content, attachment]
77
77
  end
78
78
 
metadata CHANGED
@@ -1,82 +1,60 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-gmail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 9
9
+ version: 0.0.9
5
10
  platform: ruby
6
11
  authors:
7
- - Daniel Parker
12
+ - BehindLogic
8
13
  autorequire:
9
14
  bindir: bin
10
- cert_chain:
11
- - |
12
- -----BEGIN CERTIFICATE-----
13
- MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMQ0wCwYDVQQDDARnZW1z
14
- MRswGQYKCZImiZPyLGQBGRYLYmVoaW5kbG9naWMxEzARBgoJkiaJk/IsZAEZFgNj
15
- b20wHhcNMDkxMTE5MDQ0NzIzWhcNMTAxMTE5MDQ0NzIzWjBBMQ0wCwYDVQQDDARn
16
- ZW1zMRswGQYKCZImiZPyLGQBGRYLYmVoaW5kbG9naWMxEzARBgoJkiaJk/IsZAEZ
17
- FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDs+2PvSoBC5mCz
18
- Nm95RXKOb/u+CmPA70DoG9cF0zipCie003Vm0DYL3Rtobcr32eMvHxkWoJ6xoz0I
19
- h74yNKtHjTTCxj86HWBPsE6xVMxVCftClndjCyKsiMiqvvp1wDNO0FFK+6LijmL3
20
- 2Xkp4brWq1JO92y9vYct34R7o2X//+nwZs+sss+EYhNdvdUJfWy7tA5dghGdLvRn
21
- UhJJSAtTefkBCwO7bufLEt+n7wIRbiJJ5dDCwE3NIX4wUSrNeYwXGXA/Ybki+BUl
22
- 3KJF9IC0XR9fY9DGF0FXBKrkfDlZRrnQOem2aIxeuln0KQLJXXJuDTQPHO+mK3EG
23
- UPhR7IAHAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
24
- BBQn32ZStKmqwFqs2vuglYzkvDzBZjANBgkqhkiG9w0BAQUFAAOCAQEAe3Z+iMmy
25
- IX9ChQW4hNNb1HOpgCMc2RL+vUwku9WE95dZ+BE4A6mOYTj5JXdYf4R4Z2vavr+d
26
- nwJWtXPeIBWxireb8gUU0DwqodYTpsmkj5LD1zIaZ59rXlwDA9O0V4fwE1iRG5MD
27
- mB7m8fT8WNOeg4AfjH4aSiHI1+HX1RQkc7KFdLotKnCevzYU6Jza5VUbXyJ+yCEH
28
- DFARN3mkfGI+18MRDEi39nK2O/bBd6Wf0cYPEKsGQjNNAIBtv9belepSMd1KKfQ2
29
- L7j8CnNDCrsHDe7/251D85wSvTH4Q/41NE5ahdCkkHwzDJeyhXpmNuUSswdn7woz
30
- teST6sOe8lUhZQ==
31
- -----END CERTIFICATE-----
15
+ cert_chain: []
32
16
 
33
- date: 2009-12-23 00:00:00 -05:00
17
+ date: 2010-04-18 00:00:00 -04:00
34
18
  default_executable:
35
19
  dependencies:
36
20
  - !ruby/object:Gem::Dependency
37
21
  name: shared-mime-info
38
- type: :runtime
39
- version_requirement:
40
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
41
24
  requirements:
42
25
  - - ">="
43
26
  - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
44
29
  version: "0"
45
- version:
46
- - !ruby/object:Gem::Dependency
47
- name: hoe
48
- type: :development
49
- version_requirement:
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: 2.3.3
55
- version:
30
+ type: :runtime
31
+ version_requirements: *id001
56
32
  description: A Rubyesque interface to Gmail, with all the tools you'll need. Search, read and send multipart emails; archive, mark as read/unread, delete emails; and manage labels.
57
- email:
58
- - gems@behindlogic.com
33
+ email: gems@behindlogic.com
59
34
  executables: []
60
35
 
61
36
  extensions: []
62
37
 
63
38
  extra_rdoc_files:
64
- - History.txt
65
- - Manifest.txt
39
+ - README.markdown
66
40
  files:
67
41
  - .autotest
68
42
  - History.txt
43
+ - Manifest.txt
44
+ - README.markdown
45
+ - Rakefile
46
+ - VERSION
47
+ - lib/gmail.rb
69
48
  - lib/gmail/mailbox.rb
70
49
  - lib/gmail/message.rb
71
- - lib/gmail.rb
72
50
  - lib/ietf/rfc2045.rb
73
51
  - lib/ietf/rfc822.rb
74
52
  - lib/mime/entity.rb
53
+ - lib/mime/entity_tmail.rb
75
54
  - lib/mime/message.rb
76
55
  - lib/smtp_tls.rb
77
- - Manifest.txt
78
- - Rakefile
79
- - README.markdown
56
+ - test/test_gmail.rb
57
+ - test/test_helper.rb
80
58
  has_rdoc: true
81
59
  homepage: http://dcparker.github.com/ruby-gmail
82
60
  licenses: []
@@ -85,29 +63,30 @@ post_install_message: "\n\
85
63
  \e[34mIf ruby-gmail saves you TWO hours of work, want to compensate me for, like, a half-hour?\n\
86
64
  Support me in making new and better gems:\e[0m \e[31;4mhttp://pledgie.com/campaigns/7087\e[0m\n\n"
87
65
  rdoc_options:
88
- - --main
89
- - README.markdown
66
+ - --charset=UTF-8
90
67
  require_paths:
91
68
  - lib
92
69
  required_ruby_version: !ruby/object:Gem::Requirement
93
70
  requirements:
94
71
  - - ">="
95
72
  - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
96
75
  version: "0"
97
- version:
98
76
  required_rubygems_version: !ruby/object:Gem::Requirement
99
77
  requirements:
100
78
  - - ">="
101
79
  - !ruby/object:Gem::Version
80
+ segments:
81
+ - 0
102
82
  version: "0"
103
- version:
104
83
  requirements: []
105
84
 
106
- rubyforge_project: ruby-gmail
107
- rubygems_version: 1.3.5
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.6
108
87
  signing_key:
109
88
  specification_version: 3
110
- summary: A Rubyesque interface to Gmail, with all the tools you'll need
89
+ summary: A Rubyesque interface to Gmail, with all the tools you'll need.
111
90
  test_files:
112
91
  - test/test_gmail.rb
113
92
  - test/test_helper.rb
data.tar.gz.sig DELETED
@@ -1,2 +0,0 @@
1
- �j|,�r�%�B��ZC��B'�6,��r�g�V~�9ï�+�mcL���L��.�#�_�x.&�#LX��!�ȧi×T�_�e2������k�s��-[`�c���G���^J����y3EYY�<��^X q
2
- �?D
metadata.gz.sig DELETED
Binary file