mailto 正文中的换行符:link

Line break in body of mailto: link

我想在博客 post 下方创建一个“将此转发给朋友”link 以打开我的电子邮件客户端并显示准备好的消息。我可以让它为单行消息工作,但我希望能够在消息正文中换行。我该怎么做?

<?php
printf(
    '<a href="mailto:?subject=%s&body=%s">Forward this to a friend</a>',
    the_title_attribute('echo=0'),
    sprintf('The link: %s Have a great day! Stefaan', get_the_permalink())
);
?>

如何开始“祝你有美好的一天!”在上面有空行的新行上?

The link: ...

Have a great day!

Stefaan

我的博客使用带有 Genesis 主题的 WordPress,我将我的代码放入启用了 PHP 的 genesis_footer_entry 挂钩中(参见 screenshot – 电子邮件文本为荷兰语)。

您可以在您的 sprintf 中添加 <br> 标签(假设您想要在 HTML 中显示换行符):

sprintf( 'Hi there, this might be interesting for you. This is the link: %s.<br> Have a great day!<br> Stefaan',get_the_permalink() )

编辑:

如果您想要纯文本邮件,请使用 \r\n 和双引号:

sprintf("Hi there, this might be interesting for you. This is the link: %s.\r\n Have a great day!\r\n Stefaan",get_the_permalink() )

根据电子邮件规范,每个电子邮件行都需要以旧的 <CR><LF> 对结束 - 因此您需要在 sprintf() 字符串中使用 \r\n

"This is the link: %s.\r\n Have a great day!\r\n Stefaan"

如果 \r\n 不起作用,则说明您有源语言限制。鉴于:

  • \r 是 ASCII 13(十六进制 0D
  • \n 是 ASCII 10(十六进制 0A

也许你可以使用 "&#13;&#10;"?

对 CR/LF

使用 urlencoded 字符串
%0D%0A

你想休息的地方。

例如

<a 
 class="simple-mail-link" 
 href="mailto:?subject=hello&body=Hello%0D%0A%0D%0AWorld!"
>

你可以把 PHP_EOL 扔进去

<?php
     printf( 
        '<a class="simple-mail-link" href="mailto:?subject=%s&body=%s"><div class="label"><div class="dashicons dashicons-admin-plugins"></div>Forward this to a friend</div></a>', 
        the_title_attribute( 'echo=0' ),
        sprintf( 'Hi there, this might be interesting for you. This is the link: %s. %sHave a great day! %sStefaan',get_the_permalink(), PHP_EOL, PHP_EOL )
    );

说明

a mailto: 是电子邮件地址的 URI 方案,与所有其他 URI 一样,字符需要转换为可以在 Internet 上传输的格式。

使用原始代码的简化形式来说明以下几点

printf(<href="mailto:?subject=%s&body=%s">Description</a>, the_title_attribute( 'echo=0' ) , sprintf("content link:%s more content", get_the_permalink())

代码按以下顺序运行

  1. get_the_permalink() 获取您页面的 URL
  2. sprintf() 用步骤 1
  3. 的结果替换 $content 中的 %s
  4. print_f() 然后替换
    i) 第一个 %ssubject=%sthe_title_attribute( 'echo=0' ) 的获取结果,我假设 是页面或您网站的标题,然后 ii) 第二个 %sbody=%s 与步骤 2 的结果形成完整的 a mailto link

为了保留换行符,你应该在输出之前将$content字符串转换成URL编码形式。

在 PHP 中,这是通过使用 rawurlencode() 函数完成的,它根据 RFC 3986 将字符串中的换行符 \r\n 转换为 %0D%0A

由于在sprint_f()中使用了百分号%进行转换规范,所以应该在sprint_f()对字符串进行格式化后将字符串传递给rawurlencode(),因此使用 rawurlencode(sprint_f($string, $arg))


解决方案
我已经将完整的解决方案放在一起,供您复制并粘贴到您的小部件中,以避免因实施不当而导致的漏报。

格式 1 和格式 2 包含基本相同的代码,这两种格式是为了向您说明如何插入换行符,可以通过 1) pressing enter 或 2) 通过 typing in \r\n需要换行的地方。

为了便于编辑和提高代码的可读性,我已将 $content 设为单独的字符串。

