mail 2.5.3 → 2.5.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of mail might be problematic. Click here for more details.

Files changed (66) hide show
  1. data/CHANGELOG.rdoc +65 -0
  2. data/CONTRIBUTING.md +4 -4
  3. data/Gemfile +7 -20
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +10 -9
  6. data/Rakefile +3 -20
  7. data/lib/VERSION +1 -1
  8. data/lib/mail.rb +0 -1
  9. data/lib/mail/attachments_list.rb +2 -2
  10. data/lib/mail/body.rb +4 -4
  11. data/lib/mail/check_delivery_params.rb +12 -22
  12. data/lib/mail/core_extensions/object.rb +8 -8
  13. data/lib/mail/core_extensions/smtp.rb +12 -13
  14. data/lib/mail/core_extensions/string.rb +4 -4
  15. data/lib/mail/elements/address.rb +13 -5
  16. data/lib/mail/elements/envelope_from_element.rb +15 -2
  17. data/lib/mail/encodings.rb +61 -28
  18. data/lib/mail/encodings/quoted_printable.rb +4 -3
  19. data/lib/mail/field.rb +10 -11
  20. data/lib/mail/fields/bcc_field.rb +2 -2
  21. data/lib/mail/fields/cc_field.rb +2 -2
  22. data/lib/mail/fields/comments_field.rb +1 -1
  23. data/lib/mail/fields/common/common_address.rb +13 -3
  24. data/lib/mail/fields/common/common_field.rb +4 -4
  25. data/lib/mail/fields/content_id_field.rb +1 -2
  26. data/lib/mail/fields/content_transfer_encoding_field.rb +2 -2
  27. data/lib/mail/fields/content_type_field.rb +1 -1
  28. data/lib/mail/fields/date_field.rb +1 -1
  29. data/lib/mail/fields/from_field.rb +2 -2
  30. data/lib/mail/fields/in_reply_to_field.rb +2 -1
  31. data/lib/mail/fields/message_id_field.rb +2 -3
  32. data/lib/mail/fields/references_field.rb +2 -1
  33. data/lib/mail/fields/reply_to_field.rb +2 -2
  34. data/lib/mail/fields/resent_bcc_field.rb +2 -2
  35. data/lib/mail/fields/resent_cc_field.rb +2 -2
  36. data/lib/mail/fields/resent_from_field.rb +2 -2
  37. data/lib/mail/fields/resent_sender_field.rb +2 -2
  38. data/lib/mail/fields/resent_to_field.rb +2 -2
  39. data/lib/mail/fields/sender_field.rb +7 -7
  40. data/lib/mail/fields/to_field.rb +2 -2
  41. data/lib/mail/fields/unstructured_field.rb +1 -1
  42. data/lib/mail/header.rb +5 -1
  43. data/lib/mail/message.rb +133 -37
  44. data/lib/mail/multibyte/chars.rb +2 -2
  45. data/lib/mail/multibyte/unicode.rb +5 -3
  46. data/lib/mail/network/delivery_methods/exim.rb +1 -6
  47. data/lib/mail/network/delivery_methods/file_delivery.rb +1 -1
  48. data/lib/mail/network/delivery_methods/sendmail.rb +32 -10
  49. data/lib/mail/network/delivery_methods/smtp.rb +35 -34
  50. data/lib/mail/network/delivery_methods/smtp_connection.rb +6 -6
  51. data/lib/mail/network/delivery_methods/test_mailer.rb +2 -2
  52. data/lib/mail/parsers/content_transfer_encoding.rb +81 -42
  53. data/lib/mail/parsers/content_transfer_encoding.treetop +4 -6
  54. data/lib/mail/parsers/content_type.rb +16 -12
  55. data/lib/mail/parsers/content_type.treetop +2 -2
  56. data/lib/mail/parsers/rfc2045.rb +12 -55
  57. data/lib/mail/parsers/rfc2045.treetop +1 -2
  58. data/lib/mail/parsers/rfc2822.rb +50 -50
  59. data/lib/mail/parsers/rfc2822.treetop +19 -21
  60. data/lib/mail/part.rb +6 -2
  61. data/lib/mail/patterns.rb +1 -0
  62. data/lib/mail/utilities.rb +25 -17
  63. data/lib/mail/version_specific/ruby_1_8.rb +5 -1
  64. data/lib/mail/version_specific/ruby_1_9.rb +46 -21
  65. metadata +57 -8
  66. data/lib/mail/core_extensions/shell_escape.rb +0 -56
