mail 2.7.1 → 2.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +59 -28
  3. data/lib/mail/attachments_list.rb +2 -5
  4. data/lib/mail/body.rb +24 -47
  5. data/lib/mail/check_delivery_params.rb +21 -16
  6. data/lib/mail/constants.rb +27 -5
  7. data/lib/mail/elements/address.rb +27 -27
  8. data/lib/mail/elements/address_list.rb +1 -1
  9. data/lib/mail/elements/content_disposition_element.rb +1 -1
  10. data/lib/mail/elements/content_location_element.rb +1 -1
  11. data/lib/mail/elements/content_transfer_encoding_element.rb +1 -1
  12. data/lib/mail/elements/content_type_element.rb +8 -4
  13. data/lib/mail/elements/date_time_element.rb +1 -1
  14. data/lib/mail/elements/envelope_from_element.rb +13 -7
  15. data/lib/mail/elements/message_ids_element.rb +14 -5
  16. data/lib/mail/elements/mime_version_element.rb +1 -1
  17. data/lib/mail/elements/phrase_list.rb +7 -2
  18. data/lib/mail/elements/received_element.rb +20 -6
  19. data/lib/mail/encodings/7bit.rb +5 -0
  20. data/lib/mail/encodings/base64.rb +2 -2
  21. data/lib/mail/encodings/quoted_printable.rb +2 -2
  22. data/lib/mail/encodings.rb +30 -59
  23. data/lib/mail/envelope.rb +11 -14
  24. data/lib/mail/field.rb +37 -53
  25. data/lib/mail/field_list.rb +60 -7
  26. data/lib/mail/fields/bcc_field.rb +34 -52
  27. data/lib/mail/fields/cc_field.rb +28 -49
  28. data/lib/mail/fields/comments_field.rb +27 -37
  29. data/lib/mail/fields/common_address_field.rb +170 -0
  30. data/lib/mail/fields/common_date_field.rb +58 -0
  31. data/lib/mail/fields/common_field.rb +77 -0
  32. data/lib/mail/fields/common_message_id_field.rb +42 -0
  33. data/lib/mail/fields/content_description_field.rb +7 -14
  34. data/lib/mail/fields/content_disposition_field.rb +13 -38
  35. data/lib/mail/fields/content_id_field.rb +24 -51
  36. data/lib/mail/fields/content_location_field.rb +11 -25
  37. data/lib/mail/fields/content_transfer_encoding_field.rb +31 -31
  38. data/lib/mail/fields/content_type_field.rb +46 -71
  39. data/lib/mail/fields/date_field.rb +23 -51
  40. data/lib/mail/fields/from_field.rb +28 -49
  41. data/lib/mail/fields/in_reply_to_field.rb +38 -49
  42. data/lib/mail/fields/keywords_field.rb +18 -31
  43. data/lib/mail/fields/message_id_field.rb +25 -71
  44. data/lib/mail/fields/mime_version_field.rb +19 -30
  45. data/lib/mail/fields/named_structured_field.rb +11 -0
  46. data/lib/mail/fields/named_unstructured_field.rb +11 -0
  47. data/lib/mail/fields/optional_field.rb +5 -6
  48. data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +12 -10
  49. data/lib/mail/fields/received_field.rb +43 -57
  50. data/lib/mail/fields/references_field.rb +35 -49
  51. data/lib/mail/fields/reply_to_field.rb +28 -49
  52. data/lib/mail/fields/resent_bcc_field.rb +28 -49
  53. data/lib/mail/fields/resent_cc_field.rb +28 -49
  54. data/lib/mail/fields/resent_date_field.rb +5 -29
  55. data/lib/mail/fields/resent_from_field.rb +28 -49
  56. data/lib/mail/fields/resent_message_id_field.rb +5 -29
  57. data/lib/mail/fields/resent_sender_field.rb +27 -56
  58. data/lib/mail/fields/resent_to_field.rb +28 -49
  59. data/lib/mail/fields/return_path_field.rb +50 -54
  60. data/lib/mail/fields/sender_field.rb +34 -55
  61. data/lib/mail/fields/structured_field.rb +3 -30
  62. data/lib/mail/fields/subject_field.rb +9 -11
  63. data/lib/mail/fields/to_field.rb +28 -49
  64. data/lib/mail/fields/unstructured_field.rb +16 -48
  65. data/lib/mail/header.rb +69 -110
  66. data/lib/mail/matchers/attachment_matchers.rb +15 -0
  67. data/lib/mail/message.rb +52 -66
  68. data/lib/mail/multibyte/chars.rb +8 -166
  69. data/lib/mail/multibyte/utils.rb +26 -43
  70. data/lib/mail/multibyte.rb +1 -11
  71. data/lib/mail/network/delivery_methods/exim.rb +5 -4
  72. data/lib/mail/network/delivery_methods/file_delivery.rb +11 -10
  73. data/lib/mail/network/delivery_methods/logger_delivery.rb +2 -5
  74. data/lib/mail/network/delivery_methods/sendmail.rb +56 -18
  75. data/lib/mail/network/delivery_methods/smtp.rb +25 -9
  76. data/lib/mail/network/delivery_methods/smtp_connection.rb +3 -12
  77. data/lib/mail/network/delivery_methods/test_mailer.rb +4 -2
  78. data/lib/mail/network/retriever_methods/base.rb +8 -8
  79. data/lib/mail/network/retriever_methods/imap.rb +2 -2
  80. data/lib/mail/network/retriever_methods/pop3.rb +2 -2
  81. data/lib/mail/network/retriever_methods/test_retriever.rb +2 -1
  82. data/lib/mail/parsers/address_lists_parser.rb +33070 -33064
  83. data/lib/mail/parsers/address_lists_parser.rl +7 -0
  84. data/lib/mail/parsers/content_disposition_parser.rb +833 -827
  85. data/lib/mail/parsers/content_disposition_parser.rl +7 -0
  86. data/lib/mail/parsers/content_location_parser.rb +770 -764
  87. data/lib/mail/parsers/content_location_parser.rl +7 -0
  88. data/lib/mail/parsers/content_transfer_encoding_parser.rb +474 -468
  89. data/lib/mail/parsers/content_transfer_encoding_parser.rl +7 -0
  90. data/lib/mail/parsers/content_type_parser.rb +971 -965
  91. data/lib/mail/parsers/content_type_parser.rl +7 -0
  92. data/lib/mail/parsers/date_time_parser.rb +838 -832
  93. data/lib/mail/parsers/date_time_parser.rl +7 -0
  94. data/lib/mail/parsers/envelope_from_parser.rb +3623 -3529
  95. data/lib/mail/parsers/envelope_from_parser.rl +7 -0
  96. data/lib/mail/parsers/message_ids_parser.rb +5107 -2800
  97. data/lib/mail/parsers/message_ids_parser.rl +12 -1
  98. data/lib/mail/parsers/mime_version_parser.rb +463 -457
  99. data/lib/mail/parsers/mime_version_parser.rl +7 -0
  100. data/lib/mail/parsers/phrase_lists_parser.rb +836 -830
  101. data/lib/mail/parsers/phrase_lists_parser.rl +8 -1
  102. data/lib/mail/parsers/received_parser.rb +8688 -8682
  103. data/lib/mail/parsers/received_parser.rl +7 -0
  104. data/lib/mail/parsers/rfc5322.rl +28 -13
  105. data/lib/mail/parsers.rb +11 -17
  106. data/lib/mail/part.rb +5 -9
  107. data/lib/mail/parts_list.rb +57 -0
  108. data/lib/mail/smtp_envelope.rb +57 -0
  109. data/lib/mail/utilities.rb +307 -69
  110. data/lib/mail/version.rb +1 -1
  111. data/lib/mail/yaml.rb +30 -0
  112. data/lib/mail.rb +3 -20
  113. metadata +72 -18
  114. data/lib/mail/core_extensions/smtp.rb +0 -28
  115. data/lib/mail/core_extensions/string.rb +0 -17
  116. data/lib/mail/fields/common/address_container.rb +0 -17
  117. data/lib/mail/fields/common/common_address.rb +0 -161
  118. data/lib/mail/fields/common/common_date.rb +0 -36
  119. data/lib/mail/fields/common/common_field.rb +0 -52
  120. data/lib/mail/fields/common/common_message_id.rb +0 -49
  121. data/lib/mail/version_specific/ruby_1_8.rb +0 -163
  122. data/lib/mail/version_specific/ruby_1_9.rb +0 -278
