PHP Development

How to Use PHPMailer for Contact Forms

By the Domain India teamPublished 7 min read
Knowledge base article
Contents (6 sections)

PHPMailer is the most widely used PHP library for sending email, and it is a good fit for contact forms: it builds correct headers, handles HTML and attachments, and reports errors clearly. On shared hosting, though, how PHPMailer sends matters more than how you install it. This short guide shows the setup that works on Domain India shared hosting today.

Key takeaways

On Domain India cPanel hosting, PHPMailer's SMTP mode fails because the socket functions it needs are disabled, and its mail mode silently drops your envelope sender. The reliable pattern is to let PHPMailer build the message, then send it yourself with PHP mail() and -f set to an address on your own domain. Always send from your own domain, put the visitor's address in Reply-To, and publish SPF, DKIM and DMARC records.

Full guide to email from PHP

This article covers PHPMailer for contact forms. For the complete picture (the envelope sender, SPF, DKIM and DMARC, testing, frameworks and WordPress), read PHP sendmail settings and sending email from PHP.

1. Why the usual PHPMailer examples fail on shared hosting

Most PHPMailer tutorials use SMTP: isSMTP(), a host, a port and a mailbox password. On our cPanel servers that route does not work from PHP. Shared hosting disables a set of PHP functions for security. On cPanel they include the socket functions fsockopen and stream_socket_client that SMTP needs; on both cPanel and DirectAdmin they include the process functions (proc_open, popen) that a sendmail transport needs. When SMTP is blocked, the error looks like this:

text
stream_socket_client() has been disabled for security reasons

PHPMailer's mail mode (isMail()) does send, because it uses PHP's mail(). But PHPMailer passes your envelope sender (-f) only when the PHP function escapeshellcmd is available, and that function is disabled on our cPanel servers. Without -f, the Return-Path becomes the server's own address, SPF is checked against the server instead of your domain, and your messages are more likely to land in spam.

For the full list and the reasons behind it, see PHP disabled functions on shared hosting.

2. Install PHPMailer

Composer cannot run on shared hosting, so install PHPMailer on your own computer and upload it:

  1. Install on your computer.
    In your project folder run composer require phpmailer/phpmailer. This creates a vendor/ folder.
  2. Upload the project.
    Upload the project, including vendor/, with FTP or the File Manager. Keep it outside public_html if you can, and put only your form handler in public_html.
  3. Or download manually.
    Without Composer, download the release from the PHPMailer GitHub page and upload its src folder. Then require Exception.php and PHPMailer.php directly instead of vendor/autoload.php.

Before you write the code, create a real mailbox to send from, such as [email protected], in your control panel.

3. A contact form handler that works on shared hosting

PHPMailer builds the message; PHP mail() sends it with your envelope sender:

php
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require __DIR__ . '/../vendor/autoload.php';   // adjust to where vendor/ is

$from = '[email protected]';   // a mailbox on YOUR domain
$to   = '[email protected]';      // where enquiries should arrive

$name    = trim($_POST['name'] ?? '');
$visitor = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');

if (!filter_var($visitor, FILTER_VALIDATE_EMAIL) || preg_match('/[\r\n]/', $name) || $message === '') {
    http_response_code(400);
    exit('Please fill in all fields with a valid email address.');
}

$mail = new PHPMailer(true);
try {
    $mail->isMail();
    $mail->CharSet = 'UTF-8';
    $mail->setFrom($from, 'Your Business');
    $mail->addAddress($to);
    $mail->addReplyTo($visitor, $name);          // the visitor goes in Reply-To
    $mail->Subject = 'Website enquiry from ' . $name;
    $mail->Body    = "Name: $name\nEmail: $visitor\n\n$message\n";
    $mail->preSend();                            // build the message, don't send

    // Split the built message into headers and body.
    [$head, $body] = preg_split("/\r?\n\r?\n/", $mail->getSentMIMEMessage(), 2);
    $head = preg_replace("/\r?\n[ \t]+/", ' ', $head);   // unfold long headers

    $headers = [];
    $subject = '';
    foreach (preg_split("/\r?\n/", $head) as $line) {
        if (stripos($line, 'To:') === 0) { continue; }               // mail() adds To
        if (stripos($line, 'Subject:') === 0) { $subject = trim(substr($line, 8)); continue; }
        $headers[] = $line;
    }

    $ok = mail($to, $subject, $body, implode("\r\n", $headers), '-f' . $from);
    echo $ok ? 'Thank you, your message has been sent.' : 'Sorry, the message could not be sent.';
} catch (Exception $e) {
    error_log('Contact form error: ' . $mail->ErrorInfo);
    echo 'Sorry, the message could not be sent.';
}

