mail 2.6.4 → 2.8.0

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 (179) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +111 -118
  3. data/lib/mail/attachments_list.rb +11 -10
  4. data/lib/mail/body.rb +73 -84
  5. data/lib/mail/check_delivery_params.rb +54 -10
  6. data/lib/mail/configuration.rb +2 -0
  7. data/lib/mail/constants.rb +27 -5
  8. data/lib/mail/elements/address.rb +61 -50
  9. data/lib/mail/elements/address_list.rb +11 -19
  10. data/lib/mail/elements/content_disposition_element.rb +9 -16
  11. data/lib/mail/elements/content_location_element.rb +6 -11
  12. data/lib/mail/elements/content_transfer_encoding_element.rb +6 -11
  13. data/lib/mail/elements/content_type_element.rb +16 -23
  14. data/lib/mail/elements/date_time_element.rb +7 -15
  15. data/lib/mail/elements/envelope_from_element.rb +22 -23
  16. data/lib/mail/elements/message_ids_element.rb +18 -13
  17. data/lib/mail/elements/mime_version_element.rb +7 -15
  18. data/lib/mail/elements/phrase_list.rb +12 -10
  19. data/lib/mail/elements/received_element.rb +27 -19
  20. data/lib/mail/encodings/7bit.rb +9 -14
  21. data/lib/mail/encodings/8bit.rb +2 -21
  22. data/lib/mail/encodings/base64.rb +11 -12
  23. data/lib/mail/encodings/binary.rb +3 -22
  24. data/lib/mail/encodings/identity.rb +24 -0
  25. data/lib/mail/encodings/quoted_printable.rb +6 -6
  26. data/lib/mail/encodings/transfer_encoding.rb +38 -29
  27. data/lib/mail/encodings/unix_to_unix.rb +3 -1
  28. data/lib/mail/encodings.rb +81 -54
  29. data/lib/mail/envelope.rb +11 -14
  30. data/lib/mail/field.rb +119 -98
  31. data/lib/mail/field_list.rb +60 -7
  32. data/lib/mail/fields/bcc_field.rb +34 -52
  33. data/lib/mail/fields/cc_field.rb +28 -49
  34. data/lib/mail/fields/comments_field.rb +27 -37
  35. data/lib/mail/fields/common_address_field.rb +170 -0
  36. data/lib/mail/fields/common_date_field.rb +58 -0
  37. data/lib/mail/fields/common_field.rb +77 -0
  38. data/lib/mail/fields/common_message_id_field.rb +42 -0
  39. data/lib/mail/fields/content_description_field.rb +7 -14
  40. data/lib/mail/fields/content_disposition_field.rb +13 -38
  41. data/lib/mail/fields/content_id_field.rb +24 -51
  42. data/lib/mail/fields/content_location_field.rb +11 -25
  43. data/lib/mail/fields/content_transfer_encoding_field.rb +31 -31
  44. data/lib/mail/fields/content_type_field.rb +50 -80
  45. data/lib/mail/fields/date_field.rb +23 -52
  46. data/lib/mail/fields/from_field.rb +28 -49
  47. data/lib/mail/fields/in_reply_to_field.rb +38 -49
  48. data/lib/mail/fields/keywords_field.rb +18 -31
  49. data/lib/mail/fields/message_id_field.rb +25 -71
  50. data/lib/mail/fields/mime_version_field.rb +19 -30
  51. data/lib/mail/fields/named_structured_field.rb +11 -0
  52. data/lib/mail/fields/named_unstructured_field.rb +11 -0
  53. data/lib/mail/fields/optional_field.rb +9 -7
  54. data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +13 -11
  55. data/lib/mail/fields/received_field.rb +43 -57
  56. data/lib/mail/fields/references_field.rb +35 -49
  57. data/lib/mail/fields/reply_to_field.rb +28 -49
  58. data/lib/mail/fields/resent_bcc_field.rb +28 -49
  59. data/lib/mail/fields/resent_cc_field.rb +28 -49
  60. data/lib/mail/fields/resent_date_field.rb +5 -30
  61. data/lib/mail/fields/resent_from_field.rb +28 -49
  62. data/lib/mail/fields/resent_message_id_field.rb +5 -29
  63. data/lib/mail/fields/resent_sender_field.rb +27 -56
  64. data/lib/mail/fields/resent_to_field.rb +28 -49
  65. data/lib/mail/fields/return_path_field.rb +50 -54
  66. data/lib/mail/fields/sender_field.rb +34 -55
  67. data/lib/mail/fields/structured_field.rb +3 -30
  68. data/lib/mail/fields/subject_field.rb +9 -11
  69. data/lib/mail/fields/to_field.rb +28 -49
  70. data/lib/mail/fields/unstructured_field.rb +32 -47
  71. data/lib/mail/header.rb +71 -110
  72. data/lib/mail/mail.rb +2 -10
  73. data/lib/mail/matchers/attachment_matchers.rb +15 -0
  74. data/lib/mail/matchers/has_sent_mail.rb +21 -1
  75. data/lib/mail/message.rb +113 -117
  76. data/lib/mail/multibyte/chars.rb +23 -180
  77. data/lib/mail/multibyte/unicode.rb +10 -10
  78. data/lib/mail/multibyte/utils.rb +26 -43
  79. data/lib/mail/multibyte.rb +55 -16
  80. data/lib/mail/network/delivery_methods/exim.rb +8 -11
  81. data/lib/mail/network/delivery_methods/file_delivery.rb +13 -16
  82. data/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
  83. data/lib/mail/network/delivery_methods/sendmail.rb +32 -35
  84. data/lib/mail/network/delivery_methods/smtp.rb +76 -54
  85. data/lib/mail/network/delivery_methods/smtp_connection.rb +4 -9
  86. data/lib/mail/network/delivery_methods/test_mailer.rb +8 -9
  87. data/lib/mail/network/retriever_methods/base.rb +8 -8
  88. data/lib/mail/network/retriever_methods/imap.rb +20 -7
  89. data/lib/mail/network/retriever_methods/pop3.rb +5 -3
  90. data/lib/mail/network/retriever_methods/test_retriever.rb +3 -2
  91. data/lib/mail/network.rb +1 -0
  92. data/lib/mail/parser_tools.rb +15 -0
  93. data/lib/mail/parsers/address_lists_parser.rb +33225 -116
  94. data/lib/mail/parsers/address_lists_parser.rl +179 -0
  95. data/lib/mail/parsers/content_disposition_parser.rb +882 -49
  96. data/lib/mail/parsers/content_disposition_parser.rl +89 -0
  97. data/lib/mail/parsers/content_location_parser.rb +809 -23
  98. data/lib/mail/parsers/content_location_parser.rl +78 -0
  99. data/lib/mail/parsers/content_transfer_encoding_parser.rb +509 -21
  100. data/lib/mail/parsers/content_transfer_encoding_parser.rl +71 -0
  101. data/lib/mail/parsers/content_type_parser.rb +1037 -56
  102. data/lib/mail/parsers/content_type_parser.rl +90 -0
  103. data/lib/mail/parsers/date_time_parser.rb +877 -25
  104. data/lib/mail/parsers/date_time_parser.rl +69 -0
  105. data/lib/mail/parsers/envelope_from_parser.rb +3669 -40
  106. data/lib/mail/parsers/envelope_from_parser.rl +89 -0
  107. data/lib/mail/parsers/message_ids_parser.rb +5146 -25
  108. data/lib/mail/parsers/message_ids_parser.rl +93 -0
  109. data/lib/mail/parsers/mime_version_parser.rb +497 -26
  110. data/lib/mail/parsers/mime_version_parser.rl +68 -0
  111. data/lib/mail/parsers/phrase_lists_parser.rb +870 -22
  112. data/lib/mail/parsers/phrase_lists_parser.rl +90 -0
  113. data/lib/mail/parsers/received_parser.rb +8776 -43
  114. data/lib/mail/parsers/received_parser.rl +91 -0
  115. data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
  116. data/lib/mail/parsers/rfc2045_content_type.rl +25 -0
  117. data/lib/mail/parsers/rfc2045_mime.rl +16 -0
  118. data/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
  119. data/lib/mail/parsers/rfc3629_utf8.rl +19 -0
  120. data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
  121. data/lib/mail/parsers/rfc5322.rl +74 -0
  122. data/lib/mail/parsers/rfc5322_address.rl +72 -0
  123. data/lib/mail/parsers/{ragel/date_time.rl → rfc5322_date_time.rl} +8 -1
  124. data/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
  125. data/lib/mail/parsers.rb +11 -25
  126. data/lib/mail/part.rb +6 -10
  127. data/lib/mail/parts_list.rb +62 -6
  128. data/lib/mail/smtp_envelope.rb +57 -0
  129. data/lib/mail/utilities.rb +357 -74
  130. data/lib/mail/version.rb +2 -2
  131. data/lib/mail/yaml.rb +30 -0
  132. data/lib/mail.rb +5 -35
  133. metadata +111 -66
  134. data/CHANGELOG.rdoc +0 -787
  135. data/CONTRIBUTING.md +0 -60
  136. data/Dependencies.txt +0 -2
  137. data/Gemfile +0 -11
  138. data/Rakefile +0 -29
  139. data/TODO.rdoc +0 -9
  140. data/lib/mail/core_extensions/smtp.rb +0 -25
  141. data/lib/mail/core_extensions/string/access.rb +0 -146
  142. data/lib/mail/core_extensions/string/multibyte.rb +0 -79
  143. data/lib/mail/core_extensions/string.rb +0 -21
  144. data/lib/mail/fields/common/address_container.rb +0 -17
  145. data/lib/mail/fields/common/common_address.rb +0 -136
  146. data/lib/mail/fields/common/common_date.rb +0 -36
  147. data/lib/mail/fields/common/common_field.rb +0 -61
  148. data/lib/mail/fields/common/common_message_id.rb +0 -49
  149. data/lib/mail/multibyte/exceptions.rb +0 -9
  150. data/lib/mail/parsers/ragel/common.rl +0 -185
  151. data/lib/mail/parsers/ragel/parser_info.rb +0 -61
  152. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +0 -14864
  153. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +0 -37
  154. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +0 -751
  155. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +0 -37
  156. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +0 -614
  157. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +0 -37
  158. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +0 -447
  159. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +0 -37
  160. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +0 -825
  161. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +0 -37
  162. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +0 -817
  163. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +0 -37
  164. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +0 -2149
  165. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +0 -37
  166. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +0 -1570
  167. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +0 -37
  168. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +0 -440
  169. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +0 -37
  170. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +0 -564
  171. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +0 -37
  172. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +0 -51
  173. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +0 -5144
  174. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +0 -37
  175. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +0 -37
  176. data/lib/mail/parsers/ragel/ruby.rb +0 -40
  177. data/lib/mail/parsers/ragel.rb +0 -18
  178. data/lib/mail/version_specific/ruby_1_8.rb +0 -126
  179. data/lib/mail/version_specific/ruby_1_9.rb +0 -223
