mail 2.5.2 → 2.6.4

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 (187) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.rdoc +124 -0
  3. data/CONTRIBUTING.md +21 -6
  4. data/Dependencies.txt +0 -1
  5. data/Gemfile +7 -22
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +86 -31
  8. data/Rakefile +11 -22
  9. data/lib/mail/attachments_list.rb +4 -2
  10. data/lib/mail/body.rb +36 -11
  11. data/lib/mail/check_delivery_params.rb +13 -22
  12. data/lib/mail/configuration.rb +1 -0
  13. data/lib/mail/{patterns.rb → constants.rb} +29 -6
  14. data/lib/mail/core_extensions/smtp.rb +13 -13
  15. data/lib/mail/core_extensions/string/access.rb +1 -0
  16. data/lib/mail/core_extensions/string/multibyte.rb +1 -0
  17. data/lib/mail/core_extensions/string.rb +5 -17
  18. data/lib/mail/elements/address.rb +86 -145
  19. data/lib/mail/elements/address_list.rb +10 -42
  20. data/lib/mail/elements/content_disposition_element.rb +4 -7
  21. data/lib/mail/elements/content_location_element.rb +8 -11
  22. data/lib/mail/elements/content_transfer_encoding_element.rb +4 -10
  23. data/lib/mail/elements/content_type_element.rb +5 -8
  24. data/lib/mail/elements/date_time_element.rb +4 -7
  25. data/lib/mail/elements/envelope_from_element.rb +19 -13
  26. data/lib/mail/elements/message_ids_element.rb +8 -11
  27. data/lib/mail/elements/mime_version_element.rb +4 -7
  28. data/lib/mail/elements/phrase_list.rb +3 -7
  29. data/lib/mail/elements/received_element.rb +4 -7
  30. data/lib/mail/elements.rb +1 -0
  31. data/lib/mail/encodings/7bit.rb +1 -0
  32. data/lib/mail/encodings/8bit.rb +8 -2
  33. data/lib/mail/encodings/base64.rb +7 -1
  34. data/lib/mail/encodings/binary.rb +1 -0
  35. data/lib/mail/encodings/quoted_printable.rb +11 -4
  36. data/lib/mail/encodings/transfer_encoding.rb +27 -17
  37. data/lib/mail/encodings/unix_to_unix.rb +18 -0
  38. data/lib/mail/encodings.rb +54 -39
  39. data/lib/mail/envelope.rb +1 -5
  40. data/lib/mail/field.rb +81 -31
  41. data/lib/mail/field_list.rb +19 -18
  42. data/lib/mail/fields/bcc_field.rb +17 -5
  43. data/lib/mail/fields/cc_field.rb +3 -3
  44. data/lib/mail/fields/comments_field.rb +2 -1
  45. data/lib/mail/fields/common/address_container.rb +1 -0
  46. data/lib/mail/fields/common/common_address.rb +34 -28
  47. data/lib/mail/fields/common/common_date.rb +2 -8
  48. data/lib/mail/fields/common/common_field.rb +9 -5
  49. data/lib/mail/fields/common/common_message_id.rb +3 -2
  50. data/lib/mail/fields/common/parameter_hash.rb +4 -3
  51. data/lib/mail/fields/content_description_field.rb +1 -0
  52. data/lib/mail/fields/content_disposition_field.rb +13 -12
  53. data/lib/mail/fields/content_id_field.rb +4 -4
  54. data/lib/mail/fields/content_location_field.rb +2 -1
  55. data/lib/mail/fields/content_transfer_encoding_field.rb +4 -9
  56. data/lib/mail/fields/content_type_field.rb +4 -3
  57. data/lib/mail/fields/date_field.rb +16 -15
  58. data/lib/mail/fields/from_field.rb +3 -3
  59. data/lib/mail/fields/in_reply_to_field.rb +3 -1
  60. data/lib/mail/fields/keywords_field.rb +2 -2
  61. data/lib/mail/fields/message_id_field.rb +4 -4
  62. data/lib/mail/fields/mime_version_field.rb +3 -2
  63. data/lib/mail/fields/optional_field.rb +1 -0
  64. data/lib/mail/fields/received_field.rb +4 -3
  65. data/lib/mail/fields/references_field.rb +3 -1
  66. data/lib/mail/fields/reply_to_field.rb +3 -3
  67. data/lib/mail/fields/resent_bcc_field.rb +3 -3
  68. data/lib/mail/fields/resent_cc_field.rb +3 -3
  69. data/lib/mail/fields/resent_date_field.rb +2 -1
  70. data/lib/mail/fields/resent_from_field.rb +3 -3
  71. data/lib/mail/fields/resent_message_id_field.rb +1 -0
  72. data/lib/mail/fields/resent_sender_field.rb +4 -4
  73. data/lib/mail/fields/resent_to_field.rb +3 -3
  74. data/lib/mail/fields/return_path_field.rb +1 -1
  75. data/lib/mail/fields/sender_field.rb +9 -9
  76. data/lib/mail/fields/structured_field.rb +1 -0
  77. data/lib/mail/fields/subject_field.rb +1 -0
  78. data/lib/mail/fields/to_field.rb +3 -3
  79. data/lib/mail/fields/unstructured_field.rb +15 -8
  80. data/lib/mail/fields.rb +1 -0
  81. data/lib/mail/header.rb +21 -29
  82. data/lib/mail/indifferent_hash.rb +1 -0
  83. data/lib/mail/mail.rb +16 -1
  84. data/lib/mail/matchers/attachment_matchers.rb +29 -0
  85. data/lib/mail/matchers/has_sent_mail.rb +61 -4
  86. data/lib/mail/message.rb +175 -72
  87. data/lib/mail/multibyte/chars.rb +3 -2
  88. data/lib/mail/multibyte/exceptions.rb +1 -0
  89. data/lib/mail/multibyte/unicode.rb +22 -15
  90. data/lib/mail/multibyte/utils.rb +1 -0
  91. data/lib/mail/multibyte.rb +1 -0
  92. data/lib/mail/network/delivery_methods/exim.rb +3 -7
  93. data/lib/mail/network/delivery_methods/file_delivery.rb +2 -1
  94. data/lib/mail/network/delivery_methods/sendmail.rb +33 -10
  95. data/lib/mail/network/delivery_methods/smtp.rb +32 -34
  96. data/lib/mail/network/delivery_methods/smtp_connection.rb +7 -6
  97. data/lib/mail/network/delivery_methods/test_mailer.rb +3 -2
  98. data/lib/mail/network/retriever_methods/base.rb +1 -0
  99. data/lib/mail/network/retriever_methods/imap.rb +19 -13
  100. data/lib/mail/network/retriever_methods/pop3.rb +1 -0
  101. data/lib/mail/network/retriever_methods/test_retriever.rb +1 -0
  102. data/lib/mail/network.rb +1 -0
  103. data/lib/mail/parsers/address_lists_parser.rb +133 -0
  104. data/lib/mail/parsers/content_disposition_parser.rb +68 -0
  105. data/lib/mail/parsers/content_location_parser.rb +36 -0
  106. data/lib/mail/parsers/content_transfer_encoding_parser.rb +34 -0
  107. data/lib/mail/parsers/content_type_parser.rb +67 -0
  108. data/lib/mail/parsers/date_time_parser.rb +39 -0
  109. data/lib/mail/parsers/envelope_from_parser.rb +46 -0
  110. data/lib/mail/parsers/message_ids_parser.rb +40 -0
  111. data/lib/mail/parsers/mime_version_parser.rb +42 -0
  112. data/lib/mail/parsers/phrase_lists_parser.rb +36 -0
  113. data/lib/mail/parsers/ragel/common.rl +185 -0
  114. data/lib/mail/parsers/ragel/date_time.rl +30 -0
  115. data/lib/mail/parsers/ragel/parser_info.rb +61 -0
  116. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +14864 -0
  117. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +37 -0
  118. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +751 -0
  119. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +37 -0
  120. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +614 -0
  121. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +37 -0
  122. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +447 -0
  123. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +37 -0
  124. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +825 -0
  125. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +37 -0
  126. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +817 -0
  127. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +37 -0
  128. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +2149 -0
  129. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +37 -0
  130. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +1570 -0
  131. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +37 -0
  132. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +440 -0
  133. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +37 -0
  134. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +564 -0
  135. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +37 -0
  136. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +51 -0
  137. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +5144 -0
  138. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +37 -0
  139. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +37 -0
  140. data/lib/mail/parsers/ragel/ruby.rb +40 -0
  141. data/lib/mail/parsers/ragel.rb +18 -0
  142. data/lib/mail/parsers/received_parser.rb +49 -0
  143. data/lib/mail/parsers.rb +27 -0
  144. data/lib/mail/part.rb +11 -4
  145. data/lib/mail/parts_list.rb +30 -10
  146. data/lib/mail/utilities.rb +127 -63
  147. data/lib/mail/values/unicode_tables.dat +0 -0
  148. data/lib/mail/version.rb +8 -15
  149. data/lib/mail/version_specific/ruby_1_8.rb +18 -7
  150. data/lib/mail/version_specific/ruby_1_9.rb +136 -32
  151. data/lib/mail.rb +12 -6
  152. metadata +115 -77
  153. data/lib/VERSION +0 -4
  154. data/lib/load_parsers.rb +0 -41
  155. data/lib/mail/core_extensions/nil.rb +0 -19
  156. data/lib/mail/core_extensions/object.rb +0 -13
  157. data/lib/mail/core_extensions/shell_escape.rb +0 -56
  158. data/lib/mail/parsers/address_lists.rb +0 -64
  159. data/lib/mail/parsers/address_lists.treetop +0 -19
  160. data/lib/mail/parsers/content_disposition.rb +0 -535
  161. data/lib/mail/parsers/content_disposition.treetop +0 -46
  162. data/lib/mail/parsers/content_location.rb +0 -139
  163. data/lib/mail/parsers/content_location.treetop +0 -20
  164. data/lib/mail/parsers/content_transfer_encoding.rb +0 -162
  165. data/lib/mail/parsers/content_transfer_encoding.treetop +0 -20
  166. data/lib/mail/parsers/content_type.rb +0 -967
  167. data/lib/mail/parsers/content_type.treetop +0 -68
  168. data/lib/mail/parsers/date_time.rb +0 -114
  169. data/lib/mail/parsers/date_time.treetop +0 -11
  170. data/lib/mail/parsers/envelope_from.rb +0 -194
  171. data/lib/mail/parsers/envelope_from.treetop +0 -32
  172. data/lib/mail/parsers/message_ids.rb +0 -45
  173. data/lib/mail/parsers/message_ids.treetop +0 -15
  174. data/lib/mail/parsers/mime_version.rb +0 -144
  175. data/lib/mail/parsers/mime_version.treetop +0 -19
  176. data/lib/mail/parsers/phrase_lists.rb +0 -45
  177. data/lib/mail/parsers/phrase_lists.treetop +0 -15
  178. data/lib/mail/parsers/received.rb +0 -71
  179. data/lib/mail/parsers/received.treetop +0 -11
  180. data/lib/mail/parsers/rfc2045.rb +0 -464
  181. data/lib/mail/parsers/rfc2045.treetop +0 -36
  182. data/lib/mail/parsers/rfc2822.rb +0 -5397
  183. data/lib/mail/parsers/rfc2822.treetop +0 -410
  184. data/lib/mail/parsers/rfc2822_obsolete.rb +0 -3768
  185. data/lib/mail/parsers/rfc2822_obsolete.treetop +0 -241
  186. data/lib/tasks/corpus.rake +0 -125
  187. data/lib/tasks/treetop.rake +0 -10
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f91f133d2e44832ecef1cb4bfe9cc57391aedf84
4
+ data.tar.gz: 23d0cdbc09cdbaafee76b01d7c3820a6c0dfb6d1
5
+ SHA512:
6
+ metadata.gz: c788407da309561bee6a59ec746efeea7c0cc8633206eb2085f08ad6b161df92475109a988de748e554248d2ca47e6cd31c3fd0394d0eddac5950e7bb28783a8
7
+ data.tar.gz: 55b70f9d539420d254373c7abfccf6bc85228f34c38696086be363a36fb4f966415238aaa8e9ec9e6eed02207af2a3940b9f85c5f3076e735cd19e095764abc2
data/CHANGELOG.rdoc CHANGED
@@ -1,5 +1,129 @@
1
1
  == HEAD