@@ -2,6 +2,9 @@
2
2
  require 'mail/utilities'
3
3
  require 'mail/parser_tools'
4
4
 
5
+ begin
6
+ original_verbose, $VERBOSE = $VERBOSE, nil
7
+
5
8
  %%{
6
9
  machine date_time;
7
10
  alphtype int;
@@ -82,3 +85,7 @@ module Mail::Parsers
82
85
  end
83
86
  end
84
87
  end
88
+
89
+ ensure
90
+ $VERBOSE = original_verbose
91
+ end
@@ -30,19 +30,35 @@
30
30
 
31
31
  # 3.6.4. Identification Fields
32
32
  obs_id_left = local_part;
33
- id_left = dot_atom_text | obs_id_left;
34
- # id_right modifications to support multiple '@' in msg_id.
35
- msg_id_atext = ALPHA | DIGIT | "!" | "#" | "$" | "%" | "&" | "'" | "*" |
36
- "+" | "-" | "/" | "=" | "?" | "^" | "_" | "`" | "{" | "|" |
37
- "}" | "~" | "@";
38
- msg_id_dot_atom_text = (msg_id_atext+ "."?)+;
39
33
  obs_id_right = domain;
40
34
  no_fold_literal = "[" (dtext)* "]";
41
- id_right = msg_id_dot_atom_text | no_fold_literal | obs_id_right;
42
- msg_id = (CFWS)?
43
- (("<" id_left "@" id_right ">") >msg_id_s %msg_id_e)
44
- (CFWS)?;
45
- message_ids = msg_id (CFWS? msg_id)*;
35
+
36
+ msg_id_atext = rfc5322_atext | ":" | "," | "." | " ";
37
+
38
+ id_left = msg_id_atext+ | obs_id_left;
39
+ id_left_ns = ( msg_id_atext - ( " " | "," ) )+;
40
+
41
+ # id_right modifications to support multiple '@' in msg_id.
42
+ id_right = ( msg_id_atext | "@" )+ | no_fold_literal | obs_id_right;
43
+ id_right_ns = ( msg_id_atext - ( " " | "," ) | "@" )+ | no_fold_literal;
44
+
45
+ # Handle various message-id formats:
46
+ # <id_left@id_right>
47
+ # <id_left@id_right...
48
+ # <id_left@>
49
+ # <id_left>
50
+ # <id_left...
51
+ # id_left@id_right
52
+ # id_left
53
+ # Handle comma-separated message_ids.
54
+ msg_id = (CFWS)? (
55
+ (("<" id_left "@" id_right? ">") >msg_id_s %msg_id_e) |
56
+ (("<" id_left "@" id_right? :>> "...") >msg_id_s %msg_id_e) |
57
+ (("<" id_left ">") >msg_id_s %msg_id_e) |
58
+ (("<" id_left :>> "..." ) >msg_id_s %msg_id_e) |
59
+ ((id_left_ns ("@" id_right_ns)? ) >msg_id_s %msg_id_e)
60
+ ) (CFWS)? <: ","?;
61
+ message_ids = msg_id**;
46
62
 
47
63
 
48
64
  # 3.6.7 Trace Fields
@@ -54,6 +70,5 @@
54
70
  # Envelope From
55
71
  ctime_date = day_name " "+ month " "+ day " " time_of_day " " year;
56
72
  null_sender = ('<>' ' '{0,1});
57
- envelope_from = (addr_spec_no_angle_brackets | null_sender) >address_s %address_e " "
58
- (ctime_date >ctime_date_s %ctime_date_e);
73
+ envelope_from = (addr_spec_no_angle_brackets | null_sender) >address_s %address_e (" " (ctime_date >ctime_date_s %ctime_date_e))?;
59
74
  }%%