@@ -1,53 +1,55 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- require 'mail/fields/common/parameter_hash'
3
+ require 'mail/fields/named_structured_field'
4
+ require 'mail/fields/parameter_hash'
4
5
 
5
6
  module Mail
6
- class ContentTypeField < StructuredField
7
+ class ContentTypeField < NamedStructuredField #:nodoc:
8
+ NAME = 'Content-Type'
7
9
 
8
- FIELD_NAME = 'content-type'
9
- CAPITALIZED_FIELD = 'Content-Type'
10
+ class << self
11
+ def singular?
12
+ true
13
+ end
14
+
15
+ def with_boundary(type)
16
+ new "#{type}; boundary=#{generate_boundary}"
17
+ end
18
+
19
+ def generate_boundary
20
+ "--==_mimepart_#{Mail.random_tag}"
21
+ end
22
+ end
10
23
 
11
- def initialize(value = nil, charset = 'utf-8')
12
- self.charset = charset
13
- if value.class == Array
24
+ def initialize(value = nil, charset = nil)
25
+ if value.is_a? Array
14
26
  @main_type = value[0]
15
27
  @sub_type = value[1]
16
28
  @parameters = ParameterHash.new.merge!(value.last)
17
29
  else
18
30
  @main_type = nil
19
31
  @sub_type = nil
