<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vitali Lutz</title>
    <description>The latest articles on DEV Community by Vitali Lutz (@lutvit).</description>
    <link>https://dev.to/lutvit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F112073%2F459ac9f7-5b3b-4fea-83ac-abe88f3a8762.jpg</url>
      <title>DEV Community: Vitali Lutz</title>
      <link>https://dev.to/lutvit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lutvit"/>
    <language>en</language>
    <item>
      <title>How to make the PHP mail() function awesome</title>
      <dc:creator>Vitali Lutz</dc:creator>
      <pubDate>Fri, 11 Oct 2019 20:34:30 +0000</pubDate>
      <link>https://dev.to/lutvit/how-to-make-the-php-mail-function-awesome-3cii</link>
      <guid>https://dev.to/lutvit/how-to-make-the-php-mail-function-awesome-3cii</guid>
      <description>&lt;p&gt;All PHP developers know that PHP has a built-in &lt;a href="https://www.php.net/manual/en/function.mail.php" rel="noopener noreferrer"&gt;mail()&lt;/a&gt; function for sending emails. No question, one can use this function to send messages through the contact form, send plain text email notifications with the PHP app and so on.&lt;/p&gt;

&lt;p&gt;Unfortunately, working on projects in the past which did require advanced mail functionality, I've faced four main problems with the PHP's built-in &lt;code&gt;mail()&lt;/code&gt; function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It lacks UTF-8 support&lt;/li&gt;
&lt;li&gt;It lacks HTML support&lt;/li&gt;
&lt;li&gt;You can't define the name of the sender&lt;/li&gt;
&lt;li&gt;You can't define/change the email address of the sender&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my special case, emails that have been sent often contained German Umlauts like ö, ä, ü, and ß. If you send an email with &lt;code&gt;mail()&lt;/code&gt; containing one of those special characters, you will get ugly results like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fi69vwzg9ai7ec0u1zwtq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fi69vwzg9ai7ec0u1zwtq.png" alt="PHP mail wrong content encoding"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you look into the email headers, you will notice that there is either any information about the &lt;code&gt;Content-Type&lt;/code&gt; nor the &lt;code&gt;Content-Transfer-Encoding&lt;/code&gt;, so it shouldn't be surprising seeing wrong displayed characters in the email.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnww0rspizh4qgsyg45sz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnww0rspizh4qgsyg45sz.png" alt="PHP mail wrong encoding for subject"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice how broken the subject line looks like in the email source code. I'm pretty sure a lot of email clients will have problems to display the email subject correctly.&lt;/p&gt;

&lt;p&gt;What can we do to solve the encoding problems?&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional headers – let's make PHP mail() awesome!
&lt;/h2&gt;

&lt;p&gt;Now the fun part starts!&lt;/p&gt;

&lt;p&gt;For our rescue, the &lt;code&gt;mail()&lt;/code&gt; function comes with a fourth parameter, named &lt;code&gt;$additional_headers&lt;/code&gt;. This parameter allows us to define custom email headers and pass them through as string (or as an associative array, since PHP 7.2.0) to the function.&lt;/p&gt;

&lt;p&gt;This means we can define our own headers for the email and fix practically the most known drawbacks of the PHP's &lt;code&gt;mail()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Let's get into coding, I can't hold my hands from the awesome &lt;a href="https://atom.io/" rel="noopener noreferrer"&gt;Atom Editor&lt;/a&gt; any longer, and extend the &lt;code&gt;mail()&lt;/code&gt; function for UTF-8 support. We also will be using Base64 encoding for the email text body to ensure a robust character encoding. And we will also encode the subject line and some other header parts.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Force PHP to use the UTF-8 charset&lt;/span&gt;
&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type: text/html; charset=utf-8'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

&lt;span class="c1"&gt;// Define and Base64 encode the subject line&lt;/span&gt;
&lt;span class="nv"&gt;$subject_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Test email with German Umlauts öäüß'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$subject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'=?UTF-8?B?'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;base64_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$subject_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'?='&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Add custom headers&lt;/span&gt;
&lt;span class="nv"&gt;$headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: text/plain; charset=utf-8'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$headers&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Content-Transfer-Encoding: base64'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Define and Base64 the email body text&lt;/span&gt;
&lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;base64_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'This email contains German Umlauts öäüß.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Send mail with custom headers&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'recipient@domain.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$headers&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Email has been sent!'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Oops, something gone wrong!'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let's send a test email and take a look into the email headers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpuuhbcmtzhccckizyj6r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpuuhbcmtzhccckizyj6r.png" alt="PHP mail encoding fixed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the subject line is encoded with the combination of UTF-8 and Base64. This ensures that the email subject will be displayed on most devices and clients correctly.&lt;/p&gt;

