I'm using PHPMailer to send emails via contact form.
When I enter an invalid email address in the input field, the email is still sent. I want to perform both client-side and server-side validations.
Does PHPMailer have a built-in validation system to check for invalid email address? If the email entered is invalid I want to return an error and not send the email.
The easiest and most correct way to validate email addresses is to use filter_var. Rather than relying on a patched PHPMailer, you could write a function to validate them before you send them to PHPMailer.
function validateEmailAddr($addr) {
// note: do not attempt to write any regex to validate email addresses;
// it will invariably be wrong
return filter_var($addr, FILTER_VALIDATE_EMAIL);
}
You said that you could enter something like 'sdjfygsdfisdf' and still get the email sent to you.
That's odd. Because adding any email address ('to', 'cc', 'bcc', 'replyto') in PHPMailer will go through the addOrEnqueueAnAddress() function, which does include validation checks. Adding a 'from' address uses different code, but also does validation checks.
The most obvious thing here is that you're not actually doing any error checking to trap for those errors.
Depending on whether you've got PHPMailer using exceptions or not, you might just be getting a false value returned from functions like setFrom() when you give it a bad address. If you ignore that value and carry on anyway, then yes, the email will still be sent.
So you need to add some error handling. Check for function call returning false.
However my preferred suggestion would be to switch to using exceptions for your error handler -- PHPMailer can do this just by setting a flag. This will make error handling easier, as you won't need to check for false on every single function call; just wrap the whole thing in a try catch block, and do your error handling in one go at the end.
Related
I am having a super strange issue, I will explain in detail why it is strange after the facts...
The code...
Mail::send('emails.cron.loggedinusers', $data, function($message){
// Get Admin user emails
$adminUserEmails = DB::table('users')->where('user_role', 'admin')->lists('email');
// Build nice comma separated list of Admin Emails addresses
// and also wrap each email in quotes
$filter = function($adminUserEmails){ return "'$adminUserEmails'"; };
$toEmails = array_map($filter, $adminUserEmails);
$toEmails = implode(', ', array_values($toEmails));
print_r($toEmails);
// Send email to Admins Only
$message->from('one#email.com', 'Jason');
$message->to('one#email.com')->cc($toEmails);
$message->subject('[TIMECLOCK ALERT] Users are logged into the Timeclock!');
});
When I run this code above which gets 4 Email address from the database and tries to email to them, I get this nasty error message...
Keep in mind I have changed the actual email values shown here to protect there identity but the REAL emails in the script are all legit emails...
Swift_RfcComplianceException
Address in mailbox given ['one#email.com', 'two#email.com',
'three#email.com', 'four#email.com']
does not comply with RFC 2822, 3.6.2.
Now if I replace the variable $toEmails with the actual string text...
$message->to('one#email.com')->cc('one#email.com', 'two#email.com', 'three#email.com', 'four#email.com');
Then it sends the emails without an issue and no error messages!
This is strange and weird to me because I am literally printing the $toEmails variable to screen and copy/pasting it's output into the email code above and it mails just fine but as soon as I use the variable instead of the text string, I get that awful error message above. I cannot make any sense of why this would do this, please if you have any ideas please share with me???
The error message you get is a little misleading here and perhaps worth a bug-report. RFC 2822, 3.6.2. is about originator fields while to and cc aren't such an originator field, from would be.
However the other part of the message is telling exactly what the problem is:
Address in mailbox given ['one#email.com', 'two#email.com', 'three#email.com', 'four#email.com'] does not comply ...
And that's correct. It's not a mailbox, it's a mailbox-list. Swift mailer expects a mailbox here, not a list of mailboxes. And that's what the message is telling you. You failed to provide a mailbox here. You perhaps thought you could provide a list of mailboxes here, but obviously that gave you the exception so this won't work.
And you already did find the solution, by not providing a list but by adding one mailbox after the other, one per parameter.
This is more a question here what the interface of the $message class expects than anything else. And as the misleading part of the error message was not noted by you, I guess you were not mislead by that part.
I'm using modMail class to send custom emails. I have followed the guidelines on MODX site and used the following code which I placed in a snippet:
$message = $modx->getChunk('myEmailTemplate');
$modx->getService('mail', 'mail.modPHPMailer');
$modx->mail->set(modMail::MAIL_BODY,$message);
$modx->mail->set(modMail::MAIL_FROM,'me#example.org');
$modx->mail->set(modMail::MAIL_FROM_NAME,'Johnny Tester');
$modx->mail->set(modMail::MAIL_SUBJECT,'Check out my new email template!');
$modx->mail->address('to','user#example.com');
$modx->mail->address('reply-to','me#xexample.org');
$modx->mail->setHTML(true);
if (!$modx->mail->send()) {
$modx->log(modX::LOG_LEVEL_ERROR,'An error occurred while trying to send the email: '.$modx->mail->mailer->ErrorInfo);
}
$modx->mail->reset();
The snippet has been modified to contain message from custom chunk as well as email addresses have been replaced with the correct ones. The snippet sent email once and never again. I have no idea what causes such behavior which prevents it from sending emails.
I have read that using the reset function $modx->mail->reset(); resets email fields and allows the email to be sent again yet I have a feeling that it causes problem here.
The snippet is called uncached on the page [[!email]]
Does anyone have an idea why the emails are not being sent, even though it worked once?
if there is an error in your chunk or in processing your chunk, modx is never going to get to thepoint where it logs an error. try something like:
if (!$modx->mail->send()) {
$modx->log(modX::LOG_LEVEL_ERROR,'An error occurred while trying to send the email: '.$modx->mail->mailer->ErrorInfo);
}else{
$modx->log(modX::LOG_LEVEL_ERROR,'This mail was sent: '.$message);
}
to see if it logs something. but otherwise what you have there is exactly correct - try to take the $message variable out and send just a string. if it sent mail once, then something else must be wrong. I'd start looking at mail server logs, headers, spam [gmail??] etc.
Can I send a text message using PHP or PHPmailer and in the return use a phone number and not an email?
PHP mail() and PHPmailer makes me use a valid email with an "#" symbol. Is there a way around this?
You can put whatever you want in the from field, but don't expect your mail server, or the receiving mail server to accept it.
Better to set your from: field to something like this instead:
"123-123-1234 <noreply#yourdomain.com>"
That way, you can have a valid from address, and still display a number to the end user.
I would like to filter emails sent. Emails are sent with the PHP mail() function. I would like, without modifying any PHP file if possible, to let emails out only emails that are to a specific domain, and not others. I don't have access to the SMTP server.
Just in case this helps someone ... If the emails are sent after a form is submitted (or similar action), you could change the action attribute of the form html element to point to a new php file that acts as a filter. Once passed (if so) you redirect to the "proper" destination to send the emails. The filtering could be something as easy as:
$good = "*#mydomain.foo, *#localhost";
$good = explode(',', $good);
if (pattern_grep($_POST['email'], $good)) {
// action
}
You should be able to look at the associative array for the "to" field and use the php regex class to match domains that you blacklist.
Just wondering why this is too strict, I can send very simplified emails to say tim#yahoo.com or two#google.com
but if I make the email any longer (sacagawea#gmail.com) it does not get sent.
Instead it echos back my error message:Invalid Email Address Supplied
// Create a function to check email
function checkEmail($email)
{
// Add some regex
return preg_match('/^\S+#[\w\d.-]{2,}\.[\w]{2,6}$/iU', $email) ? TRUE : FALSE;
}
If you have access to php 5.2 or above, you should use the filter functions :
function checkEmail($email){
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
Or validate it, "the right way".
This part
#[\w\d.-]{2,}
is gobbling up
#gmail.com
leaving nothing for this part
[\w\d.-]{2,}
to match.
Better to reuse something already proven, see for example http://www.regular-expressions.info/email.html
I usually don't fret myself too much for checking email validity. I just need to check there is a value in front of "#" and at the back. That's all. The rest of the "checking" job, the MTAs will do that for me. If its invalid email, i will get a response from MTA. If its able to be sent out, that means the email is most probably valid.
please try
'/^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*#[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+$/'
it also fits for subdomain email adresses as email#sub.domain.tl