mail 2.6.4 → 2.9.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 (180) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +208 -156
  3. data/lib/mail/attachments_list.rb +13 -10
  4. data/lib/mail/body.rb +96 -107
  5. data/lib/mail/configuration.rb +2 -0
  6. data/lib/mail/constants.rb +27 -5
  7. data/lib/mail/elements/address.rb +61 -50
  8. data/lib/mail/elements/address_list.rb +11 -19
  9. data/lib/mail/elements/content_disposition_element.rb +9 -16
  10. data/lib/mail/elements/content_location_element.rb +6 -11
  11. data/lib/mail/elements/content_transfer_encoding_element.rb +6 -11
  12. data/lib/mail/elements/content_type_element.rb +16 -23
  13. data/lib/mail/elements/date_time_element.rb +7 -15
  14. data/lib/mail/elements/envelope_from_element.rb +22 -23
  15. data/lib/mail/elements/message_ids_element.rb +18 -13
  16. data/lib/mail/elements/mime_version_element.rb +7 -15
  17. data/lib/mail/elements/phrase_list.rb +12 -10
  18. data/lib/mail/elements/received_element.rb +27 -19
  19. data/lib/mail/encodings/7bit.rb +9 -14
  20. data/lib/mail/encodings/8bit.rb +2 -21
  21. data/lib/mail/encodings/base64.rb +11 -12
  22. data/lib/mail/encodings/binary.rb +3 -22
  23. data/lib/mail/encodings/identity.rb +24 -0
  24. data/lib/mail/encodings/quoted_printable.rb +6 -6
  25. data/lib/mail/encodings/transfer_encoding.rb +38 -29
  26. data/lib/mail/encodings/unix_to_unix.rb +4 -2
  27. data/lib/mail/encodings.rb +83 -56
  28. data/lib/mail/envelope.rb +11 -14
  29. data/lib/mail/field.rb +181 -130
  30. data/lib/mail/field_list.rb +61 -8
  31. data/lib/mail/fields/bcc_field.rb +33 -52
  32. data/lib/mail/fields/cc_field.rb +27 -49
  33. data/lib/mail/fields/comments_field.rb +26 -37
  34. data/lib/mail/fields/common_address_field.rb +162 -0
  35. data/lib/mail/fields/common_date_field.rb +56 -0
  36. data/lib/mail/fields/common_field.rb +77 -0
  37. data/lib/mail/fields/common_message_id_field.rb +41 -0
  38. data/lib/mail/fields/content_description_field.rb +6 -14
  39. data/lib/mail/fields/content_disposition_field.rb +11 -38
  40. data/lib/mail/fields/content_id_field.rb +23 -51
  41. data/lib/mail/fields/content_location_field.rb +10 -25
  42. data/lib/mail/fields/content_transfer_encoding_field.rb +30 -31
  43. data/lib/mail/fields/content_type_field.rb +53 -84
  44. data/lib/mail/fields/date_field.rb +22 -52
  45. data/lib/mail/fields/from_field.rb +27 -49
  46. data/lib/mail/fields/in_reply_to_field.rb +37 -49
  47. data/lib/mail/fields/keywords_field.rb +17 -31
  48. data/lib/mail/fields/message_id_field.rb +24 -71
  49. data/lib/mail/fields/mime_version_field.rb +18 -30
  50. data/lib/mail/fields/named_structured_field.rb +10 -0
  51. data/lib/mail/fields/named_unstructured_field.rb +10 -0
  52. data/lib/mail/fields/optional_field.rb +9 -8
  53. data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +13 -11
  54. data/lib/mail/fields/received_field.rb +42 -57
  55. data/lib/mail/fields/references_field.rb +34 -49
  56. data/lib/mail/fields/reply_to_field.rb +27 -49
  57. data/lib/mail/fields/resent_bcc_field.rb +27 -49
  58. data/lib/mail/fields/resent_cc_field.rb +27 -49
  59. data/lib/mail/fields/resent_date_field.rb +4 -30
  60. data/lib/mail/fields/resent_from_field.rb +27 -49
  61. data/lib/mail/fields/resent_message_id_field.rb +4 -29
  62. data/lib/mail/fields/resent_sender_field.rb +26 -56
  63. data/lib/mail/fields/resent_to_field.rb +27 -49
  64. data/lib/mail/fields/return_path_field.rb +49 -54
  65. data/lib/mail/fields/sender_field.rb +33 -55
  66. data/lib/mail/fields/structured_field.rb +2 -30
  67. data/lib/mail/fields/subject_field.rb +8 -11
  68. data/lib/mail/fields/to_field.rb +27 -49
  69. data/lib/mail/fields/unstructured_field.rb +31 -47
  70. data/lib/mail/fields.rb +9 -0
  71. data/lib/mail/header.rb +71 -110
  72. data/lib/mail/mail.rb +34 -37
  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 +126 -127
  76. data/lib/mail/multibyte/chars.rb +24 -181
  77. data/lib/mail/multibyte/unicode.rb +11 -11
  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 +15 -18
  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 +125 -68
  85. data/lib/mail/network/delivery_methods/smtp_connection.rb +11 -16
  86. data/lib/mail/network/delivery_methods/test_mailer.rb +12 -13
  87. data/lib/mail/network/retriever_methods/base.rb +13 -13
  88. data/lib/mail/network/retriever_methods/imap.rb +25 -9
  89. data/lib/mail/network/retriever_methods/pop3.rb +25 -23
  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 +33228 -116
  94. data/lib/mail/parsers/address_lists_parser.rl +183 -0
  95. data/lib/mail/parsers/content_disposition_parser.rb +885 -49
  96. data/lib/mail/parsers/content_disposition_parser.rl +93 -0
  97. data/lib/mail/parsers/content_location_parser.rb +812 -23
  98. data/lib/mail/parsers/content_location_parser.rl +82 -0
  99. data/lib/mail/parsers/content_transfer_encoding_parser.rb +512 -21
  100. data/lib/mail/parsers/content_transfer_encoding_parser.rl +75 -0
  101. data/lib/mail/parsers/content_type_parser.rb +1039 -55
  102. data/lib/mail/parsers/content_type_parser.rl +94 -0
  103. data/lib/mail/parsers/date_time_parser.rb +880 -25
  104. data/lib/mail/parsers/date_time_parser.rl +73 -0
  105. data/lib/mail/parsers/envelope_from_parser.rb +3672 -40
  106. data/lib/mail/parsers/envelope_from_parser.rl +93 -0
  107. data/lib/mail/parsers/message_ids_parser.rb +5149 -25
  108. data/lib/mail/parsers/message_ids_parser.rl +97 -0
  109. data/lib/mail/parsers/mime_version_parser.rb +500 -26
  110. data/lib/mail/parsers/mime_version_parser.rl +72 -0
  111. data/lib/mail/parsers/phrase_lists_parser.rb +873 -22
  112. data/lib/mail/parsers/phrase_lists_parser.rl +94 -0
  113. data/lib/mail/parsers/received_parser.rb +8779 -43
  114. data/lib/mail/parsers/received_parser.rl +95 -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 +25 -29
  127. data/lib/mail/parts_list.rb +62 -6
  128. data/lib/mail/smtp_envelope.rb +57 -0
  129. data/lib/mail/utilities.rb +361 -74
  130. data/lib/mail/version.rb +2 -2
  131. data/lib/mail/yaml.rb +30 -0
  132. data/lib/mail.rb +4 -37
  133. metadata +125 -67
  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/check_delivery_params.rb +0 -21
  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 -223
