File: example_emails_spec.rb

package info (click to toggle)
ruby-mail 2.6.4%2Bdfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 4,256 kB
  • ctags: 1,327
  • sloc: ruby: 44,678; makefile: 3
file content (328 lines) | stat: -rw-r--r-- 15,262 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# encoding: utf-8
# frozen_string_literal: true
require 'spec_helper'

describe "Test emails" do

  describe "from RFC2822" do

    # From RFC 2822:
    # This could be called a canonical message.  It has a single author,
    # John Doe, a single recipient, Mary Smith, a subject, the date, a
    # message identifier, and a textual message in the body.
    it "should handle the basic test email" do
      mail = Mail.read(fixture('emails', 'rfc2822', 'example01.eml'))
      expect(mail.from).to eq ["jdoe@machine.example"]
      expect(mail.to).to eq ['mary@example.net']
      expect(mail.message_id).to eq '1234@local.machine.example'
      expect(mail.date).to eq ::DateTime.parse('21 Nov 1997 09:55:06 -0600')
      expect(mail.subject).to eq 'Saying Hello'
    end

    # From RFC 2822:
    # If John's secretary Michael actually sent the message, though John
    # was the author and replies to this message should go back to him, the
    # sender field would be used:
    it "should handle the sender test email" do
      mail = Mail.read(fixture('emails', 'rfc2822', 'example02.eml'))
      expect(mail.from).to eq ['jdoe@machine.example']
      expect(mail.sender).to eq 'mjones@machine.example'
      expect(mail.to).to eq ['mary@example.net']
      expect(mail.message_id).to eq '1234@local.machine.example'
      expect(mail.date).to eq ::DateTime.parse('21 Nov 1997 09:55:06 -0600')
      expect(mail.subject).to eq 'Saying Hello'
    end

    # From RFC 2822:
    # This message includes multiple addresses in the destination fields
    # and also uses several different forms of addresses.
    #
    # Note that the display names for Joe Q. Public and Giant; "Big" Box
    # needed to be enclosed in double-quotes because the former contains
    # the period and the latter contains both semicolon and double-quote
    # characters (the double-quote characters appearing as quoted-pair
    # construct).  Conversely, the display name for Who? could appear
    # without them because the question mark is legal in an atom.  Notice
    # also that jdoe@example.org and boss@nil.test have no display names
    # associated with them at all, and jdoe@example.org uses the simpler
    # address form without the angle brackets.
    #
    # "Giant; \"Big\" Box" <sysservices@example.net>
    it "should handle multiple recipients test email" do
      mail = Mail.read(fixture('emails', 'rfc2822', 'example03.eml'))
      expect(mail.from).to eq ['john.q.public@example.com']
      expect(mail.to).to eq ['mary@x.test', 'jdoe@example.org', 'one@y.test']
      expect(mail.cc).to eq ['boss@nil.test', "sysservices@example.net"]
      expect(mail.message_id).to eq '5678.21-Nov-1997@example.com'
      expect(mail.date).to eq ::DateTime.parse('1 Jul 2003 10:52:37 +0200')
    end

    # From RFC 2822:
    # A.1.3. Group addresses
    # In this message, the "To:" field has a single group recipient named A
    # Group which contains 3 addresses, and a "Cc:" field with an empty
    # group recipient named Undisclosed recipients.
    it "should handle group address email test" do
      mail = Mail.read(fixture('emails', 'rfc2822', 'example04.eml'))
      expect(mail.from).to eq ['pete@silly.example']
      expect(mail.to).to eq ['c@a.test', 'joe@where.test', 'jdoe@one.test']
      expect(mail[:cc].group_names).to eq ['Undisclosed recipients']
      expect(mail.message_id).to eq 'testabcd.1234@silly.example'
      expect(mail.date).to eq ::DateTime.parse('Thu, 13 Feb 1969 23:32:54 -0330')
    end


    # From RFC 2822:
    # A.2. Reply messages
    # The following is a series of three messages that make up a
    # conversation thread between John and Mary.  John firsts sends a
    # message to Mary, Mary then replies to John's message, and then John
    # replies to Mary's reply message.
    #
    # Note especially the "Message-ID:", "References:", and "In-Reply-To:"
    # fields in each message.
    it "should handle reply messages" do
      mail = Mail.read(fixture('emails', 'rfc2822', 'example05.eml'))
      expect(mail.from).to eq ["jdoe@machine.example"]
      expect(mail.to).to eq ['mary@example.net']
      expect(mail.subject).to eq 'Saying Hello'
      expect(mail.message_id).to eq '1234@local.machine.example'
      expect(mail.date).to eq ::DateTime.parse('Fri, 21 Nov 1997 09:55:06 -0600')
    end

    # From RFC 2822:
    # When sending replies, the Subject field is often retained, though
    # prepended with "Re: " as described in section 3.6.5.
    # Note the "Reply-To:" field in the below message.  When John replies
    # to Mary's message above, the reply should go to the address in the
    # "Reply-To:" field instead of the address in the "From:" field.
    it "should handle reply message 2" do
      mail = Mail.read(fixture('emails', 'rfc2822', 'example06.eml'))
      expect(mail.from).to eq ['mary@example.net']
      expect(mail.to).to eq ['jdoe@machine.example']
      expect(mail.reply_to).to eq ['smith@home.example']
      expect(mail.subject).to eq 'Re: Saying Hello'
      expect(mail.message_id).to eq '3456@example.net'
      expect(mail[:in_reply_to].message_ids).to eq ['1234@local.machine.example']
      expect(mail[:references].message_ids).to eq ['1234@local.machine.example']
      expect(mail.date).to eq ::DateTime.parse('Fri, 21 Nov 1997 10:01:10 -0600')
    end

    # From RFC 2822:
    # Final reply message
    it "should handle the final reply message" do
      mail = Mail.read(fixture('emails', 'rfc2822', 'example07.eml'))
      expect(mail.to).to eq ['smith@home.example']
      expect(mail.from).to eq ['jdoe@machine.example']
      expect(mail.subject).to eq 'Re: Saying Hello'
      expect(mail.date).to eq ::DateTime.parse('Fri, 21 Nov 1997 11:00:00 -0600')
      expect(mail.message_id).to eq 'abcd.1234@local.machine.tld'
      expect(mail.in_reply_to).to eq '3456@example.net'
      expect(mail[:references].message_ids).to eq ['1234@local.machine.example', '3456@example.net']
    end

    # From RFC2822
    # A.3. Resent messages
    # Say that Mary, upon receiving this message, wishes to send a copy of
    # the message to Jane such that (a) the message would appear to have
    # come straight from John; (b) if Jane replies to the message, the
    # reply should go back to John; and (c) all of the original
    # information, like the date the message was originally sent to Mary,
    # the message identifier, and the original addressee, is preserved.  In
    # this case, resent fields are prepended to the message:
    #
    # If Jane, in turn, wished to resend this message to another person,
    # she would prepend her own set of resent header fields to the above
    # and send that.
    it "should handle the rfc resent example email" do
      mail = Mail.read(fixture('emails', 'rfc2822', 'example08.eml'))
      expect(mail.resent_from).to eq ['mary@example.net']
      expect(mail.resent_to).to eq ['j-brown@other.example']
      expect(mail.resent_date).to eq ::DateTime.parse('Mon, 24 Nov 1997 14:22:01 -0800')
      expect(mail.resent_message_id).to eq '78910@example.net'
      expect(mail.from).to eq ['jdoe@machine.example']
      expect(mail.to).to eq ['mary@example.net']
      expect(mail.subject).to eq 'Saying Hello'
      expect(mail.date).to eq ::DateTime.parse('Fri, 21 Nov 1997 09:55:06 -0600')
      expect(mail.message_id).to eq '1234@local.machine.example'
    end

    # A.4. Messages with trace fields
    # As messages are sent through the transport system as described in
    # [RFC2821], trace fields are prepended to the message.  The following
    # is an example of what those trace fields might look like.  Note that
    # there is some folding white space in the first one since these lines
    # can be long.
    it "should handle the RFC trace example email" do
      mail = Mail.read(fixture('emails', 'rfc2822', 'example09.eml'))
      expect(mail.received[0].info).to eq 'from x.y.test by example.net via TCP with ESMTP id ABC12345 for <mary@example.net>'
      expect(mail.received[0].date_time).to eq ::DateTime.parse('21 Nov 1997 10:05:43 -0600')
      expect(mail.received[1].info).to eq 'from machine.example by x.y.test'
      expect(mail.received[1].date_time).to eq ::DateTime.parse('21 Nov 1997 10:01:22 -0600')
      expect(mail.from).to eq ['jdoe@machine.example']
      expect(mail.to).to eq ['mary@example.net']
      expect(mail.subject).to eq 'Saying Hello'
      expect(mail.date).to eq ::DateTime.parse('Fri, 21 Nov 1997 09:55:06 -0600')
      expect(mail.message_id).to eq '1234@local.machine.example'
    end

    # A.5. White space, comments, and other oddities
    # White space, including folding white space, and comments can be
    # inserted between many of the tokens of fields.  Taking the example
    # from A.1.3, white space and comments can be inserted into all of the
    # fields.
    #
    # The below example is aesthetically displeasing, but perfectly legal.
    # Note particularly (1) the comments in the "From:" field (including
    # one that has a ")" character appearing as part of a quoted-pair); (2)
    # the white space absent after the ":" in the "To:" field as well as
    # the comment and folding white space after the group name, the special
    # character (".") in the comment in Chris Jones's address, and the
    # folding white space before and after "joe@example.org,"; (3) the
    # multiple and nested comments in the "Cc:" field as well as the
    # comment immediately following the ":" after "Cc"; (4) the folding
    # white space (but no comments except at the end) and the missing
    # seconds in the time of the date field; and (5) the white space before
    # (but not within) the identifier in the "Message-ID:" field.

    it "should handle the rfc whitespace test email" do
      skip "fixed in pr#487"
      mail = Mail.read(fixture('emails', 'rfc2822', 'example10.eml'))
      expect(mail.from).to eq ["pete(his account)@silly.test"]
      expect(mail.to).to eq  ["c@public.example", "joe@example.org", "jdoe@one.test"]
      expect(mail[:cc].group_names).to eq ['(Empty list)(start)Undisclosed recipients ']
      expect(mail.date).to eq ::DateTime.parse('Thu, 13 Feb 1969 23:32 -0330')
      expect(mail.message_id).to eq 'testabcd.1234@silly.test'
    end

    # A.6. Obsoleted forms
    # The following are examples of obsolete (that is, the "MUST NOT
    # generate") syntactic elements described in section 4 of this
    # document.
    # A.6.1. Obsolete addressing
    # Note in the below example the lack of quotes around Joe Q. Public,
    # the route that appears in the address for Mary Smith, the two commas
    # that appear in the "To:" field, and the spaces that appear around the
    # "." in the jdoe address.
    it "should handle the rfc obsolete addressing" do
      pending
      mail = Mail.read(fixture('emails', 'rfc2822', 'example11.eml'))
      expect(mail[:from].addresses).to eq ['john.q.public@example.com']
      expect(mail.from).to eq '"Joe Q. Public" <john.q.public@example.com>'
      expect(mail.to).to eq ["@machine.tld:mary@example.net", 'jdoe@test.example']
      expect(mail.date).to eq ::DateTime.parse('Tue, 1 Jul 2003 10:52:37 +0200')
      expect(mail.message_id).to eq '5678.21-Nov-1997@example.com'
    end

    # A.6.2. Obsolete dates
    #
    # The following message uses an obsolete date format, including a non-
    # numeric time zone and a two digit year.  Note that although the
    # day-of-week is missing, that is not specific to the obsolete syntax;
    # it is optional in the current syntax as well.
    it "should handle the rfc obsolete dates" do
      pending
      mail = Mail.read(fixture('emails', 'rfc2822', 'example12.eml'))
      expect(mail.from).to eq 'jdoe@machine.example'
      expect(mail.to).to eq 'mary@example.net'
      expect(mail.date).to eq ::DateTime.parse('21 Nov 97 09:55:06 GMT')
      expect(mail.message_id).to eq '1234@local.machine.example'
    end

    # A.6.3. Obsolete white space and comments
    #
    # White space and comments can appear between many more elements than
    # in the current syntax.  Also, folding lines that are made up entirely
    # of white space are legal.
    #
    # Note especially the second line of the "To:" field.  It starts with
    # two space characters.  (Note that "__" represent blank spaces.)
    # Therefore, it is considered part of the folding as described in
    # section 4.2.  Also, the comments and white space throughout
    # addresses, dates, and message identifiers are all part of the
    # obsolete syntax.
    it "should handle the rfc obsolete whitespace email" do
      pending
      mail = Mail.read(fixture('emails', 'rfc2822', 'example13.eml'))
      expect(mail.from).to eq 'John Doe <jdoe@machine(comment).example>'
      expect(mail.to).to eq 'Mary Smith <mary@example.net>'
      expect(mail.date).to eq ::DateTime.parse('Fri, 21 Nov 1997 09:55:06 -0600')
      expect(mail.message_id).to eq '1234@local(blah).machine.example'
      expect { Mail::Message.new(email) }.not_to raise_error
    end

    it "should handle folding subject" do
      mail = Mail.read(fixture('emails', 'rfc2822', 'example14.eml'))
      expect(mail.from).to eq ["atsushi@example.com"]
      expect(mail.subject).to eq "Re: TEST テストテスト"
      expect(mail.message_id).to eq '0CC5E11ED2C1D@example.com'
      expect(mail.body.decoded).to eq "Hello\n"
    end
  end

  describe "from the wild" do

    describe "raw_email_encoded_stack_level_too_deep.eml" do
      before(:each) do
        @message = Mail.read(fixture('emails', 'mime_emails', 'raw_email_encoded_stack_level_too_deep.eml'))
      end

      it "should return an 'encoded' version without raising a SystemStackError" do
        expect { @message.encoded }.not_to raise_error
      end

      it "should have two parts" do
        expect(@message.parts.length).to eq 2
      end

    end

    describe "sig_only_email.eml" do
      before(:each) do
        @message = Mail.read(fixture('emails', 'mime_emails', 'sig_only_email.eml'))
      end

      it "should not error on multiart/signed emails" do
        expect { @message.encoded }.not_to raise_error
      end

      it "should have one attachment called signature.asc" do
        expect(@message.attachments.length).to eq 1
        expect(@message.attachments.first.filename).to eq 'signature.asc'
      end

    end

    describe "handling invalid group lists" do
      before(:each) do
        @message = Mail.read(fixture('emails', 'error_emails', 'empty_group_lists.eml'))
      end

      it "should parse the email and encode without crashing" do
        expect { @message.encoded }.not_to raise_error
      end

      it "should return an empty groups list" do
        expect(@message[:to].group_addresses).to eq []
      end
    end

  end

  describe "empty address lists" do

    before(:each) do
      @message = Mail.read(fixture('emails', 'error_emails', 'weird_to_header.eml'))
    end

    it "should parse the email and encode without crashing" do
      expect { @message.encoded }.not_to raise_error
    end

    it "should return an empty groups list" do
      expect(@message.to).to eq ['user-example@aol.com', 'e-s-a-s-2200@app.ar.com']
    end

  end

end