{"id":2866,"date":"2009-06-08T05:59:20","date_gmt":"2009-06-08T12:59:20","guid":{"rendered":"http:\/\/css-tricks.com\/?p=2866"},"modified":"2014-02-10T12:06:41","modified_gmt":"2014-02-10T19:06:41","slug":"sending-nice-html-email-with-php","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/sending-nice-html-email-with-php\/","title":{"rendered":"Sending Nice HTML Email with PHP"},"content":{"rendered":"

This is going to be a continuation of the Website Change Request Form demo we’ve been using around here for a while. If you need to catch up, first I talked about it<\/a>, then I built it<\/a>, then I screencasted it<\/a>, then I secured it<\/a>. Throughout all of this, the end result has been a boring text-only email that gets sent to a single email address.<\/p>\n

We’re going to improve that output, and make the email into a nicer looking HTML-formatted email.<\/strong><\/p>\n

\"\"<\/p>\n

<\/p>\n

It’s Not Much Different Than Text Email<\/h3>\n

Sending HTML Email through PHP uses the exact same mail<\/tt> function as text email:<\/p>\n

mail($to, $subject, $message, $headers);<\/code><\/pre>\n

The last parameter, the headers, are optional for the function but required for sending HTML email, as this is where we are able to pass along the Content-Type declaration telling email clients to parse the email as HTML.<\/p>\n

In fact, the headers area gives us the opportunity to do lots of important email functions. This is where we can set the From: and Reply To: settings if need be, as well as CC and BCC other recipients (Hey, a checkbox for CC’ing yourself would be a cool feature to add!<\/em>). Here is the code used for the new and improved HTML-Sendin’ Website Change Request Form:<\/p>\n

$to = 'bob@example.com';\r\n\r\n$subject = 'Website Change Request';\r\n\r\n$headers = \"From: \" . strip_tags($_POST['req-email']) . \"\\r\\n\";\r\n$headers .= \"Reply-To: \". strip_tags($_POST['req-email']) . \"\\r\\n\";\r\n$headers .= \"CC: susan@example.com\\r\\n\";\r\n$headers .= \"MIME-Version: 1.0\\r\\n\";\r\n$headers .= \"Content-Type: text\/html; charset=ISO-8859-1\\r\\n\";<\/code><\/pre>\n

Now We Can Use HTML Tags<\/h3>\n

The message parameter (a big string we pass to the mail<\/tt> function with the body of our email), can now have HTML tags in it. For example:<\/p>\n

$message = '<html><body>';\r\n$message .= '<h1>Hello, World!<\/h1>';\r\n$message .= '<\/body><\/html>';<\/code><\/pre>\n

Here is whole shebang, to create the table of data as shown above:<\/p>\n

$message = '<html><body>';\r\n$message .= '<img src=\"\/\/css-tricks.com\/examples\/WebsiteChangeRequestForm\/images\/wcrf-header.png\" alt=\"Website Change Request\" \/>';\r\n$message .= '<table rules=\"all\" style=\"border-color: #666;\" cellpadding=\"10\">';\r\n$message .= \"<tr style='background: #eee;'><td><strong>Name:<\/strong> <\/td><td>\" . strip_tags($_POST['req-name']) . \"<\/td><\/tr>\";\r\n$message .= \"<tr><td><strong>Email:<\/strong> <\/td><td>\" . strip_tags($_POST['req-email']) . \"<\/td><\/tr>\";\r\n$message .= \"<tr><td><strong>Type of Change:<\/strong> <\/td><td>\" . strip_tags($_POST['typeOfChange']) . \"<\/td><\/tr>\";\r\n$message .= \"<tr><td><strong>Urgency:<\/strong> <\/td><td>\" . strip_tags($_POST['urgency']) . \"<\/td><\/tr>\";\r\n$message .= \"<tr><td><strong>URL To Change (main):<\/strong> <\/td><td>\" . $_POST['URL-main'] . \"<\/td><\/tr>\";\r\n$addURLS = $_POST['addURLS'];\r\nif (($addURLS) != '') {\r\n    $message .= \"<tr><td><strong>URL To Change (additional):<\/strong> <\/td><td>\" . strip_tags($addURLS) . \"<\/td><\/tr>\";\r\n}\r\n$curText = htmlentities($_POST['curText']);           \r\nif (($curText) != '') {\r\n    $message .= \"<tr><td><strong>CURRENT Content:<\/strong> <\/td><td>\" . $curText . \"<\/td><\/tr>\";\r\n}\r\n$message .= \"<tr><td><strong>NEW Content:<\/strong> <\/td><td>\" . htmlentities($_POST['newText']) . \"<\/td><\/tr>\";\r\n$message .= \"<\/table>\";\r\n$message .= \"<\/body><\/html>\";<\/code><\/pre>\n

I think that looks A LOT nicer. And since this email is (theoretically) coming directly to you, isn’t it nice to know that it will be formatted to be easy on the eyes? <\/p>\n

Concerns<\/h3>\n

Some people just absolutely hate HTML email. For one, it can be a security risk as it’s possible to run JavaScript in them in some email clients which can be problematic. HTML emails also have a habit of being more easily caught in Spam filters. I think it’s less of a concern here as this email is essentially being created BY you FOR you.<\/p>\n

Demo<\/h3>\n

I updated the demo and download to use the new HTML email format.<\/p>\n

View Demo<\/a>   Download Files<\/a><\/p>\n

There is likely to be another one or two demos on this form yet to come. I would at least like to do one on writing the data to a database before sending the email. Email can be such a fragile thing, that saving the data to a DB first is surely a smart move.<\/p>\n","protected":false},"excerpt":{"rendered":"

This is going to be a continuation of the Website Change Request Form demo we’ve been using around here for a while. If you need to catch up, first I talked about it, then I built it, then I screencasted it, then I secured it. Throughout all of this, the end result has been a […]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":338003,"url":"https:\/\/css-tricks.com\/the-making-and-potential-benefits-of-a-css-font\/","url_meta":{"origin":2866,"position":0},"title":"The Making (and Potential Benefits) of a CSS Font","date":"April 22, 2021","format":false,"excerpt":"Not a typical one, at least. Each character is an HTML element, built with CSS. A true web font! Let me elaborate. This is a way to render text without using any font at all. Random text is split with PHP into words and letters, then rendered as HTML elements\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/04\/css-font-example.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":350620,"url":"https:\/\/css-tricks.com\/comparing-html-preprocessor-features\/","url_meta":{"origin":2866,"position":1},"title":"Comparing HTML Preprocessor Features","date":"September 30, 2021","format":false,"excerpt":"Of the languages that browsers speak, I'd wager that the very first one that developers decided needed some additional processing was HTML. Every single CMS in the world (aside from intentionally headless-only CMSs) is essentially an elaborate HTML processor: they take content and squoosh it together with HTML templates. There\u2026","rel":"","context":"In "Sponsored"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/09\/Screen-Shot-2021-09-30-at-11.27.21-AM.png?fit=1200%2C685&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":312285,"url":"https:\/\/css-tricks.com\/a-complete-guide-to-dark-mode-on-the-web\/","url_meta":{"origin":2866,"position":2},"title":"A Complete Guide to Dark Mode on the Web","date":"July 1, 2020","format":false,"excerpt":"\u201cDark mode\u201d is defined as a color scheme that uses light-colored text and other UI elements on a dark-colored background. Dark mode, dark theme, black mode, night mode\u2026 they all refer to and mean the same thing: a mostly-dark interface rather than a mostly-light interface.","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/06\/dark-mode-guide.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":300328,"url":"https:\/\/css-tricks.com\/php-templating-in-just-php\/","url_meta":{"origin":2866,"position":3},"title":"PHP Templating in Just PHP","date":"December 26, 2019","format":false,"excerpt":"With stuff like template literals in JavaScript and templating languages, like JSX, I've gotten used to wanting to write my HTML templates in one nice chunk and sprinkling in variables wherever I need them. I had a situation where I needed to do that in \"raw\" PHP the other day,\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2019\/12\/confetti.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":351454,"url":"https:\/\/css-tricks.com\/building-a-form-in-php-using-domdocument\/","url_meta":{"origin":2866,"position":4},"title":"Building a Form in PHP Using DOMDocument","date":"September 14, 2021","format":false,"excerpt":"Learn how to build an HTML form in PHP using DOMDocument \u2014 a structured and expressive way to build logical markup.","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/09\/cover@2x.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":173207,"url":"https:\/\/css-tricks.com\/web-technologies-hanging-together\/","url_meta":{"origin":2866,"position":5},"title":"Web Technologies Hanging Out Together","date":"June 24, 2014","format":false,"excerpt":"As a beginner, understanding how the different languages you learn interact with each other can be confusing. I thought we could pair up a variety of languages to see where they intersect and communicate. HTML and CSS You need HTML to have CSS, because HTML calls the CSS. In an\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"featured_media_src_url":null,"_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/2866"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=2866"}],"version-history":[{"count":12,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/2866\/revisions"}],"predecessor-version":[{"id":162471,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/2866\/revisions\/162471"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=2866"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=2866"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=2866"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}