20
- @parameters = nil
21
- value = strip_field(FIELD_NAME, value)
32
+ value = value.to_s
22
33
  end
23
- value = ensure_filename_quoted(value)
24
- super(CAPITALIZED_FIELD, value, charset)
25
- self.parse
26
- self
27
- end
28
34
 
29
- def parse(val = value)
30
- unless Utilities.blank?(val)
31
- self.value = val
32
- @element = nil
33
- element
34
- end
35
+ super ensure_filename_quoted(value), charset
35
36
  end
36
37
 
37
38
  def element
38
- begin
39
- @element ||= Mail::ContentTypeElement.new(value)
40
- rescue
41
- attempt_to_clean
42
- end
39
+ @element ||=
40
+ begin
41
+ Mail::ContentTypeElement.new(value)
42
+ rescue Mail::Field::ParseError
43
+ attempt_to_clean
44
+ end
43
45
  end
44
46
 
45
47
  def attempt_to_clean
46
48
  # Sanitize the value, handle special cases
47
- @element ||= Mail::ContentTypeElement.new(sanatize(value))
48
- rescue
49
+ Mail::ContentTypeElement.new(sanitize(value))
50
+ rescue Mail::Field::ParseError
49
51
  # All else fails, just get the MIME media type
50
- @element ||= Mail::ContentTypeElement.new(get_mime_type(value))
52
+ Mail::ContentTypeElement.new(get_mime_type(value))
51
53
  end
