diff --git a/docs/topics/email.rst b/docs/topics/email.rst
index 18d2f8084..aac93a91a 100644
--- a/docs/topics/email.rst
+++ b/docs/topics/email.rst
@@ -35,12 +35,6 @@ And here is how to use it to send an e-mail (without attachments)::
 
     mailer.send(to=["someone@example.com"], subject="Some subject", body="Some body", cc=["another@example.com"])
 
-.. note::
-    As shown in the example above, ``to`` and ``cc`` need to be lists
-    of email addresses, not single addresses, and even for one recipient,
-    i.e. ``to="someone@example.com"`` will not work.
-
-
 MailSender class reference
 ==========================
 
@@ -87,13 +81,13 @@ uses `Twisted non-blocking IO`_, like the rest of the framework.
         Send email to the given recipients.
 
         :param to: the e-mail recipients
-        :type to: list
+        :type to: str or list of str
 
         :param subject: the subject of the e-mail
         :type subject: str
 
         :param cc: the e-mails to CC
-        :type cc: list
+        :type cc: str or list of str
 
         :param body: the e-mail body
         :type body: str
diff --git a/scrapy/mail.py b/scrapy/mail.py
index c6339f25b..0bb395521 100644
--- a/scrapy/mail.py
+++ b/scrapy/mail.py
@@ -21,6 +21,8 @@ else:
 
 from twisted.internet import defer, reactor, ssl
 
+from .utils.misc import arg_to_iter
+
 logger = logging.getLogger(__name__)
 
 
@@ -48,6 +50,10 @@ class MailSender(object):
             msg = MIMEMultipart()
         else:
             msg = MIMENonMultipart(*mimetype.split('/', 1))
+
+        to = list(arg_to_iter(to))
+        cc = list(arg_to_iter(cc))
+
         msg['From'] = self.mailfrom
         msg['To'] = COMMASPACE.join(to)
         msg['Date'] = formatdate(localtime=True)

Accept single values for "to" and "cc" arguments when sending mails
Follow up to https://github.com/scrapy/scrapy/pull/2271#issuecomment-248341246

> What about checking for strings and raising an error?
> Passing a string is an easy mistake to make.
> Or maybe we can support passing a single string.
diff --git a/tests/test_mail.py b/tests/test_mail.py
index bd7e49621..b139e98d8 100644
--- a/tests/test_mail.py
+++ b/tests/test_mail.py
@@ -10,7 +10,8 @@ class MailSenderTest(unittest.TestCase):
 
     def test_send(self):
         mailsender = MailSender(debug=True)
-        mailsender.send(to=['test@scrapy.org'], subject='subject', body='body', _callback=self._catch_mail_sent)
+        mailsender.send(to=['test@scrapy.org'], subject='subject', body='body',
+                        _callback=self._catch_mail_sent)
 
         assert self.catched_msg
 
@@ -24,9 +25,16 @@ class MailSenderTest(unittest.TestCase):
         self.assertEqual(msg.get_payload(), 'body')
         self.assertEqual(msg.get('Content-Type'), 'text/plain')
 
+    def test_send_single_values_to_and_cc(self):
+        mailsender = MailSender(debug=True)
+        mailsender.send(to='test@scrapy.org', subject='subject', body='body',
+                        cc='test@scrapy.org', _callback=self._catch_mail_sent)
+
     def test_send_html(self):
         mailsender = MailSender(debug=True)
-        mailsender.send(to=['test@scrapy.org'], subject='subject', body='<p>body</p>', mimetype='text/html', _callback=self._catch_mail_sent)
+        mailsender.send(to=['test@scrapy.org'], subject='subject',
+                        body='<p>body</p>', mimetype='text/html',
+                        _callback=self._catch_mail_sent)
 
         msg = self.catched_msg['msg']
         self.assertEqual(msg.get_payload(), '<p>body</p>')
