imap_8bit

(PHP 4,PHP 5,PHP 7,PHP 8)

imap_8bit将 8 位字符串转换为 quoted-printable 字符串

说明

imap_8bit(string $string): string|false

将 8 位字符串转换为已引用的可打印字符串(根据 » RFC2045,6.7 部分)。

参数

字符串

要转换的 8 位字符串

返回值

返回已引用的可打印字符串,或在失败时返回 **false**。

另请参阅

  • imap_qprint() - 将已引用的可打印字符串转换为 8 位字符串

添加注释

用户贡献的说明 16 条说明

rayFX
20 年前
imap_8bit 似乎有一个错误,因为它不会对“?”进行编码。
在用
带有尾部“?”的德语变音符号编码邮件主题时遇到了很多麻烦...

尝试这个

$subject = "=?iso-8859-1?Q?" . str_replace("?","=3F",imap_8bit($tsubject_to_encode)) . "?=";
umu
18 年前
...deed.ztinmehc-ut.zrh@[email protected]...

我在没有 IMAP 模块的情况下使用 PHP 时
会使用以下函数代替 imap_8bit,
它基于
https://php.net/quoted_printable_decode 中找到的代码
并且(据称)会产生与 imap_8bit 完全相同的结果,
(在数千个随机字符串中进行了测试,其中包含大量
空格、制表符、crlf、lfcr、lf、cr 等内容,
到目前为止还没有发现反例 :))

