»Core Development>Code coverage>Lib/test/test_email/test_generator.py

Python code coverage for Lib/test/test_email/test_generator.py

1n/aimport io
2n/aimport textwrap
3n/aimport unittest
4n/afrom email import message_from_string, message_from_bytes
5n/afrom email.message import EmailMessage
6n/afrom email.generator import Generator, BytesGenerator
7n/afrom email import policy
8n/afrom test.test_email import TestEmailBase, parameterize
12n/aclass TestGeneratorBase:
14n/a policy = policy.default
16n/a def msgmaker(self, msg, policy=None):
17n/a policy = self.policy if policy is None else policy
18n/a return self.msgfunc(msg, policy=policy)
20n/a refold_long_expected = {
21n/a 0: textwrap.dedent("""\
22n/a To: whom_it_may_concern@example.com
23n/a From: nobody_you_want_to_know@example.com
24n/a Subject: We the willing led by the unknowing are doing the
25n/a impossible for the ungrateful. We have done so much for so long with so little
26n/a we are now qualified to do anything with nothing.
28n/a None
29n/a """),
30n/a # From is wrapped because wrapped it fits in 40.
31n/a 40: textwrap.dedent("""\
32n/a To: whom_it_may_concern@example.com
33n/a From:
34n/a nobody_you_want_to_know@example.com
35n/a Subject: We the willing led by the
36n/a unknowing are doing the impossible for
37n/a the ungrateful. We have done so much
38n/a for so long with so little we are now
39n/a qualified to do anything with nothing.
41n/a None
42n/a """),
43n/a # Neither to nor from fit even if put on a new line,
44n/a # so we leave them sticking out on the first line.
45n/a 20: textwrap.dedent("""\
46n/a To: whom_it_may_concern@example.com
47n/a From: nobody_you_want_to_know@example.com
48n/a Subject: We the
49n/a willing led by the
50n/a unknowing are doing
51n/a the impossible for
52n/a the ungrateful. We
53n/a have done so much
54n/a for so long with so
55n/a little we are now
56n/a qualified to do
57n/a anything with
58n/a nothing.
60n/a None
61n/a """),
62n/a }
63n/a refold_long_expected[100] = refold_long_expected[0]
65n/a refold_all_expected = refold_long_expected.copy()
66n/a refold_all_expected[0] = (
67n/a "To: whom_it_may_concern@example.com\n"
68n/a "From: nobody_you_want_to_know@example.com\n"
69n/a "Subject: We the willing led by the unknowing are doing the "
70n/a "impossible for the ungrateful. We have done so much for "
71n/a "so long with so little we are now qualified to do anything "
72n/a "with nothing.\n"
73n/a "\n"
74n/a "None\n")
75n/a refold_all_expected[100] = (
76n/a "To: whom_it_may_concern@example.com\n"
77n/a "From: nobody_you_want_to_know@example.com\n"
78n/a "Subject: We the willing led by the unknowing are doing the "
79n/a "impossible for the ungrateful. We have\n"
80n/a " done so much for so long with so little we are now qualified "
81n/a "to do anything with nothing.\n"
82n/a "\n"
83n/a "None\n")
85n/a length_params = [n for n in refold_long_expected]
87n/a def length_as_maxheaderlen_parameter(self, n):
88n/a msg = self.msgmaker(self.typ(self.refold_long_expected[0]))
89n/a s = self.ioclass()
90n/a g = self.genclass(s, maxheaderlen=n, policy=self.policy)
91n/a g.flatten(msg)
92n/a self.assertEqual(s.getvalue(), self.typ(self.refold_long_expected[n]))
94n/a def length_as_max_line_length_policy(self, n):
95n/a msg = self.msgmaker(self.typ(self.refold_long_expected[0]))
96n/a s = self.ioclass()
97n/a g = self.genclass(s, policy=self.policy.clone(max_line_length=n))
98n/a g.flatten(msg)
99n/a self.assertEqual(s.getvalue(), self.typ(self.refold_long_expected[n]))
101n/a def length_as_maxheaderlen_parm_overrides_policy(self, n):
102n/a msg = self.msgmaker(self.typ(self.refold_long_expected[0]))
103n/a s = self.ioclass()
104n/a g = self.genclass(s, maxheaderlen=n,
105n/a policy=self.policy.clone(max_line_length=10))
106n/a g.flatten(msg)
107n/a self.assertEqual(s.getvalue(), self.typ(self.refold_long_expected[n]))
109n/a def length_as_max_line_length_with_refold_none_does_not_fold(self, n):
110n/a msg = self.msgmaker(self.typ(self.refold_long_expected[0]))
111n/a s = self.ioclass()
112n/a g = self.genclass(s, policy=self.policy.clone(refold_source='none',
113n/a max_line_length=n))
114n/a g.flatten(msg)
115n/a self.assertEqual(s.getvalue(), self.typ(self.refold_long_expected[0]))
117n/a def length_as_max_line_length_with_refold_all_folds(self, n):
118n/a msg = self.msgmaker(self.typ(self.refold_long_expected[0]))
119n/a s = self.ioclass()
120n/a g = self.genclass(s, policy=self.policy.clone(refold_source='all',
121n/a max_line_length=n))
122n/a g.flatten(msg)
123n/a self.assertEqual(s.getvalue(), self.typ(self.refold_all_expected[n]))
125n/a def test_crlf_control_via_policy(self):
126n/a source = "Subject: test\r\n\r\ntest body\r\n"
127n/a expected = source
128n/a msg = self.msgmaker(self.typ(source))
129n/a s = self.ioclass()
130n/a g = self.genclass(s, policy=policy.SMTP)
131n/a g.flatten(msg)
132n/a self.assertEqual(s.getvalue(), self.typ(expected))
134n/a def test_flatten_linesep_overrides_policy(self):
135n/a source = "Subject: test\n\ntest body\n"
136n/a expected = source
137n/a msg = self.msgmaker(self.typ(source))
138n/a s = self.ioclass()
139n/a g = self.genclass(s, policy=policy.SMTP)
140n/a g.flatten(msg, linesep='\n')
141n/a self.assertEqual(s.getvalue(), self.typ(expected))
143n/a def test_set_mangle_from_via_policy(self):
144n/a source = textwrap.dedent("""\
145n/a Subject: test that
146n/a from is mangled in the body!
148n/a From time to time I write a rhyme.
149n/a """)
150n/a variants = (
151n/a (None, True),
152n/a (policy.compat32, True),
153n/a (policy.default, False),
154n/a (policy.default.clone(mangle_from_=True), True),
155n/a )
156n/a for p, mangle in variants:
157n/a expected = source.replace('From ', '>From ') if mangle else source
158n/a with self.subTest(policy=p, mangle_from_=mangle):
159n/a msg = self.msgmaker(self.typ(source))
160n/a s = self.ioclass()
161n/a g = self.genclass(s, policy=p)
162n/a g.flatten(msg)
163n/a self.assertEqual(s.getvalue(), self.typ(expected))
166n/aclass TestGenerator(TestGeneratorBase, TestEmailBase):
168n/a msgfunc = staticmethod(message_from_string)
169n/a genclass = Generator
170n/a ioclass = io.StringIO
171n/a typ = str
174n/aclass TestBytesGenerator(TestGeneratorBase, TestEmailBase):
176n/a msgfunc = staticmethod(message_from_bytes)
177n/a genclass = BytesGenerator
178n/a ioclass = io.BytesIO
179n/a typ = lambda self, x: x.encode('ascii')
181n/a def test_cte_type_7bit_handles_unknown_8bit(self):
182n/a source = ("Subject: Maintenant je vous présente mon "
183n/a "collègue\n\n").encode('utf-8')
184n/a expected = ('Subject: Maintenant je vous =?unknown-8bit?q?'
185n/a 'pr=C3=A9sente_mon_coll=C3=A8gue?=\n\n').encode('ascii')
186n/a msg = message_from_bytes(source)
187n/a s = io.BytesIO()
188n/a g = BytesGenerator(s, policy=self.policy.clone(cte_type='7bit'))
189n/a g.flatten(msg)
190n/a self.assertEqual(s.getvalue(), expected)
192n/a def test_cte_type_7bit_transforms_8bit_cte(self):
193n/a source = textwrap.dedent("""\
194n/a From: foo@bar.com
195n/a To: Dinsdale
196n/a Subject: Nudge nudge, wink, wink
197n/a Mime-Version: 1.0
198n/a Content-Type: text/plain; charset="latin-1"
199n/a Content-Transfer-Encoding: 8bit
201n/a oh là là, know what I mean, know what I mean?
202n/a """).encode('latin1')
203n/a msg = message_from_bytes(source)
204n/a expected = textwrap.dedent("""\
205n/a From: foo@bar.com
206n/a To: Dinsdale
207n/a Subject: Nudge nudge, wink, wink
208n/a Mime-Version: 1.0
209n/a Content-Type: text/plain; charset="iso-8859-1"
210n/a Content-Transfer-Encoding: quoted-printable
212n/a oh l=E0 l=E0, know what I mean, know what I mean?
213n/a """).encode('ascii')
214n/a s = io.BytesIO()
215n/a g = BytesGenerator(s, policy=self.policy.clone(cte_type='7bit',
216n/a linesep='\n'))
217n/a g.flatten(msg)
218n/a self.assertEqual(s.getvalue(), expected)
220n/a def test_smtputf8_policy(self):
221n/a msg = EmailMessage()
222n/a msg['From'] = "Páolo <főo@bar.com>"
223n/a msg['To'] = 'Dinsdale'
224n/a msg['Subject'] = 'Nudge nudge, wink, wink \u1F609'
225n/a msg.set_content("oh là là, know what I mean, know what I mean?")
226n/a expected = textwrap.dedent("""\
227n/a From: Páolo <főo@bar.com>
228n/a To: Dinsdale
229n/a Subject: Nudge nudge, wink, wink \u1F609
230n/a Content-Type: text/plain; charset="utf-8"
231n/a Content-Transfer-Encoding: 8bit
232n/a MIME-Version: 1.0
234n/a oh là là, know what I mean, know what I mean?
235n/a """).encode('utf-8').replace(b'\n', b'\r\n')
236n/a s = io.BytesIO()
237n/a g = BytesGenerator(s, policy=policy.SMTPUTF8)
238n/a g.flatten(msg)
239n/a self.assertEqual(s.getvalue(), expected)
242n/aif __name__ == '__main__':
243n/a unittest.main()