@@ -90,7 +98,8 @@ class MailSenderTest(unittest.TestCase):
 
         mailsender = MailSender(debug=True)
         mailsender.send(to=['test@scrapy.org'], subject=subject, body=body,
-                        attachs=attachs, charset='utf-8', _callback=self._catch_mail_sent)
+                        attachs=attachs, charset='utf-8',
+                        _callback=self._catch_mail_sent)
 
         assert self.catched_msg
         self.assertEqual(self.catched_msg['subject'], subject)
@@ -99,7 +108,8 @@ class MailSenderTest(unittest.TestCase):
         msg = self.catched_msg['msg']
         self.assertEqual(msg['subject'], subject)
         self.assertEqual(msg.get_charset(), Charset('utf-8'))
-        self.assertEqual(msg.get('Content-Type'), 'multipart/mixed; charset="utf-8"')
+        self.assertEqual(msg.get('Content-Type'),
+                         'multipart/mixed; charset="utf-8"')
 
         payload = msg.get_payload()
         assert isinstance(payload, list)

pip install -e .
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-xdist pytest-mock pytest-asyncio pytest
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==25.3.0
Automat==24.8.1
cffi==1.17.1
constantly==23.10.4
coverage==7.8.0
cryptography==44.0.2
cssselect==1.3.0
exceptiongroup==1.2.2
execnet==2.1.1
hyperlink==21.0.0
idna==3.10
incremental==24.7.2
iniconfig==2.1.0
jmespath==1.0.1
lxml==5.3.1
packaging==24.2
parsel==1.10.0
pluggy==1.5.0
pyasn1==0.6.1
pyasn1_modules==0.4.2
pycparser==2.22
PyDispatcher==2.0.7
pyOpenSSL==25.0.0
pytest==8.3.5
pytest-asyncio==0.26.0
pytest-cov==6.0.0
pytest-mock==3.14.0
pytest-xdist==3.6.1
queuelib==1.7.0
-e git+https://github.com/scrapy/scrapy.git@7e20725eb78cb34db60944cd1f155522fcf3b9f5#egg=Scrapy
service-identity==24.2.0
six==1.17.0
tomli==2.2.1
Twisted==24.11.0
typing_extensions==4.13.0
w3lib==2.3.1
zope.interface==7.2

name: scrapy
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==25.3.0
      - automat==24.8.1
      - cffi==1.17.1
      - constantly==23.10.4
      - coverage==7.8.0
      - cryptography==44.0.2
      - cssselect==1.3.0
      - exceptiongroup==1.2.2
      - execnet==2.1.1
      - hyperlink==21.0.0
      - idna==3.10
      - incremental==24.7.2
      - iniconfig==2.1.0
      - jmespath==1.0.1
      - lxml==5.3.1
      - packaging==24.2
      - parsel==1.10.0
      - pluggy==1.5.0
      - pyasn1==0.6.1
      - pyasn1-modules==0.4.2
      - pycparser==2.22
      - pydispatcher==2.0.7
      - pyopenssl==25.0.0
      - pytest==8.3.5
      - pytest-asyncio==0.26.0
      - pytest-cov==6.0.0
      - pytest-mock==3.14.0
      - pytest-xdist==3.6.1
      - queuelib==1.7.0
      - service-identity==24.2.0
      - six==1.17.0
      - tomli==2.2.1
      - twisted==24.11.0
      - typing-extensions==4.13.0
      - w3lib==2.3.1
      - zope-interface==7.2
prefix: /opt/conda/envs/scrapy

tests/test_mail.py::MailSenderTest::test_send_single_values_to_and_cc
tests/test_mail.py::MailSenderTest::test_send tests/test_mail.py::MailSenderTest::test_send_attach tests/test_mail.py::MailSenderTest::test_send_attach_utf8 tests/test_mail.py::MailSenderTest::test_send_html tests/test_mail.py::MailSenderTest::test_send_utf8
scrapy/mail.py docs/topics/email.rst
scrapy/mail.py docs/topics/email.rst