@@ -6,7 +6,7 @@
6
6
  # Resent-Bcc: header field in the email.
7
7
  #
8
8
  # Sending resent_bcc to a mail message will instantiate a Mail::Field object that
9
- # has a ResentBccField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ResentBccField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Resent-Bcc field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.resent_bcc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.resent_bcc #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
19
+ # mail.resent_bcc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
20
20
  # mail[:resent_bcc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentBccField:0x180e1c4
21
21
  # mail['resent-bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentBccField:0x180e1c4
22
22
  # mail['Resent-Bcc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentBccField:0x180e1c4
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending resent_cc to a mail message will instantiate a Mail::Field object that
9
- # has a ResentCcField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ResentCcField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Resent-Cc field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.resent_cc = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.resent_cc #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
19
+ # mail.resent_cc #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
20
20
  # mail[:resent_cc] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentCcField:0x180e1c4
21
21
  # mail['resent-cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentCcField:0x180e1c4
22
22
  # mail['Resent-Cc'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentCcField:0x180e1c4
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending resent_from to a mail message will instantiate a Mail::Field object that
9
- # has a ResentFromField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ResentFromField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Resent-From field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.resent_from = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.resent_from #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
19
+ # mail.resent_from #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
20
20
  # mail[:resent_from] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentFromField:0x180e1c4
21
21
  # mail['resent-from'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentFromField:0x180e1c4
22
22
  # mail['Resent-From'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentFromField:0x180e1c4
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending resent_sender to a mail message will instantiate a Mail::Field object that
9
- # has a ResentSenderField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ResentSenderField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Resent-Sender field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.resent_sender = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.resent_sender #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentSenderField:0x180e1c4
19
+ # mail.resent_sender #=> ['mikel@test.lindsaar.net']
20
20
  # mail[:resent_sender] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentSenderField:0x180e1c4
21
21
  # mail['resent-sender'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentSenderField:0x180e1c4
22
22
  # mail['Resent-Sender'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentSenderField:0x180e1c4
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending resent_to to a mail message will instantiate a Mail::Field object that
9
- # has a ResentToField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ResentToField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Resent-To field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.resent_to = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.resent_to #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
19
+ # mail.resent_to #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
20
20
  # mail[:resent_to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentToField:0x180e1c4
21
21
  # mail['resent-to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentToField:0x180e1c4
22
22
  # mail['Resent-To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ResentToField:0x180e1c4
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending sender to a mail message will instantiate a Mail::Field object that
9
- # has a SenderField as it's field type. This includes all Mail::CommonAddress
9
+ # has a SenderField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one Sender field can appear in a header, though it can have multiple
@@ -15,16 +15,16 @@
15
15
  # == Examples:
16
16
  #
17
17
  # mail = Mail.new
18
- # mail.sender = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.sender #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
18
+ # mail.sender = 'Mikel Lindsaar <mikel@test.lindsaar.net>'
19
+ # mail.sender #=> 'mikel@test.lindsaar.net'
20
20
  # mail[:sender] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::SenderField:0x180e1c4
21
21
  # mail['sender'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::SenderField:0x180e1c4
22
22
  # mail['Sender'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::SenderField:0x180e1c4
23
23
  #
24
- # mail[:sender].encoded #=> 'Sender: Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net\r\n'
25
- # mail[:sender].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
26
- # mail[:sender].addresses #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
27
- # mail[:sender].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
24
+ # mail[:sender].encoded #=> "Sender: Mikel Lindsaar <mikel@test.lindsaar.net>\r\n"
25
+ # mail[:sender].decoded #=> 'Mikel Lindsaar <mikel@test.lindsaar.net>'
26
+ # mail[:sender].addresses #=> ['mikel@test.lindsaar.net']
27
+ # mail[:sender].formatted #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>']
28
28
  #
