13

Hello I am trying to send html emails using php mailer class. The problem is i would like to incllude php variables in my email while using includes as to keep things organized. Heres my php mailer....

 $place = $data['place'];
 $start_time = $data['start_time'];

$mail->IsHTML(true);    // set email format to HTML
$mail->Subject = "You have an event today";
$mail->Body = file_get_contents('../emails/event.html');
$mail->Send(); // send message

my question is, is it possible to have php variables in event.html ? i tried this with no luck (below is event.html)..

<table width='600px' cellpadding='0' cellspacing='0'>
<tr><td bgcolor='#eeeeee'><img src='logo.png' /></td></tr>
<tr><td bgcolor='#ffffff'  bordercolor='#eeeeee'>
<div style='border:1px solid #eeeeee;font-family:Segoe UI,Tahoma,Verdana,Arial,sans-serif;padding:20px 10px;'>
<p style=''>This email is to remind you that you have an upcoming meeting at $place on $start_time.</p>
<p>Thanks</p>
</div>
</td></tr>
</table>
tytyguy
  • 340
  • 1
  • 4
  • 15
  • Does it work if you make it "event.php" and then properly delimit echo's for the variables? – Aaron Ray Jul 14 '11 at 04:08
  • 1
    @Aaron That would still simply get the contents of the file. `include`/`require` is the only way to execute a PHP file. – Nicole Jul 14 '11 at 04:16
  • Yeah I guess I am thinking of grabbing the page with cURL which should execute the php within the target. – Aaron Ray Jul 14 '11 at 04:22
  • 1
    @Aaron True, if you hit it as a remote URL but then it's in it's own request and then it's also public which means you don't have access to the same variables you already set up and you have to deal with any possible injection attacks. – Nicole Jul 14 '11 at 15:00

5 Answers5

21

Yes, very easily with include and a short helper function:

function get_include_contents($filename, $variablesToMakeLocal) {
    extract($variablesToMakeLocal);
    if (is_file($filename)) {
        ob_start();
        include $filename;
        return ob_get_clean();
    }
    return false;
}

$mail->IsHTML(true);    // set email format to HTML
$mail->Subject = "You have an event today";
$mail->Body = get_include_contents('../emails/event.php', $data); // HTML -> PHP!
$mail->Send(); // send message
  • The get_include_contents function is courtesy of the PHP include documentation, modified slightly to include an array of variables.

  • Important: Since your include is processing within a function, the scope of execution of the PHP template file (/emails/event.php) is in that function's scope (no variables immediately available besides super globals

  • That is why I have added extract($variablesToMakeLocal) — it extracts all array keys from $variablesToMakeLocal as variables in the function's scope, which in turn means they are within scope of the file being included.

    Since you already had place and start_time in the $data array, I simply passed that straight into the function. You may want to be aware that this will extract all keys within $data — you may or may not want that.

  • Note that now your template file is processing as a PHP file, so all the same caveats and syntax rules apply. You should not expose it to be edited by the outside world, and you must use <?php echo $place ?> to output variables, as in any PHP file.

Nicole
  • 32,841
  • 11
  • 75
  • 101
  • i walk into this knowing this might be a stupid question, but i'm going to ask anyway: is it correct to presume that the `$_SESSION` (or `$_POST`) array does NOT need to be passed to `$variablesToMakeLocal`? – WhiteRau Jan 31 '12 at 17:02
  • @WhiteRau - Correct, they can be accessed anyway (they are [superglobals](http://php.net/manual/en/language.variables.superglobals.php)), though I would probably choose to pass it in so that I could sanitize the data beforehand and so the function could be more portable (i.e. used with data from other sources instead of the template or function always using `$_SESSION`. – Nicole Jan 31 '12 at 18:44
  • I'm uncertain how I can get this to work.. I set $varsToMakeLocal = array('$toMail' => $toEmail, '$toName' => $toName); and I try to use your $mail->Body = $this->get_include_contents($htmlfile, $varsToMakeLocal); but the mail is intact and the variables don't get replaced. – Jorrick Sleijster Nov 09 '16 at 21:49
11

Couple ways to do it:

Token Template

<p> Some cool text %var1%,, %var2%,etc...</p>

Token Mailer

$mail->Body = strtr(file_get_contents('path/to/template.html'), array('%var1%' => 'Value 1', '%var2%' => 'Value 2'));

Buffer Template

<p> Some cool text $var1,, $var2,etc...</p>

Buffer Mailer

$var1 = 'Value 1';
$var2 = 'Value 2';
ob_start();
include('path/to/template.php');
$content = ob_get_clean();
$mail->Body = $content;
prodigitalson
  • 60,050
  • 10
  • 100
  • 114
3

You can put variables in the html email and then do a string_replace so the contents appear in the email instead of the variables:

try {
    $mail = new PHPMailer(true);
    $body = file_get_contents('phpmailer/subdir/contents.html');
    $body = str_replace('$fullname', $fullname, $body);
    $body = str_replace('$title', $title, $body);
    $body = str_replace('$email', $email, $body);
    $body = str_replace('$company', $company, $body);
    $body = str_replace('$address', $address, $body);
    // strip backslashes
    $body = preg_replace('/\\\\/','', $body);
    // mail settings below including these:
    $mail->MsgHTML($body);
    $mail->IsHTML(true); // send as HTML
    $mail->CharSet="utf-8"; // use utf-8 character encoding
}

This is the setup that worked for me. It not DRY perhaps, but it works.

silverliebt
  • 591
  • 5
  • 5
1

Using prodigitalson's token method, the following worked for me. PHP code was:

$e = "gsmith@gmail.com";
$sc = "2sbd2152g#!fsf";
$body = file_get_contents("../email/recovery_email.html");
$body  = eregi_replace("%e%" ,$sc, $body);
$body  = eregi_replace("%sc%" ,$sc, $body);
$mail->MsgHTML($body);

The HTML was just:

<p>Click this link: www.mysite.com/recover.php?e=%e%&sc=%sc%<p>

The eregi_replace worked better that strtr in my case - (the latter didn't work at all).

Nick
  • 5,995
  • 12
  • 54
  • 78
0

Maybe a little bit late to the party, but here is the method I always use. (Found this one somewhere on stackoverflow but can't find the link to it. so credits for this solution are not for me!)

First thing to do is replace the variables in html email like so:

<p style=''>This email is to remind you that you have an upcoming meeting at {{ place }} on {{ start_time }}.</p>

Then in PHP you first get the contents of the mailtemplate and assign it to a variable, lets say $mailBody. Then make a new array with the variables you would like to insert in the HTML email template. Once set, you can use a loop to get correct varibales inside the email.

$mailBody = file_get_contents('../emails/event.html');
//make the new array
$mailVariables = array();
//Assign needed variables to the new array
$mailVariables['place'] = $data['place'];
$mailVariables['start_time'] = $data['start_time']; 

foreach($mailVariables as $key => $value) {
    $mailBody = str_replace('{{ '.$key.' }}', $value, $mailBody);
}

$mail->IsHTML(true);    // set email format to HTML
$mail->Subject = "You have an event today";
$mail->Body = $mailBody;
$mail->Send(); // send message

This way you can keep everything clean with just a few lines of extra code. I've used this even to send bulk emails with all diffrent body's and a lot of variables and it runs fairly quick.

Hope it helps.

KevinT
  • 43
  • 5