2
2
 
3
+ == Version 2.6.4 - Wed Mar 23 08:16 -0700 2016 Jeremy Daer <jeremydaer@gmail.com>
4
+
5
+ Features:
6
+ * #772 - Normalize encoding matchers (grosser)
7
+ * #775 - Avoid failed encodings / stop bad charsets early (grosser)
8
+ * #782 – Make the gem compatible with Rubinius (robin850)
9
+ * #865 - Allow a body with an invalid encoding to be round tripped (kjg)
10
+ * #866 - Support decoding message bodies with non-Ruby-standard charsets (jeremy)
11
+ * #868 - Use the Ruby19.charset_encoder when decoding message bodies (kjg)
12
+ * #872 - Low-level option to include BCC field in the encoded message (grossadamm)
13
+ * #901 - Allow mail.text_part = '…' and mail.html_part = '<p>…</p>' (taavo)
14
+ * #924 - Matcher for having attachments (schepedw)
15
+
16
+ Performance:
17
+ * #956 - Use native String#encode for CR/LF conversion (carsonreinke)
18
+ * #970 - Support Ruby 2.3+ frozen string literals (twalpole)
19
+
20
+ Bugs:
21
+ * #719 - Fix to not extract header content that looks like its field name (kjg)
22
+ * #789 - Fix encoding collapsing not dealing with multiple encodings in 1 line (grosser)
23
+ * #808 - Mail::Field correctly responds_to? the methods of its instantiated field (thegcat)
24
+ * #849 - Handle calling Part#inline? when the Content-Disposition field couldn't be parsed (kjg)
25
+ * #874 – Stay under 1000-char SMTP line length limits (pushrax)
26
+ * #877 - Make Mail::Field == other take the field value into account (kjg)
27
+ * #907 - Mail::ContentDispositionField should work with nil value (kjg)
28
+ * #910 - Mail::Address should handle b_value_encoded local and domain parts (kjg)
29
+ * #918 - Account for possibility of absent delivery-status headers (kjg)
30
+
31
+ == Version 2.6.3 - Mon Nov 3 23:53 +1100 2014 Mikel Lindsaar <mikel@reinteractive.net>
32
+
33
+ * #796 support uu encoding (grosser)
34
+
35
+ == Version 2.6.2 (Unreleased) - Wed Oct 22 13:42 -0500 2014 Benjamin Fleischer <github@benjaminfleischer.com>
36
+
37
+ Performance:
38
+ * #681 - fewer hotspot object allocations (srawlins)
39
+ * #815 - autoload parsers for load-time speed and memory usage (grosser)
40
+
41
+ Bugs:
42
+ * #736 - Mail.new copes with non-UTF8 messages marked as UTF8 (jeremy)
43
+
44
+ == Version 2.6.1 - Sun Jun 8 15:34 +1100 2014 Mikel Lindsaar <mikel@reinteractive.net>
45
+
46
+ Features:
47
+ * Silence warnings on loading ragel-generated parsers (bf4)
48
+
49
+ == Version 2.6.0 - Mon Jun 2 22:49 +1100 2014 Mikel Lindsaar <mikel@reinteractive.net>
50
+
51
+ Features:
52
+ * Allow interceptors and observers to be unregistered (zuhao)
53
+ * Added feature to find the mail in uid (taketin)
54
+ * Save settings passed to TestMailer#new (svanderbleek)
55
+ * Allow the setting of envelope from directly (jeremy)
56
+ * Accept other IETF/IANA-registered Content-Types and Content-Transfer-Encodings (jeremy)
57
+ * Alias shift-jis charset to Shift_JIS Ruby encoding (jeremy)
58
+ * Add support for ks_c_5601-1987 charset, aliased to CP949 Ruby encoding (jeremy)
59
+ * Don't allow colons in header names (jeremy)
60
+ * Can assign arrays of Message-IDs to References and In-Reply-To (jeremy)
61
+ * Setting the html_ or text_part sets a default text/html or text/plain content type (jeremy)
62
+ * Setting the html_ or text_part to nil removes it (jeremy)
63
+ * Addresses without a parsable email or display name still format as their raw text (jeremy)
64
+ * Close pull request 504 - Alias GB2312 charset to GB18030 Ruby encoding (bpot)
65
+ * Close pull request 399 - Accept :ca_path and :ca_file options for SMTP delivery (ndbroadbent)
66
+ * Close pull request 389 - Don't add superfluous message headers to MIME parts (djmaze, jeremy)
67
+
68
+ Performance:
69
+ * Migrate to RAGEL based parser, awesome work by (bpot)
70
+ * Performance improvements for people parsing email headers (ConradIrwin)
71
+ * Close pull request 488 - Speed up field construction & comparison (bpot)
72
+
73
+ Bugs:
74
+ * Fix for when content looks like field name (kjg)
75
+ * Don't change original when you change a copy (TylerRick)
76
+ * Don't include separating semicolon in paramter value when sanitizing (bpot)
77
+ * Fix fencepost encoding problem with binhex strings and only one token (drasch)
78
+ * Fix sendmail delivery to addresses with a leading hyphen (lifo, jeremy)
79
+ * Correctly format mbox From headers per RFC4155 (bpot, jeremy)
80
+ * Fix bogus '=' at the end of some quoted-printable messages (jeremy)
81
+ * Shouldn't be fooled into encoding strings on 1.8 by unrelated Encoding constant (emiellohr, jeremy)
82
+ * Header encoding should be US-ASCII, not the default external encoding (jeremy)
83
+ * Address elements should return decoded display names by default (jeremy)
84
+ * Fix up tests that depend on utf-8 external encoding; read fixtures as binary (jeremy)
85
+ * Capture stderr from Sendmail and Exim deliveries (jeremy)
86
+ * RFC2822 quoted_string content may be empty (jeremy)
87
+ * Calling #to_s on a field with a nil value returns an empty string instead of nil (jeremy)
88
+ * The Received header may contain zero name/value pairs, qmail-style (jeremy)
89
+ * Fix that setting an attachment with a :mime_type and :encoding would override the :encoding (jeremy)
90
+ * Fix that declaring an html_part but no text_part would use multipart/alternative anyway (jeremy)
91
+ * Close pull request 508 - Don't add an extra CRLF to MIME parts; split MIME parts on correct CRLF boundaries (Aalanar)
92
+ * Close pull request 506 - Escape backslashes in quoted strings (ConradIrwin)
93
+ * Close pull request 496 - Correctly handle quoted-printable line breaks (jeremy)
94
+ * Close pull request 493 - Repair misencoded quoted-printable line breaks (jeremy)
95
+ * Close pull request 487 - Extract comments from group email addresses (bpot)
96
+ * Close pull request 481 - Correctly quote filename attributes (bpot)
97
+ * Close pull request 480 - Support mixed encodings in a single header body (adamvaughan)
98
+ * Close pull request 471 - Fix Ruby 1.8 build when UTF16/32 default to little-endian (kennyj)
99
+
100
+ Coping with third-party bugs:
101
+ * Parse multipart boundary from Content-Type headers containing extra semicolons (jeremy)
102
+ * Close pull request 389 - Only add Content-ID to inline attachments to appease Outlook (djmaze, jeremy)
103
+
104
+ Housekeeping:
105
+ * Add development gem dependency on rdoc (jeremy)
106
+ * Refresh Bundler dependencies & setup (jeremy)
107
+ * Remove i18n dependency and last vestiges of activesupport dependency in specs (jeremy)
108
+ * Clarify that Sender is a single address, not an address list (jeremy)
109
+ * Add an MIT-LICENSE file to make licensing clear & obvious; update to 2013 (jeremy)
110
+ * Close pull request 501 - Tighten up header/body whitespace splitting (ConradIrwin)
111
+ * Close pull request 499 - Clean up some dead code (ConradIrwin)
112
+ * Close pull request 489, 495 - Docs typos (JackDanger, francois)
113
+ * Close pull request 485 - Be explicit about unsupported address parsing (bpot)
114
+ * Close pull request 484 - Remove #tree specs in preparation for deprecation removal (bpot)
115
+ * Close pull request 482 - Update address field specs to reflect to #initialize API (bpot)
116
+ * Close pull request 475 - Shush warning on Object#blank? redefinition (amatsuda)
117
+ * Close pull request 472 - Clean up UTF8/UTF-8 internals (kennyj)
118
+
119
+ == Version 2.5.3 - Sun Dec 4 15:52:00 +1100 2012 Mikel Lindsaar <mikel@reinteractive.net>
120
+
121
+ * Close pull request 468 - Remove debug output to STDOUT (tadman)
122
+ * Fix up spec warnings
123
+ * Remove un needed require
124
+ * Ensure spec_helper constants only defined once
125
+ * Use stub against time instead of DateTime to avoid double redefinition error
126
+
3
127
  == Version 2.5.2 - Sun Nov 18 15:01:00 +1100 2012 Mikel Lindsaar <mikel@reinteractive.net>