29
29
  require 'mail/fields/common/common_address'
30
30
 
@@ -6,7 +6,7 @@
6
6
  # field in the email.
7
7
  #
8
8
  # Sending to to a mail message will instantiate a Mail::Field object that
9
- # has a ToField as it's field type. This includes all Mail::CommonAddress
9
+ # has a ToField as its field type. This includes all Mail::CommonAddress
10
10
  # module instance metods.
11
11
  #
12
12
  # Only one To field can appear in a header, though it can have multiple
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # mail = Mail.new
18
18
  # mail.to = 'Mikel Lindsaar <mikel@test.lindsaar.net>, ada@test.lindsaar.net'
19
- # mail.to #=> ['Mikel Lindsaar <mikel@test.lindsaar.net>', 'ada@test.lindsaar.net']
19
+ # mail.to #=> ['mikel@test.lindsaar.net', 'ada@test.lindsaar.net']
20
20
  # mail[:to] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ToField:0x180e1c4
21
21
  # mail['to'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ToField:0x180e1c4
22
22
  # mail['To'] #=> '#<Mail::Field:0x180e5e8 @field=#<Mail::ToField:0x180e1c4
@@ -146,7 +146,7 @@ module Mail
146
146
  line = ""
147
147
  while !words.empty?
148
148
  break unless word = words.first.dup
149
- word.encode!(charset) if defined?(Encoding) && charset
149
+ word.encode!(charset) if charset && word.respond_to?(:encode!)
150
150
  word = encode(word) if should_encode
151
151
  word = encode_crlf(word)
152
152
  # Skip to next line if we're going to go past the limit
@@ -50,7 +50,7 @@ module Mail
50
50
  def initialize(header_text = nil, charset = nil)
51
51
  @errors = []
52
52
  @charset = charset
53
- self.raw_source = header_text.to_crlf
53
+ self.raw_source = header_text.to_crlf.lstrip
54
54
  split_header if header_text
55
55
  end
56
56
 
@@ -154,6 +154,9 @@ module Mail
154
154
  # h['X-Mail-SPAM'] # => nil
155
155
  def []=(name, value)
156
156
  name = dasherize(name)
157
+ if name.include?(':')
158
+ raise ArgumentError, "Header names may not contain a colon: #{name.inspect}"
159
+ end
157
160
  fn = name.downcase
158
161
  selected = select_field_for(fn)
159
162
 
@@ -198,6 +201,7 @@ module Mail
198
201
 
199
202
  def encoded
200
203
  buffer = ''
204
+ buffer.force_encoding('us-ascii') if buffer.respond_to?(:force_encoding)
201
205
  fields.each do |field|
202
206
  buffer << field.encoded
203
207
  end
@@ -108,6 +108,9 @@ module Mail
108
108
  @charset = 'UTF-8'
109
109
  @defaulted_charset = true
110
110
 
111
+ @smtp_envelope_from = nil
112
+ @smtp_envelope_to = nil
113
+
111
114
  @perform_deliveries = true
112
115
  @raise_delivery_errors = true
113
116
 
@@ -122,7 +125,7 @@ module Mail
122
125
  if args.flatten.first.respond_to?(:each_pair)
123
126
  init_with_hash(args.flatten.first)
124
127
  else
125
- init_with_string(args.flatten[0].to_s.strip)
128
+ init_with_string(args.flatten[0].to_s)
126
129
  end
127
130
 
128
131
  if block_given?
@@ -169,7 +172,7 @@ module Mail
169
172
  # obj.mail.deliver
170
173
  #
171
174
  # Would cause Mail to call obj.deliver_mail passing itself as a parameter,
172
- # which then can just yield and let Mail do it's own private do_delivery
175
+ # which then can just yield and let Mail do its own private do_delivery
173
176
  # method.
174
177
  attr_accessor :delivery_handler
175
178
 
@@ -938,8 +941,8 @@ module Mail
938
941
  #
