dball-mail 2.2.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/CHANGELOG.rdoc +459 -0
  2. data/README.rdoc +582 -0
  3. data/Rakefile +66 -0
  4. data/TODO.rdoc +9 -0
  5. data/lib/VERSION +4 -0
  6. data/lib/mail/attachments_list.rb +105 -0
  7. data/lib/mail/body.rb +286 -0
  8. data/lib/mail/configuration.rb +71 -0
  9. data/lib/mail/core_extensions/nil.rb +11 -0
  10. data/lib/mail/core_extensions/string.rb +27 -0
  11. data/lib/mail/elements/address.rb +306 -0
  12. data/lib/mail/elements/address_list.rb +74 -0
  13. data/lib/mail/elements/content_disposition_element.rb +30 -0
  14. data/lib/mail/elements/content_location_element.rb +25 -0
  15. data/lib/mail/elements/content_transfer_encoding_element.rb +24 -0
  16. data/lib/mail/elements/content_type_element.rb +35 -0
  17. data/lib/mail/elements/date_time_element.rb +26 -0
  18. data/lib/mail/elements/envelope_from_element.rb +34 -0
  19. data/lib/mail/elements/message_ids_element.rb +29 -0
  20. data/lib/mail/elements/mime_version_element.rb +26 -0
  21. data/lib/mail/elements/phrase_list.rb +21 -0
  22. data/lib/mail/elements/received_element.rb +30 -0
  23. data/lib/mail/elements.rb +14 -0
  24. data/lib/mail/encodings/7bit.rb +31 -0
  25. data/lib/mail/encodings/8bit.rb +31 -0
  26. data/lib/mail/encodings/base64.rb +33 -0
  27. data/lib/mail/encodings/binary.rb +31 -0
  28. data/lib/mail/encodings/quoted_printable.rb +38 -0
  29. data/lib/mail/encodings/transfer_encoding.rb +58 -0
  30. data/lib/mail/encodings.rb +268 -0
  31. data/lib/mail/envelope.rb +35 -0
  32. data/lib/mail/field.rb +223 -0
  33. data/lib/mail/field_list.rb +33 -0
  34. data/lib/mail/fields/bcc_field.rb +56 -0
  35. data/lib/mail/fields/cc_field.rb +55 -0
  36. data/lib/mail/fields/comments_field.rb +41 -0
  37. data/lib/mail/fields/common/address_container.rb +16 -0
  38. data/lib/mail/fields/common/common_address.rb +125 -0
  39. data/lib/mail/fields/common/common_date.rb +42 -0
  40. data/lib/mail/fields/common/common_field.rb +50 -0
  41. data/lib/mail/fields/common/common_message_id.rb +44 -0
  42. data/lib/mail/fields/common/parameter_hash.rb +58 -0
  43. data/lib/mail/fields/content_description_field.rb +19 -0
  44. data/lib/mail/fields/content_disposition_field.rb +69 -0
  45. data/lib/mail/fields/content_id_field.rb +63 -0
  46. data/lib/mail/fields/content_location_field.rb +42 -0
  47. data/lib/mail/fields/content_transfer_encoding_field.rb +50 -0
  48. data/lib/mail/fields/content_type_field.rb +198 -0
  49. data/lib/mail/fields/date_field.rb +55 -0
  50. data/lib/mail/fields/from_field.rb +55 -0
  51. data/lib/mail/fields/in_reply_to_field.rb +55 -0
  52. data/lib/mail/fields/keywords_field.rb +44 -0
  53. data/lib/mail/fields/message_id_field.rb +83 -0
  54. data/lib/mail/fields/mime_version_field.rb +53 -0
  55. data/lib/mail/fields/optional_field.rb +13 -0
  56. data/lib/mail/fields/received_field.rb +67 -0
  57. data/lib/mail/fields/references_field.rb +55 -0
  58. data/lib/mail/fields/reply_to_field.rb +55 -0
  59. data/lib/mail/fields/resent_bcc_field.rb +55 -0
  60. data/lib/mail/fields/resent_cc_field.rb +55 -0
  61. data/lib/mail/fields/resent_date_field.rb +35 -0
  62. data/lib/mail/fields/resent_from_field.rb +55 -0
  63. data/lib/mail/fields/resent_message_id_field.rb +34 -0
  64. data/lib/mail/fields/resent_sender_field.rb +62 -0
  65. data/lib/mail/fields/resent_to_field.rb +55 -0
  66. data/lib/mail/fields/return_path_field.rb +64 -0
  67. data/lib/mail/fields/sender_field.rb +67 -0
  68. data/lib/mail/fields/structured_field.rb +51 -0
  69. data/lib/mail/fields/subject_field.rb +16 -0
  70. data/lib/mail/fields/to_field.rb +55 -0
  71. data/lib/mail/fields/unstructured_field.rb +179 -0
  72. data/lib/mail/fields.rb +35 -0
  73. data/lib/mail/header.rb +264 -0
  74. data/lib/mail/mail.rb +255 -0
  75. data/lib/mail/message.rb +1972 -0
  76. data/lib/mail/network/delivery_methods/file_delivery.rb +40 -0
  77. data/lib/mail/network/delivery_methods/sendmail.rb +62 -0
  78. data/lib/mail/network/delivery_methods/smtp.rb +136 -0
  79. data/lib/mail/network/delivery_methods/test_mailer.rb +40 -0
  80. data/lib/mail/network/retriever_methods/imap.rb +213 -0
  81. data/lib/mail/network/retriever_methods/pop3.rb +194 -0
  82. data/lib/mail/network/retriever_methods/test_retriever.rb +31 -0
  83. data/lib/mail/network.rb +10 -0
  84. data/lib/mail/parsers/address_lists.rb +64 -0
  85. data/lib/mail/parsers/address_lists.treetop +19 -0
  86. data/lib/mail/parsers/content_disposition.rb +535 -0
  87. data/lib/mail/parsers/content_disposition.treetop +46 -0
  88. data/lib/mail/parsers/content_location.rb +139 -0
  89. data/lib/mail/parsers/content_location.treetop +20 -0
  90. data/lib/mail/parsers/content_transfer_encoding.rb +162 -0
  91. data/lib/mail/parsers/content_transfer_encoding.treetop +20 -0
  92. data/lib/mail/parsers/content_type.rb +967 -0
  93. data/lib/mail/parsers/content_type.treetop +68 -0
  94. data/lib/mail/parsers/date_time.rb +114 -0
  95. data/lib/mail/parsers/date_time.treetop +11 -0
  96. data/lib/mail/parsers/envelope_from.rb +194 -0
  97. data/lib/mail/parsers/envelope_from.treetop +32 -0
  98. data/lib/mail/parsers/message_ids.rb +45 -0
  99. data/lib/mail/parsers/message_ids.treetop +15 -0
  100. data/lib/mail/parsers/mime_version.rb +144 -0
  101. data/lib/mail/parsers/mime_version.treetop +19 -0
  102. data/lib/mail/parsers/phrase_lists.rb +45 -0
  103. data/lib/mail/parsers/phrase_lists.treetop +15 -0
  104. data/lib/mail/parsers/received.rb +71 -0
  105. data/lib/mail/parsers/received.treetop +11 -0
  106. data/lib/mail/parsers/rfc2045.rb +464 -0
  107. data/lib/mail/parsers/rfc2045.treetop +36 -0
  108. data/lib/mail/parsers/rfc2822.rb +5318 -0
  109. data/lib/mail/parsers/rfc2822.treetop +410 -0
  110. data/lib/mail/parsers/rfc2822_obsolete.rb +3757 -0
  111. data/lib/mail/parsers/rfc2822_obsolete.treetop +241 -0
  112. data/lib/mail/part.rb +116 -0
  113. data/lib/mail/parts_list.rb +43 -0
  114. data/lib/mail/patterns.rb +34 -0
  115. data/lib/mail/utilities.rb +211 -0
  116. data/lib/mail/version.rb +24 -0
  117. data/lib/mail/version_specific/ruby_1_8.rb +97 -0
  118. data/lib/mail/version_specific/ruby_1_9.rb +87 -0
  119. data/lib/mail.rb +80 -0
  120. data/lib/tasks/corpus.rake +125 -0
  121. data/lib/tasks/treetop.rake +10 -0
  122. metadata +255 -0