格式 1

 <?php
  //Start new line by pressing enter
  //IMPORTANT NOTE: do not remove the %s 
    $content="Hi there, this might be interesting for you
    This is the link: %s
    Have a great day!
    Stefaan
    ";
  //No need to amend the code below  
    printf( 
            '<a class="simple-mail-link" href="mailto:?subject=%s&body=%s">
            <div class="label">
            <div class="dashicons dashicons-admin-plugins"></div>
            Forward this to a friend</div></a>',the_title_attribute( 'echo=0' ),
            rawurlencode(sprintf( $content,get_the_permalink()))
            );
?>

格式 2

<?php
  //Start new line by adding \r\n
  //IMPORTANT NOTE: do not remove the %s 
    $content="Hi there, this might be interesting for you\r\nThis is the link: %s\r\nHave a great day!\r\nStefaan";
 //No need to amend the code below          
    printf( 
            '<a class="simple-mail-link" href="mailto:?subject=%s&body=%s">
            <div class="label">
            <div class="dashicons dashicons-admin-plugins"></div>
            Forward this to a friend</div></a>',the_title_attribute( 'echo=0' ),
            rawurlencode(sprintf( $content,get_the_permalink()))
            );              
?>

演示

<a class="simple-mail-link" href="mailto:?subject=Page%20Title&amp;body=Hi%20there%2C%20this%20might%20be%20interesting%20for%20you%0D%0AThis%20is%20the%20link%3A%20http%3A%2F%2Fblahblahblah.com%0D%0AHave%20a%20great%20day%21%0D%0AStefaan"><div class="label"> <div class="dashicons dashicons-admin-plugins"></div>Forward this to a friend</div></a></body>

向您的 sprintf() 调用添加另一个 %s 参数,并将换行字符 %0A 的 URL 编码版本传递给它(两次):

printf( 
        '<a class="simple-mail-link" href="mailto:?subject=%s&body=%s"><div class="label"><div class="dashicons dashicons-admin-plugins"></div>Forward this to a friend</div></a>', 
        'subject',
        sprintf( 'Hi there, this might be interesting for you. This is the link: %s. %sHave a great day! Stefaan', "link-here", "%0A%0A" )
    );

编辑: 此外,您也可以只将 %0A 添加到字符串本身,但您必须记住通过在它之前添加一个额外的字符来转义 % 字符:

printf( 
        '<a class="simple-mail-link" href="mailto:?subject=%s&body=%s"><div class="label"><div class="dashicons dashicons-admin-plugins"></div>Forward this to a friend</div></a>', 
        'subject',
        sprintf( 'Hi there, this might be interesting for you. This is the link: %s. %%0A%%0AHave a great day! Stefaan', "link-here" )
    );

您不能在 bodymailto[=] 中使用 HTML 标签41=]

根据RFC 2368,这是不可能的:

The special hname "body" indicates that the associated hvalue is the body of the message. The "body" hname should contain the content for the first text/plain body part of the message. The mailto URL is primarily intended for generation of short text messages that are actually the content of automatic processing (such as "subscribe" messages for mailing lists), not general MIME bodies.

所以任何依赖于 HTML 标签的解决方案都是不可能的。 我建议的解决方案是使用 \r\n 以及 PHP 函数 rawurlencode

所以这是代码

<?php

     printf( 
    '<a class="simple-mail-link" href="mailto:x@y.com?subject=%s&body=%s"><div class="label"><div class="dashicons dashicons-admin-plugins"></div>Forward this to a friend</div></a>', 
    'My Subject',
    rawurlencode(sprintf( "Hi there, this might be interesting for you.\r\nThis is the link: %s.\r\nHave a great day!\r\nStefaan", get_the_permalink()))
    );

?>

注意:我尝试用携带变量 http://example.com/test.php

替换 get_the_permalink() 的代码

参考文献:

MailTo with HTML body

What is the equivalent of JavaScript's encodeURIcomponent in PHP?

我决定彻底解决这个问题并解决这里所做的所有尝试。如果你想要,看看目前接受的

工作解决方案

要在 mailto: URL body 参数中使用文本,percent-encode it. In PHP, use rawurlencode()。主题也应该被编码。

$subj = "Whatever subject";
$body = "Multi-\r\nline\r\nbody";
printf(
    "mailto:?subject=%s&body=%s",
    rawurlencode($subj),
    rawurlencode($body)
);
mailto:?subject=Whatever%2Osubject&body=Multi-%0D%0Aline%0D%0Abody