939
942
  # Example:
940
943
  #
941
- # mail.sender = 'Mikel <mikel@test.lindsaar.net>'
942
- # mail.sender #=> 'mikel@test.lindsaar.net'
944
+ # mail.resent_sender = 'Mikel <mikel@test.lindsaar.net>'
945
+ # mail.resent_sender #=> 'mikel@test.lindsaar.net'
943
946
  def resent_sender=( val )
944
947
  header[:resent_sender] = val
945
948
  end
@@ -1023,6 +1026,82 @@ module Mail
1023
1026
  header[:sender] = val
1024
1027
  end
1025
1028
 
1029
+ # Returns the SMTP Envelope From value of the mail object, as a single
1030
+ # string of an address spec.
1031
+ #
1032
+ # Defaults to Return-Path, Sender, or the first From address.
1033
+ #
1034
+ # Example:
1035
+ #
1036
+ # mail.smtp_envelope_from = 'Mikel <mikel@test.lindsaar.net>'
1037
+ # mail.smtp_envelope_from #=> 'mikel@test.lindsaar.net'
1038
+ #
1039
+ # Also allows you to set the value by passing a value as a parameter
1040
+ #
1041
+ # Example:
1042
+ #
1043
+ # mail.smtp_envelope_from 'Mikel <mikel@test.lindsaar.net>'
1044
+ # mail.smtp_envelope_from #=> 'mikel@test.lindsaar.net'
1045
+ def smtp_envelope_from( val = nil )
1046
+ if val
1047
+ self.smtp_envelope_from = val
1048
+ else
1049
+ @smtp_envelope_from || return_path || sender || from_addrs.first
1050
+ end
1051
+ end
1052
+
1053
+ # Sets the From address on the SMTP Envelope.
1054
+ #
1055
+ # Example:
1056
+ #
1057
+ # mail.smtp_envelope_from = 'Mikel <mikel@test.lindsaar.net>'
1058
+ # mail.smtp_envelope_from #=> 'mikel@test.lindsaar.net'
1059
+ def smtp_envelope_from=( val )
1060
+ @smtp_envelope_from = val
1061
+ end
1062
+
1063
+ # Returns the SMTP Envelope To value of the mail object.
1064
+ #
1065
+ # Defaults to #destinations: To, Cc, and Bcc addresses.
1066
+ #
1067
+ # Example:
1068
+ #
1069
+ # mail.smtp_envelope_to = 'Mikel <mikel@test.lindsaar.net>'
1070
+ # mail.smtp_envelope_to #=> 'mikel@test.lindsaar.net'
1071
+ #
1072
+ # Also allows you to set the value by passing a value as a parameter
1073
+ #
1074
+ # Example:
1075
+ #
1076
+ # mail.smtp_envelope_to ['Mikel <mikel@test.lindsaar.net>', 'Lindsaar <lindsaar@test.lindsaar.net>']
1077
+ # mail.smtp_envelope_to #=> ['mikel@test.lindsaar.net', 'lindsaar@test.lindsaar.net']
1078
+ def smtp_envelope_to( val = nil )
1079
+ if val
1080
+ self.smtp_envelope_to = val
1081
+ else
1082
+ @smtp_envelope_to || destinations
1083
+ end
1084
+ end
1085
+
1086
+ # Sets the To addresses on the SMTP Envelope.
1087
+ #
1088
+ # Example:
1089
+ #
1090
+ # mail.smtp_envelope_to = 'Mikel <mikel@test.lindsaar.net>'
1091
+ # mail.smtp_envelope_to #=> 'mikel@test.lindsaar.net'
1092
+ #
1093
+ # mail.smtp_envelope_to = ['Mikel <mikel@test.lindsaar.net>', 'Lindsaar <lindsaar@test.lindsaar.net>']
1094
+ # mail.smtp_envelope_to #=> ['mikel@test.lindsaar.net', 'lindsaar@test.lindsaar.net']
1095
+ def smtp_envelope_to=( val )
1096
+ @smtp_envelope_to =
1097
+ case val
1098
+ when Array, NilClass
1099
+ val
1100
+ else
1101
+ [val]
1102
+ end
1103
+ end
1104
+
1026
1105
  # Returns the decoded value of the subject field, as a single string.