52
54
 
53
55
  def main_type
@@ -61,31 +63,22 @@ module Mail
61
63
  def string
62
64
  "#{main_type}/#{sub_type}"
63
65
  end
66
+ alias_method :content_type, :string
64
67
 
65
68
  def default
66
69
  decoded
67
70
  end
68
71
 
69
- alias :content_type :string
70
-
71
72
  def parameters
72
- unless @parameters
73
+ unless defined? @parameters
73
74
  @parameters = ParameterHash.new
74
75
  element.parameters.each { |p| @parameters.merge!(p) }
75
76
  end
76
77
  @parameters
77
78
  end
78
79
 
79
- def ContentTypeField.with_boundary(type)
80
- new("#{type}; boundary=#{generate_boundary}")
81
- end
82
-
83
- def ContentTypeField.generate_boundary
84
- "--==_mimepart_#{Mail.random_tag}"
85
- end
86
-
87
80
  def value
88
- if @value.class == Array
81
+ if @value.is_a? Array
89
82
  "#{@main_type}/#{@sub_type}; #{stringify(parameters)}"
90
83
  else
91
84
  @value
@@ -97,34 +90,17 @@ module Mail
97
90
  end
98
91
 
99
92
  def filename
100
- case
101
- when parameters['filename']
102
- @filename = parameters['filename']
103
- when parameters['name']
104
- @filename = parameters['name']
105
- else
106
- @filename = nil
107
- end
108
- @filename
93
+ @filename ||= parameters['filename'] || parameters['name']
109
94
  end
110
95
 
111
- # TODO: Fix this up
112
96
  def encoded
113
- if parameters.length > 0
114
- p = ";\r\n\s#{parameters.encoded}"
115
- else
116
- p = ""
117
- end
118
- "#{CAPITALIZED_FIELD}: #{content_type}#{p}\r\n"
97
+ p = ";\r\n\s#{parameters.encoded}" if parameters && parameters.length > 0
98
+ "#{name}: #{content_type}#{p}\r\n"
119
99
  end
120
100
 
121
101
  def decoded
122
- if parameters.length > 0
123
- p = "; #{parameters.decoded}"
124
- else
125
- p = ""
126
- end
127
- "#{content_type}" + p
102
+ p = "; #{parameters.decoded}" if parameters && parameters.length > 0
103
+ "#{content_type}#{p}"
128
104
  end
129
105
 
130
106
  private
@@ -140,30 +116,24 @@ module Mail
140
116
 
141
117
  # Various special cases from random emails found that I am not going to change
142
118
  # the parser for
143
- def sanatize( val )
144
-
119
+ def sanitize(val)
145
120
  # TODO: check if there are cases where whitespace is not a separator
146
121
  val = val.
147
122
  gsub(/\s*=\s*/,'='). # remove whitespaces around equal sign
148
- tr(' ',';').
149
- squeeze(';').
150
- gsub(';', '; '). #use '; ' as a separator (or EOL)
123
+ gsub(/[; ]+/, '; '). #use '; ' as a separator (or EOL)
151
124
  gsub(/;\s*$/,'') #remove trailing to keep examples below
152
125
 
