public static function qEncode($input, $max_length = 75)
    {
        // Don't encode empty strings
        if (empty($input)) {
            return $input;
        }

        // Don't encode if all code points are in ASCII range 0-127
        if (!preg_match('/[\\x80-\\xff]+/', $input)) {
            return $input;
        }

        $qpHexDigits  = '0123456789ABCDEF';
        $input_length = strlen($input);
        // Substract delimiters, character set and encoding
        $line_limit   = $max_length - 12;
        $line_length  = 0;

        $output = '=?UTF-8?Q?';

        for ($i=0; $i < $input_length; $i++) {
            $char = $input[$i];
            $ascii = ord($char);

            // No encoding for all 62 alphanumeric characters
            if (48 <= $ascii && $ascii <= 57 || 65 <= $ascii && $ascii <= 90 || 97 <= $ascii && $ascii <= 122) {
                $replace_length = 1;
                $replace_char = $char;

                // Encode space as underscore (means better readability for humans)
            } elseif ($ascii == 32) {
                $replace_length = 1;
                $replace_char = '_';

                // Encode
            } else {
                $replace_length = 3;
                // Bit operation is around 10 percent faster
                // than 'strtoupper(dechex($ascii))'
                $replace_char = '='
                              . $qpHexDigits[$ascii >> 4]
                              . $qpHexDigits[$ascii & 0x0f];

                // Account for following bytes of UTF8-multi-byte
                // sequence (max. length is 4 octets, RFC3629)
                $lookahead_limit = min($i+4, $input_length);

                for ($lookahead = $i+1; $lookahead < $lookahead_limit; $lookahead++) {
                    $ascii_ff = ord($input[$lookahead]);
                    if (128 <= $ascii_ff && $ascii_ff <= 191) {
                        $replace_char .= '='
                                       . $qpHexDigits[$ascii_ff >> 4]
                                       . $qpHexDigits[$ascii_ff & 0x0f];
                        $replace_length += 3;
                        $i++;
                    } else {
                        break;
                    }
                }
            }

            // Would the line become too long?
            if ($line_length + $replace_length > $line_limit) {
                $output .= "?= =?UTF-8?Q?";
                $line_length = 0;
            }

            $output .= $replace_char;
            $line_length += $replace_length;
        }

        $output .= '?=';
        return $output;
    }