data/README.rdoc ADDED
@@ -0,0 +1,582 @@
1
+ = Mail
2
+
3
+ == Introduction
4
+
5
+ Mail is an internet library for Ruby that is designed to handle emails
6
+ generation, parsing and sending in a simple, rubyesque manner.
7
+
8
+ The purpose of this library is to provide a single point of access to handle
9
+ all email functions, including sending and receiving emails. All network
10
+ type actions are done through proxy methods to Net::SMTP, Net::POP3 etc.
11
+
12
+ Built from my experience with TMail, it is designed to be a pure ruby
13
+ implementation that makes generating, sending and parsing emails a no
14
+ brainer.
15
+
16
+ It is also designed form the ground up to work with Ruby 1.9. This is because
17
+ Ruby 1.9 handles text encodings much more magically than Ruby 1.8.x and so
18
+ these features have been taken full advantage of in this library allowing
19
+ Mail to handle a lot more messages more cleanly than TMail. Mail does run on
20
+ Ruby 1.8.x... it's just not as fun to code.
21
+
22
+ Finally, Mail has been designed with a very simple object oriented system
23
+ that really opens up the email messages you are parsing, if you know what
24
+ you are doing, you can fiddle with every last bit of your email directly.
25
+
26
+ == Compatibility
27
+
28
+ Mail is tested and works on the following platforms:
29
+
30
+ * jruby-1.4.0 [ [x86_64-java] ]
31
+ * ree-1.8.7-2010.01 [ x86_64 ]
32
+ * ruby-1.8.6-p399 [ x86_64 ]
33
+ * ruby-1.8.7-p249 [ x86_64 ]
34
+ * ruby-1.9.1-head [ x86_64 ] (10 April 2010)
35
+ * ruby-1.9.2-head [ x86_64 ] (10 April 2010)
36
+
37
+ Mail seems to work fine on JRuby as well, however there is some weird QP
38
+ problem that only shows up while running the specs, running it directly
39
+ works fine.... weird. Any jRuby gurus who want to help out, please do.
40
+
41
+ == Discussion
42
+
43
+ If you want to discuss mail with like minded individuals, please subscribe to
44
+ the Google Group http://groups.google.com/group/mail-ruby
45
+
46
+ == Current Capabilities of Mail
47
+
48
+ * RFC2822 Support, Reading and Writing
49
+ * RFC2045-2049 Support for multipart emails
50
+ * Support for creating multipart alternate emails
51
+ * Support for reading multipart/report emails & getting details from such
52
+ * Support for multibyte emails - needs quite a lot of work and testing
53
+ * Wrappers for File, Net/POP3, Net/SMTP
54
+ * Auto encoding of non US-ASCII header fields
55
+ * Auto encoding of non US-ASCII bodies
56
+
57
+ Mail is RFC2822 compliant now, that is, it can parse and generate valid US-ASCII
58
+ emails. There are a few obsoleted syntax emails that it will have problems with, but
59
+ it also is quite robust, meaning, if it finds something it doesn't understand it will
60
+ not crash, instead, it will skip the problem and keep parsing. In the case of a header
61
+ it doesn't understand, it will initialise the header as an optional unstructured
62
+ field and continue parsing.
63
+
64
+ This means Mail won't (ever) crunch your data (I think).
65
+
66
+ You can also create MIME emails. There are helper methods for making a
67
+ multipart/alternate email for text/plain and text/html (the most common pair)
68
+ and you can manually create any other type of MIME email.
69
+
70
+ == Roadmap
71
+
72
+ Next TODO:
73
+
74
+ * Improve MIME support for character sets in headers, currently works, mostly, needs
75
+ refinement.
76
+ * Add IMAP wrapper
77
+
78
+ == Testing Policy
79
+
80
+ Basically... we do BDD on Mail. No method gets written in Mail without a
81
+ corresponding or covering spec. We expect as a minimum 100% coverage
82
+ measured by RCov. While this is not perfect by any measure, it is pretty
83
+ good. Additionally, all functional tests from TMail are to be passing before
84
+ the gem gets released.
85
+
86
+ It also means you can be sure Mail will behave correctly.
87
+
88
+ == API Policy
89
+
90
+ No API removals within a single point release. All removals to be depreciated with
91
+ warnings for at least one MINOR point release before removal.
92
+
93
+ Also, all private or protected methods to be declared as such - though this is still I/P.
94
+
95
+ == Installation
96
+
97
+ Installation is fairly simple, I host mail on gemcutter, so you can just do:
98
+
99
+ # gem install mail
100
+
101
+ if you are on gemcutter, if you aren't, you can by doing:
102
+
103
+ # gem install gemcutter
104
+ # gem tumble
105
+ # gem install mail
106
+
107
+ Warning though, the above will change your first gem repository to gemcutter, this
108
+ may or may not be a problem for you.
109
+
110
+ If you want to install mail manually, you can download the gem from github and do:
111
+
112
+ # gem install mail-2.2.0.gem
113
+
114
+ == Encodings
115
+
116
+ If you didn't know, handling encodings in Emails is not as straight forward as you
117
+ would hope.
118
+
119
+ I have tried to simplify it some:
120
+
121
+ 1. All objects that can render into an email, have an :encoded method. Encoded will
122
+ return the object as a complete string ready to send in the mail system, that is,
123
+ it will include the header field and value and CRLF at the end and wrapped as
124
+ needed.
125
+
126
+ 2. All objects that can render into an email, have a :decoded method. Decoded will
127
+ return the object's "value" only as a string. This means it will not include
128
+ the header fields (like 'To:' or 'Subject:').
129
+
130
+ 3. By default, calling :to_s on a container object will call it's encoded method, while
131
+ :to_s on a field object will call it's decoded method. So calling :to_s on a Mail
132
+ object will return the mail, all encoded ready to send, while calling :to_s on the
133
+ From field or the body will return the decoded value of the object. The header object
134
+ of Mail is considered a container. If you are in doubt, call :encoded, or :decoded
135
+ explicitly, this is safer if you are not sure.
136
+
137
+ 4. Structured fields that have parameter values that can be encoded (e.g. Content-Type) will
138
+ provide decoded parameter values when you call the parameter names as methods against
139
+ the object.
140
+
141
+ 5. Structured fields that have parameter values that can be encoded (e.g. Content-Type) will
142
+ provide encoded parameter values when you call the parameter names through the
143
+ object.parameters['<parameter_name>'] method call.
144
+
145
+ == Contributing
146
+
147
+ Please do! Contributing is easy in Mail:
148
+
149
+ 1. Check the Reference RFCs, they are in the References directory, so no excuses.
150
+ 2. Open a ticket on github, maybe someone else has the problem too
151
+ 3. Make a fork of my github repository
152
+ 4. Make a spec driven change to the code base
153
+ 5. Make sure it works and all specs pass, on Ruby versions 1.8.6, 1.8.7 and 1.9
154
+ 6. Update the README if needed to reflect your change / addition
155
+ 7. With all specs passing push your changes back to your fork
156
+ 8. Send me a pull request
157
+
158
+ == Usage
159
+
160
+ All major mail functions should be able to happen from the Mail::module.
161
+ So, you should be able to just "require 'mail'" to get started.
162
+
163
+ === Making an email
164
+
165
+ require 'mail'
166
+
167
+ mail = Mail.new do
168
+ from 'mikel@test.lindsaar.net'
169
+ to 'you@test.lindsaar.net'
170
+ subject 'This is a test email'
171
+ body File.read('body.txt')
172
+ end
173
+
174
+ mail.to_s #=> "From: mikel@test.lindsaar.net\r\nTo: you@...
175
+
176
+ === Making an email, have it your way:
177
+
178
+ require 'mail'
179
+
180
+ mail = Mail.new do
181
+ body File.read('body.txt')
182
+ end
183
+
184
+ mail['from'] = 'mikel@test.lindsaar.net'
185
+ mail[:to] = 'you@test.lindsaar.net'
186
+ mail.subject = 'This is a test email'
187
+
188
+ mail.to_s #=> "From: mikel@test.lindsaar.net\r\nTo: you@...
189
+
190
+ === Don't Worry About Message IDs:
191
+
192
+ require 'mail'
193
+
194
+ mail = Mail.new do
195
+ to 'you@test.lindsaar.net'
196
+ body 'Some simple body'
197
+ end
198
+
199
+ mail.to_s =~ /Message\-ID: <[\d\w_]+@.+.mail/ #=> 27
200
+
201
+ Mail will automatically add a Message-ID field if it is missing and
202
+ give it a unique, random Message-ID along the lines of:
203
+
204
+ <4a7ff76d7016_13a81ab802e1@local.fqdn.mail>
205
+
206
+ === Or do worry about Message-IDs:
207
+
208
+ require 'mail'
209
+
210
+ mail = Mail.new do
211
+ to 'you@test.lindsaar.net'
212
+ message_id '<ThisIsMyMessageId@some.domain.com>'
213
+ body 'Some simple body'
214
+ end
215
+
216
+ mail.to_s =~ /Message\-ID: <ThisIsMyMessageId@some.domain.com>/ #=> 27
217
+
218
+ Mail will take the message_id you assign to it trusting that you know
219
+ what you are doing.
220
+
221
+ === Sending an email:
222
+
223
+ Mail defaults to sending via SMTP to local host port 25. If you have a
224
+ sendmail or postfix daemon running on on this port, sending email is as
225
+ easy as:
226
+
227
+ Mail.deliver do
228
+ from 'me@test.lindsaar.net'
229
+ to 'you@test.lindsaar.net'
230
+ subject 'Here is the image you wanted'
231
+ body File.read('body.txt')
232
+ add_file '/full/path/to/somefile.png'
233
+ end
234
+
235
+ or
236
+
237
+ mail = Mail.new do
238
+ from 'me@test.lindsaar.net'
239
+ to 'you@test.lindsaar.net'
240
+ subject 'Here is the image you wanted'
241
+ body File.read('body.txt')
242
+ add_file {:filename => 'somefile.png', :content => File.read('/somefile.png')}
243
+ end
244
+
245
+ mail.deliver!
246
+
247
+ Sending via sendmail can be done like so:
248
+
249
+ mail = Mail.new do
250
+ from 'me@test.lindsaar.net'
251
+ to 'you@test.lindsaar.net'
252
+ subject 'Here is the image you wanted'
253
+ body File.read('body.txt')
254
+ add_file {:filename => 'somefile.png', :content => File.read('/somefile.png')}
255
+ end
256
+
257
+ mail.delivery_method :sendmail
258
+
259
+ mail.deliver
260
+
261
+ {Learn more about SMTP Delivery}[link:classes/Mail/SMTP.html]
262
+
263
+ {Learn more about File Delivery}[link:classes/Mail/FileDelivery.html]
264
+
265
+ {Learn more about Sendmail Delivery}[link:classes/Mail/Sendmail.html]
266
+
267
+ {Learn more about Test Email Delivery}[link:classes/Mail/TestMailer.html]
268
+
269
+ === Getting emails from a pop server:
270
+
271
+ The most recent email:
272
+
273
+ Mail.defaults do
274
+ retriever_method :pop3, { :address => "pop.gmail.com",
275
+ :port => 995,
276
+ :user_name => '<username>',
277
+ :password => '<password>',
278
+ :enable_ssl => true }
279
+ end
280
+
281
+ Mail.all #=> Returns an array of all emails
282
+ Mail.first #=> Returns the first unread email
283
+ Mail.last #=> Returns the first unread email
284
+
285
+ The first 10 emails sorted by date in ascending order:
286
+
287
+ require 'mail'
288
+
289
+ Mail.defaults do
290
+ retriever_method :pop3, { :address => "pop.gmail.com",
291
+ :port => 995,
292
+ :user_name => '<username>',
293
+ :password => '<password>',
294
+ :enable_ssl => true }
295
+ end
296
+
297
+ emails = Mail.find(:what => :first, :count => 10, :order => :asc)
298
+ emails.length #=> 10
299
+
300
+ Or even all emails:
301
+
302
+ Mail.defaults do
303
+ retriever_method :pop3, { :address => "pop.gmail.com",
304
+ :port => 995,
305
+ :user_name => '<username>',
306
+ :password => '<password>',
307
+ :enable_ssl => true }
308
+ end
309
+
310
+ emails = Mail.all
311
+
312
+ emails.length #=> LOTS!
313
+
314
+ {Learn more about POP3}[link:classes/Mail/POP3.html]
315
+
316
+ {Learn more about IMAP}[link:classes/Mail/IMAP.html]
317
+
318
+ === Reading an Email
319
+
320
+ require 'mail'
321
+
322
+ mail = Mail.read('/path/to/message.eml')
323
+
324
+ mail.envelope.from #=> 'mikel@test.lindsaar.net'
325
+ mail.from.addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
326
+ mail.sender.address #=> 'mikel@test.lindsaar.net'
327
+ mail.to #=> 'bob@test.lindsaar.net'
328
+ mail.cc #=> 'sam@test.lindsaar.net'
329
+ mail.subject #=> "This is the subject"
330
+ mail.date.to_s #=> '21 Nov 1997 09:55:06 -0600'
331
+ mail.message_id #=> '<4D6AA7EB.6490534@xxx.xxx>'
332
+ mail.body.decoded #=> 'This is the body of the email...
333
+
334
+ Many more methods available.
335
+
336
+ === Reading a Multipart Email
337
+
338
+ require 'mail'
339
+
340
+ mail = Mail.read('multipart_email')
341
+
342
+ mail.multipart? #=> true
343
+ mail.parts.length #=> 2
344
+ mail.preamble #=> "Text before the first part"
345
+ mail.epilogue #=> "Text after the last part"
346
+ mail.parts.map { |p| p.content_type } #=> ['text/plain', 'application/pdf']
347
+ mail.parts.map { |p| p.class } #=> [Mail::Message, Mail::Message]
348
+ mail.parts[0].content_type_parameters #=> {'charset' => 'ISO-8859-1'}
349
+ mail.parts[1].content_type_parameters #=> {'name' => 'my.pdf'}
350
+
351
+ Mail generates a tree of parts. Each message has many or no parts. Each part
352
+ is another message which can have many or no parts.
353
+
354
+ A message will only have parts if it is a multipart/mixed or related/mixed
355
+ content type and has a boundary defined.
356
+
357
+ === Writing and sending a multipart/alternative (html and text) email
358
+
359
+ Mail makes some basic assumptions and makes doing the common thing as
360
+ simple as possible.... (asking a lot from a mail library)
361
+
362
+ require 'mail'
363
+
364
+ mail = Mail.deliver do
365
+ to 'nicolas@test.lindsaar.net.au'
366
+ from 'Mikel Lindsaar <mikel@test.lindsaar.net.au>'
367
+ subject 'First multipart email sent with Mail'
368
+ text_part do
369
+ body 'This is plain text'
370
+ end
371
+ html_part do
372
+ content_type 'text/html; charset=UTF-8'
373
+ body '<h1>This is HTML</h1>'
374
+ end
375
+ end
376
+
377
+ Mail then delivers the email at the end of the block and returns the
378
+ resulting Mail::Message object, which you can then inspect if you
379
+ so desire...
380
+
381
+ puts mail.to_s #=>
382
+
383
+ To: nicolas@test.lindsaar.net.au
384
+ From: Mikel Lindsaar <mikel@test.lindsaar.net.au>
385
+ Subject: First multipart email sent with Mail
386
+ Content-Type: multipart/alternative;
387
+ boundary=--==_mimepart_4a914f0c911be_6f0f1ab8026659
388
+ Message-ID: <4a914f12ac7e_6f0f1ab80267d1@baci.local.mail>
389
+ Date: Mon, 24 Aug 2009 00:15:46 +1000
390
+ Mime-Version: 1.0
391
+ Content-Transfer-Encoding: 7bit
392
+
393
+
394
+ ----==_mimepart_4a914f0c911be_6f0f1ab8026659
395
+ Content-ID: <4a914f12c8c4_6f0f1ab80268d6@baci.local.mail>
396
+ Date: Mon, 24 Aug 2009 00:15:46 +1000
397
+ Mime-Version: 1.0
398
+ Content-Type: text/plain
399
+ Content-Transfer-Encoding: 7bit
400
+
401
+ This is plain text
402
+ ----==_mimepart_4a914f0c911be_6f0f1ab8026659
403
+ Content-Type: text/html; charset=UTF-8
404
+ Content-ID: <4a914f12cf86_6f0f1ab802692c@baci.local.mail>
405
+ Date: Mon, 24 Aug 2009 00:15:46 +1000
406
+ Mime-Version: 1.0
407
+ Content-Transfer-Encoding: 7bit
408
+
409
+ <h1>This is HTML</h1>
410
+ ----==_mimepart_4a914f0c911be_6f0f1ab8026659--
411
+
412
+ Mail inserts the content transfer encoding, the mime version,
413
+ the content-id's and handles the content-type and boundary.
414
+
415
+ Mail assumes that if your text in the body is only us-ascii, that your
416
+ transfer encoding is 7bit and it is text/plain. You can override this
417
+ by explicitly declaring it.
418
+
419
+ === Making Multipart/Alternate, without a block
420
+
421
+ You don't have to use a block with the text and html part included, you
422
+ can just do it declaratively. However, you need to add Mail::Parts to
423
+ an email, not Mail::Messages.
424
+
425
+ require 'mail'
426
+
427
+ mail = Mail.new do
428
+ to 'nicolas@test.lindsaar.net.au'
429
+ from 'Mikel Lindsaar <mikel@test.lindsaar.net.au>'
430
+ subject 'First multipart email sent with Mail'
431
+ end
432
+
433
+ text_part = Mail::Part.new do
434
+ body 'This is plain text'
435
+ end
436
+
437
+ html_part = Mail::Part.new do
438
+ content_type 'text/html; charset=UTF-8'
439
+ body '<h1>This is HTML</h1>'
440
+ end
441
+
442
+ mail.text_part = text_part
443
+ mail.html_part = html_part
444
+
445
+ Results in the same email as done using the block form
446
+
447
+ === Getting error reports from an email:
448
+
449
+ require 'mail'
450
+
451
+ @mail = Mail.read('/path/to/bounce_message.eml')
452
+
453
+ @mail.bounced? #=> true
454
+ @mail.final_recipient #=> rfc822;mikel@dont.exist.com
455
+ @mail.action #=> failed
456
+ @mail.error_status #=> 5.5.0
457
+ @mail.diagnostic_code #=> smtp;550 Requested action not taken: mailbox unavailable
458
+ @mail.retryable? #=> false
459
+
460
+ === Attaching and Detaching Files
461
+
462
+ require 'mail'
463
+
464
+ You can just read the file off an absolute path, Mail will try
465
+ to guess the mime_type and will encode the file in Base64 for you.
466
+
467
+ @mail = Mail.new
468
+ @mail.add_file("/path/to/file.jpg")
469
+ @mail.parts.first.attachment? #=> true
470
+ @mail.parts.first.content_transfer_encoding.to_s #=> 'base64'
471
+ @mail.attachments.first.mime_type #=> 'image/jpg'
472
+ @mail.attachments.first.filename #=> 'file.jpg'
473
+ @mail.attachments.first.decoded == File.read('/path/to/file.jpg') #=> true
474
+
475
+ Or You can pass in file_data and give it a filename, again, mail
476
+ will try and guess the mime_type for you.
477
+
478
+ @mail = Mail.new
479
+ @mail.attachments['myfile.pdf'] = File.read('path/to/myfile.pdf')
480
+ @mail.parts.first.attachment? #=> true
481
+ @mail.attachments.first.mime_type #=> 'application/pdf'
482
+ @mail.attachments.first.decoded == File.read('path/to/myfile.pdf') #=> true
483
+
484
+ You can also override the guessed MIME media type if you really know better
485
+ than mail (this should be rarely needed)
486
+
487
+ @mail = Mail.new
488
+ file_data = File.read('path/to/myfile.pdf')
489
+ @mail.attachments['myfile.pdf'] = { :mime_type => 'application/x-pdf',
490
+ :content => File.read('path/to/myfile.pdf') }
491
+ @mail.parts.first.mime_type #=> 'application/x-pdf'
492
+
493
+ Of course... Mail will round trip an attachment as well
494
+
495
+ @mail = Mail.new do
496
+ to 'nicolas@test.lindsaar.net.au'
497
+ from 'Mikel Lindsaar <mikel@test.lindsaar.net.au>'
498
+ subject 'First multipart email sent with Mail'
499
+ text_part do
500
+ body 'Here is the attachment you wanted'
501
+ end
502
+ html_part do
503
+ content_type 'text/html; charset=UTF-8'
504
+ body '<h1>Funky Title</h1><p>Here is the attachment you wanted</p>'
505
+ end
506
+ add_file '/path/to/myfile.pdf'
507
+ end
508
+
509
+ @round_tripped_mail = Mail.new(@mail.encoded)
510
+
511
+ @round_tripped_mail.attachments.length #=> 1
512
+ @round_tripped_mail.attachments.first.filename #=> 'myfile.pdf'
513
+
514
+ == Using Mail with Testing or Spec'ing Libraries
515
+
516
+ If mail is part of your system, you'll need a way to test it without actually
517
+ sending emails, the TestMailer can do this for you.
518
+
519
+ require 'mail'
520
+ => true
521
+ Mail.defaults do
522
+ delivery_method :test
523
+ end
524
+ => #<Mail::Configuration:0x19345a8 @delivery_method=Mail::TestMailer>
525
+ Mail::TestMailer.deliveries
526
+ => []
527
+ Mail.deliver do
528
+ to 'mikel@me.com'
529
+ from 'you@you.com'
530
+ subject 'testing'
531
+ body 'hello'
532
+ end
533
+ => #<Mail::Message:0x19284ec ...
534
+ Mail::TestMailer.deliveries.length
535
+ => 1
536
+ Mail::TestMailer.deliveries.first
537
+ => #<Mail::Message:0x19284ec ...
538
+ Mail::TestMailer.deliveries.clear
539
+ => []
540
+
541
+ == Excerpts from TREC Spam Corpus 2005
542
+
543
+ The spec fixture files in spec/fixtures/emails/from_trec_2005 are from the
544
+ 2005 TREC Public Spam Corpus. They remain copyrighted under the terms of
545
+ that project and license agreement. They are used in this project to verify
546
+ and describe the development of this email parser implementation.
547
+
548
+ http://plg.uwaterloo.ca/~gvcormac/treccorpus/
549
+
550
+ They are used as allowed by 'Permitted Uses, Clause 3':
551
+
552
+ "Small excerpts of the information may be displayed to others
553
+ or published in a scientific or technical context, solely for
554
+ the purpose of describing the research and development and
555
+ related issues."
556
+
557
+ -- http://plg.uwaterloo.ca/~gvcormac/treccorpus/
558
+
559
+ == License:
560
+
561
+ (The MIT License)
562
+
563
+ Copyright (c) 2009
564
+
565
+ Permission is hereby granted, free of charge, to any person obtaining
566
+ a copy of this software and associated documentation files (the
567
+ 'Software'), to deal in the Software without restriction, including
568
+ without limitation the rights to use, copy, modify, merge, publish,
569
+ distribute, sublicense, and/or sell copies of the Software, and to
570
+ permit persons to whom the Software is furnished to do so, subject to
571
+ the following conditions:
572
+
573
+ The above copyright notice and this permission notice shall be
574
+ included in all copies or substantial portions of the Software.
575
+
576
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
577
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
578
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
579
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
580
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
581
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
582
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,66 @@
1
+ begin
2
+ require "rubygems"
3
+ require "bundler"
4
+ rescue LoadError
5
+ raise "Could not load the bundler gem. Install it with `gem install bundler`."
6
+ end
7
+
8
+ if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("1.0.0")
9
+ raise RuntimeError, "Your bundler version is too old for Mail" +
10
+ "Run `gem install bundler` to upgrade."
11
+ end
12
+
13
+ begin
14
+ # Set up load paths for all bundled gems
15
+ ENV["BUNDLE_GEMFILE"] = File.expand_path("../Gemfile", __FILE__)
16
+ Bundler.setup
17
+ rescue Bundler::GemNotFound
18
+ raise RuntimeError, "Bundler couldn't find some gems." +
19
+ "Did you run `bundle install`?"
20
+ end
21
+
22
+ require File.expand_path('../spec/environment', __FILE__)
23
+
24
+ require 'rake/rdoctask'
25
+ require 'rake/testtask'
26
+ require 'spec/rake/spectask'
27
+
28
+ desc "Build a gem file"
29
+ task :build do
30
+ system "gem build mail.gemspec"
31
+ end
32
+
33
+ task :default => :spec
34
+
35
+ Spec::Rake::SpecTask.new(:rcov) do |t|
36
+ t.spec_files = FileList['test/**/tc_*.rb', 'spec/**/*_spec.rb']
37
+ t.rcov = true
38
+ t.rcov_opts = t.rcov_opts << ['--exclude', '/Library,/opt,/System,/usr']
39
+ end
40
+
41
+ Spec::Rake::SpecTask.new(:spec) do |t|
42
+ t.warning = true
43
+ t.spec_files = FileList["#{File.dirname(__FILE__)}/spec/**/*_spec.rb"]
44
+ t.spec_opts = %w(--backtrace --diff --color)
45
+ t.libs << "#{File.dirname(__FILE__)}/spec"
46
+ t.libs << "#{File.dirname(__FILE__)}/spec/mail"
47
+ end
48
+
49
+ Rake::RDocTask.new(:rdoc) do |rdoc|
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = 'Mail - A Ruby Mail Library'
52
+
53
+ rdoc.options << '-c' << 'utf-8'
54
+ rdoc.options << '--line-numbers'
55
+ rdoc.options << '--inline-source'
56
+ rdoc.options << '-m' << 'README.rdoc'
57
+
58
+ rdoc.rdoc_files.include('README.rdoc')
59
+ rdoc.rdoc_files.include('lib/**/*.rb')
60
+ rdoc.rdoc_files.include('lib/network/**/*.rb')
61
+ rdoc.rdoc_files.exclude('lib/parsers/*')
62
+
63
+ end
64
+
65
+ # load custom rake tasks
66
+ Dir["#{File.dirname(__FILE__)}/lib/tasks/**/*.rake"].sort.each { |ext| load ext }
data/TODO.rdoc ADDED
@@ -0,0 +1,9 @@
1
+ == Not really in any order:
2
+
3
+ * Add multibyte handling to fields, if they get a multibyte string, try encoding it into
4
+ UTF-8 B first, if this fails, throw an error.
5
+
6
+ * Cleanup the treetop parsers......... do I _really_ need that many entrance files?
7
+
8
+ * Simplify the relationship of Headers and Fields. Doing too much of the Field work
9
+ in the Header class on instantiating fields. Header should just say "Field, do it!"
data/lib/VERSION ADDED
@@ -0,0 +1,4 @@
1
+ patch:9
2
+ major:2
3
+ build:
4
+ minor:2