要将其用作 HTML link 的目标,请将 HTML 中具有特殊含义的字符替换为实体引用 – htmlspecialchars() is used for that in PHP, and Wordpress has a fancier (and filtrable) esc_html().

$subj = "Whatever subject";
$body = "Multi-\r\nline\r\nbody";
printf(
    '<a href="%s">mailto: URL with multi-line body</a>',
    htmlspecialchars(sprintf(
        "mailto:?subject=%s&body=%s",
        rawurlencode($subj),
        rawurlencode($body)
    ), ENT_QUOTES)
);

<a href="mailto:?subject=Whatever%2Osubject&amp;Multi-%0D%0Aline%0D%0Abody">mailto: URL with multi-line body</a>

我相信到现在为止,您已经知道如何修改 PHP 代码来生成这样的 link。

调试问题

您必须处理多个级别的技术,每个级别都有自己的转义方案:

  • PHP(例如 "\n" 是一个带有换行符的字符串,而不是带有反斜杠和字母 n;如果你想要的话,你需要转义反斜杠 – "\n")

  • (s)printf(例如,要打印文字 %,您必须编写 %%)

  • HTML(例如&开始一个实体引用;按字面意思应该编码为实体引用&amp;

  • URL(例如 space 不是 URL 的有效部分,它必须是 percent-encoded 作为 %20

这需要手动完成太多,请确保它是正确的而不检查中间步骤。如果你把任何一个中间步骤弄错了,它就会作为一个整体被破坏。

  • 您是否确认 PHP 代码的保存与您编写的完全一致?
  • 你看过它产生的 HTML 了吗?
  • 您是否尝试通过在浏览器中右键单击 link 并选择“复制电子邮件地址”来复制 URL?

安全的方法是手动构建最后一步的产品,只有在成功后,才继续尝试以编程方式生成它。在这种情况下,这样的产品是 URL,一旦粘贴到浏览器的地址栏中,就会打开预填充了多行正文的邮件编辑器。您可以从一个简单的工作示例开始,然后使它变得越来越复杂,直到它满足您的需要。当手动构建太乏味时,您可能选择了一种过于复杂的产品——选择最简单的仍然可以按照您想要的方式工作的产品,您可以在以后添加复杂性。

如果您在手动构建 URL 时仍然卡住,那您就不走运了。您要么必须阅读有关该主题的更多信息,寻求帮助,要么放弃。如果不仅仅是您,问题出在您的浏览器和电子邮件客户端之间。至少其中一个有错误。根据我使用 mailto: URLs 的经验,这并不少见。即使您让它为您工作,您博客的访问者也可能没有他们的设置那么幸运。


旁白:HTML 提出的尝试规范

我花时间查看了 HTML 规范对我在其他答案和问题本身中提出的尝试中看到的问题的看法。具体来说:

  • 属性值中未编码的符号
  • 属性值换行
  • 属性值
  • 中 HTML 标记 (<br>) 中的 <> 未编码

句法级别

HTML 这些天的实现非常稳健,甚至 HTML 规范也变得非常宽松,可以将与符号 (&) 编码为实体引用 (&amp;;称为 character references 在 HTML5) 中,因此您通常不会这样做。 (不过,HTML 4 规范需要编码。)

在 HTML 文件中的实际字节级别,引用 attribute values in HTML5 可以自由包含几乎*任何字符,除了用于引用它们的引号(必须替换为角色参考)。

* 详情见HTML5 spec.Preprocessing the input stream and ambiguous ampersand

这就是为什么即使换行符和未编码的 <br> 在引用的属性值中也是可以的。但实际上,它们在 hrefnot OK(与 title 不同),因为...

语义级别

在语义层面,解析所有内容时,允许任何字符串(包括空字符串)作为属性值,但specific attributes add further constraints.

这就是HTML咬你的地方——href is specified to contain a valid URL potentially surrounded by spaces,不能包含

  • 换行符和中间的其他 space 个字符和
  • <> 和许多其他字符。

这些字符必须是 percent-encoded。对于 URL 及其语法 的实际 定义,HTML 规范遵从其他规范。

Handling invalid URLs is implementation-defined,这些机制在浏览器之间可能不一致。只要尊重规范。我的 Firefox 忽略换行符并保留 spaces – spaces 也不允许出现在 URLs 中,但 Firefox 在对 URL.[= 做任何其他事情之前对其进行编码。 49=]