简体   繁体   中英

Line break in body of mailto: link

I want to create a “Forward this to a friend” link below a blog post that opens my email client with a prepared message. I can get it to work for a single-line message, but I'd like to be able to break lines inside the message body. How can I do that?

<?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())
);
?>

How do I start “Have a great day!” on a new line with an empty line above?

The link: ...

Have a great day!

Stefaan

My blog uses WordPress with a Genesis theme and I put my code into the genesis_footer_entry hook with PHP enabled (see screenshot – email text is in Dutch).

Explanation

a mailto: is a URI scheme for email address, like all other URIs, characters need to be translated into a format that can be transmitted over the Internet.

Take a simplified form of your original code to illustrate the points below

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

The code runs in the following sequences

  1. get_the_permalink() gets the URL of your page
  2. sprintf() replaces %s in $content with the result of step 1
  3. print_f() then replaces
    i) the first %s ie subject=%s with the fetched result of the_title_attribute( 'echo=0' ) , which I assume is the title of the page or your site and then ii) the second %s ie body=%s with the result of step 2 to form a complete a mailto link

In order to retain the line breaks, you should convert the $content string into URL encoded form before outputting it.

In PHP that's done by using the rawurlencode() function, it translates line breaks \\r\\n in string into %0D%0A , as per RFC 3986 .

Since the percentage sign % is used for conversion specification in sprint_f() , you should pass the string to rawurlencode() after the string has been formatted by sprint_f() , therefore the use of rawurlencode(sprint_f($string, $arg))


Solution
I have put together the solution in full for you to copy and paste into your widget to avoid false negative due to wrongful implementation.

Format 1 and format 2 contain essentially the same code, the two formats are there to illustrate to you how you can insert line break, either by 1) pressing enter OR 2) by typing in \\r\\n where line break is needed.

I have made $content a separate string for your ease of editing and readability of code.

Format 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()))
            );
?>

Format 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()))
            );              
?>

Demo

 <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> 

You cannot use HTML tags in body of mailto

According to RFC 2368 , this is not possible:

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.

So any solution depends on HTML tags is not possible. The solution I'm suggesting is to use \\r\\n along with PHP function rawurlencode

So here's the code

<?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()))
    );

?>

Note: I tried the code with replacing get_the_permalink() with variable carrying http://example.com/test.php

references:

MailTo with HTML body

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

According to the e-mail specification, every e-mail line needs to end in the old <CR><LF> pair - so you need to use \\r\\n in the sprintf() string.

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

And if \\r\\n doesn't work, you've got a source-language limitation. Given that:

  • \\r is ASCII 13 (hex 0D )
  • \\n is ASCII 10 (hex 0A )

perhaps you could use "&#13;&#10;" ?

Use urlencoded string for CR/LF

%0D%0A

where you want a break.

In example

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

Add another %s argument to your sprintf() call and pass it the URL-encoded version of the line-feed char %0A (twice):

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" )
    );

Edit: Additionally, you could also just add the %0A to the string itself, but you have to remember to escape the % char by adding an extra one before it:

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" )
    );

I decided to go through the issue thoroughly and address all the attempts that were made here. If you want a quick answer , look at the currently accepted one.

Working solution

To use a text in mailto: URL body parameter, percent-encode it. In PHP, use rawurlencode() . Subject should be encoded, too.

$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

To use it as a target of a HTML link , replace characters that have special meaning in HTML with entity references – 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> 

I am sure that by now, you know how to modify your PHP code to produce such a link.

Debugging the issue

You have to deal with several levels of technologies , each having its own escaping scheme:

  • PHP (eg "\\n" is a string with a newline, not with a backslash and the letter n; you would need to escape the backslash if you wanted that – "\\\\n" )

  • (s)printf (eg to print a literal % , you have to write %% )

  • HTML (eg & starts an entity reference; to be taken literally, it should be encoded as the entity reference &amp; )

  • URL (eg space is not a valid part of a URL and it must be percent-encoded as %20 )

This is too much to do manually and be sure it is correct without examining the intermediate steps . If you get any of the intermediate steps wrong, it is broken as a whole.

  • Did you verify that the PHP code is saved exactly as you wrote it?
  • Did you look at the HTML it produces?
  • And did you try to copy the URL by right-clicking the link in the browser and choosing “Copy Email Address”?

The safe approach is to manually construct the product of last step , and only once it works, proceed and try to produce it programmatically. In this case, such a product is the URL that once pasted into the browser's location bar opens mail composer with multi-line body pre-filled. You can begin with a simple working example and make it more and more complex , till it meets your needs. When manual construction is too tedious, you have probably chosen a product that is too complex – choose the simplest one that still works the way you want, you can add complexity later.

If you get stuck even with manually building the URL, you are out of luck. Either you have to read more on the topic, reach out for help, or give up. If it is not just you, the problem is somewhere between your browser and your email client. At least one of them has a bug. In my experience with mailto: URLs, this is not uncommon. Even if you get it to work for you, the visitors of your blog may not be so lucky with their setup.


Aside: HTML spec on presented attempts

I took the time to look at what HTML spec says about the issues I see in the attempts that were presented in other answers and in the question itself. Specifically:

  • unencoded ampersand in attribute value
  • newline in attribute value
  • unencoded < and > in HTML markup ( <br> ) in attribute value

Syntactic level

HTML implementations are pretty robust these days and even the HTML spec became very permissive regarding encoding ampersands ( & ) into entity references ( &amp; ; called character references in HTML5), therefore you will usually get away with not doing that. (HTML 4 spec required the encoding, though.)

At the level of actual bytes in the HTML file, quoted attribute values in HTML5 are free to contain almost* any characters, except the quote that is used to quote them (which must be replaced by a character reference).

* For details, see Preprocessing the input stream and ambiguous ampersand in HTML5 spec.

This is why even newline and unencoded <br> are OK inside quoted attribute values. But actually, they are not OK in href (unlike in eg title ), because…

Semantic level

At the semantic level, when everything is parsed, any string (including empty string) is allowed as attribute value, but specific attributes add further constraints .

This is where HTML bites you – href is specified to contain a valid URL potentially surrounded by spaces , which cannot contain

  • newlines and other space characters in the middle and
  • < , > , and many other characters at all.

These characters have to be percent-encoded . For the actual definition of URL and its syntax , HTML spec defers to other specifications.

Handling invalid URLs is implementation-defined , these machanisms may not be consistent across browsers. Just respect the specifications. My Firefox ignores newlines and preserves spaces – spaces are not allowed in URLs either, but Firefox encodes them before it does anything else with the URL.

You could add <br> tag in your sprintf (assuming you want to display break line in for 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() )

EDIT:

If you want plain text mail use \\r\\n and double quotes:

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() )

You could probably chuck a PHP_EOL in there

<?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 )
    );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM