{"record":{"id":"1014acd865c557d2","repo":"django/django","slug":"bcc-is-not-a-valid-email-header-use-the-bcc-arg","errorCode":null,"errorMessage":"Bcc is not a valid email header. Use the \"bcc\" argument to specify blind carbon copy recipients.","messagePattern":"Bcc is not a valid email header\\. Use the \"bcc\" argument to specify blind carbon copy recipients\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"django/core/mail/message.py","lineNumber":365,"sourceCode":"        self._set_list_header_if_not_empty(msg, \"Cc\", self.cc)\n        self._set_list_header_if_not_empty(msg, \"Reply-To\", self.reply_to)\n\n        # Email header names are case-insensitive (RFC 2045), so we have to\n        # accommodate that when doing comparisons.\n        header_names = [key.lower() for key in self.extra_headers]\n        if \"date\" not in header_names:\n            if settings.EMAIL_USE_LOCALTIME:\n                tz = get_current_timezone()\n            else:\n                tz = timezone.utc\n            msg[\"Date\"] = datetime.now(tz)\n        if \"message-id\" not in header_names:\n            # Use cached DNS_NAME for performance\n            msg[\"Message-ID\"] = make_msgid(domain=DNS_NAME)\n        for name, value in self.extra_headers.items():\n            header = name.lower()\n            if header == \"bcc\":\n                raise ValueError(\n                    'Bcc is not a valid email header. Use the \"bcc\" '\n                    \"argument to specify blind carbon copy recipients.\"\n                )\n            # Avoid headers handled above.\n            if header not in {\"from\", \"to\", \"cc\", \"reply-to\"}:\n                msg[name] = force_str(value, strings_only=True)\n        self._idna_encode_address_header_domains(msg)\n        return msg\n\n    def recipients(self):\n        \"\"\"\n        Return a list of all recipients of the email (includes direct\n        addressees as well as Cc and Bcc entries).\n        \"\"\"\n        return [email for email in (self.to + self.cc + self.bcc) if email]\n\n    def send(self, fail_silently=False, *, using=None):\n        \"\"\"Send the email message.\"\"\"","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/django/django/blob/ae25a40be07e8a749edf526df37c93e59d4a22c9/django/core/mail/message.py#L347-L383","documentation":"Inside EmailMessage.message() (django/core/mail/message.py:365), while copying user-supplied extra_headers onto the MIME message, a header whose lowercased name equals 'bcc' is rejected. BCC recipients must never appear as a message header — they are SMTP-envelope-only — and must be supplied through the dedicated `bcc` constructor argument so they are not written into the message text.","triggerScenarios":"EmailMessage(headers={'Bcc': 'hidden@x.com'}) or headers={'bcc': 'hidden@x.com'} — any header whose lowercased name equals 'bcc' triggers the ValueError at line 365.","commonSituations":"Porting code that set Bcc as a raw header in older email libraries; configuration that lets users add arbitrary headers; misunderstanding that Bcc is transport-only and must not appear in the message.","solutions":["Move BCC recipients out of `headers` and into the `bcc=` constructor argument: EmailMessage(bcc=['hidden@x.com']).","Filter user-supplied header dictionaries to drop any 'bcc' key before passing to headers.","If BCC must be hidden per-recipient, send one message per recipient instead."],"exampleFix":"// before\nEmailMessage(headers={\"Bcc\": \"hidden@example.com\"})\n// after\nEmailMessage(bcc=[\"hidden@example.com\"])","handlingStrategy":"validation","validationCode":"def sanitize_headers(headers):\n    blocked = {\"bcc\"}\n    return {k: v for k, v in (headers or {}).items() if k.lower() not in blocked}","typeGuard":null,"tryCatchPattern":"try:\n    msg = EmailMessage(headers=headers, bcc=bcc_list).message()\nexcept ValueError as e:\n    if \"bcc\" in str(e).lower():\n        # move bcc out of headers and retry\n        bcc_list = headers.pop(\"bcc\")\n        msg = EmailMessage(headers=headers, bcc=bcc_list).message()","preventionTips":["Never put Bcc in headers; always use the bcc= constructor argument.","Filter user-supplied header dicts to drop blocked names (bcc at minimum).","Document for users that Bcc is transport-only and must not appear in the message."],"tags":["email","privacy","headers","validation"],"analyzedSha":"ae25a40be07e8a749edf526df37c93e59d4a22c9","analyzedAt":"2026-08-06T21:46:51.801Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}