data/lib/mail/parsers.rb CHANGED
@@ -1,19 +1,13 @@
1
1
  # frozen_string_literal: true
2
- # Ragel-generated parsers are full of known warnings. Suppress them.
3
- begin
4
- orig, $VERBOSE = $VERBOSE, nil
5
2
 
6
- require 'mail/parsers/address_lists_parser'
7
- require 'mail/parsers/content_disposition_parser'
8
- require 'mail/parsers/content_location_parser'
9
- require 'mail/parsers/content_transfer_encoding_parser'
10
- require 'mail/parsers/content_type_parser'
11
- require 'mail/parsers/date_time_parser'
12
- require 'mail/parsers/envelope_from_parser'
13
- require 'mail/parsers/message_ids_parser'
14
- require 'mail/parsers/mime_version_parser'
15
- require 'mail/parsers/phrase_lists_parser'
16
- require 'mail/parsers/received_parser'
17
- ensure
18
- $VERBOSE = orig
19
- end
3
+ require 'mail/parsers/address_lists_parser'
4
+ require 'mail/parsers/content_disposition_parser'
5
+ require 'mail/parsers/content_location_parser'
6
+ require 'mail/parsers/content_transfer_encoding_parser'
7
+ require 'mail/parsers/content_type_parser'
8
+ require 'mail/parsers/date_time_parser'
9
+ require 'mail/parsers/envelope_from_parser'
10
+ require 'mail/parsers/message_ids_parser'
11
+ require 'mail/parsers/mime_version_parser'
12
+ require 'mail/parsers/phrase_lists_parser'
13
+ require 'mail/parsers/received_parser'
data/lib/mail/part.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
+ require 'mail/constants'
4
+ require 'mail/utilities'
5
+
3
6
  module Mail