4
128
 
5
129
  * Removing double loading of treetop parsers to remove warnings
data/CONTRIBUTING.md CHANGED
@@ -12,12 +12,14 @@ pull request merged quickly:
12
12
  5. Add a spec for your change. Only refactoring and documentation changes
13
13
  require no new specs. If you are adding functionality or fixing a bug, we need
14
14
  a spec!
15
- 6. Test the spec _at_ _least_ against MRI-1.9.2 and MRI-1.8.7
15
+ 6. Test the spec _at_ _least_ against MRI-1.9.3 and MRI-1.8.7
16
16
  7. Update the README if needed to reflect your change / addition
17
- 8. With all specs passing push your changes back to your fork
18
- 9. Send me a pull request
17
+ 8. Update the CHANGELOG and give yourself credit
18
+ 9. With all specs passing push your changes back to your fork
19
+ 10. Send me a pull request.
20
+ - If it needs any changes, please push or force push to the same branch you made the pull request from. GitHub will just update the pull request with your changes.
19
21
 
20
- Note, specs that break MRI 1.8.7 will not be accepted.
22
+ Note, specs that break MRI 1.8.7 or 1.9.3 will not be accepted.
21
23
 
22
24
  At this point you're waiting on us. We like to at least comment on, if not
23
25
  accept, pull requests within three business days (and, typically, one business
@@ -28,7 +30,7 @@ taken straight from the Ruby on Rails guide:
28
30
 
29
31
  * Tell me you have tested it against more than one version of Ruby, RVM is great for
30
32
  this. I test against 7 rubies before I push into master.
31
- * Use good, idiomatic, strcutred and modular code
33
+ * Use good, idiomatic, structured and modular code
32
34
  * Include tests that fail without your code, and pass with it
33
35
  * Update the documentation, the surrounding one, examples elsewhere, guides,
34
36
  whatever is affected by your contribution
@@ -42,4 +44,17 @@ Syntax:
42
44
  * a = b and not a=b.
43
45
  * Follow the conventions you see used in the source already.
44
46
 
45
- And in case we didn't emphasize it enough: we love specs!
47
+ And in case we didn't emphasize it enough: we love specs!
48
+
49
+ ### Testing against mime-types versions:
50
+
51
+ Use [appraisal](https://github.com/thoughtbot/appraisal) to run against all supported versions of mime-types.
52
+
53
+ 1. Run `(bundle check || bundle) && appraisal` so that all the 'appraised' gemfiles are bundled.
54
+ 2. Run either `appraisal rake` or `rake appraisal` to run all the tests.
55
+
56
+ To run only one 'appraised' gemfile, run. e.g. `BUNDLE_GEMFILE=gemfiles/mime_types_edge.gemfile (bundle check || bundle) && rake`
57
+
58
+ To change the appraisals, modify the `Appraisals` file, run `appraisal`, commit the generated gemfiles, and modify the .travis.yml matrix.
59
+
60
+ To run on all rubies / gemfiles, just like TravisCI, see [WWTD](https://github.com/grosser/wwtd).
data/Dependencies.txt CHANGED
@@ -1,3 +1,2 @@
1
- treetop: we need to include this in the gem spec
2
1
  tlsmail: if ruby < 1.8.6... we could make it optional, or embed it in Mail
3
2
  mime/types: I think we embed a simplified version, or help maintain it, it is old (2006)
data/Gemfile CHANGED
@@ -1,26 +1,11 @@
1
- source :rubygems
1
+ source "https://rubygems.org"
2
2
 
3
- gem "activesupport", ">= 2.3.6"
4
- gem "tlsmail" if RUBY_VERSION <= '1.8.6'
5
- gem "mime-types", "~> 1.16"
6
- gem "treetop", "~> 1.4.10"
7
- gem "i18n", ">= 0.4.0"
3
+ gemspec
8
4
 
9
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
10
- gem 'jruby-openssl'
11
- end
5
+ gem "tlsmail", "~> 0.0.1" if RUBY_VERSION <= "1.8.6"
6
+ gem "jruby-openssl", :platforms => :jruby
12
7
 
13
- group :test do
14
- gem "rake", "> 0.8.7"
15
- gem "rspec", "~> 2.12.0"
16
- case
17
- when defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
18
- # Skip it
19
- when RUBY_PLATFORM == 'java'
20
- # Skip it
21
- when RUBY_VERSION < '1.9'
22
- gem "ruby-debug"
23
- else
24
- # Skip it
25
- end
8
+ # For gems not required to run tests
9
+ group :local_development, :test do
10
+ gem "appraisal", "~> 1.0" unless RUBY_VERSION <= "1.8.7"
26
11
  end
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009-2016 Mikel Lindsaar
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- Mail
1
+ Mail [![Build Status](https://travis-ci.org/mikel/mail.png?branch=master)](https://travis-ci.org/mikel/mail)
2
2
  ====
3
3
 
4
4
  Introduction
@@ -15,11 +15,11 @@ Built from my experience with TMail, it is designed to be a pure ruby
15
15
  implementation that makes generating, sending and parsing emails a no
16
16
  brainer.
17
17
 
18
- It is also designed form the ground up to work with Ruby 1.9. This is because
19
- Ruby 1.9 handles text encodings much more magically than Ruby 1.8.x and so
20
- these features have been taken full advantage of in this library allowing
21
- Mail to handle a lot more messages more cleanly than TMail. Mail does run on
22
- Ruby 1.8.x... it's just not as fun to code.
18
+ It is also designed from the ground up to work with the more modern versions
19
+ of Ruby. This is because Ruby > 1.9 handles text encodings much more wonderfully
20
+ than Ruby 1.8.x and so these features have been taken full advantage of in this
21
+ library allowing Mail to handle a lot more messages more cleanly than TMail.
22
+ Mail does run on Ruby 1.8.x... it's just not as fun to code.
23
23
 
24
24
  Finally, Mail has been designed with a very simple object oriented system
25
25
  that really opens up the email messages you are parsing, if you know what
@@ -42,15 +42,23 @@ me a nice email :)
42
42
  Compatibility
43
43
  -------------
44
44
 
45
- Mail is tested by Travis ([![Travis Build Status](https://travis-ci.org/mikel/mail.png "Build Status")](https://travis-ci.org/mikel/mail)) and works on the [following platforms](https://github.com/mikel/mail/blob/master/.travis.yml)
45
+ Every Mail commit is tested by Travis on the [following platforms](https://github.com/mikel/mail/blob/master/.travis.yml)
46
46
 
47
- * ruby-1.8.7-p370 [ i686 ]
48
- * ruby-1.9.2-p290 [ x86_64 ]
49
- * ruby-1.9.3-p327 [ x86_64 ]
50
- * jruby-1.6.8 [ x86_64 ]
51
- * jruby-1.7.0 [ x86_64 ]
52
- * rbx-d18 [ x86_64 ]
53
- * rbx-d19 [ x86_64 ]
47
+ * ruby-1.8.7 [ i686 ]
48
+ * ruby-1.9.2 [ x86_64 ]
49
+ * ruby-1.9.3 [ x86_64 ]
50
+ * ruby-2.0.0 [ x86_64 ]
51
+ * ruby-2.1.2 [ x86_64 ]
52
+ * ruby-head [ x86_64 ]
53
+ * jruby [ x86_64 ]
54
+ * jruby-head [ x86_64 ]
55
+ * rbx-2 [ x86_64 ]
56
+
57
+ Testing a specific mime type (needed for 1.8.7 for example) can be done manually with:
58
+
59
+ ```sh
60
+ BUNDLE_GEMFILE=gemfiles/mime_types_1.16.gemfile (bundle check || bundle) && rake
61
+ ```
54
62
 
55
63
  Discussion
56
64
  ----------
@@ -102,6 +110,8 @@ the gem gets released.
102
110
 
103
111
  It also means you can be sure Mail will behave correctly.
104
112
 
113
+ Note: If you care about core extensions (aka "monkey-patching"), please read the Core Extensions section near the end of this README.
114
+
105
115
  API Policy
106
116
  ----------
107
117
 
@@ -130,12 +140,12 @@ I have tried to simplify it some:
130
140
  it will include the header field and value and CRLF at the end and wrapped as
131
141
  needed.
132
142
 
133
- 2. All objects that can render into an email, have a :decoded method. Decoded will
143
+ 2. All objects that can render into an email, have a `#decoded` method. Decoded will
134
144
  return the object's "value" only as a string. This means it will not include
135
145
  the header fields (like 'To:' or 'Subject:').
136
146
 
137
147
  3. By default, calling <code>#to_s</code> on a container object will call its encoded
138
- method, while <code>#to_s</code> on a field object will call it's decoded method.
148
+ method, while <code>#to_s</code> on a field object will call its decoded method.
139
149
  So calling <code>#to_s</code> on a Mail object will return the mail, all encoded
140
150
  ready to send, while calling <code>#to_s</code> on the From field or the body will
141
151
  return the decoded value of the object. The header object of Mail is considered a
@@ -185,6 +195,8 @@ mail['from'] = 'mikel@test.lindsaar.net'
185
195
  mail[:to] = 'you@test.lindsaar.net'
186
196
  mail.subject = 'This is a test email'
187
197
 
198
+ mail.header['X-Custom-Header'] = 'custom value'
199
+
188
200
  mail.to_s #=> "From: mikel@test.lindsaar.net\r\nTo: you@...
189
201
  ```
190
202
 
@@ -202,7 +214,7 @@ mail.to_s =~ /Message\-ID: <[\d\w_]+@.+.mail/ #=> 27
202
214
  Mail will automatically add a Message-ID field if it is missing and
203
215
  give it a unique, random Message-ID along the lines of:
204
216
 
205
- <4a7ff76d7016_13a81ab802e1@local.fqdn.mail>
217
+ <4a7ff76d7016_13a81ab802e1@local.host.mail>
206
218
 
207
219
  ### Or do worry about Message-IDs:
208
220
 
@@ -227,10 +239,10 @@ easy as:
227
239
 
228
240
  ```ruby
229
241
  Mail.deliver do
230
- from 'me@test.lindsaar.net'
231
- to 'you@test.lindsaar.net'
232
- subject 'Here is the image you wanted'
233
- body File.read('body.txt')
242
+ from 'me@test.lindsaar.net'
243
+ to 'you@test.lindsaar.net'
244
+ subject 'Here is the image you wanted'
245
+ body File.read('body.txt')
234
246
  add_file '/full/path/to/somefile.png'
235
247
  end
236
248
  ```
@@ -265,7 +277,16 @@ mail.delivery_method :sendmail
265
277
  mail.deliver
266
278
  ```
267
279
 
268
- Exim requires it's own delivery manager, and can be used like so:
280
+ Sending via smtp (for example to [mailcatcher](https://github.com/sj26/mailcatcher))
281
+ ```ruby
282
+
283
+ Mail.defaults do
284
+ delivery_method :smtp, address: "localhost", port: 1025
285
+ end
286
+ ```
287
+
288
+
289
+ Exim requires its own delivery manager, and can be used like so:
269
290
 
270
291
  ```ruby
271
292
  mail.delivery_method :exim, :location => "/usr/bin/exim"
@@ -318,7 +339,7 @@ emails.length #=> LOTS!
318
339
  ```ruby
319
340
  mail = Mail.read('/path/to/message.eml')
320
341
 
321
- mail.envelope.from #=> 'mikel@test.lindsaar.net'
342
+ mail.envelope_from #=> 'mikel@test.lindsaar.net'
322
343
  mail.from.addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
323
344
  mail.sender.address #=> 'mikel@test.lindsaar.net'
324
345
  mail.to #=> 'bob@test.lindsaar.net'
@@ -338,8 +359,8 @@ mail = Mail.read('multipart_email')
338
359
 
339
360
  mail.multipart? #=> true
340
361
  mail.parts.length #=> 2
341
- mail.preamble #=> "Text before the first part"
342
- mail.epilogue #=> "Text after the last part"
362
+ mail.body.preamble #=> "Text before the first part"
363
+ mail.body.epilogue #=> "Text after the last part"
343
364
  mail.parts.map { |p| p.content_type } #=> ['text/plain', 'application/pdf']
344
365
  mail.parts.map { |p| p.class } #=> [Mail::Message, Mail::Message]
345
366
  mail.parts[0].content_type_parameters #=> {'charset' => 'ISO-8859-1'}
@@ -349,7 +370,7 @@ mail.parts[1].content_type_parameters #=> {'name' => 'my.pdf'}
349
370
  Mail generates a tree of parts. Each message has many or no parts. Each part
350
371
  is another message which can have many or no parts.
351
372
 
352
- A message will only have parts if it is a multipart/mixed or related/mixed
373
+ A message will only have parts if it is a multipart/mixed or multipart/related
353
374
  content type and has a boundary defined.
354
375
 
355
376
  ### Testing and extracting attachments
@@ -362,7 +383,7 @@ mail.attachments.each do | attachment |
362
383
  filename = attachment.filename
363
384
  begin
364
385
  File.open(images_dir + filename, "w+b", 0644) {|f| f.write attachment.body.decoded}
365
- rescue Exception => e
386
+ rescue => e
366
387
  puts "Unable to save data for #{filename} because #{e.message}"
367
388
  end
368
389
  end
@@ -545,7 +566,7 @@ Using Mail with Testing or Spec'ing Libraries
545
566
  If mail is part of your system, you'll need a way to test it without actually
546
567
  sending emails, the TestMailer can do this for you.
547
568
 
548
- ```
569
+ ```ruby
549
570
  require 'mail'
550
571
  => true
551
572
  Mail.defaults do
@@ -569,9 +590,9 @@ Mail::TestMailer.deliveries.clear
569
590
  => []
570
591
  ```
571
592
 
572
- There is also a set of RSpec matchers stolen fr^H^H^H^H^H^H^H^H inspired by Shoulda's ActionMailer matchers (you'll want to set <code>delivery_method</code> as above too):
593
+ There is also a set of RSpec matchers stolen/inspired by Shoulda's ActionMailer matchers (you'll want to set <code>delivery_method</code> as above too):
573
594
 
574
- ```
595
+ ```ruby
575
596
  Mail.defaults do
576
597
  delivery_method :test # in practice you'd do this in spec_helper.rb
577
598
  end
@@ -615,9 +636,43 @@ describe "sending an email" do
615
636
  # Note that apart from recipients, repeating a modifier overwrites old value.
616
637
 
617
638
  it { should have_sent_email.from('you@you.com').to('mike1@me.com').matching_body(/hell/)
639
+
640
+ # test for attachments
641
+
642
+ # ... by specific attachment
643
+ it { should_have_sent_email.with_attachments(my_attachment) }
644
+
645
+ # ... or any attachment
646
+ it { should_have_sent_email.with_attachments(any_attachment) }
647
+
648
+ # ... by array of attachments
649
+ it { should_have_sent_email.with_attachments([my_attachment1, my_attachment2]) } #note that order is important
650
+
651
+ #... by presence
652
+ it { should_have_sent_email.with_any_attachments }
653
+
654
+ #... or by absence
655
+ it { should_have_sent_email.with_no_attachments }
656
+
618
657
  end
619
658
  ```
620
659
 
660
+ Core Extensions
661
+ ---------------
662
+
663
+ The mail gem adds several constants and methods to Ruby's core objects (similar to the activesupport gem from the Rails project). For example:
664
+
665
+ NilClass::blank?
666
+ NilClass::to_crlf
667
+ NilClass::to_lf
668
+ Object::blank?
669
+ String::to_crlf
670
+ String::to_lf
671
+ String::blank?
672
+ ...etc...
673
+
674
+ For all the details, check out lib/mail/core_extensions/.
675
+
621
676
  Excerpts from TREC Spam Corpus 2005
622
677
  -----------------------------------
623
678
 
@@ -642,7 +697,7 @@ License
642
697
 
643
698
  (The MIT License)
644
699
 
645
- Copyright (c) 2009, 2010, 2011, 2012 Mikel Lindsaar
700
+ Copyright (c) 2009-2016 Mikel Lindsaar
646
701
 
647
702
  Permission is hereby granted, free of charge, to any person obtaining
648
703
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -1,25 +1,8 @@
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`?"
1
+ if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __FILE__)
20
3
  end
21
-
22
- require File.expand_path('../spec/environment', __FILE__)
4
+ require 'rubygems'
5
+ require 'bundler/setup'
23
6
 
24
7
  require 'rake/testtask'
25
8
  require 'rspec/core/rake_task'
@@ -36,5 +19,11 @@ RSpec::Core::RakeTask.new(:spec) do |t|
36
19
  t.rspec_opts = %w(--backtrace --color)
37
20
  end
38
21
 
22
+ begin
23
+ require "appraisal"
24
+ rescue LoadError, SyntaxError
25
+ warn "Appraisal is only available in test/development on Ruby 1.9+"
26
+ end
27
+
39
28
  # load custom rake tasks
40
- Dir["#{File.dirname(__FILE__)}/lib/tasks/**/*.rake"].sort.each { |ext| load ext }
29
+ Dir["#{File.dirname(__FILE__)}/tasks/**/*.rake"].sort.each { |ext| load ext }
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Mail
2
3
  class AttachmentsList < Array
3
4
 
@@ -60,7 +61,7 @@ module Mail
60
61
  if value[:mime_type]
61
62
  default_values[:content_type] = value.delete(:mime_type)
62
63
  @mime_type = MIME::Types[default_values[:content_type]].first
63
- default_values[:content_transfer_encoding] = guess_encoding
64
+ default_values[:content_transfer_encoding] ||= guess_encoding
64
65
  end
65
66
 
66
67
  hash = default_values.merge(value)
@@ -71,6 +72,7 @@ module Mail
71
72
 
72
73
  if hash[:body].respond_to? :force_encoding and hash[:body].respond_to? :valid_encoding?
73
74
  if not hash[:body].valid_encoding? and default_values[:content_transfer_encoding].downcase == "binary"
75
+ hash[:body] = hash[:body].dup if hash[:body].frozen?
74
76
  hash[:body].force_encoding("BINARY")
75
77
  end
76
78
  end
@@ -94,7 +96,7 @@ module Mail
94
96
  def set_mime_type(filename)
95
97
  # Have to do this because MIME::Types is not Ruby 1.9 safe yet
96
98
  if RUBY_VERSION >= '1.9'
97
- filename = filename.encode(Encoding::UTF_8) if filename.respond_to?(:encode)
99
+ filename = filename.encode(Encoding::UTF_8) if filename.respond_to?(:encode)
98
100
  end
99
101
 
100
102
  @mime_type = MIME::Types.type_for(filename).first
data/lib/mail/body.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  # encoding: utf-8
2
+ # frozen_string_literal: true
2
3
  module Mail
3
4
 
4
5
  # = Body
5
6
  #
6
7
  # The body is where the text of the email is stored. Mail treats the body
7
8
  # as a single object. The body itself has no information about boundaries
8
- # used in the MIME standard, it just looks at it's content as either a single
9
+ # used in the MIME standard, it just looks at its content as either a single
9
10
  # block of text, or (if it is a multipart message) as an array of blocks of text.
10
11
  #
11
12
  # A body has to be told to split itself up into a multipart message by calling
@@ -33,7 +34,7 @@ module Mail
33
34
  @charset = nil
34
35
  @part_sort_order = [ "text/plain", "text/enriched", "text/html" ]
35
36
  @parts = Mail::PartsList.new
36
- if string.blank?
37
+ if Utilities.blank?(string)
37
38
  @raw_source = ''
38
39
  else
39
40
  # Do join first incase we have been given an Array in Ruby 1.9
@@ -127,9 +128,9 @@ module Mail
127
128
  def sort_parts!
128
129
  @parts.each do |p|
129
130
  p.body.set_sort_order(@part_sort_order)
130
- @parts.sort!(@part_sort_order)
131
131
  p.body.sort_parts!
132
132
  end
133
+ @parts.sort!(@part_sort_order)
133
134
  end
134
135
 
135
136
  # Returns the raw source that the body was initialized with, without
@@ -156,7 +157,7 @@ module Mail
156
157
  be = get_best_encoding(transfer_encoding)
157
158
  dec = Mail::Encodings::get_encoding(encoding)
158
159
  enc = Mail::Encodings::get_encoding(be)
159
- if transfer_encoding == encoding and dec.nil?
160
+ if dec.nil?
160
161
  # Cannot decode, so skip normalization
161
162
  raw_source
162
163
  else
@@ -201,7 +202,7 @@ module Mail
201
202
  end
202
203
 
203
204
  def encoding=( val )
204
- @encoding = if val == "text" || val.blank?
205
+ @encoding = if val == "text" || Utilities.blank?(val)
205
206
  (only_us_ascii? ? '7bit' : '8bit')
206
207
  else
207
208
  val
@@ -254,18 +255,19 @@ module Mail
254
255
  @parts = Mail::PartsList.new[val]
255
256
  end
256
257
  end
257
-
258
+
258
259
  def split!(boundary)
259
260
  self.boundary = boundary
260
- parts = raw_source.split(/--#{Regexp.escape(boundary)}(?=(?:--)?\s*$)/)
261
+ parts = extract_parts
262
+
261
263
  # Make the preamble equal to the preamble (if any)
262
264
  self.preamble = parts[0].to_s.strip
263
265
  # Make the epilogue equal to the epilogue (if any)
264
- self.epilogue = parts[-1].to_s.sub('--', '').strip
266
+ self.epilogue = parts[-1].to_s.strip
265
267
  parts[1...-1].to_a.each { |part| @parts << Mail::Part.new(part) }
266
268
  self
267
269
  end
268
-
270
+
269
271
  def only_us_ascii?
270
272
  !(raw_source =~ /[^\x01-\x7f]/)
271
273
  end
@@ -275,13 +277,36 @@ module Mail
275
277
  end
276
278
 
277
279
  private
280
+
281
+ # split parts by boundary, ignore first part if empty, append final part when closing boundary was missing
282
+ def extract_parts
283
+ parts_regex = /
284
+ (?: # non-capturing group
285
+ \A | # start of string OR
286
+ \r\n # line break
287
+ )
288
+ (
289
+ --#{Regexp.escape(boundary || "")} # boundary delimiter
290
+ (?:--)? # with non-capturing optional closing
291
+ )
292
+ (?=\s*$) # lookahead matching zero or more spaces followed by line-ending
293
+ /x
294
+ parts = raw_source.split(parts_regex).each_slice(2).to_a
295
+ parts.each_with_index { |(part, _), index| parts.delete_at(index) if index > 0 && Utilities.blank?(part) }
296
+
297
+ if parts.size > 1
298
+ final_separator = parts[-2][1]
299
+ parts << [""] if final_separator != "--#{boundary}--"
300
+ end
301
+ parts.map(&:first)
302
+ end
278
303
 
279
304
  def crlf_boundary
280
- "\r\n\r\n--#{boundary}\r\n"
305
+ "\r\n--#{boundary}\r\n"
281
306
  end
282
307
 
283
308
  def end_boundary
284
- "\r\n\r\n--#{boundary}--\r\n"
309
+ "\r\n--#{boundary}--\r\n"
285
310
  end
286
311
 
287
312
  def set_charset