diff --git a/Lib/email/message.py b/Lib/email/message.py
index b6512f2198..f932186875 100644
--- a/Lib/email/message.py
+++ b/Lib/email/message.py
@@ -7,7 +7,6 @@
 __all__ = ['Message', 'EmailMessage']
 
 import re
-import uu
 import quopri
 from io import BytesIO, StringIO
 
@@ -101,6 +100,35 @@ def _unquotevalue(value):
         return utils.unquote(value)
 
 
+def _decode_uu(encoded):
+    """Decode uuencoded data."""
+    decoded_lines = []
+    encoded_lines_iter = iter(encoded.splitlines())
+    for line in encoded_lines_iter:
+        if line.startswith(b"begin "):
+            mode, _, path = line.removeprefix(b"begin ").partition(b" ")
+            try:
+                int(mode, base=8)
+            except ValueError:
+                continue
+            else:
+                break
+    else:
+        raise ValueError("`begin` line not found")
+    for line in encoded_lines_iter:
+        if not line:
+            raise ValueError("Truncated input")
+        elif line.strip(b' \t\r\n\f') == b'end':
+            break
+        try:
+            decoded_line = binascii.a2b_uu(line)
+        except binascii.Error:
+            # Workaround for broken uuencoders by /Fredrik Lundh
+            nbytes = (((line[0]-32) & 63) * 4 + 5) // 3
+            decoded_line = binascii.a2b_uu(line[:nbytes])
+        decoded_lines.append(decoded_line)
+
+    return b''.join(decoded_lines)
 
 class Message:
     """Basic message object.
@@ -288,13 +316,10 @@ def get_payload(self, i=None, decode=False):
                 self.policy.handle_defect(self, defect)
             return value
         elif cte in ('x-uuencode', 'uuencode', 'uue', 'x-uue'):
-            in_file = BytesIO(bpayload)
-            out_file = BytesIO()
             try:
-                uu.decode(in_file, out_file, quiet=True)
-                return out_file.getvalue()
-            except uu.Error:
-                # Some decoding problem
+                return _decode_uu(bpayload)
+            except ValueError:
+                # Some decoding problem.
                 return bpayload
         if isinstance(payload, str):
             return bpayload
diff --git a/Lib/test/test_uu.py b/Lib/test/test_uu.py
deleted file mode 100644
index f71d877365..0000000000
--- a/Lib/test/test_uu.py
+++ /dev/null
@@ -1,258 +0,0 @@
-"""
-Tests for uu module.
-Nick Mathewson
-"""
-
-import unittest
-from test.support import os_helper
-
-import os
-import stat
-import sys
-import uu
-import io
-
-plaintext = b"The symbols on top of your keyboard are !@#$%^&*()_+|~\n"
-
-encodedtext = b"""\
-M5&AE('-Y;6)O;',@;VX@=&]P(&]F('EO=7(@:V5Y8F]A<F0@87)E("% (R0E
-*7B8J*"E?*WQ^"@  """
-
-# Stolen from io.py
-class FakeIO(io.TextIOWrapper):
-    """Text I/O implementation using an in-memory buffer.
-
-    Can be a used as a drop-in replacement for sys.stdin and sys.stdout.
-    """
-
-    # XXX This is really slow, but fully functional
-
-    def __init__(self, initial_value="", encoding="utf-8",
-                 errors="strict", newline="\n"):
-        super(FakeIO, self).__init__(io.BytesIO(),
-                                     encoding=encoding,
-                                     errors=errors,
-                                     newline=newline)
-        self._encoding = encoding
-        self._errors = errors
-        if initial_value:
-            if not isinstance(initial_value, str):
-                initial_value = str(initial_value)
-            self.write(initial_value)
-            self.seek(0)
-
-    def getvalue(self):
-        self.flush()
-        return self.buffer.getvalue().decode(self._encoding, self._errors)
-
-
-def encodedtextwrapped(mode, filename, backtick=False):
-    if backtick:
-        res = (bytes("begin %03o %s\n" % (mode, filename), "ascii") +
-               encodedtext.replace(b' ', b'`') + b"\n`\nend\n")
-    else:
-        res = (bytes("begin %03o %s\n" % (mode, filename), "ascii") +
-               encodedtext + b"\n \nend\n")
-    return res
-
-class UUTest(unittest.TestCase):
-
-    # TODO: RUSTPYTHON
-    @unittest.expectedFailure
-    def test_encode(self):
-        inp = io.BytesIO(plaintext)
-        out = io.BytesIO()
-        uu.encode(inp, out, "t1")
-        self.assertEqual(out.getvalue(), encodedtextwrapped(0o666, "t1"))
-        inp = io.BytesIO(plaintext)
-        out = io.BytesIO()
-        uu.encode(inp, out, "t1", 0o644)
-        self.assertEqual(out.getvalue(), encodedtextwrapped(0o644, "t1"))
-        inp = io.BytesIO(plaintext)
-        out = io.BytesIO()
-        uu.encode(inp, out, "t1", backtick=True)
-        self.assertEqual(out.getvalue(), encodedtextwrapped(0o666, "t1", True))
-        with self.assertRaises(TypeError):
-            uu.encode(inp, out, "t1", 0o644, True)
-
-    def test_decode(self):
-        for backtick in True, False:
-            inp = io.BytesIO(encodedtextwrapped(0o666, "t1", backtick=backtick))
-            out = io.BytesIO()
-            uu.decode(inp, out)
-            self.assertEqual(out.getvalue(), plaintext)
-            inp = io.BytesIO(
-                b"UUencoded files may contain many lines,\n" +
-                b"even some that have 'begin' in them.\n" +
-                encodedtextwrapped(0o666, "t1", backtick=backtick)
-            )
-            out = io.BytesIO()
-            uu.decode(inp, out)
-            self.assertEqual(out.getvalue(), plaintext)
-
-    def test_truncatedinput(self):
-        inp = io.BytesIO(b"begin 644 t1\n" + encodedtext)
-        out = io.BytesIO()
-        try:
-            uu.decode(inp, out)
-            self.fail("No exception raised")
-        except uu.Error as e:
-            self.assertEqual(str(e), "Truncated input file")
-
-    def test_missingbegin(self):
-        inp = io.BytesIO(b"")
-        out = io.BytesIO()
-        try:
-            uu.decode(inp, out)
-            self.fail("No exception raised")
-        except uu.Error as e:
-            self.assertEqual(str(e), "No valid begin line found in input file")
-
-    def test_garbage_padding(self):
-        # Issue #22406
-        encodedtext1 = (
-            b"begin 644 file\n"
-            # length 1; bits 001100 111111 111111 111111
-            b"\x21\x2C\x5F\x5F\x5F\n"
-            b"\x20\n"
-            b"end\n"
-        )
-        encodedtext2 = (
-            b"begin 644 file\n"
-            # length 1; bits 001100 111111 111111 111111
-            b"\x21\x2C\x5F\x5F\x5F\n"
-            b"\x60\n"
-            b"end\n"
-        )
-        plaintext = b"\x33"  # 00110011
-
-        for encodedtext in encodedtext1, encodedtext2:
-            with self.subTest("uu.decode()"):
-                inp = io.BytesIO(encodedtext)
-                out = io.BytesIO()
-                uu.decode(inp, out, quiet=True)
-                self.assertEqual(out.getvalue(), plaintext)
-
-            with self.subTest("uu_codec"):
-                import codecs
-                decoded = codecs.decode(encodedtext, "uu_codec")
-                self.assertEqual(decoded, plaintext)
-
-    # TODO: RUSTPYTHON
-    @unittest.expectedFailure
-    def test_newlines_escaped(self):
-        # Test newlines are escaped with uu.encode
-        inp = io.BytesIO(plaintext)
-        out = io.BytesIO()
-        filename = "test.txt\n\roverflow.txt"
-        safefilename = b"test.txt\\n\\roverflow.txt"
-        uu.encode(inp, out, filename)
-        self.assertIn(safefilename, out.getvalue())
-
-class UUStdIOTest(unittest.TestCase):
-
-    def setUp(self):
-        self.stdin = sys.stdin
-        self.stdout = sys.stdout
-
-    def tearDown(self):
-        sys.stdin = self.stdin
-        sys.stdout = self.stdout
-
-    def test_encode(self):
-        sys.stdin = FakeIO(plaintext.decode("ascii"))
-        sys.stdout = FakeIO()
-        uu.encode("-", "-", "t1", 0o666)
-        self.assertEqual(sys.stdout.getvalue(),
-                         encodedtextwrapped(0o666, "t1").decode("ascii"))
-
-    def test_decode(self):
-        sys.stdin = FakeIO(encodedtextwrapped(0o666, "t1").decode("ascii"))
-        sys.stdout = FakeIO()
-        uu.decode("-", "-")
-        stdout = sys.stdout
-        sys.stdout = self.stdout
-        sys.stdin = self.stdin
-        self.assertEqual(stdout.getvalue(), plaintext.decode("ascii"))
-
-class UUFileTest(unittest.TestCase):
-
-    def setUp(self):
-        # uu.encode() supports only ASCII file names
-        self.tmpin  = os_helper.TESTFN_ASCII + "i"
-        self.tmpout = os_helper.TESTFN_ASCII + "o"
-        self.addCleanup(os_helper.unlink, self.tmpin)
-        self.addCleanup(os_helper.unlink, self.tmpout)
-
-    def test_encode(self):
-        with open(self.tmpin, 'wb') as fin:
-            fin.write(plaintext)
-
-        with open(self.tmpin, 'rb') as fin:
-            with open(self.tmpout, 'wb') as fout:
-                uu.encode(fin, fout, self.tmpin, mode=0o644)
-
-        with open(self.tmpout, 'rb') as fout:
-            s = fout.read()
-        self.assertEqual(s, encodedtextwrapped(0o644, self.tmpin))
-
-        # in_file and out_file as filenames
-        uu.encode(self.tmpin, self.tmpout, self.tmpin, mode=0o644)
-        with open(self.tmpout, 'rb') as fout:
-            s = fout.read()
-        self.assertEqual(s, encodedtextwrapped(0o644, self.tmpin))
-
-    def test_decode(self):
-        with open(self.tmpin, 'wb') as f:
-            f.write(encodedtextwrapped(0o644, self.tmpout))
-
-        with open(self.tmpin, 'rb') as f:
-            uu.decode(f)
-
-        with open(self.tmpout, 'rb') as f:
-            s = f.read()
-        self.assertEqual(s, plaintext)
-        # XXX is there an xp way to verify the mode?
-
-    def test_decode_filename(self):
-        with open(self.tmpin, 'wb') as f:
-            f.write(encodedtextwrapped(0o644, self.tmpout))
-
-        uu.decode(self.tmpin)
-
-        with open(self.tmpout, 'rb') as f:
-            s = f.read()
-        self.assertEqual(s, plaintext)
-
-    def test_decodetwice(self):
-        # Verify that decode() will refuse to overwrite an existing file
-        with open(self.tmpin, 'wb') as f:
-            f.write(encodedtextwrapped(0o644, self.tmpout))
-        with open(self.tmpin, 'rb') as f:
-            uu.decode(f)
-
-        with open(self.tmpin, 'rb') as f:
-            self.assertRaises(uu.Error, uu.decode, f)
-
-    # TODO: RUSTPYTHON
-    @unittest.expectedFailure
-    def test_decode_mode(self):
-        # Verify that decode() will set the given mode for the out_file
-        expected_mode = 0o444
-        with open(self.tmpin, 'wb') as f:
-            f.write(encodedtextwrapped(expected_mode, self.tmpout))
-
-        # make file writable again, so it can be removed (Windows only)
-        self.addCleanup(os.chmod, self.tmpout, expected_mode | stat.S_IWRITE)
-
-        with open(self.tmpin, 'rb') as f:
-            uu.decode(f)
-
-        self.assertEqual(
-            stat.S_IMODE(os.stat(self.tmpout).st_mode),
-            expected_mode
-        )
-
-
-if __name__=="__main__":
-    unittest.main()
diff --git a/Lib/uu.py b/Lib/uu.py
deleted file mode 100755
index d68d29374a..0000000000
--- a/Lib/uu.py
+++ /dev/null
@@ -1,199 +0,0 @@
-#! /usr/bin/env python3
-
-# Copyright 1994 by Lance Ellinghouse
-# Cathedral City, California Republic, United States of America.
-#                        All Rights Reserved
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Lance Ellinghouse
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
-# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-# FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE CENTRUM BE LIABLE
-# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# Modified by Jack Jansen, CWI, July 1995:
-# - Use binascii module to do the actual line-by-line conversion
-#   between ascii and binary. This results in a 1000-fold speedup. The C
-#   version is still 5 times faster, though.
-# - Arguments more compliant with python standard
-
-"""Implementation of the UUencode and UUdecode functions.
-
-encode(in_file, out_file [,name, mode])
-decode(in_file [, out_file, mode])
-"""
-
-import binascii
-import os
-import sys
-
-__all__ = ["Error", "encode", "decode"]
-
-class Error(Exception):
-    pass
-
-def encode(in_file, out_file, name=None, mode=None):
-    """Uuencode file"""
-    #
-    # If in_file is a pathname open it and change defaults
-    #
-    opened_files = []
-    try:
-        if in_file == '-':
-            in_file = sys.stdin.buffer
-        elif isinstance(in_file, str):
-            if name is None:
-                name = os.path.basename(in_file)
-            if mode is None:
-                try:
-                    mode = os.stat(in_file).st_mode
-                except AttributeError:
-                    pass
-            in_file = open(in_file, 'rb')
-            opened_files.append(in_file)
-        #
-        # Open out_file if it is a pathname
-        #
-        if out_file == '-':
-            out_file = sys.stdout.buffer
-        elif isinstance(out_file, str):
-            out_file = open(out_file, 'wb')
-            opened_files.append(out_file)
-        #
-        # Set defaults for name and mode
-        #
-        if name is None:
-            name = '-'
-        if mode is None:
-            mode = 0o666
-        #
-        # Write the data
-        #
-        out_file.write(('begin %o %s\n' % ((mode & 0o777), name)).encode("ascii"))
-        data = in_file.read(45)
-        while len(data) > 0:
-            out_file.write(binascii.b2a_uu(data))
-            data = in_file.read(45)
-        out_file.write(b' \nend\n')
-    finally:
-        for f in opened_files:
-            f.close()
-
-
-def decode(in_file, out_file=None, mode=None, quiet=False):
-    """Decode uuencoded file"""
-    #
-    # Open the input file, if needed.
-    #
-    opened_files = []
-    if in_file == '-':
-        in_file = sys.stdin.buffer
-    elif isinstance(in_file, str):
-        in_file = open(in_file, 'rb')
-        opened_files.append(in_file)
-
-    try:
-        #
-        # Read until a begin is encountered or we've exhausted the file
-        #
-        while True:
-            hdr = in_file.readline()
-            if not hdr:
-                raise Error('No valid begin line found in input file')
-            if not hdr.startswith(b'begin'):
-                continue
-            hdrfields = hdr.split(b' ', 2)
-            if len(hdrfields) == 3 and hdrfields[0] == b'begin':
-                try:
-                    int(hdrfields[1], 8)
-                    break
-                except ValueError:
-                    pass
-        if out_file is None:
-            # If the filename isn't ASCII, what's up with that?!?
-            out_file = hdrfields[2].rstrip(b' \t\r\n\f').decode("ascii")
-            if os.path.exists(out_file):
-                raise Error('Cannot overwrite existing file: %s' % out_file)
-        if mode is None:
-            mode = int(hdrfields[1], 8)
-        #
-        # Open the output file
-        #
-        if out_file == '-':
-            out_file = sys.stdout.buffer
-        elif isinstance(out_file, str):
-            fp = open(out_file, 'wb')
-            try:
-                os.path.chmod(out_file, mode)
-            except AttributeError:
-                pass
-            out_file = fp
-            opened_files.append(out_file)
-        #
-        # Main decoding loop
-        #
-        s = in_file.readline()
-        while s and s.strip(b' \t\r\n\f') != b'end':
-            try:
-                data = binascii.a2b_uu(s)
-            except binascii.Error as v:
-                # Workaround for broken uuencoders by /Fredrik Lundh
-                nbytes = (((s[0]-32) & 63) * 4 + 5) // 3
-                data = binascii.a2b_uu(s[:nbytes])
-                if not quiet:
-                    sys.stderr.write("Warning: %s\n" % v)
-            out_file.write(data)
-            s = in_file.readline()
-        if not s:
-            raise Error('Truncated input file')
-    finally:
-        for f in opened_files:
-            f.close()
-
-def test():
-    """uuencode/uudecode main program"""
-
-    import optparse
-    parser = optparse.OptionParser(usage='usage: %prog [-d] [-t] [input [output]]')
-    parser.add_option('-d', '--decode', dest='decode', help='Decode (instead of encode)?', default=False, action='store_true')
-    parser.add_option('-t', '--text', dest='text', help='data is text, encoded format unix-compatible text?', default=False, action='store_true')
-
-    (options, args) = parser.parse_args()
-    if len(args) > 2:
-        parser.error('incorrect number of arguments')
-        sys.exit(1)
-
-    # Use the binary streams underlying stdin/stdout
-    input = sys.stdin.buffer
-    output = sys.stdout.buffer
-    if len(args) > 0:
-        input = args[0]
-    if len(args) > 1:
-        output = args[1]
-
-    if options.decode:
-        if options.text:
-            if isinstance(output, str):
-                output = open(output, 'wb')
-            else:
-                print(sys.argv[0], ': cannot do -t to stdout')
-                sys.exit(1)
-        decode(input, output)
-    else:
-        if options.text:
-            if isinstance(input, str):
-                input = open(input, 'rb')
-            else:
-                print(sys.argv[0], ': cannot do -t from stdin')
-                sys.exit(1)
-        encode(input, output)
-
-if __name__ == '__main__':
-    test()