1027
1106
  #
1028
1107
  # Example:
@@ -1516,7 +1595,7 @@ module Mail
1516
1595
 
1517
1596
  # Returns an AttachmentsList object, which holds all of the attachments in
1518
1597
  # the receiver object (either the entier email or a part within) and all
1519
- # of it's descendants.
1598
+ # of its descendants.
1520
1599
  #
1521
1600
  # It also allows you to add attachments to the mail object directly, like so:
1522
1601
  #
@@ -1559,9 +1638,7 @@ module Mail
1559
1638
  # Accessor for html_part
1560
1639
  def html_part(&block)
1561
1640
  if block_given?
1562
- @html_part = Mail::Part.new(&block)
1563
- add_multipart_alternate_header unless html_part.blank?
1564
- add_part(@html_part)
1641
+ self.html_part = Mail::Part.new(:content_type => 'text/html', &block)
1565
1642
  else
1566
1643
  @html_part || find_first_mime_type('text/html')
1567
1644
  end
@@ -1570,9 +1647,7 @@ module Mail
1570
1647
  # Accessor for text_part
1571
1648
  def text_part(&block)
1572
1649
  if block_given?
1573
- @text_part = Mail::Part.new(&block)
1574
- add_multipart_alternate_header unless html_part.blank?
1575
- add_part(@text_part)
1650
+ self.text_part = Mail::Part.new(:content_type => 'text/plain', &block)
1576
1651
  else
1577
1652
  @text_part || find_first_mime_type('text/plain')
1578
1653
  end
@@ -1581,36 +1656,54 @@ module Mail
1581
1656
  # Helper to add a html part to a multipart/alternative email. If this and
1582
1657
  # text_part are both defined in a message, then it will be a multipart/alternative
1583
1658
  # message and set itself that way.
1584
- def html_part=(msg = nil)
1659
+ def html_part=(msg)
1660
+ # Assign the html part and set multipart/alternative if there's a text part.
1585
1661
  if msg
1586
1662
  @html_part = msg
1587
- else
1588
- @html_part = Mail::Part.new('Content-Type: text/html;')
1663
+ @html_part.content_type = 'text/html' unless @html_part.has_content_type?
1664
+ add_multipart_alternate_header if text_part
1665
+ add_part @html_part
1666
+
1667
+ # If nil, delete the html part and back out of multipart/alternative.
1668
+ elsif @html_part
1669
+ parts.delete_if { |p| p.object_id == @html_part.object_id }
1670
+ @html_part = nil
1671
+ if text_part
1672
+ self.content_type = nil
1673
+ body.boundary = nil
1674
+ end
1589
1675
  end
1590
- add_multipart_alternate_header unless text_part.blank?
1591
- add_part(@html_part)
1592
1676
  end
1593
1677
 
1594
1678
  # Helper to add a text part to a multipart/alternative email. If this and
1595
1679
  # html_part are both defined in a message, then it will be a multipart/alternative
1596
1680
  # message and set itself that way.
1597
- def text_part=(msg = nil)
1681
+ def text_part=(msg)
1682
+ # Assign the text part and set multipart/alternative if there's an html part.
1598
1683
  if msg
1599
1684
  @text_part = msg
1600
- else
1601
- @text_part = Mail::Part.new('Content-Type: text/plain;')
1685
+ @text_part.content_type = 'text/plain' unless @text_part.has_content_type?
1686
+ add_multipart_alternate_header if html_part
1687
+ add_part @text_part
1688
+
1689
+ # If nil, delete the text part and back out of multipart/alternative.
1690
+ elsif @text_part
1691
+ parts.delete_if { |p| p.object_id == @text_part.object_id }
1692
+ @text_part = nil
1693
+ if html_part
1694
+ self.content_type = nil
1695
+ body.boundary = nil
1696
+ end
1602
1697
  end
