Email

PHP Email Using Embedded Images in HTML Email

PHP Email Using Embedded Images in HTML Email - practical guide with code examples, common pitfalls, and FAQ.

PHP Email Using Embedded Images in HTML Email

PHP provides built-in mail functions and supports rich HTML email with embedded images and attachments.

This guide covers PHP Email Using Embedded Images in HTML Email with working code you can adapt for your own projects. We will walk through the setup, show what the code actually does at each step, and flag the spots where things tend to break.

If you have worked with Email before, skip ahead to the code examples. If this is your first time, read the whole thing - the order matters.

For the official reference, see the RFC 2392 - Content-ID and Message-ID.

How It Works

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// send-html-email.php
<?php
$to = 'recipient@example.com';
$subject = 'HTML Email with Embedded Image';
$boundary = md5(time());

$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/related; boundary=\"$boundary\"\r\n";
$headers .= "From: sender@example.com\r\n";

$body = "--$boundary\r\n";
$body .= "Content-Type: text/html; charset=UTF-8\r\n\r\n";
$body .= "<html><body>";
$body .= "<h1>Hello</h1>";
$body .= "<img src=\"cid:logo\">";
$body .= "</body></html>\r\n";
$body .= "--$boundary\r\n";
$body .= "Content-Type: image/png\r\n";
$body .= "Content-Transfer-Encoding: base64\r\n";
$body .= "Content-ID: <logo>\r\n\r\n";
$body .= base64_encode(file_get_contents('logo.png')) . "\r\n";
$body .= "--$boundary--";

mail($to, $subject, $body, $headers);
?>

The key idea here: get something running first, then refine. The code above is intentionally minimal so you can see the structure without noise.

Step-by-Step Walkthrough

  1. Set up your environment. Make sure your PHP version matches what the framework or library expects. Run php -v to check.
  2. Create the base files. Copy the example above into your project directory. Adjust the connection details or paths to match your local setup.
  3. Test immediately. Do not write 200 lines before running the code. Test after every meaningful change. This habit catches typos and config errors before they compound.
  4. Read the error messages. PHP error messages are verbose for a reason. The file path and line number in the error output will point you to the problem 90% of the time.
  5. Refactor once it works. Move hardcoded values into configuration. Extract repeated logic into functions. But only after the basic version runs.

Working with the Code

There are a few things to keep in mind when adapting this for production:

  • Error handling is not optional. The examples here use basic try/catch blocks. In production, log errors and show generic messages to users.
  • Input validation goes before everything else. If the data comes from a user, treat it as hostile until proven otherwise.
  • File paths differ between OS environments. Use the appropriate directory separator or PHP constants like DIRECTORY_SEPARATOR when building paths.
Common Mistakes
  • Not checking return values. Functions that fail silently are the hardest bugs to track. Always check what comes back.
  • Skipping error reporting during development. Set error_reporting(E_ALL) and display_errors = On locally. Turn display off in production but keep logging on.
  • Hardcoding credentials. Even in tutorials, get in the habit of using environment variables or a config file outside the web root.
  • Ignoring character encoding. Use UTF-8 everywhere: database, connection string, HTML meta tag. Mismatched encodings cause garbled text that is painful to debug later.
  • Copy-pasting without reading. Seriously - read the code before you run it. One wrong table name or missing semicolon will cost you thirty minutes of confusion.

Frequently Asked Questions

Check your SPF, DKIM, and DMARC DNS records. Also ensure the From address domain matches your sending server. Content with all-caps subjects or too many links triggers filters.

You can use base64 data URIs in the img src, but many email clients block them. CID embedding has the widest support.

Outlook uses the Word rendering engine. Use tables for layout, inline CSS, and avoid CSS grid or flexbox in emails.