使用非ASCII内容类型从php发送加密邮件
我正在尝试使用下面的代码发送加密邮件,其中明文为text/html,字符集为utf-8。 无论如何,我无法正确显示邮件(在MS Outlook中)。 您可能会注意到,我(同时)尝试将相关的使用非ASCII内容类型从php发送加密邮件,php,email,encryption,Php,Email,Encryption,我正在尝试使用下面的代码发送加密邮件,其中明文为text/html,字符集为utf-8。 无论如何,我无法正确显示邮件(在MS Outlook中)。 您可能会注意到,我(同时)尝试将相关的内容类型:头添加到要加密的数据文件中,并显示在调用openssl\u pkcs7\u encrypt的头中(并尝试了各种其他组合) 当消息未加密发送时,所需的内容类型适用于该消息,但它不能处理加密消息。结果总是好像“内部”内容类型是text/plain;字符集=ascii 我尝试在加密之前为数据文件预加头,只是
内容类型:
头添加到要加密的数据文件中,并显示在调用openssl\u pkcs7\u encrypt
的头中(并尝试了各种其他组合)
当消息未加密发送时,所需的内容类型适用于该消息,但它不能处理加密消息。结果总是好像“内部”内容类型是text/plain;字符集=ascii
我尝试在加密之前为数据文件预加头,只是因为我想我在SE上找到了一些类似的建议,用于类似的情况。但显然,这只会使标题行作为解密消息的一部分出现(换句话说,提交给openssl\u pkcs7\u encrypt
的文件实际上应该只是“纯”内容(正如我最初怀疑的那样)
但是,在headers参数中包含它也没有帮助:在enncryped文件中存在的头中,添加了一个带有正确的“外部”S/MIME内容类型的头,它覆盖了给定的“内部”内容类型
问题:我应该在哪里以及如何结合使用openssl\u pkcs7\u encrypt()
和mail()
指定加密邮件的“内部”内容类型
$hdr_to = implode(',',$empfaenger);
$hdr_subject = '=?UTF-8?q?' . quoted_printable_encode($subject) . '?=';
$other_headers = array(
"From" => $hdr_from,
"Content-Type" => "text/html; charset=utf-8",
"X-Mailer" => "PHP/".phpversion()
);
$mailbody = wordwrap($_REQUEST['message']);
//write msg to disk
$msg_fn = tempnam("/tmp","MSG");
$enc_fn = tempnam("/tmp","ENC");
$fp = fopen($msg_fn, "w");
fwrite($fp, 'Content-Type: ' . $other_headers['Content-Type'] . CRLF . CRLF);
fwrite($fp, $mailbody);
fclose($fp);
// Encrypt message
$enc_ok = openssl_pkcs7_encrypt($msg_fn,$enc_fn,$pubkeys,$other_headers,PKCS7_TEXT,1);
//$enc_ok = false; // for debugging: simulate encryption failure
if (!$enc_ok) {
// Will try to send unencrypted instead
} else {
// Seperate headers and body for mail()
$data = str_replace("\n",CRLF,file_get_contents($enc_fn));
$parts = explode(CRLF.CRLF, $data, 2);
$mailbody = $parts[1];
$other_headers = $parts[0];
}
// Send mail
$mail_ok = mail($hdr_to, $hdr_subject, $mailbody, $other_headers);
问题在于PKCS7_TEXT
标志作为加密函数的参数
我的预期媒体类型是text/html;charset=utf-8
,即
- 属于类型
文本
- 属于子类型
html
- 带参数的
charset=utf-8
从表面上看,类型与名称
PKCS7_TEXT的含义相匹配
将文本/普通内容类型头添加到加密/签名的邮件中。如果解密或验证,则会从输出中删除这些头-如果解密或验证的邮件不是MIME类型的文本/普通,则会发生错误
准确地说,所述标题和一个空行(将其与消息正文分开)似乎是预先加好的,这会将以前存在的任何标题行(内容类型:
或其他)变成正文的一部分
因此,简单的解决方案是不使用PKCS7_TEXT
标志(除非您的消息是纯ASCII²文本)
²对于拉丁语-1文本也可以,但我不会指望它。在上面引用的所有描述表明会发生错误之后,UTF-8文本再次成功解密(即,没有显式错误),但显示通常与代码页相关的显示人工制品。内容类型标头必须在邮件正文前加上前缀(用空行分隔),因此它位于加密部分内。@not2savvy您的意思是,就像我按照
fwrite($fp,'Content-type:'。$other_标头['Content-type'].CRLF所做的那样。$other_标头['Content-type'].CRLF)
?抱歉,我忽略了这一部分。我认为这是正确的。您的外部内容类型可以被覆盖。您可以将$enc_ok中的结果添加到您的问题中吗?另外,您是否确保爆炸(CRLF.CRLF,…
按预期工作,因为我不确定它是否只是LF本身。@not2savvy无需担心。$enc_ok
只是true
因为加密确实有效(即,证书没有问题);举个简单的例子,我可能已经排除了测试和明文回退分支。--是的,我注意到$enc_fn
的内容只有LF换行符,when(IIRC)CRLF是必需的。由于前面一行的str\u replace
,explode工作正常。我分心了。我的意思是询问$enc\u fn
的内容。注意:虽然非ascii文本可以很好地加密和解密,但邮件客户端在处理非ascii文本时如何处理还没有定义,因此除非encod正确打印(base-64或引用可打印)。