mail-portertech 2.6.2.edge

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.rdoc +753 -0
  3. data/CONTRIBUTING.md +60 -0
  4. data/Dependencies.txt +2 -0
  5. data/Gemfile +15 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +683 -0
  8. data/Rakefile +29 -0
  9. data/TODO.rdoc +9 -0
  10. data/lib/mail.rb +91 -0
  11. data/lib/mail/attachments_list.rb +104 -0
  12. data/lib/mail/body.rb +291 -0
  13. data/lib/mail/check_delivery_params.rb +20 -0
  14. data/lib/mail/configuration.rb +75 -0
  15. data/lib/mail/core_extensions/nil.rb +19 -0
  16. data/lib/mail/core_extensions/object.rb +13 -0
  17. data/lib/mail/core_extensions/smtp.rb +24 -0
  18. data/lib/mail/core_extensions/string.rb +43 -0
  19. data/lib/mail/core_extensions/string/access.rb +145 -0
  20. data/lib/mail/core_extensions/string/multibyte.rb +78 -0
  21. data/lib/mail/elements.rb +14 -0
  22. data/lib/mail/elements/address.rb +270 -0
  23. data/lib/mail/elements/address_list.rb +51 -0
  24. data/lib/mail/elements/content_disposition_element.rb +26 -0
  25. data/lib/mail/elements/content_location_element.rb +21 -0
  26. data/lib/mail/elements/content_transfer_encoding_element.rb +17 -0
  27. data/lib/mail/elements/content_type_element.rb +31 -0
  28. data/lib/mail/elements/date_time_element.rb +22 -0
  29. data/lib/mail/elements/envelope_from_element.rb +39 -0
  30. data/lib/mail/elements/message_ids_element.rb +24 -0
  31. data/lib/mail/elements/mime_version_element.rb +22 -0
  32. data/lib/mail/elements/phrase_list.rb +16 -0
  33. data/lib/mail/elements/received_element.rb +26 -0
  34. data/lib/mail/encodings.rb +304 -0
  35. data/lib/mail/encodings/7bit.rb +31 -0
  36. data/lib/mail/encodings/8bit.rb +31 -0
  37. data/lib/mail/encodings/base64.rb +33 -0
  38. data/lib/mail/encodings/binary.rb +31 -0
  39. data/lib/mail/encodings/quoted_printable.rb +39 -0
  40. data/lib/mail/encodings/transfer_encoding.rb +58 -0
  41. data/lib/mail/envelope.rb +30 -0
  42. data/lib/mail/field.rb +247 -0
  43. data/lib/mail/field_list.rb +33 -0
  44. data/lib/mail/fields.rb +35 -0
  45. data/lib/mail/fields/bcc_field.rb +56 -0
  46. data/lib/mail/fields/cc_field.rb +55 -0
  47. data/lib/mail/fields/comments_field.rb +41 -0
  48. data/lib/mail/fields/common/address_container.rb +16 -0
  49. data/lib/mail/fields/common/common_address.rb +135 -0
  50. data/lib/mail/fields/common/common_date.rb +35 -0
  51. data/lib/mail/fields/common/common_field.rb +57 -0
  52. data/lib/mail/fields/common/common_message_id.rb +48 -0
  53. data/lib/mail/fields/common/parameter_hash.rb +58 -0
  54. data/lib/mail/fields/content_description_field.rb +19 -0
  55. data/lib/mail/fields/content_disposition_field.rb +70 -0
  56. data/lib/mail/fields/content_id_field.rb +62 -0
  57. data/lib/mail/fields/content_location_field.rb +42 -0
  58. data/lib/mail/fields/content_transfer_encoding_field.rb +44 -0
  59. data/lib/mail/fields/content_type_field.rb +201 -0
  60. data/lib/mail/fields/date_field.rb +57 -0
  61. data/lib/mail/fields/from_field.rb +55 -0
  62. data/lib/mail/fields/in_reply_to_field.rb +56 -0
  63. data/lib/mail/fields/keywords_field.rb +44 -0
  64. data/lib/mail/fields/message_id_field.rb +82 -0
  65. data/lib/mail/fields/mime_version_field.rb +53 -0
  66. data/lib/mail/fields/optional_field.rb +13 -0
  67. data/lib/mail/fields/received_field.rb +75 -0
  68. data/lib/mail/fields/references_field.rb +56 -0
  69. data/lib/mail/fields/reply_to_field.rb +55 -0
  70. data/lib/mail/fields/resent_bcc_field.rb +55 -0
  71. data/lib/mail/fields/resent_cc_field.rb +55 -0
  72. data/lib/mail/fields/resent_date_field.rb +35 -0
  73. data/lib/mail/fields/resent_from_field.rb +55 -0
  74. data/lib/mail/fields/resent_message_id_field.rb +34 -0
  75. data/lib/mail/fields/resent_sender_field.rb +62 -0
  76. data/lib/mail/fields/resent_to_field.rb +55 -0
  77. data/lib/mail/fields/return_path_field.rb +65 -0
  78. data/lib/mail/fields/sender_field.rb +67 -0
  79. data/lib/mail/fields/structured_field.rb +51 -0
  80. data/lib/mail/fields/subject_field.rb +16 -0
  81. data/lib/mail/fields/to_field.rb +55 -0
  82. data/lib/mail/fields/unstructured_field.rb +204 -0
  83. data/lib/mail/header.rb +274 -0
  84. data/lib/mail/indifferent_hash.rb +146 -0
  85. data/lib/mail/mail.rb +267 -0
  86. data/lib/mail/matchers/has_sent_mail.rb +157 -0
  87. data/lib/mail/message.rb +2160 -0
  88. data/lib/mail/multibyte.rb +42 -0
  89. data/lib/mail/multibyte/chars.rb +474 -0
  90. data/lib/mail/multibyte/exceptions.rb +8 -0
  91. data/lib/mail/multibyte/unicode.rb +400 -0
  92. data/lib/mail/multibyte/utils.rb +60 -0
  93. data/lib/mail/network.rb +14 -0
  94. data/lib/mail/network/delivery_methods/exim.rb +52 -0
  95. data/lib/mail/network/delivery_methods/file_delivery.rb +45 -0
  96. data/lib/mail/network/delivery_methods/sendmail.rb +89 -0
  97. data/lib/mail/network/delivery_methods/smtp.rb +142 -0
  98. data/lib/mail/network/delivery_methods/smtp_connection.rb +61 -0
  99. data/lib/mail/network/delivery_methods/test_mailer.rb +44 -0
  100. data/lib/mail/network/retriever_methods/base.rb +63 -0
  101. data/lib/mail/network/retriever_methods/imap.rb +173 -0
  102. data/lib/mail/network/retriever_methods/pop3.rb +140 -0
  103. data/lib/mail/network/retriever_methods/test_retriever.rb +43 -0
  104. data/lib/mail/parsers.rb +26 -0
  105. data/lib/mail/parsers/address_lists_parser.rb +132 -0
  106. data/lib/mail/parsers/content_disposition_parser.rb +67 -0
  107. data/lib/mail/parsers/content_location_parser.rb +35 -0
  108. data/lib/mail/parsers/content_transfer_encoding_parser.rb +33 -0
  109. data/lib/mail/parsers/content_type_parser.rb +64 -0
  110. data/lib/mail/parsers/date_time_parser.rb +36 -0
  111. data/lib/mail/parsers/envelope_from_parser.rb +45 -0
  112. data/lib/mail/parsers/message_ids_parser.rb +39 -0
  113. data/lib/mail/parsers/mime_version_parser.rb +41 -0
  114. data/lib/mail/parsers/phrase_lists_parser.rb +33 -0
  115. data/lib/mail/parsers/ragel.rb +17 -0
  116. data/lib/mail/parsers/ragel/common.rl +184 -0
  117. data/lib/mail/parsers/ragel/date_time.rl +30 -0
  118. data/lib/mail/parsers/ragel/parser_info.rb +61 -0
  119. data/lib/mail/parsers/ragel/ruby.rb +39 -0
  120. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +14864 -0
  121. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +37 -0
  122. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +751 -0
  123. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +37 -0
  124. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +614 -0
  125. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +37 -0
  126. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +447 -0
  127. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +37 -0
  128. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +825 -0
  129. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +37 -0
  130. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +817 -0
  131. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +37 -0
  132. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +2129 -0
  133. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +37 -0
  134. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +1570 -0
  135. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +37 -0
  136. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +440 -0
  137. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +37 -0
  138. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +564 -0
  139. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +37 -0
  140. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +51 -0
  141. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +5144 -0
  142. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +37 -0
  143. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +37 -0
  144. data/lib/mail/parsers/received_parser.rb +47 -0
  145. data/lib/mail/part.rb +120 -0
  146. data/lib/mail/parts_list.rb +57 -0
  147. data/lib/mail/patterns.rb +37 -0
  148. data/lib/mail/utilities.rb +225 -0
  149. data/lib/mail/values/unicode_tables.dat +0 -0
  150. data/lib/mail/version.rb +4 -0
  151. data/lib/mail/version_specific/ruby_1_8.rb +119 -0
  152. data/lib/mail/version_specific/ruby_1_9.rb +159 -0
  153. metadata +276 -0
@@ -0,0 +1,60 @@
1
+ Contributing to Mail
2
+ ====================
3
+
4
+ Hi there, I welcome pull requests! Here are some thoughts on how to get your
5
+ pull request merged quickly:
6
+
7
+ 1. Check the Reference RFCs, they are in the References directory, so no excuses.
8
+ 2. Check for a ticket on GitHub, maybe someone else has the problem too
9
+ 3. Make a fork of my GitHub repository
10
+ 4. Run the specs. We only take pull requests with passing tests, and it's great
11
+ to know that you have a clean slate: `bundle && bundle exec rake`
12
+ 5. Add a spec for your change. Only refactoring and documentation changes
13
+ require no new specs. If you are adding functionality or fixing a bug, we need
14
+ a spec!
15
+ 6. Test the spec _at_ _least_ against MRI-1.9.3 and MRI-1.8.7
16
+ 7. Update the README if needed to reflect your change / addition
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.
21
+
22
+ Note, specs that break MRI 1.8.7 or 1.9.3 will not be accepted.
23
+
24
+ At this point you're waiting on us. We like to at least comment on, if not
25
+ accept, pull requests within three business days (and, typically, one business
26
+ day). We may suggest some changes or improvements or alternatives.
27
+
28
+ Some things that will increase the chance that your pull request is accepted,
29
+ taken straight from the Ruby on Rails guide:
30
+
31
+ * Tell me you have tested it against more than one version of Ruby, RVM is great for
32
+ this. I test against 7 rubies before I push into master.
33
+ * Use good, idiomatic, structured and modular code
34
+ * Include tests that fail without your code, and pass with it
35
+ * Update the documentation, the surrounding one, examples elsewhere, guides,
36
+ whatever is affected by your contribution
37
+
38
+ Syntax:
39
+
40
+ * Two spaces, no tabs.
41
+ * No trailing whitespace. Blank lines should not have any space.
42
+ * Prefer &&/|| over and/or.
43
+ * MyClass.my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
44
+ * a = b and not a=b.
45
+ * Follow the conventions you see used in the source already.
46
+
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).
@@ -0,0 +1,2 @@
1
+ tlsmail: if ruby < 1.8.6... we could make it optional, or embed it in Mail
2
+ mime/types: I think we embed a simplified version, or help maintain it, it is old (2006)
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "tlsmail", "~> 0.0.1" if RUBY_VERSION <= "1.8.6"
6
+ gem "jruby-openssl", :platforms => :jruby
7
+
8
+ group :development, :test do
9
+ gem "appraisal", "~> 1.0"
10
+ end
11
+
12
+ # For gems not required to run tests
13
+ group :local_development, :test do
14
+ gem "ruby-debug", :platforms => :mri_18
15
+ end
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009-2013 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.
@@ -0,0 +1,683 @@
1
+ Mail [![Build Status](https://travis-ci.org/mikel/mail.png?branch=master)](https://travis-ci.org/mikel/mail)
2
+ ====
3
+
4
+ Introduction
5
+ ------------
6
+
7
+ Mail is an internet library for Ruby that is designed to handle emails
8
+ generation, parsing and sending in a simple, rubyesque manner.
9
+
10
+ The purpose of this library is to provide a single point of access to handle
11
+ all email functions, including sending and receiving emails. All network
12
+ type actions are done through proxy methods to Net::SMTP, Net::POP3 etc.
13
+
14
+ Built from my experience with TMail, it is designed to be a pure ruby
15
+ implementation that makes generating, sending and parsing emails a no
16
+ brainer.
17
+
18
+ It is also designed form 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
+
24
+ Finally, Mail has been designed with a very simple object oriented system
25
+ that really opens up the email messages you are parsing, if you know what
26
+ you are doing, you can fiddle with every last bit of your email directly.
27
+
28
+ Donations
29
+ -------------
30
+
31
+ Mail has been downloaded millions of times, by people around the world, in fact,
32
+ it represents more than 1% of *all* gems downloaded.
33
+
34
+ It is (like all open source software) a labour of love and something I am doing
35
+ with my own free time. If you would like to say thanks, please feel free to
36
+ [make a donation](http://www.pledgie.com/campaigns/8790) and feel free to send
37
+ me a nice email :)
38
+
39
+ <a href='http://www.pledgie.com/campaigns/8790'><img alt='Click here to lend your support to: mail and make a donation at www.pledgie.com !' src='http://www.pledgie.com/campaigns/8790.png?skin_name=chrome' border='0' /></a>
40
+
41
+
42
+ Compatibility
43
+ -------------
44
+
45
+ Every Mail commit is tested by Travis on the [following platforms](https://github.com/mikel/mail/blob/master/.travis.yml)
46
+
47
+ * ruby-1.8.7-p374 [ i686 ]
48
+ * ruby-1.9.2-p320 [ x86_64 ]
49
+ * ruby-1.9.3-p327 [ x86_64 ]
50
+ * ruby-2.0.0-p451 [ 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
+ ```
62
+
63
+ Discussion
64
+ ----------
65
+
66
+ If you want to discuss mail with like minded individuals, please subscribe to
67
+ the [Google Group](http://groups.google.com/group/mail-ruby).
68
+
69
+ Current Capabilities of Mail
70
+ ----------------------------
71
+
72
+ * RFC2822 Support, Reading and Writing
73
+ * RFC2045-2049 Support for multipart emails
74
+ * Support for creating multipart alternate emails
75
+ * Support for reading multipart/report emails &amp; getting details from such
76
+ * Support for multibyte emails - needs quite a lot of work and testing
77
+ * Wrappers for File, Net/POP3, Net/SMTP
78
+ * Auto encoding of non US-ASCII header fields
79
+ * Auto encoding of non US-ASCII bodies
80
+
81
+ Mail is RFC2822 compliant now, that is, it can parse and generate valid US-ASCII
82
+ emails. There are a few obsoleted syntax emails that it will have problems with, but
83
+ it also is quite robust, meaning, if it finds something it doesn't understand it will
84
+ not crash, instead, it will skip the problem and keep parsing. In the case of a header
85
+ it doesn't understand, it will initialise the header as an optional unstructured
86
+ field and continue parsing.
87
+
88
+ This means Mail won't (ever) crunch your data (I think).
89
+
90
+ You can also create MIME emails. There are helper methods for making a
91
+ multipart/alternate email for text/plain and text/html (the most common pair)
92
+ and you can manually create any other type of MIME email.
93
+
94
+ Roadmap
95
+ -------
96
+
97
+ Next TODO:
98
+
99
+ * Improve MIME support for character sets in headers, currently works, mostly, needs
100
+ refinement.
101
+
102
+ Testing Policy
103
+ --------------
104
+
105
+ Basically... we do BDD on Mail. No method gets written in Mail without a
106
+ corresponding or covering spec. We expect as a minimum 100% coverage
107
+ measured by RCov. While this is not perfect by any measure, it is pretty
108
+ good. Additionally, all functional tests from TMail are to be passing before
109
+ the gem gets released.
110
+
111
+ It also means you can be sure Mail will behave correctly.
112
+
113
+ API Policy
114
+ ----------
115
+
116
+ No API removals within a single point release. All removals to be deprecated with
117
+ warnings for at least one MINOR point release before removal.
118
+
119
+ Also, all private or protected methods to be declared as such - though this is still I/P.
120
+
121
+ Installation
122
+ ------------
123
+
124
+ Installation is fairly simple, I host mail on rubygems, so you can just do:
125
+
126
+ # gem install mail
127
+
128
+ Encodings
129
+ ---------
130
+
131
+ If you didn't know, handling encodings in Emails is not as straight forward as you
132
+ would hope.
133
+
134
+ I have tried to simplify it some:
135
+
136
+ 1. All objects that can render into an email, have an `#encoded` method. Encoded will
137
+ return the object as a complete string ready to send in the mail system, that is,
138
+ it will include the header field and value and CRLF at the end and wrapped as
139
+ needed.
140
+
141
+ 2. All objects that can render into an email, have a `#decoded` method. Decoded will
142
+ return the object's "value" only as a string. This means it will not include
143
+ the header fields (like 'To:' or 'Subject:').
144
+
145
+ 3. By default, calling <code>#to_s</code> on a container object will call its encoded
146
+ method, while <code>#to_s</code> on a field object will call its decoded method.
147
+ So calling <code>#to_s</code> on a Mail object will return the mail, all encoded
148
+ ready to send, while calling <code>#to_s</code> on the From field or the body will
149
+ return the decoded value of the object. The header object of Mail is considered a
150
+ container. If you are in doubt, call <code>#encoded</code>, or <code>#decoded</code>
151
+ explicitly, this is safer if you are not sure.
152
+
153
+ 4. Structured fields that have parameter values that can be encoded (e.g. Content-Type) will
154
+ provide decoded parameter values when you call the parameter names as methods against
155
+ the object.
156
+
157
+ 5. Structured fields that have parameter values that can be encoded (e.g. Content-Type) will
158
+ provide encoded parameter values when you call the parameter names through the
159
+ <code>object.parameters['<parameter_name>']</code> method call.
160
+
161
+ Contributing
162
+ ------------
163
+
164
+ Please do! Contributing is easy in Mail. Please read the CONTRIBUTING.md document for more info
165
+
166
+ Usage
167
+ -----
168
+
169
+ All major mail functions should be able to happen from the Mail module.
170
+ So, you should be able to just <code>require 'mail'</code> to get started.
171
+
172
+ ### Making an email
173
+
174
+ ```ruby
175
+ mail = Mail.new do
176
+ from 'mikel@test.lindsaar.net'
177
+ to 'you@test.lindsaar.net'
178
+ subject 'This is a test email'
179
+ body File.read('body.txt')
180
+ end
181
+
182
+ mail.to_s #=> "From: mikel@test.lindsaar.net\r\nTo: you@...
183
+ ```
184
+
185
+ ### Making an email, have it your way:
186
+
187
+ ```ruby
188
+ mail = Mail.new do
189
+ body File.read('body.txt')
190
+ end
191
+
192
+ mail['from'] = 'mikel@test.lindsaar.net'
193
+ mail[:to] = 'you@test.lindsaar.net'
194
+ mail.subject = 'This is a test email'
195
+
196
+ mail.header['X-Custom-Header'] = 'custom value'
197
+
198
+ mail.to_s #=> "From: mikel@test.lindsaar.net\r\nTo: you@...
199
+ ```
200
+
201
+ ### Don't Worry About Message IDs:
202
+
203
+ ```ruby
204
+ mail = Mail.new do
205
+ to 'you@test.lindsaar.net'
206
+ body 'Some simple body'
207
+ end
208
+
209
+ mail.to_s =~ /Message\-ID: <[\d\w_]+@.+.mail/ #=> 27
210
+ ```
211
+
212
+ Mail will automatically add a Message-ID field if it is missing and
213
+ give it a unique, random Message-ID along the lines of:
214
+
215
+ <4a7ff76d7016_13a81ab802e1@local.host.mail>
216
+
217
+ ### Or do worry about Message-IDs:
218
+
219
+ ```ruby
220
+ mail = Mail.new do
221
+ to 'you@test.lindsaar.net'
222
+ message_id '<ThisIsMyMessageId@some.domain.com>'
223
+ body 'Some simple body'
224
+ end
225
+
226
+ mail.to_s =~ /Message\-ID: <ThisIsMyMessageId@some.domain.com>/ #=> 27
227
+ ```
228
+
229
+ Mail will take the message_id you assign to it trusting that you know
230
+ what you are doing.
231
+
232
+ ### Sending an email:
233
+
234
+ Mail defaults to sending via SMTP to local host port 25. If you have a
235
+ sendmail or postfix daemon running on on this port, sending email is as
236
+ easy as:
237
+
238
+ ```ruby
239
+ Mail.deliver do
240
+ from 'me@test.lindsaar.net'
241
+ to 'you@test.lindsaar.net'
242
+ subject 'Here is the image you wanted'
243
+ body File.read('body.txt')
244
+ add_file '/full/path/to/somefile.png'
245
+ end
246
+ ```
247
+
248
+ or
249
+
250
+ ```ruby
251
+ mail = Mail.new do
252
+ from 'me@test.lindsaar.net'
253
+ to 'you@test.lindsaar.net'
254
+ subject 'Here is the image you wanted'
255
+ body File.read('body.txt')
256
+ add_file :filename => 'somefile.png', :content => File.read('/somefile.png')
257
+ end
258
+
259
+ mail.deliver!
260
+ ```
261
+
262
+ Sending via sendmail can be done like so:
263
+
264
+ ```ruby
265
+ mail = Mail.new do
266
+ from 'me@test.lindsaar.net'
267
+ to 'you@test.lindsaar.net'
268
+ subject 'Here is the image you wanted'
269
+ body File.read('body.txt')
270
+ add_file :filename => 'somefile.png', :content => File.read('/somefile.png')
271
+ end
272
+
273
+ mail.delivery_method :sendmail
274
+
275
+ mail.deliver
276
+ ```
277
+
278
+ Sending via smtp (for example to [mailcatcher](https://github.com/sj26/mailcatcher))
279
+ ```ruby
280
+
281
+ Mail.defaults do
282
+ delivery_method :smtp, address: "localhost", port: 1025
283
+ end
284
+ ```
285
+
286
+
287
+ Exim requires its own delivery manager, and can be used like so:
288
+
289
+ ```ruby
290
+ mail.delivery_method :exim, :location => "/usr/bin/exim"
291
+
292
+ mail.deliver
293
+ ```
294
+
295
+ ### Getting emails from a pop server:
296
+
297
+ You can configure Mail to receive email using <code>retriever_method</code>
298
+ within <code>Mail.defaults</code>:
299
+
300
+ ```ruby
301
+ Mail.defaults do
302
+ retriever_method :pop3, :address => "pop.gmail.com",
303
+ :port => 995,
304
+ :user_name => '<username>',
305
+ :password => '<password>',
306
+ :enable_ssl => true
307
+ end
308
+ ```
309
+
310
+ You can access incoming email in a number of ways.
311
+
312
+ The most recent email:
313
+
314
+ ```ruby
315
+ Mail.all #=> Returns an array of all emails
316
+ Mail.first #=> Returns the first unread email
317
+ Mail.last #=> Returns the last unread email
318
+ ```
319
+
320
+ The first 10 emails sorted by date in ascending order:
321
+
322
+ ```ruby
323
+ emails = Mail.find(:what => :first, :count => 10, :order => :asc)
324
+ emails.length #=> 10
325
+ ```
326
+
327
+ Or even all emails:
328
+
329
+ ```ruby
330
+ emails = Mail.all
331
+ emails.length #=> LOTS!
332
+ ```
333
+
334
+
335
+ ### Reading an Email
336
+
337
+ ```ruby
338
+ mail = Mail.read('/path/to/message.eml')
339
+
340
+ mail.envelope_from #=> 'mikel@test.lindsaar.net'
341
+ mail.from.addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
342
+ mail.sender.address #=> 'mikel@test.lindsaar.net'
343
+ mail.to #=> 'bob@test.lindsaar.net'
344
+ mail.cc #=> 'sam@test.lindsaar.net'
345
+ mail.subject #=> "This is the subject"
346
+ mail.date.to_s #=> '21 Nov 1997 09:55:06 -0600'
347
+ mail.message_id #=> '<4D6AA7EB.6490534@xxx.xxx>'
348
+ mail.body.decoded #=> 'This is the body of the email...
349
+ ```
350
+
351
+ Many more methods available.
352
+
353
+ ### Reading a Multipart Email
354
+
355
+ ```ruby
356
+ mail = Mail.read('multipart_email')
357
+
358
+ mail.multipart? #=> true
359
+ mail.parts.length #=> 2
360
+ mail.body.preamble #=> "Text before the first part"
361
+ mail.body.epilogue #=> "Text after the last part"
362
+ mail.parts.map { |p| p.content_type } #=> ['text/plain', 'application/pdf']
363
+ mail.parts.map { |p| p.class } #=> [Mail::Message, Mail::Message]
364
+ mail.parts[0].content_type_parameters #=> {'charset' => 'ISO-8859-1'}
365
+ mail.parts[1].content_type_parameters #=> {'name' => 'my.pdf'}
366
+ ```
367
+
368
+ Mail generates a tree of parts. Each message has many or no parts. Each part
369
+ is another message which can have many or no parts.
370
+
371
+ A message will only have parts if it is a multipart/mixed or multipart/related
372
+ content type and has a boundary defined.
373
+
374
+ ### Testing and extracting attachments
375
+ ```ruby
376
+ mail.attachments.each do | attachment |
377
+ # Attachments is an AttachmentsList object containing a
378
+ # number of Part objects
379
+ if (attachment.content_type.start_with?('image/'))
380
+ # extracting images for example...
381
+ filename = attachment.filename
382
+ begin
383
+ File.open(images_dir + filename, "w+b", 0644) {|f| f.write attachment.body.decoded}
384
+ rescue => e
385
+ puts "Unable to save data for #{filename} because #{e.message}"
386
+ end
387
+ end
388
+ end
389
+ ```
390
+ ### Writing and sending a multipart/alternative (html and text) email
391
+
392
+ Mail makes some basic assumptions and makes doing the common thing as
393
+ simple as possible.... (asking a lot from a mail library)
394
+
395
+ ```ruby
396
+ mail = Mail.deliver do
397
+ to 'nicolas@test.lindsaar.net.au'
398
+ from 'Mikel Lindsaar <mikel@test.lindsaar.net.au>'
399
+ subject 'First multipart email sent with Mail'
400
+
401
+ text_part do
402
+ body 'This is plain text'
403
+ end
404
+
405
+ html_part do
406
+ content_type 'text/html; charset=UTF-8'
407
+ body '<h1>This is HTML</h1>'
408
+ end
409
+ end
410
+ ```
411
+
412
+ Mail then delivers the email at the end of the block and returns the
413
+ resulting Mail::Message object, which you can then inspect if you
414
+ so desire...
415
+
416
+ ```
417
+ puts mail.to_s #=>
418
+
419
+ To: nicolas@test.lindsaar.net.au
420
+ From: Mikel Lindsaar <mikel@test.lindsaar.net.au>
421
+ Subject: First multipart email sent with Mail
422
+ Content-Type: multipart/alternative;
423
+ boundary=--==_mimepart_4a914f0c911be_6f0f1ab8026659
424
+ Message-ID: <4a914f12ac7e_6f0f1ab80267d1@baci.local.mail>
425
+ Date: Mon, 24 Aug 2009 00:15:46 +1000
426
+ Mime-Version: 1.0
427
+ Content-Transfer-Encoding: 7bit
428
+
429
+
430
+ ----==_mimepart_4a914f0c911be_6f0f1ab8026659
431
+ Content-ID: <4a914f12c8c4_6f0f1ab80268d6@baci.local.mail>
432
+ Date: Mon, 24 Aug 2009 00:15:46 +1000
433
+ Mime-Version: 1.0
434
+ Content-Type: text/plain
435
+ Content-Transfer-Encoding: 7bit
436
+
437
+ This is plain text
438
+ ----==_mimepart_4a914f0c911be_6f0f1ab8026659
439
+ Content-Type: text/html; charset=UTF-8
440
+ Content-ID: <4a914f12cf86_6f0f1ab802692c@baci.local.mail>
441
+ Date: Mon, 24 Aug 2009 00:15:46 +1000
442
+ Mime-Version: 1.0
443
+ Content-Transfer-Encoding: 7bit
444
+
445
+ <h1>This is HTML</h1>
446
+ ----==_mimepart_4a914f0c911be_6f0f1ab8026659--
447
+ ```
448
+
449
+ Mail inserts the content transfer encoding, the mime version,
450
+ the content-id's and handles the content-type and boundary.
451
+
452
+ Mail assumes that if your text in the body is only us-ascii, that your
453
+ transfer encoding is 7bit and it is text/plain. You can override this
454
+ by explicitly declaring it.
455
+
456
+ ### Making Multipart/Alternate, without a block
457
+
458
+ You don't have to use a block with the text and html part included, you
459
+ can just do it declaratively. However, you need to add Mail::Parts to
460
+ an email, not Mail::Messages.
461
+
462
+ ```ruby
463
+ mail = Mail.new do
464
+ to 'nicolas@test.lindsaar.net.au'
465
+ from 'Mikel Lindsaar <mikel@test.lindsaar.net.au>'
466
+ subject 'First multipart email sent with Mail'
467
+ end
468
+
469
+ text_part = Mail::Part.new do
470
+ body 'This is plain text'
471
+ end
472
+
473
+ html_part = Mail::Part.new do
474
+ content_type 'text/html; charset=UTF-8'
475
+ body '<h1>This is HTML</h1>'
476
+ end
477
+
478
+ mail.text_part = text_part
479
+ mail.html_part = html_part
480
+ ```
481
+
482
+ Results in the same email as done using the block form
483
+
484
+ ### Getting error reports from an email:
485
+
486
+ ```ruby
487
+ @mail = Mail.read('/path/to/bounce_message.eml')
488
+
489
+ @mail.bounced? #=> true
490
+ @mail.final_recipient #=> rfc822;mikel@dont.exist.com
491
+ @mail.action #=> failed
492
+ @mail.error_status #=> 5.5.0
493
+ @mail.diagnostic_code #=> smtp;550 Requested action not taken: mailbox unavailable
494
+ @mail.retryable? #=> false
495
+ ```
496
+
497
+ ### Attaching and Detaching Files
498
+
499
+ You can just read the file off an absolute path, Mail will try
500
+ to guess the mime_type and will encode the file in Base64 for you.
501
+
502
+ ```ruby
503
+ @mail = Mail.new
504
+ @mail.add_file("/path/to/file.jpg")
505
+ @mail.parts.first.attachment? #=> true
506
+ @mail.parts.first.content_transfer_encoding.to_s #=> 'base64'
507
+ @mail.attachments.first.mime_type #=> 'image/jpg'
508
+ @mail.attachments.first.filename #=> 'file.jpg'
509
+ @mail.attachments.first.decoded == File.read('/path/to/file.jpg') #=> true
510
+ ```
511
+
512
+ Or You can pass in file_data and give it a filename, again, mail
513
+ will try and guess the mime_type for you.
514
+
515
+ ```ruby
516
+ @mail = Mail.new
517
+ @mail.attachments['myfile.pdf'] = File.read('path/to/myfile.pdf')
518
+ @mail.parts.first.attachment? #=> true
519
+ @mail.attachments.first.mime_type #=> 'application/pdf'
520
+ @mail.attachments.first.decoded == File.read('path/to/myfile.pdf') #=> true
521
+ ```
522
+
523
+ You can also override the guessed MIME media type if you really know better
524
+ than mail (this should be rarely needed)
525
+
526
+ ```ruby
527
+ @mail = Mail.new
528
+ file_data = File.read('path/to/myfile.pdf')
529
+ @mail.attachments['myfile.pdf'] = { :mime_type => 'application/x-pdf',
530
+ :content => File.read('path/to/myfile.pdf') }
531
+ @mail.parts.first.mime_type #=> 'application/x-pdf'
532
+ ```
533
+
534
+ Of course... Mail will round trip an attachment as well
535
+
536
+ ```ruby
537
+ @mail = Mail.new do
538
+ to 'nicolas@test.lindsaar.net.au'
539
+ from 'Mikel Lindsaar <mikel@test.lindsaar.net.au>'
540
+ subject 'First multipart email sent with Mail'
541
+
542
+ text_part do
543
+ body 'Here is the attachment you wanted'
544
+ end
545
+
546
+ html_part do
547
+ content_type 'text/html; charset=UTF-8'
548
+ body '<h1>Funky Title</h1><p>Here is the attachment you wanted</p>'
549
+ end
550
+
551
+ add_file '/path/to/myfile.pdf'
552
+ end
553
+
554
+ @round_tripped_mail = Mail.new(@mail.encoded)
555
+
556
+ @round_tripped_mail.attachments.length #=> 1
557
+ @round_tripped_mail.attachments.first.filename #=> 'myfile.pdf'
558
+ ```
559
+ See "Testing and extracting attachments" above for more details.
560
+
561
+ Using Mail with Testing or Spec'ing Libraries
562
+ ---------------------------------------------
563
+
564
+ If mail is part of your system, you'll need a way to test it without actually
565
+ sending emails, the TestMailer can do this for you.
566
+
567
+ ```ruby
568
+ require 'mail'
569
+ => true
570
+ Mail.defaults do
571
+ delivery_method :test
572
+ end
573
+ => #<Mail::Configuration:0x19345a8 @delivery_method=Mail::TestMailer>
574
+ Mail::TestMailer.deliveries
575
+ => []
576
+ Mail.deliver do
577
+ to 'mikel@me.com'
578
+ from 'you@you.com'
579
+ subject 'testing'
580
+ body 'hello'
581
+ end
582
+ => #<Mail::Message:0x19284ec ...
583
+ Mail::TestMailer.deliveries.length
584
+ => 1
585
+ Mail::TestMailer.deliveries.first
586
+ => #<Mail::Message:0x19284ec ...
587
+ Mail::TestMailer.deliveries.clear
588
+ => []
589
+ ```
590
+
591
+ 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):
592
+
593
+ ```ruby
594
+ Mail.defaults do
595
+ delivery_method :test # in practice you'd do this in spec_helper.rb
596
+ end
597
+
598
+ describe "sending an email" do
599
+ include Mail::Matchers
600
+
601
+ before(:each) do
602
+ Mail::TestMailer.deliveries.clear
603
+
604
+ Mail.deliver do
605
+ to ['mikel@me.com', 'mike2@me.com']
606
+ from 'you@you.com'
607
+ subject 'testing'
608
+ body 'hello'
609
+ end
610
+ end
611
+
612
+ it { should have_sent_email } # passes if any email at all was sent
613
+
614
+ it { should have_sent_email.from('you@you.com') }
615
+ it { should have_sent_email.to('mike1@me.com') }
616
+
617
+ # can specify a list of recipients...
618
+ it { should have_sent_email.to(['mike1@me.com', 'mike2@me.com']) }
619
+
620
+ # ...or chain recipients together
621
+ it { should have_sent_email.to('mike1@me.com').to('mike2@me.com') }
622
+
623
+ it { should have_sent_email.with_subject('testing') }
624
+
625
+ it { should have_sent_email.with_body('hello') }
626
+
627
+ # Can match subject or body with a regex
628
+ # (or anything that responds_to? :match)
629
+
630
+ it { should have_sent_email.matching_subject(/test(ing)?/) }
631
+ it { should have_sent_email.matching_body(/h(a|e)llo/) }
632
+
633
+ # Can chain together modifiers
634
+ # Note that apart from recipients, repeating a modifier overwrites old value.
635
+
636
+ it { should have_sent_email.from('you@you.com').to('mike1@me.com').matching_body(/hell/)
637
+ end
638
+ ```
639
+
640
+ Excerpts from TREC Spam Corpus 2005
641
+ -----------------------------------
642
+
643
+ The spec fixture files in spec/fixtures/emails/from_trec_2005 are from the
644
+ 2005 TREC Public Spam Corpus. They remain copyrighted under the terms of
645
+ that project and license agreement. They are used in this project to verify
646
+ and describe the development of this email parser implementation.
647
+
648
+ http://plg.uwaterloo.ca/~gvcormac/treccorpus/
649
+
650
+ They are used as allowed by 'Permitted Uses, Clause 3':
651
+
652
+ "Small excerpts of the information may be displayed to others
653
+ or published in a scientific or technical context, solely for
654
+ the purpose of describing the research and development and
655
+ related issues."
656
+
657
+ -- http://plg.uwaterloo.ca/~gvcormac/treccorpus/
658
+
659
+ License
660
+ -------
661
+
662
+ (The MIT License)
663
+
664
+ Copyright (c) 2009-2013 Mikel Lindsaar
665
+
666
+ Permission is hereby granted, free of charge, to any person obtaining
667
+ a copy of this software and associated documentation files (the
668
+ 'Software'), to deal in the Software without restriction, including
669
+ without limitation the rights to use, copy, modify, merge, publish,
670
+ distribute, sublicense, and/or sell copies of the Software, and to
671
+ permit persons to whom the Software is furnished to do so, subject to
672
+ the following conditions:
673
+
674
+ The above copyright notice and this permission notice shall be
675
+ included in all copies or substantial portions of the Software.
676
+
677
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
678
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
679
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
680
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
681
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
682
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
683
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.