How to Send Email from PHP (With Guided Walkthrough)

RunCloud has provisioned your server for a web application and set it up, but how about email? It is not necessary to provision your server in order to send email. But what if you want to send email from your server? We actually recommend using MailGun, SES or Mandrill for transactional email rather than sending it from your own server. We admit it, we are using MailGun and we are really happy with their service.

If you want to send email from your server, please use SwiftMailer or PHPMailer instead of using the direct php mail function. But here, we are just doing testing and we will be sending email from the server.

Install Sendmail

Please make sure you are login as root inside your server.

To install the necessary tools, enter this command:

apt-get update && apt-get install mailutils

Correcting the sendmail_path inside php.ini

If you want to send an email from PHP7.1, edit the /etc/php71rc/php.ini and search for sendmail_path =. It should be like this:

; For Win32 only.
; http://php.net/sendmail-from
;sendmail_from = me@example.com

; For Unix only.  You may supply arguments as well (default: "sendmail -t -i").
; http://php.net/sendmail-path
;sendmail_path =

; Force the addition of the specified parameters to be passed as extra parameters
; to the sendmail binary. These parameters will always replace the value of
; the 5th parameter to mail().
;mail.force_extra_parameters =

; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename
mail.add_x_header = On

Uncomment the sendmail_path and add the sendmail path. You should have something like this:

; For Win32 only.
; http://php.net/sendmail-from
;sendmail_from = me@example.com

; For Unix only.  You may supply arguments as well (default: "sendmail -t -i").
; http://php.net/sendmail-path
sendmail_path = /usr/sbin/sendmail -t -i

; Force the addition of the specified parameters to be passed as extra parameters
; to the sendmail binary. These parameters will always replace the value of
; the 5th parameter to mail().
;mail.force_extra_parameters =

; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename
mail.add_x_header = On

Now restart the php71 with:

systemctl restart php71rc-fpm

If you want other php version to send email too, you can edit their php.ini file:

/etc/php55rc/php.ini # PHP5.5
systemctl restart php55rc-fpm

/etc/php56rc/php.ini # PHP5.6
systemctl restart php56rc-fpm

/etc/php70rc/php.ini # PHP7.0
systemctl restart php70rc-fpm

/etc/php71rc/php.ini # PHP7.1
systemctl restart php71rc-fpm

Change hostname

Now edit your server hostname. You can find it inside /etc/hosts:

127.0.0.1      localhost.localdomain localhost

Change it to your domain:

127.0.0.1      test.runcloud.me test

And then we change the hostname on the fly with:

hostname test.runcloud.me

Configure sendmail

Now we run:

sendmailconfig

And answer all the question with Y.

The Basic of PHP Mail function

mail($to, $subject, $message, $headers)

That is the basic way to start sending your email from your server. Now we will do it more like real world usage, but please use SwiftMailer or PHPMailer later.

<?php

$to = 'youremail@gmail.com';
$subject = 'This is a test email';
$message = 'Hello john!';
$from = 'jane@runcloud.me';

$headers = sprintf("From: %s\r\nReply-To: %s", $from, $from);

mail($to, $subject, $message, $headers);

Now create the mail.php inside your web application. Make sure you have replaced the $from variable to your own domain name.

Now open your browser and hit the mail.php inside your web app. Wait for a minute……… and crap!!!! The email is not there.

Testing your email with mail-tester.com

Mail Tester is a service to test your email whether you can send the email or not. Now open up Mail Tester website and you should get an email to send to. Add this email to your $to variable and you should get something like this:

<?php

$to = 'web-ovl78@mail-tester.com';
$subject = 'This is a test email';
$message = 'Hello john!';
$from = 'jane@runcloud.me';

$headers = sprintf("From: %s\r\nReply-To: %s", $from, $from);

mail($to, $subject, $message, $headers);

Now hit the mail.php again inside your browser and check the score from Mail Tester. This is my result.

With this score, your email will never reach any inbox. Phewww.

SPF

Sender Policy Framework (SPF) is the TXT based DNS record that you can add to your DNS as a policy to for sending email. Your server hostname need to be verified as an email sender.

You can use SPF Wizard to generate your SPF record. This is the records that I am using for my domain (runcloud.me)

runcloud.me. IN TXT "v=spf1 a:test.runcloud.me -all"

AND

test.runcloud.me. IN TXT "v=spf1 ip4:45.118.132.8 -all"

Don’t forget to change your a:<your own domain> and ip4:<your server IP>

This is how it looks like from Cloudflare.

Based on the config, we set our A record(test.runcloud.me) can send email on behalf of runcloud.me. So you can send email using any user. For example, jane@runcloud.me.

For the second record, we said that our server IP Address can send email on behalf of test.runcloud.me.

Now we send the email again to Mail Tester and then check the score.

Alright.. now we are getting somewhere.

MX Record

The Mail Tester will check for MX records. And the domain (runcloud.me) does not have any MX record. Because of there is no MX record, the score will be minus 3. Now I will add bogus MX record. You should use the real MX record for your domain. The bogus MX is just for the sake of testing.

Now I will check the score again after adding my MX record.

Wait!!! I should get 9? Why did I only get 8 marks? Well, that is because I modify the TXT record for the SPF and set it to automatic TTL from CloudFlare. Now I just need to wait to 12 hours. Naah.. Not gonna do that. Let just assume that I already got 9 marks.

PTR Record

Your server reverse IP lookup should return your server hostname (test.runcloud.me). You can do this from Digital Ocean or Linode panel if you are using their service. Or any IaaS based company that provides VPS/Server will always give you access to modify your PTR record.

DKIM

DomainKeys Identified Mail (DKIM) as it name said, is a domain key. This is also a verification for receiving email. I won’t do DKIM part since it is painful and the score is only 1 mark. But if you really want to send email from your server, you should install it and add it to your DNS.

DMARC

Domain-based Message Authentication, Reporting & Conformance (DMARC) is also a policy to state that this domain (runcloud.me) is protected by SPF and/or DKIM. I won’t do this too and you should Google on how to do it. And DMARC is still not widely used. But it is good to have it.

SSL/TLS

Your email should be sending email using SSL/TLS. Fail to do so will resulting in Gmail to block your email as you can see the in the Google Support. You can always monitor your sending email by issuing:

tail -f /var/log/mail.log

This command will monitor sending and response log.

Conclusion

Although I have got the 8 marks from Mail Tester, but Google will still reject my email. Is it worth it to send email from your server? For me, I’m just doing this for fun, but I will never sending email from my own server. Just leave it to the expert, MailGun, Mandrill, SES, etc. If your web application only support PHP Mail function, it sucks. Period!

Categories: Server Management, Tips & Tricks, Tutorials

Simplifying Server Management

RunCloud is a cloud server management tool that allows you to maintain full control of your server and host multiple WordPress, WooCommerce, Laravel, and PHP applications with fast and easy configuration.

Start Your Free Trial

5 days free trial no credit card required cancel anytime

5 thoughts on “How to Send Email from PHP (With Guided Walkthrough)

  1. Any idea how MailGun compares with SES. What are the reasons for you using MailGun compared to SES?

  2. The guide is not validated by runcloud team. Port 25 is blocked by default. I’m bit dissapointed as i thought runcloud powered up developer without having to put effort too much on server administration but things like simple sendmail is not supported out of the box

    1. Hi Victor, this was 2017 article. RunCloud now supports sendmail (but still not recommended) out-of-the-box. Please contact your host if Port 25 is blocked.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.