PHP Mailer和HTML包含PHP变量

13

你好,我正在尝试使用 PHP Mailer 类发送HTML邮件。问题是我想在电子邮件中包含PHP变量,同时使用includes以保持组织结构。以下是我的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

我的问题是,是否可以在event.html中使用PHP变量?我尝试过,但没有成功(下面是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>

如果你将它命名为“event.php”,然后正确地定界变量的echo,它会工作吗? - Aaron Ray
1
@Aaron 这仍然只是获取文件的内容。include/require 是唯一执行 PHP 文件的方法。 - Nicole
是的,我想使用cURL抓取页面,这样就可以在目标中执行php。 - Aaron Ray
1
如果您将其作为远程URL进行访问,则@Aaron为True,但此时它是自己的请求,这也意味着它是公共的,这意味着您无法访问已设置的相同变量,并且必须处理任何可能的注入攻击。 - Nicole
5个回答

21
是的,非常容易,只需使用include和一个简短的辅助函数即可。
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
  • get_include_contents 函数是由 PHP include 文档 提供的,稍作修改以包含一个变量数组。

  • 重要提示:由于您的包含操作是在函数内部进行的,所以 PHP 模板文件(/emails/event.php)的执行范围在该函数的范围内(除了 超全局变量 之外没有其他立即可用的变量)。

  • 这就是为什么我添加了 extract($variablesToMakeLocal) —— 它会将 $variablesToMakeLocal 中的所有数组键作为函数范围内的变量提取出来,从而意味着它们在被包含的文件范围内。

    由于您已经在 $data 数组中有 placestart_time,所以我直接将它们传递给函数。您可能需要注意,这将提取 $data 中的所有键 —— 您可能需要或不需要这样做。

  • 请注意,现在您的模板文件正在作为 PHP 文件进行处理,因此所有相同的注意事项和语法规则都适用。您不应该将其暴露给外部世界进行编辑,并且必须使用 <?php echo $place ?> 来输出变量,就像在任何 PHP 文件中一样。


我明白这可能是一个蠢问题,但我还是要问一下:假设 $_SESSION(或 $_POST)数组不需要传递到 $variablesToMakeLocal 中,这种做法正确吗? - WhiteRau
@WhiteRau - 正确,它们可以通过任何方式访问(它们是超全局变量),但我可能会选择传递它,以便我可以在此之前对数据进行清理,并且函数可以更具可移植性(即使用来自其他来源的数据而不是模板或函数始终使用$_SESSION)。 - Nicole
我不确定如何让它工作。我设置了$varsToMakeLocal = array('$toMail' => $toEmail, '$toName' => $toName);,并尝试使用您的$mail->Body = $this->get_include_contents($htmlfile, $varsToMakeLocal);,但邮件保持不变,变量没有被替换。 - Jorrick Sleijster

12
有几种方法可以实现这个:
令牌模板
<p> Some cool text %var1%,, %var2%,etc...</p>

令牌邮件程序

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

缓冲区模板

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

缓冲区邮件发送程序

$var1 = 'Value 1';
$var2 = 'Value 2';
ob_start();
include('path/to/template.php');
$content = ob_get_clean();
$mail->Body = $content;

3

您可以在html邮件中放置变量,然后进行string_replace操作,以便变量内容在电子邮件中显示而不是变量本身:

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
}

这是适合我的设置。可能不够DRY(Don't Repeat Yourself),但它有效。


1
这证明这是我唯一可行的解决方案。谢谢。 - awl19

1

使用 prodigitalson 的令牌方法,以下内容对我有效。PHP 代码如下:

$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);

HTML代码如下:

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

在我的情况下,eregi_replacestrtr 更有效(后者根本不起作用)。

0
也许有点晚了,但这是我经常使用的方法。 (在stackoverflow上找到了这个方法,但找不到链接。所以这个解决方案的功劳不是我的!)
首先要做的是像这样替换html电子邮件中的变量:
<p style=''>This email is to remind you that you have an upcoming meeting at {{ place }} on {{ start_time }}.</p>

在 PHP 中,您首先获取邮件模板的内容并将其分配给一个变量,例如$mailBody。然后使用变量创建新数组,该数组包含要插入 HTML 电子邮件模板中的变量。设置完成后,您可以使用循环在电子邮件中获取正确的变量。

$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

通过添加几行额外的代码,您可以保持所有内容的清洁。

我甚至使用它来发送带有各种正文和大量变量的批量电子邮件,速度相当快。

希望这有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接