Mail script not working

okay. So we’ve found something that works. Excellent. Let’s refine a little bit.

There’s obviously a couple things you should change…
$mail->Subject = 'Here is the subject'; You probably want a better Subject :wink:

Let’s handle a little security…
require 'PHPMailer/src/PHPMailer.php';
after this line:

$email = filter_var($_POST['E-mail'], FILTER_SANITIZE_EMAIL) || "not-a-valid-email@not-a-real-email.com";
$name = filter_var($_POST['Name'], FILTER_SANITIZE_STRING) || "Bad Name";
$phone = filter_var($_POST['Phone'], FILTER_SANITIZE_NUMBER) || "Bad Phone";

and now you can do substitutions.

$mail->addReplyTo($_POST['E-mail'], 'Information');
becomes
$mail->addReplyTo($email, $name);

$mail->Body = '<ul><li>Name:'.$_POST['Name']."</li><li>Phone: ".$_POST['Phone']."</li><li>Email: ".$_POST['E-mail']."</li></ul>";
becomes
$mail->Body = '<ul><li>Name: $name</li><li>Phone: $phone</li><li>Email: $email</li></ul>";

and
$mail->AltBody = "Name: ".$_POST['Name']." | Phone: ".$_POST['Phone']." | Email: ".$_POST['E-mail'];
becomes
$mail->AltBody = "Name: $name | Phone: $phone | Email: $email";

(You can, of course, dress these up however you like. You’ve got a working system now.)

@m_hutley Great job in getting it working!

I’ve been following this thread from the sidelines and have a question:

FILTER_SANITIZE_STRING is deprecated in PHP 8.1.0.

What would you recommend using instead?

If I had to replace it, i’d preg_replace on ~[^\w\s]~ with an empty string. It’s not perfect, because it will exclude characters from outside the latin range. If you anticipate getting a lot of non-latin (read: not a-z) characters in your names, you’d have to do more targetted removal.

Alternatively, strip_tags might suffice.

1 Like

I was doing some reading around the deprecation and what to use instead. I understood the general advice to be don’t worry so much about sanitizing what you store in the db, rather worry about escaping it properly whenever you use it in a browser (mail client) context. Would you agree with that?

If so, would a function like htmlspecialchars() not be better? If I’m understanding things correctly, this would render <script> as &lt;script&gt; in the markup (defeating XXS), but would still mean that the email previewed correctly, if somebody really needed to include < or > in their mail.

I’ll stop after this message, as I don’t want to hijack the OP’s thread.

My caution is more in the realm of “I dont know what an XSS attack looks like in an email”. or I suppose more to the point “I don’t know the behavior of mail clients when receiving html entities”.

Rendering <script> as &lt;script&gt; might work… unless your mail client tries to be clever and translates HTML entities back into their markup form…? I’m not sure how well strip_tags handles “errant” <'s or >'s, for that matter, but if your name has a < or > in it… I’ve got more questions for you.

1 Like

m_hutley

As soon as I add the 3 security lines the form produces an error message 500.

Oh, apologies, that should have been FILTER_SANITIZE_NUMBER_INT.

If your server is set to Fatal on Deprecation, you’ll need to replace the Name filter with something else (strip_tags($_POST['Name'] or htmlspecialchars($_POST['Name']) or something equivalent.)

OK, that new line worked.
Can I add my own email address for a copy?

You can add as many Addresses (“To”) as you want by calling addAddress again. You can also call addCC or addBCC in the same way.

OK, great, works fine.
However, just noticed that the comment field at the bottom of the form is not transmitted to email, just name, phone, email.

You’d have to add it to the body, the same as with the other values. I would probably filter it the same as Name, and just tell people not to put HTML into your form :stuck_out_tongue:

I did that per your suggestion. The text area field now shows in the email but not the text inside. I’m sure I have screwed it up somewhere but can’t figure out where.
Here’s the script as it is now:

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

require 'PHPMailer/src/Exception.php';
require 'PHPMailer/src/PHPMailer.php';
$email = filter_var($_POST['E-mail'], FILTER_SANITIZE_EMAIL) || "not-a-valid-email@not-a-real-email.com";
$name = filter_var($_POST['Name'], FILTER_SANITIZE_STRING) || "Bad Name";
$phone = filter_var($_POST['Phone'], FILTER_SANITIZE_NUMBER_INT) || "Bad Phone";
$textarea = filter_var($_POST['Textarea'], FILTER_SANITIZE_STRING) || "Please provide your info";

$mail = new PHPMailer(true);
try {
  $mail->setFrom('bm@bmrealty.com', 'Form Mail Handler');
  $mail->addAddress('bm@bmrealty.com',);   
  $mail->addAddress('em@icom-design.com',);  
  $mail->addReplyTo($_POST['E-mail'], 'Information');
  $mail->isHTML(true);                                  //Set email format to HTML
  $mail->Subject = 'BMREALTY Website Inquiry';
  $mail->Body = '<ul>
                                   <li>Name:'.$_POST['Name']."</li>
                                   <li>Phone: ".$_POST['Phone']."</li>
                                   <li>Email: ".$_POST['E-mail']."</li>
                                   <li>Additional Information: ".$_POST['Additional Information']."</li>
                            </ul>";
  
  $mail->AltBody = "Name: ".$_POST['Name']." | Phone: ".$_POST['Phone']." | Email: ".$_POST['E-mail'];
  $mail->send();
    echo 'Thank you for your message. Brigitte will respond as soon as possible.';
} catch (Exception $e) {
    echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
?>

For sanity check’s sake, try removing the space in the name and in the variable. I’m… not sure HTML likes having form field names with spaces.

Also, the reason we created the variables here:

is to use them here :stuck_out_tongue:

It doesnt help to filter the variable if you’re going to use the unfiltered one in the email.

I’m sorry, I don’t think I understand what you’re saying.
I’m PHP illiterate.

So if i set a variable: $x = 2;
When i want to use that variable, i put $x in my code, and it will use the value 2.

If i call a function that returns a value, and store that value;
$y = strlen("Hello");
$y will hold (in this case) the length of the string “Hello”, or 5. And again, if i want to USE that value, i use $y.

Our security line calls the function filter_var(), and stores the transformed result in variable names: $name, $email, etc.

Currently, your email body calls the UNtransformed (“raw”) values:

<li>Name:'.$_POST['Name']."</li>
            ^This bit.

Filtering the data is only helpful if you use the filtered data, not the raw data. The raw data is in $_POST, our filtered data is in $name, $email, etc.

OK, got it. Works now.
Thanks again for your patience with me, it’s greatly appreciated.

1 Like

m_hutley
I do have another question: I am trying to incorporate the name of the inquirer in the echo, like this:

 $mail->send();
    echo 'Dear ".$_POST['Name'].", 
    <br>Thank you for your message. 
    <br>I will respond as soon as possible.';

but it does not work. What did I do wrong?

What does “it does not work” mean? Did you get an error message? What happened that should not have done, or didn’t happen that should have?

I expect the issue is that you’ve used different quote marks around the variable than you have around the main string, but if you could be more specific in telling us what the problem is, it would make things easier all round.

This is the error message:

error

You opened the string with a single quote, and then tried to close it with a double quote.