1603
- add_multipart_alternate_header unless html_part.blank?
1604
- add_part(@text_part)
1605
1698
  end
1606
1699
 
1607
1700
  # Adds a part to the parts list or creates the part list
1608
1701
  def add_part(part)
1609
1702
  if !body.multipart? && !self.body.decoded.blank?
1610
- @text_part = Mail::Part.new('Content-Type: text/plain;')
1611
- @text_part.body = body.decoded
1612
- self.body << @text_part
1613
- add_multipart_alternate_header
1703
+ @text_part = Mail::Part.new('Content-Type: text/plain;')
1704
+ @text_part.body = body.decoded
1705
+ self.body << @text_part
1706
+ add_multipart_alternate_header
1614
1707
  end
1615
1708
  add_boundary
1616
1709
  self.body << part
@@ -1646,7 +1739,7 @@ module Mail
1646
1739
  # m.add_file(:filename => 'filename.png', :content => File.read('/path/to/file.jpg'))
1647
1740
  #
1648
1741
  # Note also that if you add a file to an existing message, Mail will convert that message
1649
- # to a MIME multipart email, moving whatever plain text body you had into it's own text
1742
+ # to a MIME multipart email, moving whatever plain text body you had into its own text
1650
1743
  # plain part.
1651
1744
  #
1652
1745
  # Example:
@@ -1683,7 +1776,7 @@ module Mail
1683
1776
  self.body << text_part
1684
1777
  end
1685
1778
 
1686
- # Encodes the message, calls encode on all it's parts, gets an email message
1779
+ # Encodes the message, calls encode on all its parts, gets an email message
1687
1780
  # ready to send
1688
1781
  def ready_to_send!
1689
1782
  identify_and_set_transfer_encoding
@@ -1875,7 +1968,7 @@ module Mail
1875
1968
  # Additionally, I allow for the case where someone might have put whitespace
1876
1969
  # on the "gap line"
1877
1970
  def parse_message
1878
- header_part, body_part = raw_source.split(/#{CRLF}#{WSP}*#{CRLF}(?!#{WSP})/m, 2)
1971
+ header_part, body_part = raw_source.lstrip.split(/#{CRLF}#{CRLF}|#{CRLF}#{WSP}*#{CRLF}(?!#{WSP})/m, 2)
1879
1972
  self.header = header_part
1880
1973
  self.body = body_part
1881
1974
  end
@@ -1904,11 +1997,11 @@ module Mail
1904
1997
 
1905
1998
 
1906
1999
  def process_body_raw
1907
- @body = Mail::Body.new(@body_raw)
1908
- @body_raw = nil
1909
- separate_parts if @separate_parts
2000
+ @body = Mail::Body.new(@body_raw)
2001
+ @body_raw = nil
2002
+ separate_parts if @separate_parts
1910
2003
 
1911
- add_encoding_to_body
2004
+ add_encoding_to_body
1912
2005
  end
1913
2006
 
1914
2007
  def set_envelope_header
@@ -1938,16 +2031,19 @@ module Mail
1938
2031
  end
1939
2032
 
1940
2033
  def add_required_fields
1941
- add_multipart_mixed_header unless !body.multipart?
1942
- body = nil if body.nil?
1943
- add_message_id unless (has_message_id? || self.class == Mail::Part)
1944
- add_date unless has_date?
1945
- add_mime_version unless has_mime_version?
2034
+ add_required_message_fields
2035
+ add_multipart_mixed_header if body.multipart?
1946
2036
  add_content_type unless has_content_type?
1947
2037
  add_charset unless has_charset?
1948
2038
  add_content_transfer_encoding unless has_content_transfer_encoding?
1949
2039
  end
1950
2040
 
2041
+ def add_required_message_fields
2042
+ add_date unless has_date?
2043
+ add_mime_version unless has_mime_version?
2044
+ add_message_id unless has_message_id?
2045
+ end
2046
+
1951
2047
  def add_multipart_alternate_header
1952
2048
  header['content-type'] = ContentTypeField.with_boundary('multipart/alternative').value
1953
2049
  header['content_type'].parameters[:charset] = @charset