而且可以强制编码尾随空格,
这与 imap_8bit 所做的相反,
我认为这违反了 RFC2045,
(参见 http://bugs.php.net/bug.php?id=35290
通过注释掉一个中心行。

<?php
function quoted_printable_encode($sText,$bEmulate_imap_8bit=true) {
// split text into lines
$aLines=explode(chr(13).chr(10),$sText);

for (
$i=0;$i<count($aLines);$i++) {
$sLine =& $aLines[$i];
if (
strlen($sLine)===0) continue; // do nothing, if empty

$sRegExp = '/[^\x09\x20\x21-\x3C\x3E-\x7E]/e';

// imap_8bit encodes x09 everywhere, not only at lineends,
// for EBCDIC safeness encode !"#$@[\]^`{|}~,
// for complete safeness encode every character :)
if ($bEmulate_imap_8bit)
$sRegExp = '/[^\x20\x21-\x3C\x3E-\x7E]/e';

$sReplmt = 'sprintf( "=%02X", ord ( "$0" ) ) ;';
$sLine = preg_replace( $sRegExp, $sReplmt, $sLine );

// encode x09,x20 at lineends
{
$iLength = strlen($sLine);
$iLastChar = ord($sLine{$iLength-1});

// !!!!!!!!
// imap_8_bit does not encode x20 at the very end of a text,
// here is, where I don't agree with imap_8_bit,
// please correct me, if I'm wrong,
// or comment next line for RFC2045 conformance, if you like
if (!($bEmulate_imap_8bit && ($i==count($aLines)-1)))

if ((
$iLastChar==0x09)||($iLastChar==0x20)) {
$sLine{$iLength-1}='=';
$sLine .= ($iLastChar==0x09)?'09':'20';
}
}
// imap_8bit encodes x20 before chr(13), too
// although IMHO not requested by RFC2045, why not do it safer :)
// and why not encode any x20 around chr(10) or chr(13)
if ($bEmulate_imap_8bit) {
$sLine=str_replace(' =0D','=20=0D',$sLine);
//$sLine=str_replace(' =0A','=20=0A',$sLine);
//$sLine=str_replace('=0D ','=0D=20',$sLine);
//$sLine=str_replace('=0A ','=0A=20',$sLine);
}

// finally split into softlines no longer than 76 chars,
// for even more safeness one could encode x09,x20
// at the very first character of the line
// and after soft linebreaks, as well,
// but this wouldn't be caught by such an easy RegExp
preg_match_all( '/.{1,73}([^=]{0,2})?/', $sLine, $aMatch );
$sLine = implode( '=' . chr(13).chr(10), $aMatch[0] ); // add soft crlf's
}

// join lines into text
return implode(chr(13).chr(10),$aLines);
}
?>
Michael Konecny
13 年前
MS Exchange 服务器中存在一个错误,它错误地处理 CRLF。似乎它同时将 CR 和 LF 转换为 LF,所以,您不仅会得到一个新行,还会得到两行。
然后电子邮件客户端会错误地分析标题信息,并通常在消息正文中查看。

这会使自定义创建的标题无法使用。

我发现解决此问题的唯一方法是违反标题格式设置的 RFC 规则,并且仅将 \n 用于新行。

不幸的是,我还没能得知发生此问题的 Exchange 服务器版本,但我觉得这并不只是我偶然遇到的问题。

希望这能帮到某些人。
enter dot pl 上的 k dot kozlowski
19 年前
我对使用波兰文字符编码大型主题遇到问题。问题在于 imap_8bit() 分割主题(在第 75 个字符处),但当我添加“=?ISO-8859-2?Q?”时,标题太长。

这是一个解决方案
<?php
$subject
= str_replace(" ", "_", trim($subject)) ;
// 我们需要删除 imap_8bit() 生成的“=\r\n”并替换 '?'
$subject = str_replace("?", "=3F", str_replace("=\r\n", "", imap_8bit($subject))) ;
// 现在,我们按 \r\n 分割,但对“=?ISO ...”的文本进行编码
$subject = str_replace("\r\n", "?=\r\n =?ISO-8859-2?Q?", chunk_split($subject, 55)) ;
// 我们还必须删除最后不必要的编码文本:
$subject = "=?ISO-8859-2?Q?" .substr($subject, 0, strlen($subject)-20) . "?=" ;
?>
匿名用户
16 年前
umu 的代码似乎运行得很好。但是,如果你在 Unix 系统上,你应该将所有 chr(13).chr(10) 替换为仅为 chr(10)

无论如何,它都在 php5.mail() -> [email protected] -> outlook express 中为我运行
jufer dot info 上的 dave
8 年前
按照 RFC2047 将一封邮件主题字符串编码成一个有关注符字符和 75 个字符总行长的编码单词。
示例:“Subject Testä” -> “=?ISO-8859-1?Q?Subject_Test=E4?="
<?php
function getSubjectEncoded($_str,$_charset='ISO-8859-1'){
// 27.08.2015 david jufer
// Convert an 8bit string to a encoded-word string (according to RFC2047) www.ietf.org/rfc/rfc2047.txt
// encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
// An 'encoded-word' may not be more than 75 characters long, including 'charset', 'encoding', 'encoded-text', and delimiters.
// The "Q" encoding is similar to the "Quoted-Printable" content-transfer-encoding defined in RFC 2045
$ret = '';
$str = imap_8bit($_str);
$len = 7+strlen($_charset);
// remove linebreaks from imap_8bit, string chunks are too long
$str = str_replace("=\r\n",'',$str);
// insert linebreaks at right position, be aware of special chars ("ä" "=E4") do not split them
$s = 0;
$l = 75-$len;
while(
strlen($str)>$s){
$ts = $s;
if(
substr($str,($s+$l)-2,1)=='='){
$s += $l-2;
}else if(
substr($str,($s+$l)-1,1)=='='){
$s += $l-1;
}else{
$s += $l;
}
$ret .= "\r\n".substr($str,$ts,$s-$ts);
}
// remove first linebreak, replace SPACES with "_"
$ret = str_replace(' ','_',trim($ret));
// put together encoded-word
$ret = '=?'.$_charset.'?Q?'.str_replace("\r\n","?=\r\n =?".$_charset."?Q?",$ret)."?=";
// rückgabe
return $ret;
}
?>
FF.ST 上的 MagicalTux
20 年前
阅读 Bully 的笔记
你可以使用以下代码生成更大的主题
<?
$encoded = str_replace("=\r\n","",imap_8bit($string_to_encode));
?>
有误。该头不得超过每行 75 个字符。

正确的解决方案
<?
$encoded = rtrim( str_replace( "\n","\n\t", imap_8bit ($string_to_encode)))."\r\n";
?>

它将在编码的新行开头添加 \t。
邮件系统将主题后面的行看成该头的扩展。
esh dot software at energiash dot com
14 年前
创建可引用打印电子邮件时的正确方法是

$subject="Subject: =?iso-8859-1?Q?". imap_8bit("áéíóú"). "?=";

而以下方法是错误的,因为在 "=ED" 处 qprint 将生成 8bit 数据 ( í )

$subject="Subject: =?iso-8859-1?Q?". imap_qprint("=ED"). "?=";
roman at REMOVETHIS dot teamnet dot com dot pl
17 年前
代码基于 k dot kozlowski at enter dot pl,但针对 UTF-8
(我在垃圾邮件测试中使用非常长的主题时唯一遇到的问题是 SUBJECT_ENCODED_TWICE,但其他 MUA 也生成同样的问题)
<?
function header_quoted_printable_encode($string, $encoding='UTF-8') {

$string = str_replace(" ", "_", trim($string)) ;
// 我们需要删除 imap_8bit() 生成的 "=\r\n" 和替换 ?
$string = str_replace("?", "=3F", str_replace("=\r\n", "", imap_8bit($string))) ;

// 现在我们按 \r\n 分割 - 我不清楚具体是多少字符(头名称是否计算在内?)
$string = chunk_split($string, 73);
// 我们还必须删除最后一个不需要的 \r\n
$string = substr($string, 0, strlen($string)-2);
// 用编码文本 "=?UTF ..." 替换换行符
$string = str_replace("\r\n", "?=".HEAD_CRLF." =?".$encoding."?Q?", $string) ;

return '=?'.$encoding.'?Q?'.$string.'?=';
}
?>
hans at lintoo dot dk
18 年前
我修改了 nick at plumdigitalmedia dot com 的注释,以便它可以支持 ISO-8859-1 编码头
<?php
public function encodeSubject($string,$prefix="=?ISO-8859-1?Q?",$postfix="?=") {
$crlf = "\n\t";
$string = preg_replace('!(\r\n|\r|\n)!', $crlf, $string) . $crlf ;
$f[] = '/([\000-\010\013\014\016-\037\075\177-\377])/e' ;
$r[] = "'=' . sprintf('%02X', ord('\\1'))" ;
$f[] = '/([\011\040])' . $crlf . '/e' ;
$r[] = "'=' . sprintf('%02X', ord('\\1')) . '" . $crlf . "'" ;
$string = preg_replace($f, $r, $string);
return
$prefix.trim(wordwrap($string, 70 - strlen($prefix) - strlen($postfix), ' ' . $postfix . $crlf . $prefix, true)).$postfix;
}
?>
此致,汉斯,电子邮件地址:http://lintoo.dk/
marco dot manngatter at ecg-leipzig dot de
18 年前
您可以使用以下内容来生成较大的主题。
使用 imap_qprint() 函数来转换您的主题。

示例
<?php

$subject
.= "=?iso-8859-1?Q?" . imap_qprint($subject) . "?=";

?>
nick at plumdigitalmedia dot com
19 年前
此函数似乎会将行包装在单词中间,而不只是空白处,在用来设置电子邮件正文文本时,这样会影响某些版本的 Outlook Express。相对于此函数,我们更有幸使用到了

<?

函数 quoted_printable($string)
{
$crlf = "\n" ;
$string = preg_replace('!(\r\n|\r|\n)!', $crlf, $string) . $crlf ;
$f[] = '/([\000-\010\013\014\016-\037\075\177-\377])/e' ;
$r[] = "'=' . sprintf('%02X', ord('\\1'))" ;
$f[] = '/([\011\040])' . $crlf . '/e' ;
$r[] = "'=' . sprintf('%02X', ord('\\1')) . '" . $crlf . "'" ;
$string = preg_replace($f, $r, $string) ;
return trim(wordwrap($string, 70, ' =' . $crlf)) ;
}

?>
php dot net at werner-ott dot de
21 年前
对“75 个字符后拆分”现象的评论

通过在 75 个字符后拆分行,这个函数的行为符合 RFC2047(http://www.ietf.org/rfc/rfc2047.txt)(指定用于消息头中的非 ASCII 文本),“2. 编码单词的语法”。

所谓的“编码单词”具有以下格式

编码单词 = "=?" 字符集 "?" 编码 "?" 编码文本 "?="

'编码单词' 的长度不得超过 75 个字符,包括 'charset'、'encoding'、'encoded-text' 和定界符。如果要编码的文本大于可容纳在 75 个字符的 'encoded-word' 中,可以使用多个 'encoded-word'(以 CRLF SPACE 分隔)。

hth
WOT
bully at newearth dot de
22 年前
你可以使用以下代码生成更大的主题

$encoded = str_replace("=\r\n","",imap_8bit($string_to_encode));
zuffa at isdd dot sk
23 年前
警告!
此函数将输入文本拆分为
多行,对齐到 75 个字符。
在需要输入时,这一点至关重要
文本只作为一条直线时,为
例如电子邮件报头值中。
hans at lintoo dot dk
18 年前
此注释下方的代码会给 SpamAssassin 带来看很多麻烦,要解决此问题,你需要使用诸如以下内容来编码你的主题
<?php
/**
* 必要时编码标头
* 根据 RFC2047
*/
私有函数 encodeHeader($input, $charset = 'ISO-8859-1')
{
preg_match_all('/(\s?\w*[\x80-\xFF]+\w*\s?)/', $input, $matches);
foreach (
$matches[1] as $value) {
$replacement = preg_replace('/([\x20\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $value);
$input = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $input);
}

返回
wordwrap($input,75,"\n\t",true);
}
?>
To Top