153
- if val =~ /(boundary=(\S*))/i
154
- val = "#{$`.downcase}boundary=#{$2}#{$'.downcase}"
126
+ if val =~ /((boundary|name|filename)=(\S*))/i
127
+ val = "#{$`.downcase}#{$2}=#{$3}#{$'.downcase}"
155
128
  else
156
129
  val.downcase!
157
130
  end
158
131
 
159
132
  case
160
- when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;;+(.*)$/i
161
- # Handles 'text/plain;; format="flowed"' (double semi colon)
162
- "#{$1}/#{$2}; #{$3}"
163
133
  when val.chomp =~ /^\s*([\w\-]+)\/([\w\-]+)\s*;\s?(ISO[\w\-]+)$/i
164
134
  # Microsoft helper:
165
135
  # Handles 'type/subtype;ISO-8559-1'
166
- "#{$1}/#{$2}; charset=#{quote_atom($3)}"
136
+ "#{$1}/#{$2}; charset=#{Utilities.quote_atom($3)}"
167
137
  when val.chomp =~ /^text;?$/i
168
138
  # Handles 'text;' and 'text'
169
139
  "text/plain;"
@@ -172,7 +142,7 @@ module Mail
172
142
  "text/plain; #{$2}"
173
143
  when val =~ /([\w\-]+\/[\w\-]+);\scharset="charset="(\w+)""/i
174
144
  # Handles text/html; charset="charset="GB2312""
175
- "#{$1}; charset=#{quote_atom($2)}"
145
+ "#{$1}; charset=#{Utilities.quote_atom($2)}"
176
146
  when val =~ /([\w\-]+\/[\w\-]+);\s+(.*)/i
177
147
  type = $1
178
148
  # Handles misquoted param values
@@ -180,19 +150,19 @@ module Mail
180
150
  # and: audio/x-midi;\r\n\sname=Part .exe
181
151
  params = $2.to_s.split(/\s+/)
182
152
  params = params.map { |i| i.to_s.chomp.strip }
183
- params = params.map { |i| i.split(/\s*\=\s*/) }
184
- params = params.map { |i| "#{i[0]}=#{dquote(i[1].to_s.gsub(/;$/,""))}" }.join('; ')
153
+ params = params.map { |i| i.split(/\s*\=\s*/, 2) }
154
+ params = params.map { |i| "#{i[0]}=#{Utilities.dquote(i[1].to_s.gsub(/;$/,""))}" }.join('; ')
185
155
  "#{type}; #{params}"
186
156
  when val =~ /^\s*$/
187
157
  'text/plain'
188
158
  else
189
- ''
159
+ val
190
160
  end
191
161
  end
192
162
 
193
- def get_mime_type( val )
194
- case
195
- when val =~ /^([\w\-]+)\/([\w\-]+);.+$/i
163
+ def get_mime_type(val)
164
+ case val
165
+ when /^([\w\-]+)\/([\w\-]+);.+$/i
196
166
  "#{$1}/#{$2}"
197
167
  else
198
168
  'text/plain'
@@ -1,58 +1,29 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- #
4
- # = Date Field
5
- #
6
- # The Date field inherits from StructuredField and handles the Date: header
7
- # field in the email.
8
- #
9
- # Sending date to a mail message will instantiate a Mail::Field object that
10
- # has a DateField as its field type. This includes all Mail::CommonAddress
11
- # module instance methods.
12
- #
13
- # There must be excatly one Date field in an RFC2822 email.
14
- #
15
- # == Examples:
16
- #
17
- # mail = Mail.new
18
- # mail.date = 'Mon, 24 Nov 1997 14:22:01 -0800'
19
- # mail.date #=> #<DateTime: 211747170121/86400,-1/3,2299161>
20
- # mail.date.to_s #=> 'Mon, 24 Nov 1997 14:22:01 -0800'
21
- # mail[:date] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
22
- # mail['date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
23
- # mail['Date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
24
- #
25
- require 'mail/fields/common/common_date'
3
+ require 'mail/fields/common_date_field'
26
4
 
27
5
  module Mail