&lt;p&gt;The PHP's &lt;code&gt;mail()&lt;/code&gt; function has properly applied our custom headers for &lt;code&gt;Content-Type&lt;/code&gt; and &lt;code&gt;Content-Transfer-Encoding&lt;/code&gt;, which is really great so far. Now the email body text is encoded with the Base64 algorithm and we can use all characters supported by UTF-8 inside the email body.&lt;/p&gt;

&lt;p&gt;One important task is finished. We have fixed the encoding part.&lt;/p&gt;

&lt;p&gt;Next, we can go further and add some more headers to get full control over the email's recipient and sender information. If you like you can even use the &lt;code&gt;Reply-To&lt;/code&gt; header to define freely the contact information for email replies.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;


&lt;span class="mf"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;// Define the sender&lt;/span&gt;
&lt;span class="nv"&gt;$sender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'sender@domain.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// or:&lt;/span&gt;
&lt;span class="c1"&gt;// $sender = '=?UTF-8?B?' . base64_encode('John Döe') . '?= &amp;lt;sender@domain.com&amp;gt;';&lt;/span&gt;

&lt;span class="c1"&gt;// Define the recipient&lt;/span&gt;
&lt;span class="nv"&gt;$recipient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'recipient@domain.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// or:&lt;/span&gt;
&lt;span class="c1"&gt;// $recipient = '=?UTF-8?B?' . base64_encode('Margret Müller') . '?= &amp;lt;recipient@domain.com&amp;gt;';&lt;/span&gt;

&lt;span class="c1"&gt;// Add custom headers&lt;/span&gt;
&lt;span class="nv"&gt;$headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: text/plain; charset=utf-8'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$headers&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Content-Transfer-Encoding: base64'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$headers&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'From: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$sender&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="mf"&gt;...&lt;/span&gt;

&lt;span class="nb"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$recipient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; You must always pass the recipient value as the first parameter to the &lt;code&gt;mail()&lt;/code&gt; function!&lt;/p&gt;

&lt;p&gt;As soon as you check the email headers again you will notice that the new headers have been applied to the email too. If you define custom contact information make sure you use the right string format for the pairs name and email address.&lt;/p&gt;

&lt;p&gt;Please notice in the code example above that we have &lt;strong&gt;encoded the sender's name with Base64&lt;/strong&gt;. This needs to be done only for the name but not for the email address.&lt;/p&gt;

&lt;p&gt;You have to agree with me that we have extended the &lt;code&gt;mail()&lt;/code&gt; function in the right direction. The last thing one can wish is HTML support. This part is very easy to do, just modify the header corresponding for the &lt;code&gt;Content-Type&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: text/html; charset=utf-8'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You don't need to do anything else.&lt;/p&gt;

&lt;p&gt;As email body you can now use text and HTML, which, by the way, will be Base64 encoded. The result is a modern-looking email containing all sorts of fancy HTML formatting.&lt;/p&gt;

&lt;p&gt;For best practice and most email client support, I would recommend using inline CSS styles instead of defining them in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section of the email wrapped inside the &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; block.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I appreciate that the PHP developers gave us the &lt;code&gt;mail()&lt;/code&gt; function and enabled us to extend it with custom headers. By using the &lt;code&gt;$additional_headers&lt;/code&gt; parameter of the &lt;code&gt;mail()&lt;/code&gt; function we got great power over the email headers.&lt;/p&gt;

&lt;p&gt;But, with great power comes great responsibility, as we all know! Modify the headers only if you really need to. In the worst case, you can break the whole mailing functionality of your app – you don't want it to happen.&lt;/p&gt;

&lt;p&gt;Workarounds and examples used in this article I use in a slightly modified version on my website &lt;a href="https://www.newslettermarketer.de/" rel="noopener noreferrer"&gt;NewsletterMarketer&lt;/a&gt; and some of my other websites for the contact form, transaction emails and to send bulk email newsletters.&lt;/p&gt;

&lt;p&gt;I also maintain a &lt;a href="https://github.com/lutvit/php-mail/" rel="noopener noreferrer"&gt;Github repository for a custom PHP function&lt;/a&gt;, that is basically a wrapper for the &lt;code&gt;mail()&lt;/code&gt; function and has already implemented all fixes shown in this article and some additional great features.&lt;/p&gt;

&lt;p&gt;For all small email tasks like contact forms and all kinds of transaction emails I always use my customized &lt;code&gt;mail()&lt;/code&gt; function. But, if I need to use external mail servers and send emails through SMTP I mostly use the mature, production-ready PHP class called &lt;a href="https://github.com/PHPMailer/PHPMailer" rel="noopener noreferrer"&gt;PHPMailer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope you can now enjoy the PHP's &lt;code&gt;mail()&lt;/code&gt; function as I do :)&lt;/p&gt;

</description>
      <category>php</category>
      <category>mail</category>
      <category>headers</category>
    </item>
  </channel>
</rss>