@@ -1,42 +1,31 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- #
4
- # = Comments Field
5
- #
6
- # The Comments field inherits from UnstructuredField and handles the Comments:
7
- # header field in the email.
8
- #
9
- # Sending comments to a mail message will instantiate a Mail::Field object that
10
- # has a CommentsField as its field type.
11
- #
12
- # An email header can have as many comments fields as it wants. There is no upper
13
- # limit, the comments field is also optional (that is, no comment is needed)
14
- #
15
- # == Examples:
16
- #
17
- # mail = Mail.new
18
- # mail.comments = 'This is a comment'
19
- # mail.comments #=> 'This is a comment'
20
- # mail[:comments] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
21
- # mail['comments'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
22
- # mail['comments'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
23
- #
24
- # mail.comments = "This is another comment"
25
- # mail[:comments].map { |c| c.to_s }
26
- # #=> ['This is a comment', "This is another comment"]
27
- #
3
+
28
4
  module Mail
29
- class CommentsField < UnstructuredField
30
-
31
- FIELD_NAME = 'comments'
32
- CAPITALIZED_FIELD = 'Comments'
33
-
34
- def initialize(value = nil, charset = 'utf-8')
35
- @charset = charset
36
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value))
37
- self.parse
38
- self
39
- end
40
-
5
+ # = Comments Field
6
+ #
7
+ # The Comments field inherits from UnstructuredField and handles the Comments:
8
+ # header field in the email.
9
+ #
10
+ # Sending comments to a mail message will instantiate a Mail::Field object that
11
+ # has a CommentsField as its field type.
12
+ #
13
+ # An email header can have as many comments fields as it wants. There is no upper
14
+ # limit, the comments field is also optional (that is, no comment is needed)
15
+ #
16
+ # == Examples:
17
+ #
18
+ # mail = Mail.new
19
+ # mail.comments = 'This is a comment'
20
+ # mail.comments #=> 'This is a comment'
21
+ # mail[:comments] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
22
+ # mail['comments'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
23
+ # mail['comments'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::CommentsField:0x180e1c4
24
+ #
25
+ # mail.comments = "This is another comment"
26
+ # mail[:comments].map { |c| c.to_s }
27
+ # #=> ['This is a comment', "This is another comment"]
28
+ class CommentsField < NamedUnstructuredField #:nodoc:
29
+ NAME = 'Comments'
41
30
  end