Notes on this handler:

  • The -f value is a fixed address you control. Never build it from form input.
  • The visitor's address goes only in Reply-To. Putting it in From makes the message fail SPF and DMARC.
  • For attachments or HTML, add addAttachment(), isHTML(true) and AltBody before preSend(). The same split-and-send code handles them.
  • If mail() alone is enough (plain-text enquiries, no attachments), the shorter handler in the full guide does the same job without PHPMailer.

4. Protect the form from abuse

An unprotected contact form is quickly found by spam bots, and every message it sends counts towards your account's sending limit (200 messages per hour per account on cPanel, 1,000 per day on DirectAdmin).

  • Validate every field on the server, as the example does.
  • Add a CAPTCHA or a hidden honeypot field.
  • Send enquiries only to your own fixed address, never to an address typed into the form.

5. Check that it works

Send a test enquiry to a Gmail address you own, open the message and choose Show original. SPF, DKIM and DMARC should show PASS, and the Return-Path should be your own address. If SPF or DKIM fails, set up the records described in the full guide.

6. Other ways to send

  • An HTTPS email API. Transactional providers accept email over HTTPS. On cPanel, a single cURL request (curl_exec) works, but client libraries that rely on curl_multi_exec or sockets may fail. On most DirectAdmin sites curl_exec is disabled too, while allow_url_fopen is on, so file_get_contents() with an HTTPS stream context is the route there. Test before you rely on either.
  • A VPS or the App Platform. On a server you control, or on the App Platform, PHPMailer's SMTP mode works normally and can send through any authenticated mailbox.
Why does PHPMailer SMTP fail on shared hosting?

SMTP needs PHP socket functions such as fsockopen and stream_socket_client, which are disabled on Domain India cPanel hosting for security. Use PHPMailer to build the message and send it with PHP mail() and the -f envelope sender, or send through an HTTPS email API.

Why does my PHPMailer email go to spam when using isMail()?

PHPMailer only passes the -f envelope sender when escapeshellcmd is available, and it is disabled on our cPanel servers. Without -f the Return-Path is the server's address, so SPF does not align with your domain. Call mail() yourself with -f, as in the handler above, and publish SPF, DKIM and DMARC.

Can I install PHPMailer with Composer on shared hosting?

Composer cannot run on shared hosting. Run composer require phpmailer/phpmailer on your own computer and upload the project with its vendor folder, or download PHPMailer from GitHub and upload its src folder.

Which From address should a contact form use?

A mailbox on your own domain, such as [email protected]. Put the visitor's email address in Reply-To so that replying still reaches them.

How many emails can my contact form send?

Every message counts towards your hosting account's limit: 200 messages per hour per account on cPanel and 1,000 per day on DirectAdmin. Protect the form with a CAPTCHA or honeypot so bots can't use it up.

Ready to put a working contact form on your site? Compare cPanel hosting and DirectAdmin hosting, or open a support ticket if your form still won't send.

Hosting that sends your website's email

Email accounts on your own domain, PHP mail() that works on every shared plan, and support that will check your mail setup with you.

See hosting plans

Was this article helpful?

Your answer helps us decide what to improve next.

Still need help? Open a support ticket and our team will reply.

Prefer an app? Add this site to your home screen.Get the app
PHPMailer Contact Forms on Shared Hosting