在 PHP 中格式化 VCard
我正在尝试通过 PHP 生成 VCard,然后他们将其通过电子邮件发送给用户。我用硬编码数据编写了一个初始脚本,但最终结果将填充来自 MySQL 的 VCard。
当并排查看 VCard 与合法 VCard(从另一个站点下载并测试)时,它们看起来几乎相同,但是当我尝试导入生成的 VCard 时,它显示没有数据。实际上,如果我在手机上打开它,它甚至不会识别出它是电子名片,而只是将我发送到损坏的 Google 文档。
我从维基百科借用了一些代码来格式化电子名片,一切看起来都很好。您发现我的格式有任何错误吗?我尝试过不同的换行符 - 无济于事。有想法吗?
这是我生成/邮件的代码:
<?php
$content = "BEGIN:VCARD\r";
$content .= "VERSION:3.0\r";
$content .= "CLASS:PUBLIC\r";
$content .= "FN:Joe Wegner\r";
$content .= "N:Wegner;Joe ;;;\r";
$content .= "TITLE:Technology And Systems Administrator\r";
$content .= "ORG:Wegner Design\r";
$content .= "ADR;TYPE=work:;;21 W. 20th St.;Broadview ;IL;60559;\r";
$content .= "EMAIL;TYPE=internet,pref:[email protected]\r";
$content .= "TEL;TYPE=work,voice:__munged__\r";
$content .= "TEL;TYPE=HOME,voice:__munged__\r";
$content .= "URL:http://www.wegnerdesign.com\r";
$content .= "END:VCARD";
mail_attachment("Joe Wegner.vcf", $content, "[email protected]", "[email protected]", "Wegner Design Contacts", "[email protected]", "Joe Wegner's Contact Info", "");
function mail_attachment($filename, $content, $mailto, $from_mail, $from_name, $replyto, $subject, $message) {
$fileatt_type = "application/octet-stream";
$headers = "FROM: ".$from_mail;
$data = chunk_split(base64_encode($content));
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
$headers .= "\nMIME-Version: 1.0\n" .
"Content-Type: multipart/mixed;\n" .
" boundary=\"{$mime_boundary}\"";
$message .= "This is a multi-part message in MIME format.\n\n" .
"--{$mime_boundary}\n" .
"Content-Type:text/html; charset=\"iso-8859-1\"\n" .
"Content-Transfer-Encoding: 7bit\n\n" .
$message . "\n\n";
$message .= "--{$mime_boundary}\n" .
"Content-Type: {$fileatt_type};\n" .
" name=\"{$filename}\"\n" .
"Content-Transfer-Encoding: base64\n\n" .
$data . "\n\n" .
"--{$mime_boundary}--\n";
echo "sending message";
mail($mailto, $subject, $message, $headers);
}
?>
更新1:这让我更加困惑,但也许它会帮助你调试。我已将生成的(坏的)VCard 下载到我的计算机上,并从其他网站下载了好的 VCard。正如预期的那样,我生成的生成的打开时没有任何数据,但好的生成的运行良好。然后,我创建了第三个扩展名为 .vcf 的空文件,并将文本从我的(坏)文件复制到该空文件中。我打开该文件,所有数据都完美显示。为了进一步测试,我将好 VCard 文件中的文本复制到坏文件中,但打开时仍然没有数据。所以,看来这与编码或其他一些我不理解的文件有关。这不是权限——这都是相同的。
更新 2: 我更改了 PHP,以便它强制我下载 VCard 并通过电子邮件发送。下载的文件打开得很好,所以错误要么发生在我对文件进行编码(正确的词?)的方式中,要么发生在 GMail 解释它的方式中。
更新3:已修复:弄清楚了。我不确定为什么会这样 - 因为我能找到的所有其他教程都说相反 - 但有一些关键的变化。首先,我将电子邮件的编码从 base64 更改为 8 位,并将附件内容更改为传递给电子邮件函数的字符串(以便它是 8 位形式,而不是 64)。这使得 VCard 在我的桌面上有效且可读。为了让它在我的 Android 上读取,我必须将 $fileatt_type 变量更改为“text/x-vcard”,否则 Gmail 会认为它是一个文档。
I'm trying to generate a VCard via PHP, and them email it out to the user. I wrote an initial script with hard-coded data, but the end-result will fill in the VCard from MySQL.
When viewing the VCard side-by-side with a legitimate VCard (downloaded and tested from another site) they look pretty much identical, but when I try and import my generated VCard it shows up with no data. Actually, if I open it on my phone, it doesn't even recognize that it is a vcard, and instead just sends me to a broken Google Doc.
I've borrowed some code from wikipedia for formatting the vcard, and everything seems fine. Do you see any errors in my formatting? I've tried different line breaks - to no avail. Ideas?
Here is the code for my generation / mail:
<?php
$content = "BEGIN:VCARD\r";
$content .= "VERSION:3.0\r";
$content .= "CLASS:PUBLIC\r";
$content .= "FN:Joe Wegner\r";
$content .= "N:Wegner;Joe ;;;\r";
$content .= "TITLE:Technology And Systems Administrator\r";
$content .= "ORG:Wegner Design\r";
$content .= "ADR;TYPE=work:;;21 W. 20th St.;Broadview ;IL;60559;\r";
$content .= "EMAIL;TYPE=internet,pref:[email protected]\r";
$content .= "TEL;TYPE=work,voice:__munged__\r";
$content .= "TEL;TYPE=HOME,voice:__munged__\r";
$content .= "URL:http://www.wegnerdesign.com\r";
$content .= "END:VCARD";
mail_attachment("Joe Wegner.vcf", $content, "[email protected]", "[email protected]", "Wegner Design Contacts", "[email protected]", "Joe Wegner's Contact Info", "");
function mail_attachment($filename, $content, $mailto, $from_mail, $from_name, $replyto, $subject, $message) {
$fileatt_type = "application/octet-stream";
$headers = "FROM: ".$from_mail;
$data = chunk_split(base64_encode($content));
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
$headers .= "\nMIME-Version: 1.0\n" .
"Content-Type: multipart/mixed;\n" .
" boundary=\"{$mime_boundary}\"";
$message .= "This is a multi-part message in MIME format.\n\n" .
"--{$mime_boundary}\n" .
"Content-Type:text/html; charset=\"iso-8859-1\"\n" .
"Content-Transfer-Encoding: 7bit\n\n" .
$message . "\n\n";
$message .= "--{$mime_boundary}\n" .
"Content-Type: {$fileatt_type};\n" .
" name=\"{$filename}\"\n" .
"Content-Transfer-Encoding: base64\n\n" .
$data . "\n\n" .
"--{$mime_boundary}--\n";
echo "sending message";
mail($mailto, $subject, $message, $headers);
}
?>
Update 1: This makes me more confused, but perhaps it will help you debug. I've downloaded my (bad) generated VCard to my computer, as well as a good VCard downloaded from a different website. As expected, my generated one opens with no data, but the good one works fine. I then created a third empty file with a .vcf extension, and copied the text from my (bad) file into that empty file. I opened that file, and all the data showed perfectly. To test even further, I copied the text from the good VCard file into my bad file, and it still opened with no data. So, it appears it's something about encoding or some other file thing that I don't understand. It's not permissions - that's all identical.
Update 2: I changed my PHP so that it would force me to download the VCard as well as email it. The downloaded file opens perfectly fine, so the error is either happening in how I'm encoding (right word?) the file, or how GMail is interpretting it.
Update 3: Fixed : Figured it out. I'm not sure why this is - because every other tutorial I can find out there says the opposite - but there were a few key changes. First, I changed the encoding on the email from base64 to 8bit, and I changed the attachment content to just be the string passed to the email function (so that it is in 8bit form, not 64). That made the VCard valid and readable on my desktop. To get it to read on my android I had to change the $fileatt_type variable to "text/x-vcard", otherwise Gmail thinks it is a document.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
每行末尾缺少 \n。如果您查看普通的 vCard(例如使用 notepad++),它的每一行末尾都有一个 CR 和 LF,而您创建的 vCard 只有 CR('\r')。这对我有用:
You are missing a \n at the end of each line. If you look at a normal vCard (with notepad++ for example), it has a CR and LF at the end of each line, the one you create only has CR ('\r'). this works for me:
我最近必须让 vcards 在 android 和 iphone 上工作。我使用了以下函数,它是上面列出的函数的修改版本。这将发送 gmail 和 iPhone 上的邮件都可以打开的 vcard。他们也在 Thunderbird 中工作。
I had to get vcards working in android and iphone recently. I used the following function which is a modified version of the one listed above. This will send vcards that both gmail and mail on the iphone will be able to open. They work in Thunderbird as well.
我根据 RFC 编写了一个 vCard 验证器,这可能会有所帮助。它并不完整,但清理后的文件至少与我尝试过的工具和服务(Gmail、gnokii 和其他一些我不记得的工具和服务)很好地兼容。 HTH。
I wrote a vCard validator based on the RFC which could help. It's not complete, but the cleaned files are at least nicely compatible with the tools and services I've tried (Gmail, gnokii and some others I can't remember). HTH.