mail 2.6.6 → 2.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +5 -5
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +134 -119
  4. data/lib/mail/attachments_list.rb +10 -9
  5. data/lib/mail/body.rb +73 -84
  6. data/lib/mail/check_delivery_params.rb +28 -21
  7. data/lib/mail/configuration.rb +2 -0
  8. data/lib/mail/constants.rb +27 -5
  9. data/lib/mail/elements/address.rb +53 -47
  10. data/lib/mail/elements/address_list.rb +11 -19
  11. data/lib/mail/elements/content_disposition_element.rb +9 -16
  12. data/lib/mail/elements/content_location_element.rb +6 -11
  13. data/lib/mail/elements/content_transfer_encoding_element.rb +6 -11
  14. data/lib/mail/elements/content_type_element.rb +16 -23
  15. data/lib/mail/elements/date_time_element.rb +7 -15
  16. data/lib/mail/elements/envelope_from_element.rb +22 -23
  17. data/lib/mail/elements/message_ids_element.rb +18 -13
  18. data/lib/mail/elements/mime_version_element.rb +7 -15
  19. data/lib/mail/elements/phrase_list.rb +12 -10
  20. data/lib/mail/elements/received_element.rb +27 -19
  21. data/lib/mail/encodings/7bit.rb +9 -14
  22. data/lib/mail/encodings/8bit.rb +2 -21
  23. data/lib/mail/encodings/base64.rb +11 -12
  24. data/lib/mail/encodings/binary.rb +3 -22
  25. data/lib/mail/encodings/identity.rb +24 -0
  26. data/lib/mail/encodings/quoted_printable.rb +6 -6
  27. data/lib/mail/encodings/transfer_encoding.rb +38 -29
  28. data/lib/mail/encodings/unix_to_unix.rb +3 -1
  29. data/lib/mail/encodings.rb +81 -54
  30. data/lib/mail/envelope.rb +11 -14
  31. data/lib/mail/field.rb +119 -98
  32. data/lib/mail/field_list.rb +60 -7
  33. data/lib/mail/fields/bcc_field.rb +34 -52
  34. data/lib/mail/fields/cc_field.rb +28 -49
  35. data/lib/mail/fields/comments_field.rb +27 -37
  36. data/lib/mail/fields/common_address_field.rb +170 -0
  37. data/lib/mail/fields/common_date_field.rb +58 -0
  38. data/lib/mail/fields/common_field.rb +77 -0
  39. data/lib/mail/fields/common_message_id_field.rb +42 -0
  40. data/lib/mail/fields/content_description_field.rb +7 -14
  41. data/lib/mail/fields/content_disposition_field.rb +13 -38
  42. data/lib/mail/fields/content_id_field.rb +24 -51
  43. data/lib/mail/fields/content_location_field.rb +11 -25
  44. data/lib/mail/fields/content_transfer_encoding_field.rb +31 -31
  45. data/lib/mail/fields/content_type_field.rb +50 -80
  46. data/lib/mail/fields/date_field.rb +23 -52
  47. data/lib/mail/fields/from_field.rb +28 -49
  48. data/lib/mail/fields/in_reply_to_field.rb +38 -49
  49. data/lib/mail/fields/keywords_field.rb +18 -31
  50. data/lib/mail/fields/message_id_field.rb +25 -71
  51. data/lib/mail/fields/mime_version_field.rb +19 -30
  52. data/lib/mail/fields/named_structured_field.rb +11 -0
  53. data/lib/mail/fields/named_unstructured_field.rb +11 -0
  54. data/lib/mail/fields/optional_field.rb +9 -7
  55. data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +13 -11
  56. data/lib/mail/fields/received_field.rb +43 -57
  57. data/lib/mail/fields/references_field.rb +35 -49
  58. data/lib/mail/fields/reply_to_field.rb +28 -49
  59. data/lib/mail/fields/resent_bcc_field.rb +28 -49
  60. data/lib/mail/fields/resent_cc_field.rb +28 -49
  61. data/lib/mail/fields/resent_date_field.rb +5 -30
  62. data/lib/mail/fields/resent_from_field.rb +28 -49
  63. data/lib/mail/fields/resent_message_id_field.rb +5 -29
  64. data/lib/mail/fields/resent_sender_field.rb +27 -56
  65. data/lib/mail/fields/resent_to_field.rb +28 -49
  66. data/lib/mail/fields/return_path_field.rb +50 -54
  67. data/lib/mail/fields/sender_field.rb +34 -55
  68. data/lib/mail/fields/structured_field.rb +3 -30
  69. data/lib/mail/fields/subject_field.rb +9 -11
  70. data/lib/mail/fields/to_field.rb +28 -49
  71. data/lib/mail/fields/unstructured_field.rb +32 -47
  72. data/lib/mail/header.rb +71 -110
  73. data/lib/mail/mail.rb +2 -10
  74. data/lib/mail/matchers/attachment_matchers.rb +15 -0
  75. data/lib/mail/matchers/has_sent_mail.rb +21 -1
  76. data/lib/mail/message.rb +113 -117
  77. data/lib/mail/multibyte/chars.rb +21 -178
  78. data/lib/mail/multibyte/unicode.rb +10 -10
  79. data/lib/mail/multibyte/utils.rb +26 -43
  80. data/lib/mail/multibyte.rb +55 -16
  81. data/lib/mail/network/delivery_methods/exim.rb +5 -4
  82. data/lib/mail/network/delivery_methods/file_delivery.rb +11 -10
  83. data/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
  84. data/lib/mail/network/delivery_methods/sendmail.rb +62 -21
  85. data/lib/mail/network/delivery_methods/smtp.rb +75 -50
  86. data/lib/mail/network/delivery_methods/smtp_connection.rb +3 -4
  87. data/lib/mail/network/delivery_methods/test_mailer.rb +4 -2
  88. data/lib/mail/network/retriever_methods/base.rb +8 -8
  89. data/lib/mail/network/retriever_methods/imap.rb +20 -7
  90. data/lib/mail/network/retriever_methods/pop3.rb +5 -3
  91. data/lib/mail/network/retriever_methods/test_retriever.rb +2 -1
  92. data/lib/mail/network.rb +1 -0
  93. data/lib/mail/parser_tools.rb +15 -0
  94. data/lib/mail/parsers/address_lists_parser.rb +33225 -116
  95. data/lib/mail/parsers/address_lists_parser.rl +179 -0
  96. data/lib/mail/parsers/content_disposition_parser.rb +882 -49
  97. data/lib/mail/parsers/content_disposition_parser.rl +89 -0
  98. data/lib/mail/parsers/content_location_parser.rb +809 -23
  99. data/lib/mail/parsers/content_location_parser.rl +78 -0
  100. data/lib/mail/parsers/content_transfer_encoding_parser.rb +509 -21
  101. data/lib/mail/parsers/content_transfer_encoding_parser.rl +71 -0
  102. data/lib/mail/parsers/content_type_parser.rb +1037 -56
  103. data/lib/mail/parsers/content_type_parser.rl +90 -0
  104. data/lib/mail/parsers/date_time_parser.rb +877 -25
  105. data/lib/mail/parsers/date_time_parser.rl +69 -0
  106. data/lib/mail/parsers/envelope_from_parser.rb +3669 -40
  107. data/lib/mail/parsers/envelope_from_parser.rl +89 -0
  108. data/lib/mail/parsers/message_ids_parser.rb +5146 -25
  109. data/lib/mail/parsers/message_ids_parser.rl +93 -0
  110. data/lib/mail/parsers/mime_version_parser.rb +497 -26
  111. data/lib/mail/parsers/mime_version_parser.rl +68 -0
  112. data/lib/mail/parsers/phrase_lists_parser.rb +870 -22
  113. data/lib/mail/parsers/phrase_lists_parser.rl +90 -0
  114. data/lib/mail/parsers/received_parser.rb +8776 -43
  115. data/lib/mail/parsers/received_parser.rl +91 -0
  116. data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
  117. data/lib/mail/parsers/rfc2045_content_type.rl +25 -0
  118. data/lib/mail/parsers/rfc2045_mime.rl +16 -0
  119. data/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
  120. data/lib/mail/parsers/rfc3629_utf8.rl +19 -0
  121. data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
  122. data/lib/mail/parsers/rfc5322.rl +74 -0
  123. data/lib/mail/parsers/rfc5322_address.rl +72 -0
  124. data/lib/mail/parsers/{ragel/date_time.rl → rfc5322_date_time.rl} +8 -1
  125. data/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
  126. data/lib/mail/parsers.rb +11 -25
  127. data/lib/mail/part.rb +6 -10
  128. data/lib/mail/parts_list.rb +62 -6
  129. data/lib/mail/smtp_envelope.rb +57 -0
  130. data/lib/mail/utilities.rb +343 -74
  131. data/lib/mail/version.rb +2 -2
  132. data/lib/mail/yaml.rb +30 -0
  133. data/lib/mail.rb +5 -35
  134. metadata +111 -66
  135. data/CHANGELOG.rdoc +0 -803
  136. data/CONTRIBUTING.md +0 -60
  137. data/Dependencies.txt +0 -2
  138. data/Gemfile +0 -14
  139. data/Rakefile +0 -29
  140. data/TODO.rdoc +0 -9
  141. data/lib/mail/core_extensions/smtp.rb +0 -25
  142. data/lib/mail/core_extensions/string/access.rb +0 -146
  143. data/lib/mail/core_extensions/string/multibyte.rb +0 -79
  144. data/lib/mail/core_extensions/string.rb +0 -21
  145. data/lib/mail/fields/common/address_container.rb +0 -17
  146. data/lib/mail/fields/common/common_address.rb +0 -136
  147. data/lib/mail/fields/common/common_date.rb +0 -36
  148. data/lib/mail/fields/common/common_field.rb +0 -61
  149. data/lib/mail/fields/common/common_message_id.rb +0 -49
  150. data/lib/mail/multibyte/exceptions.rb +0 -9
  151. data/lib/mail/parsers/ragel/common.rl +0 -185
  152. data/lib/mail/parsers/ragel/parser_info.rb +0 -61
  153. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +0 -14864
  154. data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +0 -37
  155. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +0 -751
  156. data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +0 -37
  157. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +0 -614
  158. data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +0 -37
  159. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +0 -447
  160. data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +0 -37
  161. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +0 -825
  162. data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +0 -37
  163. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +0 -817
  164. data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +0 -37
  165. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +0 -2149
  166. data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +0 -37
  167. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +0 -1570
  168. data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +0 -37
  169. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +0 -440
  170. data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +0 -37
  171. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +0 -564
  172. data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +0 -37
  173. data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +0 -51
  174. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +0 -5144
  175. data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +0 -37
  176. data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +0 -37
  177. data/lib/mail/parsers/ragel/ruby.rb +0 -40
  178. data/lib/mail/parsers/ragel.rb +0 -18
  179. data/lib/mail/version_specific/ruby_1_8.rb +0 -126
  180. data/lib/mail/version_specific/ruby_1_9.rb +0 -226
@@ -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