4
7
  class Part < Message
5
-
6
8
  # Creates a new empty Content-ID field and inserts it in the correct order
7
9
  # into the Header. The ContentIdField object will automatically generate
8
10
  # a unique content ID if you try and encode it or output it to_s without
@@ -19,15 +21,9 @@ module Mail
19
21
  header.has_content_id?
20
22
  end
21
23
 
22
- def inline_content_id
23
- # TODO: Deprecated in 2.2.2 - Remove in 2.3
24
- warn("Part#inline_content_id is deprecated, please call Part#cid instead")
25
- cid
26
- end
27
-
28
24
  def cid
29
25
  add_content_id unless has_content_id?
30
- uri_escape(unbracket(content_id))
26
+ Utilities.uri_escape(Utilities.unbracket(content_id))
31
27
  end
32
28
 
33
29
  def url
@@ -104,7 +100,7 @@ module Mail
104
100
 
105
101
  # A part may not have a header.... so, just init a body if no header
106
102
  def parse_message
107
- header_part, body_part = raw_source.split(/#{Constants::CRLF}#{Constants::WSP}*#{Constants::CRLF}/m, 2)
103
+ header_part, body_part = raw_source.split(/#{Constants::LAX_CRLF}#{Constants::WSP}*#{Constants::LAX_CRLF}/m, 2)
108
104
  if header_part =~ Constants::HEADER_LINE
109
105
  self.header = header_part
110
106
  self.body = body_part
@@ -44,6 +44,63 @@ module Mail
44
44
  raise NoMethodError, "#collect! is not defined, please call #collect and create a new PartsList"
45
45
  end
46
46
 
47
+ def inspect_structure(parent_id = '')
48
+ enum_for(:map).with_index { |part, i|
49
+ i = i + 1 # Use 1-based indexes since this is for humans to read
50
+ id = parent_id.empty? ? "#{i}" : "#{parent_id}.#{i}"
51
+ if part.content_type == "message/rfc822"
52
+ sub_list = Mail.new(part.body).parts
53
+ else
54
+ sub_list = part.parts
55
+ end
56
+ id + '. ' + part.inspect +
57
+ if sub_list.any?
58
+ "\n" + sub_list.inspect_structure(id)
59
+ end.to_s
60
+ }.join("\n")
61
+ end
62
+
63
+ def recursive_each(&block)
64
+ each do |part|
65
+ if part.content_type == "message/rfc822"
66
+ sub_list = Mail.new(part.body).parts
67
+ else
68
+ sub_list = part.parts
69
+ end
70
+
71
+ yield part
72
+
73
+ sub_list.recursive_each(&block)
74
+ end
75
+ end
76
+
77
+ def recursive_size
78
+ i = 0
79
+ recursive_each {|p| i += 1 }
80
+ i
81
+ end
82
+
83
+ def recursive_delete_if
84
+ delete_if { |part|
85
+ if part.content_type == "message/rfc822"
86
+ sub_list = Mail.new(part.body).parts
87
+ else
88
+ sub_list = part.parts
89
+ end
90
+ (yield part).tap {
91
+ if sub_list.any?
92
+ sub_list.recursive_delete_if {|part| yield part }
93
+ end
94
+ }
95
+ }
96
+ end
97
+
98
+ def delete_attachments
99
+ recursive_delete_if { |part|
100
+ part.attachment?
101
+ }
102
+ end
103
+
47
104
  def sort
48
105
  self.class.new(@parts.sort)
49
106
  end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mail
4
+ class SmtpEnvelope #:nodoc:
5
+ # Reasonable cap on address length to avoid SMTP line length
6
+ # overflow on old SMTP servers.
7
+ MAX_ADDRESS_BYTESIZE = 2000
8
+
9
+ attr_reader :from, :to, :message
10
+
11
+ def initialize(mail)
12
+ self.from = mail.smtp_envelope_from
13
+ self.to = mail.smtp_envelope_to
14
+ self.message = mail.encoded
15
+ end
16
+
17
+ def from=(addr)
18
+ if Utilities.blank? addr
19
+ raise ArgumentError, "SMTP From address may not be blank: #{addr.inspect}"
20
+ end
21
+
22
+ @from = validate_addr 'From', addr
23
+ end
24
+
25
+ def to=(addr)
26
+ if Utilities.blank?(addr)
27
+ raise ArgumentError, "SMTP To address may not be blank: #{addr.inspect}"
28
+ end
29
+
30
+ @to = Array(addr).map do |addr|
31
+ validate_addr 'To', addr
32
+ end
33
+ end
34
+
35
+ def message=(message)
36
+ if Utilities.blank?(message)
37
+ raise ArgumentError, 'SMTP message may not be blank'
38
+ end
39
+
40
+ @message = message
41
+ end
42
+
43
+
44
+ private
45
+ def validate_addr(addr_name, addr)
46
+ if addr.bytesize > MAX_ADDRESS_BYTESIZE
47
+ raise ArgumentError, "SMTP #{addr_name} address may not exceed #{MAX_ADDRESS_BYTESIZE} bytes: #{addr.inspect}"
48
+ end
49
+
50
+ if /[\r\n]/ =~ addr
51
+ raise ArgumentError, "SMTP #{addr_name} address may not contain CR or LF line breaks: #{addr.inspect}"
52
+ end
53
+
54
+ addr
55
+ end
56
+ end
57
+ end