Multibyte strings7 min readExamples run on PHP 8.5.10

mb_encode_mimeheader()

Learn how mb_encode_mimeheader() turns non-ASCII text into ASCII-safe MIME encoded words, with parameters, examples, edge cases and common mistakes.

Signature

mb_encode_mimeheader(
    string $string,
    ?string $charset = null,
    ?string $transfer_encoding = null,
    string $newline = "\r\n",
    int $indent = 0
): string
Available since PHP 4.0.67.48.08.18.28.38.48.5All versions →

Purpose

Email and similar protocols carry header lines such as Subject: or a display name in From: as plain ASCII. When a header value contains characters like é or ñ, it has to be wrapped in a MIME encoded word, which looks like =?UTF-8?B?...?=. The word names the character set, the transfer encoding, and the encoded payload.

mb_encode_mimeheader() builds those encoded words for you. It takes a string in your internal encoding and returns an ASCII representation that is safe to place in a header.

Signature (PHP 8.4)

Parameters and defaults

  • $string: the text to encode. The manual says its encoding should match mb_internal_encoding().
  • $charset: the name of the character set the string is in, such as "UTF-8". When null, the default comes from the current NLS setting (mbstring.language). Being explicit is more predictable.
  • $transfer_encoding: "B" for Base64 or "Q" for Quoted-Printable. If you leave it as null, it falls back to "B".
  • $newline: the end-of-line marker used when long output is folded onto several lines. The default is "\r\n". The manual notes the folding length is hard-coded to 74 characters.
  • $indent: how many characters of the header line already precede the string, for example the length of Subject: . It lets the folding logic account for text already on the first line.

Return value and failure cases

The function returns a string: the converted version, represented in ASCII. It does not return false. Plain ASCII input comes back as it was, so you can call it on every header value without checking first.

Changelog items from the manual: since PHP 8.0.0, $charset and $transfer_encoding are nullable; since PHP 8.3.0, NUL (0) bytes are no longer dropped in Quoted-Printable output but are encoded as =00.

Example 1: ASCII passes through

Example
<?php
mb_internal_encoding('UTF-8');
echo mb_encode_mimeheader("Hello World", "UTF-8", "B"), "\n";
Output
Hello World

Because nothing here needs encoding, the header text stays readable.

Example 2: Base64 versus Quoted-Printable

Example
<?php
mb_internal_encoding('UTF-8');
$text = "\u{E9}";
echo mb_encode_mimeheader($text, "UTF-8", "B"), "\n";
echo mb_encode_mimeheader($text, "UTF-8", "Q"), "\n";
Output
=?UTF-8?B?w6k=?=
=?UTF-8?Q?=C3=A9?=

The same letter is encoded two ways. B produces compact Base64, while Q keeps ASCII characters readable and writes other bytes as =XX hex pairs. Q is usually friendlier when most of the text is ASCII, and B is more compact when most of it is not.

Example 3: a display name in an address header

Example
<?php
mb_internal_encoding('UTF-8');
$name = mb_encode_mimeheader("\u{F1}", "UTF-8", "B");
echo '"' . addcslashes($name, '"') . '" <ana@example.com>' . "\n";
Output
"=?UTF-8?B?w7E=?=" <ana@example.com>

Only the human-readable name is encoded. The address itself must stay plain ASCII, so never pass the whole name <address> string through the function.

Edge cases

  • Line folding. Long encoded output is broken across lines using $newline. If your mail library expects bare \n or a specific style, pass it explicitly instead of relying on "\r\n".
  • Word boundaries. The manual warns that the function is not designed to break lines at higher-level contextual points such as word boundaries, and the output may gain unexpected spaces. For long, mixed text, inspect the result.
  • Indent. If the header name is already on the line, supply $indent so the first line is measured correctly.
  • NUL bytes. In Quoted-Printable output they are encoded as =00 in PHP 8.3 and later.
  • Charset. Pass a charset name mbstring understands. Relying on the NLS default can make the output depend on configuration.

Common mistakes

  1. Encoding an entire header line. Encode only the value that may be non-ASCII, never the header name, the colon, or an email address.
  2. Mismatched encodings. The string must actually be in the encoding you declare. Declaring UTF-8 for Latin-1 bytes produces a header that decodes to garbage.
  3. Assuming a fixed result for long text. Folding and spacing can differ from what you expect, so test with realistic strings.
  4. Forgetting quotes. A display name with special characters such as quotes or commas often needs to be quoted. Escape the quotes in the encoded result as shown in the third example.
  5. Using it for body text. This function is for headers only. Message bodies need a different transfer encoding.
  • mb_decode_mimeheader(): the reverse operation, decoding a MIME header field.
  • mb_internal_encoding(): shows or sets the encoding that $string is expected to use.
  • addcslashes(): handy for escaping quotes around an encoded display name.

Recap

mb_encode_mimeheader() turns multibyte text into ASCII encoded words for headers. Always state the charset, choose B or Q on purpose, encode only the header value, and set $newline and $indent when your context demands it. ASCII-only input is returned unchanged.

Tested examples

ASCII input passes through unchanged
<?php
mb_internal_encoding('UTF-8');
echo mb_encode_mimeheader("Hello World", "UTF-8", "B"), "\n";
Output
Hello World
Base64 versus Quoted-Printable
<?php
mb_internal_encoding('UTF-8');
$text = "\u{E9}";
echo mb_encode_mimeheader($text, "UTF-8", "B"), "\n";
echo mb_encode_mimeheader($text, "UTF-8", "Q"), "\n";
Output
=?UTF-8?B?w6k=?=
=?UTF-8?Q?=C3=A9?=
Encoding a display name in an address header
<?php
mb_internal_encoding('UTF-8');
$name = mb_encode_mimeheader("\u{F1}", "UTF-8", "B");
echo '"' . addcslashes($name, '"') . '" <ana@example.com>' . "\n";
Output
"=?UTF-8?B?w7E=?=" <ana@example.com>