28
- class DateField < StructuredField
29
-
30
- include Mail::CommonDate
31
-
32
- FIELD_NAME = 'date'
33
- CAPITALIZED_FIELD = "Date"
34
-
35
- def initialize(value = nil, charset = 'utf-8')
36
- self.charset = charset
37
- if Utilities.blank?(value)
38
- value = ::DateTime.now.strftime('%a, %d %b %Y %H:%M:%S %z')
39
- else
40
- value = strip_field(FIELD_NAME, value)
41
- value.to_s.gsub!(/\(.*?\)/, '')
42
- value = ::DateTime.parse(value.to_s.squeeze(" ")).strftime('%a, %d %b %Y %H:%M:%S %z')
43
- end
44
- super(CAPITALIZED_FIELD, value, charset)
45
- rescue ArgumentError => e
46
- raise e unless "invalid date"==e.message
47
- end
48
-
49
- def encoded
50
- do_encode(CAPITALIZED_FIELD)
51
- end
52
-
53
- def decoded
54
- do_decode
55
- end
56
-
6
+ # = Date Field
7
+ #
8
+ # The Date field inherits from StructuredField and handles the Date: header
9
+ # field in the email.
10
+ #
11
+ # Sending date to a mail message will instantiate a Mail::Field object that
12
+ # has a DateField as its field type. This includes all Mail::CommonAddress
13
+ # module instance methods.
14
+ #
15
+ # There must be excatly one Date field in an RFC2822 email.
16
+ #
17
+ # == Examples:
18
+ #
19
+ # mail = Mail.new
20
+ # mail.date = 'Mon, 24 Nov 1997 14:22:01 -0800'
21
+ # mail.date #=> #<DateTime: 211747170121/86400,-1/3,2299161>
22
+ # mail.date.to_s #=> 'Mon, 24 Nov 1997 14:22:01 -0800'
23
+ # mail[:date] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
24
+ # mail['date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
25
+ # mail['Date'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::DateField:0x180e1c4
26
+ class DateField < CommonDateField #:nodoc:
27
+ NAME = 'Date'
57
28
  end
58
29
  end
@@ -1,55 +1,34 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- #
4
- # = From Field
5
- #
6
- # The From field inherits from StructuredField and handles the From: header
7
- # field in the email.
8
- #
9
- # Sending from to a mail message will instantiate a Mail::Field object that
10
- # has a FromField as its field type. This includes all Mail::CommonAddress
11
- # module instance metods.
12
- #
13
- # Only one From field can appear in a header, though it can have multiple
14
- # addresses and groups of addresses.
15
- #
16
- # == Examples:
17
- #
18
- # mail = Mail.new
19
- # mail.from = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
20
- # mail.from #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
21
- # mail[:from] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
22
- # mail['from'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
23
- # mail['From'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
24
- #
25
- # mail[:from].encoded #=> 'from: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
26
- # mail[:from].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
27
- # mail[:from].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
28
- # mail[:from].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
29
- #
30
- require 'mail/fields/common/common_address'
3
+ require 'mail/fields/common_address_field'
31
4
 
32
5
  module Mail
33
- class FromField < StructuredField
34
-
35
- include Mail::CommonAddress
36
-
37
- FIELD_NAME = 'from'
38
- CAPITALIZED_FIELD = 'From'
39
-
40
- def initialize(value = nil, charset = 'utf-8')
41
- self.charset = charset
42
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
43
- self
44
- end
45
-
46
- def encoded
47
- do_encode(CAPITALIZED_FIELD)
48
- end
49
-
50
- def decoded
51
- do_decode
52
- end
53
-
6
+ # = From Field
7
+ #
8
+ # The From field inherits from StructuredField and handles the From: header
9
+ # field in the email.
10
+ #
11
+ # Sending from to a mail message will instantiate a Mail::Field object that
12
+ # has a FromField as its field type. This includes all Mail::CommonAddress
13
+ # module instance metods.
14
+ #
15
+ # Only one From field can appear in a header, though it can have multiple
16
+ # addresses and groups of addresses.
17
+ #
18
+ # == Examples:
19
+ #
20
+ # mail = Mail.new
21
+ # mail.from = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
22
+ # mail.from #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
23
+ # mail[:from] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
24
+ # mail['from'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
25
+ # mail['From'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::FromField:0x180e1c4
26
+ #
27
+ # mail[:from].encoded #=> 'from: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
28
+ # mail[:from].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
29
+ # mail[:from].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
30
+ # mail[:from].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
31
+ class FromField < CommonAddressField #:nodoc:
32
+ NAME = 'From'
54
33
  end
55
34
  end
