SMTPLIB
CC recipients missing in Python smtplib? sendmail() builds the SMTP envelope from to_addrs, not the Cc: header. Add CC/BCC to to_addrs or use send_message().
Updated Jul 1, 2026
The short answer
"Python smtplib cc Not Working" isn't an error code — it's the symptom of CC recipients never receiving an email even though a Cc: header is set. The cause: smtplib.sendmail() builds the SMTP envelope (RCPT TO) only from its to_addrs argument, ignoring message headers. Fix it by passing every recipient — To, Cc, and Bcc — in to_addrs, or use send_message(), which reads those headers for you.
This is not an SMTP reply code or a Python exception — it's a behavioral symptom. Your message arrives at the To recipients, but the addresses you put in the Cc: header never receive a copy. There's usually no traceback, because nothing technically failed: smtplib delivered exactly to the recipients you told it to.
The confusion comes from conflating two different things in email:
From:, To:, Cc:) — text inside the message that mail clients display.MAIL FROM / RCPT TO) — the routing instructions the server actually uses to decide who gets the mail.These are independent, exactly as the real envelope and letterhead of a physical letter are independent. This separation is defined in RFC 5321 §2.3.1: a mail object is transported with an envelope and content; the envelope determines delivery, and the headers are part of the content.
SMTP.sendmail(from_addr, to_addrs, msg) builds the envelope only from its to_addrs argument. Per the Python smtplib docs:
The from_addr and to_addrs parameters are used to construct the message envelope used by the transport agents.
sendmaildoes not modify the message headers in any way.
So if you write a Cc: header into your MIMEMultipart but pass only the To address as to_addrs, smtplib issues RCPT TO for the To recipient only. The CC header is delivered as visible text, but no RCPT TO is ever sent for those addresses — hence "CC not working." The same applies to BCC.
Option 1 — include every recipient in to_addrs (works on all versions). to_addrs must be the complete list of envelope recipients: To + Cc + Bcc combined.
from email.mime.multipart import MIMEMultipartfrom email.mime.text import MIMETextimport smtplibto_addrs = ["alice@example.com"]cc_addrs = ["bob@example.com", "carol@example.com"]bcc_addrs = ["audit@example.com"]msg = MIMEMultipart()msg["From"] = "sender@example.com"msg["To"] = ", ".join(to_addrs)msg["Cc"] = ", ".join(cc_addrs) # visible header# Do NOT add a Bcc header — keep BCC out of the message textmsg.attach(MIMEText("Hello", "plain"))all_recipients = to_addrs + cc_addrs + bcc_addrs # the envelopewith smtplib.SMTP_SSL("smtp.example.com", 465) as s:s.login("user", "app-password")s.sendmail("sender@example.com", all_recipients, msg.as_string())
Note that CC recipients still get the email even though they're in to_addrs — to_addrs is the envelope recipient list, not the To: header. Keep BCC addresses out of the message headers so they stay hidden, but do include them in all_recipients.
Option 2 — let send_message() read the headers for you. The higher-level SMTP.send_message() extracts recipients automatically: when to_addrs is omitted, it "combines the values (if any) of the To, Cc, and Bcc fields." It also strips the Bcc (and Resent-Bcc) header before transmission, so BCC stays private.
msg["Bcc"] = "audit@example.com" # send_message reads it, then removes itwith smtplib.SMTP_SSL("smtp.example.com", 465) as s:s.login("user", "app-password")s.send_message(msg) # no explicit recipient list needed
There is a real CPython bug (gh-113658) where, starting in Python 3.12.1, send_message() fails to extract recipients when both a Cc and a Bcc header are present and both are set to empty strings (e.g. msg["Cc"] = "" and msg["Bcc"] = ""). In that case it sends RCPT TO:<> instead of the real recipient. Populated Cc/Bcc headers are unaffected. It was fixed in a later 3.12.x release. If you hit this, either omit the empty Cc/Bcc headers entirely, upgrade Python, or fall back to Option 1 by passing to_addrs explicitly.
to_addrs (or are you using send_message())? The header alone is never enough.send_message()? Avoid setting empty Cc and Bcc headers together — that combination triggers the RCPT TO:<> bug. Upgrade or pass to_addrs explicitly.References
FAQ
Because smtplib.sendmail() builds the SMTP envelope (RCPT TO) only from its to_addrs argument and never reads the Cc: header. Add the CC addresses to to_addrs (to_addrs = to + cc + bcc), or switch to send_message(), which reads To/Cc/Bcc headers automatically.
One API, every provider
Courier connects to your email, SMS, and push providers, handles retries and failover, and surfaces delivery errors in plain language.
Reply-code definitions per RFC 5321 §2.3.1. Last reviewed Jul 1, 2026. Courier is not affiliated with third-party providers; error behavior may vary by implementation.
© 2026 Courier. All rights reserved.