42
31
  end
@@ -0,0 +1,162 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Mail
5
+ class AddressContainer < Array #:nodoc:
6
+ def initialize(field, list = nil)
7
+ @field = field
8
+ super list if list
9
+ end
10
+
11
+ def <<(address)
12
+ @field << address
13
+ end
14
+ end
15
+
16
+ class CommonAddressField < NamedStructuredField #:nodoc:
17
+ def self.singular?
18
+ true
19
+ end
20
+
21
+ def initialize(value = nil, charset = nil)
22
+ super encode_if_needed(value, charset), charset
23
+ end
24
+
25
+ def element # :nodoc:
26
+ @element ||= AddressList.new(value)
27
+ end
28
+
29
+ # Allows you to iterate through each address object in the address_list
30
+ def each
31
+ element.addresses.each do |address|
32
+ yield(address)
33
+ end
34
+ end
35
+
36
+ def default
37
+ addresses
38
+ end
39
+
40
+ def address
41
+ addresses.first
42
+ end
43
+
44
+ # Returns the address string of all the addresses in the address list
45
+ def addresses
46
+ list = element.addresses.map { |a| a.address }
47
+ Mail::AddressContainer.new(self, list)
48
+ end
49
+
50
+ # Returns the formatted string of all the addresses in the address list
51
+ def formatted
52
+ list = element.addresses.map { |a| a.format }
53
+ Mail::AddressContainer.new(self, list)
54
+ end
55
+
56
+ # Returns the display name of all the addresses in the address list
57
+ def display_names
58
+ list = element.addresses.map { |a| a.display_name }
59
+ Mail::AddressContainer.new(self, list)
60
+ end
61
+
62
+ # Returns the actual address objects in the address list
63
+ def addrs
64
+ list = element.addresses
65
+ Mail::AddressContainer.new(self, list)
66
+ end
67
+
68
+ # Returns a hash of group name => address strings for the address list
69
+ def groups
70
+ element.addresses_grouped_by_group
71
+ end
72
+
73
+ # Returns the addresses that are part of groups
74
+ def group_addresses
75
+ decoded_group_addresses
76
+ end
77
+
78
+ # Returns a list of decoded group addresses
79
+ def decoded_group_addresses
80
+ groups.map { |k,v| v.map { |a| a.decoded } }.flatten
81
+ end
82
+
83
+ # Returns a list of encoded group addresses
84
+ def encoded_group_addresses
85
+ groups.map { |k,v| v.map { |a| a.encoded } }.flatten
86
+ end
87
+
88
+ # Returns the name of all the groups in a string
89
+ def group_names # :nodoc:
90
+ element.group_names
91
+ end
92
+
93
+ def <<(val)
94
+ case
95
+ when val.nil?
96
+ raise ArgumentError, "Need to pass an address to <<"
97
+ when Utilities.blank?(val)
98
+ self
99
+ else
100
+ self.value = [self.value, encode_if_needed(val)].reject { |a| Utilities.blank?(a) }.join(", ")
101
+ end
102
+ end
103
+
104
+ def encode_if_needed(val, val_charset = charset) #:nodoc:
105
+ case val
106
+ when nil
107
+ val
108
+
109
+ # Need to join arrays of addresses into a single value
110
+ when Array
111
+ val.compact.map { |a| encode_if_needed a, val_charset }.join(', ')
112
+
113
+ # Pass through UTF-8; encode non-UTF-8.
114
+ else
115
+ utf8_if_needed(val, val_charset) || Encodings.encode_non_usascii(val, val_charset)
116
+ end
117
+ end
118
+
119
+ private
120
+
121
+ # Pass through UTF-8 addresses
122
+ def utf8_if_needed(val, val_charset)
123
+ if /\AUTF-?8\z/i.match?(val_charset)
124
+ val
125
+ elsif val.encoding == Encoding::UTF_8
126
+ val
127
+ elsif (utf8 = val.dup.force_encoding(Encoding::UTF_8)).valid_encoding?
128
+ utf8
129
+ end
130
+ end
131
+
132
+ def do_encode
133
+ return '' if Utilities.blank?(value)
134
+ address_array = element.addresses.reject { |a| encoded_group_addresses.include?(a.encoded) }.compact.map { |a| a.encoded }
135
+ address_text = address_array.join(", \r\n\s")
136
+ group_array = groups.map { |k,v| "#{k}: #{v.map { |a| a.encoded }.join(", \r\n\s")};" }
137
+ group_text = group_array.join(" \r\n\s")
138
+ return_array = [address_text, group_text].reject { |a| Utilities.blank?(a) }
139
+ "#{name}: #{return_array.join(", \r\n\s")}\r\n"
140
+ end
141
+
142
+ def do_decode
143
+ return nil if Utilities.blank?(value)
144
+ address_array = element.addresses.reject { |a| decoded_group_addresses.include?(a.decoded) }.map { |a| a.decoded }
145
+ address_text = address_array.join(", ")
146
+ group_array = groups.map { |k,v| "#{k}: #{v.map { |a| a.decoded }.join(", ")};" }
147
+ group_text = group_array.join(" ")
148
+ return_array = [address_text, group_text].reject { |a| Utilities.blank?(a) }
149
+ return_array.join(", ")
150
+ end
151
+
152
+ def get_group_addresses(group_list)
153
+ if group_list.respond_to?(:addresses)
154
+ group_list.addresses.map do |address|
155
+ Mail::Address.new(address)
156
+ end
157
+ else
158
+ []
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,56 @@
1
+ require 'mail/utilities'
2
+
3
+ module Mail
4
+ class CommonDateField < NamedStructuredField #:nodoc:
5
+ def self.singular?
6
+ true
7
+ end
8
+
9
+ def self.normalize_datetime(string)
10
+ if Utilities.blank?(string)
11
+ datetime = ::DateTime.now
12
+ else
13
+ stripped = string.to_s.gsub(/\(.*?\)/, '').squeeze(' ')
14
+ begin
15
+ datetime = ::DateTime.parse(stripped)
16
+ rescue ArgumentError => e
17
+ raise unless 'invalid date' == e.message
18
+ end
19
+ end
20
+
21
+ if datetime
22
+ datetime.strftime('%a, %d %b %Y %H:%M:%S %z')
23
+ else
24
+ string
25
+ end
26
+ end
27
+
28
+ def initialize(value = nil, charset = nil)
29
+ super self.class.normalize_datetime(value), charset
30
+ end
31
+
32
+ # Returns a date time object of the parsed date
33
+ def date_time
34
+ ::DateTime.parse("#{element.date_string} #{element.time_string}")
35
+ rescue ArgumentError => e
36
+ raise e unless e.message == 'invalid date'
37
+ end
38
+
39
+ def default
40
+ date_time
41
+ end
42
+
43
+ def element
44
+ @element ||= Mail::DateTimeElement.new(value)
45
+ end
46
+
47
+ private
48
+ def do_encode
49
+ "#{name}: #{value}\r\n"
50
+ end
51
+
52
+ def do_decode
53
+ value.to_s
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,77 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/constants'
4
+
5
+ module Mail
6
+ class CommonField #:nodoc:
7
+ def self.singular?
8
+ false
9
+ end
10
+
11
+ def self.parse(*args)
12
+ new(*args).tap(&:parse)
13
+ end
14
+
15
+ attr_accessor :name
16
+ attr_reader :value
17
+ attr_accessor :charset
18
+ attr_reader :errors
19
+
20
+ def initialize(name = nil, value = nil, charset = nil)
21
+ @errors = []
22
+
23
+ self.name = name
24
+ self.value = value
25
+ self.charset = charset || 'utf-8'
26
+ end
27
+
28
+ def singular?
29
+ self.class.singular?
30
+ end
31
+
32
+ def value=(value)
33
+ @element = nil
34
+ @value = value.is_a?(Array) ? value : value.to_s
35
+ parse
36
+ end
37
+
38
+ def parse
39
+ tap(&:element)
40
+ end
41
+
42
+ def element
43
+ nil
44
+ end
45
+
46
+ def to_s
47
+ decoded.to_s
48
+ end
49
+
50
+ def default
51
+ decoded
52
+ end
53
+
54
+ def decoded
55
+ do_decode
56
+ end
57
+
58
+ def encoded
59
+ do_encode
60
+ end
61
+
62
+ def responsible_for?(field_name)
63
+ name.to_s.casecmp(field_name.to_s) == 0
64
+ end
65
+
66
+ private
67
+
68
+ FILENAME_RE = /\b(filename|name)=([^;"\r\n]+\s[^;"\r\n]+)/
69
+ def ensure_filename_quoted(value)
70
+ if value.is_a?(String)
71
+ value.sub FILENAME_RE, '\1="\2"'
72
+ else
73
+ value
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'mail/utilities'
4
+
5
+ module Mail
6
+ class CommonMessageIdField < NamedStructuredField #:nodoc:
7
+ def element
8
+ @element ||= Mail::MessageIdsElement.new(value)
9
+ end
10
+
11
+ def message_id
12
+ element.message_id
13
+ end
14
+
15
+ def message_ids
16
+ element.message_ids
17
+ end
18
+
19
+ def default
20
+ ids = message_ids
21
+ ids.one? ? ids.first : ids
22
+ end
23
+
24
+ def to_s
25
+ decoded.to_s
26
+ end
27
+
28
+ private
29
+ def do_encode
30
+ %Q{#{name}: #{formatted_message_ids("\r\n ")}\r\n}
31
+ end
32
+
33
+ def do_decode
34
+ formatted_message_ids
35
+ end
36
+
37
+ def formatted_message_ids(join = ' ')
38
+ message_ids.map { |m| "<#{m}>" }.join(join) if message_ids.any?
39
+ end
40
+ end
41
+ end
@@ -1,20 +1,12 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- #
4
- #
5
- #
3
+
6
4
  module Mail
7
- class ContentDescriptionField < UnstructuredField
8
-
9
- FIELD_NAME = 'content-description'
10
- CAPITALIZED_FIELD = 'Content-Description'
11
-
12
- def initialize(value = nil, charset = 'utf-8')
13
- self.charset = charset
14
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
15
- self.parse
16
- self
5
+ class ContentDescriptionField < NamedUnstructuredField #:nodoc:
6
+ NAME = 'Content-Description'
7
+
8
+ def self.singular?
9
+ true
17
10
  end
18
-
19
11
  end
20
12
  end
@@ -1,25 +1,16 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- require 'mail/fields/common/parameter_hash'
4
3
 
5
4
  module Mail
6
- class ContentDispositionField < StructuredField
5
+ class ContentDispositionField < NamedStructuredField #:nodoc:
6
+ NAME = 'Content-Disposition'
7
7
 
8
- FIELD_NAME = 'content-disposition'
9
- CAPITALIZED_FIELD = 'Content-Disposition'
10
-
11
- def initialize(value = nil, charset = 'utf-8')
12
- self.charset = charset
13
- value = ensure_filename_quoted(value)
14
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
15
- self.parse
16
- self
8
+ def self.singular?
9
+ true
17
10
  end
18
11
 
19
- def parse(val = value)
20
- unless Utilities.blank?(val)
21
- @element = Mail::ContentDispositionElement.new(val)
22
- end
12
+ def initialize(value = nil, charset = nil)
13
+ super ensure_filename_quoted(value), charset
23
14
  end
24
15
 
25
16
  def element
@@ -37,35 +28,17 @@ module Mail
37
28
  end
38
29
 
39
30
  def filename
40
- case
41
- when !Utilities.blank?(parameters['filename'])
42
- @filename = parameters['filename']
43
- when !Utilities.blank?(parameters['name'])
44
- @filename = parameters['name']
45
- else
46
- @filename = nil
47
- end
48
- @filename
31
+ @filename ||= parameters['filename'] || parameters['name']
49
32
  end
50
33
 
51
- # TODO: Fix this up
52
34
  def encoded
53
- if parameters.length > 0
54
- p = ";\r\n\s#{parameters.encoded}\r\n"
55
- else
56
- p = "\r\n"
57
- end
58
- "#{CAPITALIZED_FIELD}: #{disposition_type}" + p
35
+ p = ";\r\n\s#{parameters.encoded}" if parameters.length > 0
36
+ "#{name}: #{disposition_type}#{p}\r\n"
59
37
  end
60
38
 
61
39
  def decoded
62
- if parameters.length > 0
63
- p = "; #{parameters.decoded}"
64
- else
65
- p = ""
66
- end
67
- "#{disposition_type}" + p
40
+ p = "; #{parameters.decoded}" if parameters.length > 0
41
+ "#{disposition_type}#{p}"
68
42
  end
69
-
70
43
  end
71
44
  end
@@ -1,63 +1,35 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- #
4
- #
5
- #
3
+ require 'mail/utilities'
4
+
6
5
  module Mail
7
- class ContentIdField < StructuredField
8
-
9
- FIELD_NAME = 'content-id'
10
- CAPITALIZED_FIELD = "Content-ID"
11
-
12
- def initialize(value = nil, charset = 'utf-8')
13
- self.charset = charset
14
- @uniq = 1
15
- if Utilities.blank?(value)
16
- value = generate_content_id
17
- else
18
- value = strip_field(FIELD_NAME, value)
19
- end
20
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
21
- self.parse
22
- self
23
- end
24
-
25
- def parse(val = value)
26
- unless Utilities.blank?(val)
27
- @element = Mail::MessageIdsElement.new(val)
28
- end
29
- end
30
-
6
+ class ContentIdField < NamedStructuredField #:nodoc:
7
+ NAME = 'Content-ID'
8
+
9
+ def self.singular?
10
+ true
11
+ end
12
+
13
+ def initialize(value = nil, charset = nil)
14
+ value = Mail::Utilities.generate_message_id if Utilities.blank?(value)
15
+ super value, charset
16
+ end
17
+
31
18
  def element
32
19
  @element ||= Mail::MessageIdsElement.new(value)
33
20
  end
34
-
35
- def name
36
- 'Content-ID'
37
- end
38
-
21
+
39
22
  def content_id
40
23
  element.message_id
41
24
  end
42
-
43
- def to_s
44
- "<#{content_id}>"
45
- end
46
-
47
- # TODO: Fix this up
48
- def encoded
49
- "#{CAPITALIZED_FIELD}: #{to_s}\r\n"
50
- end
51
-
52
- def decoded
53
- "#{to_s}"
54
- end
55
-
25
+
56
26
  private
57
-
58
- def generate_content_id
59
- "<#{Mail.random_tag}@#{::Socket.gethostname}.mail>"
60
- end
61
-
27
+ def do_decode
28
+ "<#{content_id}>"
29
+ end
30
+
31
+ def do_encode
32
+ "#{name}: #{do_decode}\r\n"
33
+ end
62
34
  end
63
35
  end
@@ -1,27 +1,14 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- #
4
- #
5
- #
3
+
6
4
  module Mail
7
- class ContentLocationField < StructuredField
8
-
9
- FIELD_NAME = 'content-location'
10
- CAPITALIZED_FIELD = 'Content-Location'
11
-
12
- def initialize(value = nil, charset = 'utf-8')
13
- self.charset = charset
14
- super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
15
- self.parse
16
- self
17
- end
18
-
19
- def parse(val = value)
20
- unless Utilities.blank?(val)
21
- @element = Mail::ContentLocationElement.new(val)
22
- end
5
+ class ContentLocationField < NamedStructuredField #:nodoc:
6
+ NAME = 'Content-Location'
7
+
8
+ def self.singular?
9
+ true
23
10
  end
24
-
11
+
25
12
  def element
26
13
  @element ||= Mail::ContentLocationElement.new(value)
27
14
  end
@@ -30,14 +17,12 @@ module Mail
30
17
  element.location
31
18
  end
32
19
 
33
- # TODO: Fix this up
34
20
  def encoded
35
- "#{CAPITALIZED_FIELD}: #{location}\r\n"
21
+ "#{name}: #{location}\r\n"
36
22
  end
37
-
23
+
38
24
  def decoded
39
- location
25
+ location
40
26
  end
41
-
42
27
  end
43
28
  end