@@ -1,57 +1,46 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- #
4
- # = In-Reply-To Field
5
- #
6
- # The In-Reply-To field inherits from StructuredField and handles the
7
- # In-Reply-To: header field in the email.
8
- #
9
- # Sending in_reply_to to a mail message will instantiate a Mail::Field object that
10
- # has a InReplyToField as its field type. This includes all Mail::CommonMessageId
11
- # module instance metods.
12
- #
13
- # Note that, the #message_ids method will return an array of message IDs without the
14
- # enclosing angle brackets which per RFC are not syntactically part of the message id.
15
- #
16
- # Only one InReplyTo field can appear in a header, though it can have multiple
17
- # Message IDs.
18
- #
19
- # == Examples:
20
- #
21
- # mail = Mail.new
22
- # mail.in_reply_to = '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
23
- # mail.in_reply_to #=> '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
24
- # mail[:in_reply_to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
25
- # mail['in_reply_to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
26
- # mail['In-Reply-To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
27
- #
28
- # mail[:in_reply_to].message_ids #=> ['F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom']
29
- #
30
- require 'mail/fields/common/common_message_id'
3
+ require 'mail/fields/common_message_id_field'
31
4
 
32
5
  module Mail
33
- class InReplyToField < StructuredField
34
-
35
- include Mail::CommonMessageId
36
-
37
- FIELD_NAME = 'in-reply-to'
38
- CAPITALIZED_FIELD = 'In-Reply-To'
39
-
40
- def initialize(value = nil, charset = 'utf-8')
41
- self.charset = charset
42
- value = value.join("\r\n\s") if value.is_a?(Array)
43
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
44
- self.parse
45
- self
46
- end
47
-
48
- def encoded
49
- do_encode(CAPITALIZED_FIELD)
6
+ # = In-Reply-To Field
7
+ #
8
+ # The In-Reply-To field inherits from StructuredField and handles the
9
+ # In-Reply-To: header field in the email.
10
+ #
11
+ # Sending in_reply_to to a mail message will instantiate a Mail::Field object that
12
+ # has a InReplyToField as its field type. This includes all Mail::CommonMessageId
13
+ # module instance metods.
14
+ #
15
+ # Note that, the #message_ids method will return an array of message IDs without the
16
+ # enclosing angle brackets which per RFC are not syntactically part of the message id.
17
+ #
18
+ # Only one InReplyTo field can appear in a header, though it can have multiple
19
+ # Message IDs.
20
+ #
21
+ # == Examples:
22
+ #
23
+ # mail = Mail.new
24
+ # mail.in_reply_to = '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
25
+ # mail.in_reply_to #=> '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
26
+ # mail[:in_reply_to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
27
+ # mail['in_reply_to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
28
+ # mail['In-Reply-To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::InReplyToField:0x180e1c4
29
+ #
30
+ # mail[:in_reply_to].message_ids #=> ['F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom']
31
+ class InReplyToField < CommonMessageIdField #:nodoc:
32
+ NAME = 'In-Reply-To'
33
+
34
+ def self.singular?
35
+ true
50
36
  end
51
-
52
- def decoded
53
- do_decode
37
+
38
+ def initialize(value = nil, charset = nil)
39
+ if value.is_a?(Array)
40
+ super value.join("\r\n\s"), charset
41
+ else
42
+ super
43
+ end
54
44
  end
55
-
56
45
  end
57
46
  end
@@ -1,44 +1,31 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- #
4
- # keywords = "Keywords:" phrase *("," phrase) CRLF
3
+ require 'mail/fields/named_structured_field'
4
+
5
5
  module Mail
6
- class KeywordsField < StructuredField
7
-
8
- FIELD_NAME = 'keywords'
9
- CAPITALIZED_FIELD = 'Keywords'
10
-
11
- def initialize(value = nil, charset = 'utf-8')
12
- self.charset = charset
13
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
14
- self
15
- end
6
+ # keywords = "Keywords:" phrase *("," phrase) CRLF
7
+ class KeywordsField < NamedStructuredField #:nodoc:
8
+ NAME = 'Keywords'
16
9
 
17
- def parse(val = value)
18
- unless Utilities.blank?(val)
19
- @phrase_list ||= PhraseList.new(value)
20
- end
10
+ def element
11
+ @element ||= PhraseList.new(value)
21
12
  end
22
-
23
- def phrase_list
24
- @phrase_list ||= PhraseList.new(value)
25
- end
26
-
13
+
27
14
  def keywords
28
- phrase_list.phrases
29
- end
30
-
31
- def encoded
32
- "#{CAPITALIZED_FIELD}: #{keywords.join(",\r\n ")}\r\n"
33
- end
34
-
35
- def decoded
36
- keywords.join(', ')
15
+ element.phrases
37
16
  end
38
17
 
39
18
  def default
40
19
  keywords
41
20
  end
42
-
21
+
22
+ private
23
+ def do_decode
24
+ keywords.join(', ')
25
+ end
26
+
27
+ def do_encode
28
+ "#{name}: #{keywords.join(",\r\n ")}\r\n"
29
+ end
43
30
  end
44
31
  end
@@ -1,83 +1,37 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- #
4
- # = Message-ID Field
5
- #
6
- # The Message-ID field inherits from StructuredField and handles the
7
- # Message-ID: header field in the email.
8
- #
9
- # Sending message_id to a mail message will instantiate a Mail::Field object that
10
- # has a MessageIdField as its field type. This includes all Mail::CommonMessageId
11
- # module instance metods.
12
- #
13
- # Only one MessageId field can appear in a header, and syntactically it can only have
14
- # one Message ID. The message_ids method call has been left in however as it will only
15
- # return the one message id, ie, an array of length 1.
16
- #
17
- # Note that, the #message_ids method will return an array of message IDs without the
18
- # enclosing angle brackets which per RFC are not syntactically part of the message id.
19
- #
20
- # == Examples:
21
- #
22
- # mail = Mail.new
23
- # mail.message_id = '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
24
- # mail.message_id #=> '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
25
- # mail[:message_id] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
26
- # mail['message_id'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
27
- # mail['Message-ID'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
28
- #
29
- # mail[:message_id].message_id #=> 'F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom'
30
- # mail[:message_id].message_ids #=> ['F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom']
31
- #
32
- require 'mail/fields/common/common_message_id'
3
+ require 'mail/fields/common_message_id_field'
4
+ require 'mail/utilities'
33
5
 
34
6
  module Mail
35
- class MessageIdField < StructuredField
36
-
37
- include Mail::CommonMessageId
38
-
39
- FIELD_NAME = 'message-id'
40
- CAPITALIZED_FIELD = 'Message-ID'
41
-
42
- def initialize(value = nil, charset = 'utf-8')
43
- self.charset = charset
44
- @uniq = 1
45
- if Utilities.blank?(value)
46
- self.name = CAPITALIZED_FIELD
47
- self.value = generate_message_id
48
- else
49
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
50
- end
51
- self.parse
52
- self
7
+ # Only one Message-ID field may appear in a header.
8
+ #
9
+ # Note that parsed Message IDs do not contain their enclosing angle
10
+ # brackets which, per RFC, are not part of the ID.
11
+ #
12
+ # mail = Mail.new
13
+ # mail.message_id = '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
14
+ # mail.message_id #=> '<F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom>'
15
+ # mail[:message_id] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
16
+ # mail['message_id'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
17
+ # mail['Message-ID'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::MessageIdField:0x180e1c4
18
+ #
19
+ # mail[:message_id].message_id #=> 'F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom'
20
+ # mail[:message_id].message_ids #=> ['F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@test.me.dom']
21
+ class MessageIdField < CommonMessageIdField #:nodoc:
22
+ NAME = 'Message-ID'
53
23
 
24
+ def self.singular?
25
+ true
54
26
  end
55
-
56
- def name
57
- 'Message-ID'
27
+
28
+ def initialize(value = nil, charset = nil)
29
+ value = Mail::Utilities.generate_message_id if Utilities.blank?(value)
30
+ super value, charset
58
31
  end
59
-
32
+
60
33
  def message_ids
61
34
  [message_id]
62
35
  end
63
-
64
- def to_s
65
- "<#{message_id}>"
66
- end
67
-
68
- def encoded
69
- do_encode(CAPITALIZED_FIELD)
70
- end
71
-
72
- def decoded
73
- do_decode
74
- end
75
-
76
- private
77
-
78
- def generate_message_id
79
- "<#{Mail.random_tag}@#{::Socket.gethostname}.mail>"
80
- end
81
-
82
36
  end
83
37
  end