Checking for valid email addresses - php

I'm running a website with more than 60 000 registered users. Every week notifications are send to these users via email, now I've noticed some of the mail addresses do not exists anymore eg. the domain address is valid but the email name en asdas# is not valid anymore since person does not work at a company anymore etc. Now I'm looping through the database and doing some regular expression checks and checking if the MX records exist with the following two functions
function verify_email($email){
if(!preg_match('/^[_A-z0-9-]+((\.|\+)[_A-z0-9-]+)*#[A-z0-9-]+(\.[A-z0-9-]+)*(\.[A-z]{2,4})$/',$email)){
return false;
} else {
return true;
}
}
// Our function to verify the MX records
function verify_email_dns($email){
list($name, $domain) = split('#',$email);
if(!checkdnsrr($domain,'MX')){
return false;
} else {
return true;
}
}
If the email address is in an invalid format or the domain does not exists I delete the users account. Are there any methods I could use to check if the email address still exists or not if the domain name is valid and the email address is in the correct format? For example abc#test.com does not exist anymore but test.com is a valid domain name.
NOTE: If a mail is send to users and the email address does not exist anymore i get a email in my inbox resulting in 1000 per day which I'm trying to avoid.

The standard way is to connect to the remote mailserver and send it a VRFY command. However, some servers don't allow that because it makes it much easier for spammers to find out valid e-mail addresses. You can also try sending it a RCPT TO command (you'll get a 550 response if the address is invalid), but they tend to block you if you do that too many times, for the same reason
If you're already getting bounced e-mails in your inbox, it seems like you could just parse those and automatically remove people from your list that are causing delivery failures

Related

Send mails in a loop and output response to after every email is sent

I'm trying to send emails in a loop and it is working fine but it prints the result to page in one go rather one by one.
What I want is, it should print a response for every email sent. This is what I have so far:
//foreach loop
$Response = $ObjMail->send();
if ($Response) {
echo "Email Sent Successfully to $val[name] </br>";
} else {
echo "There was an error sending Email to $val[email]";
}
Depending on your $ObjMail, a "successfully send mail" generally will equate to
the sending mail server (i.e. smtp server) accepted the email or
the mail() function got called (actually read the doc, especially the return value part).
Email functions rarely return a very useful value, as long as the email being sent is at least somewhat plausible. It will even return true, if the email address doesn't exist, the email gets bounced, your smtp server is blacklisted, ...
The probable answer to your question: Your output is almost instantaneous by default, unless your local sendmail (the default on most hosts) call takes longer than a few microseconds, which it usually doesn't. Additionally, it doesn't say anything about the mails actually being sent. (And I assume, that you thought that was actually the case, it's not.)
My advice is, drop the stylish output and just send the mails. You can't be certain if they actually reached their target. If the $ObjMail actually returns an error, that would probably be wise to log somewhere, so that you don't repeatedly send to the same false address.

PHPMailer and multiples destination addresses issue

Im using phpmailer to send emails and i check that when i add some addresses and just one of them is an invalid address (not exists) E.G. "asdfasfasf#asdfasdfsfsfs.commm" and send the email i see that the email was sent (to correct addresses) and i have no idea how to check if one of the adresses is wrong to be able to log that issue before sending the email.
The code to send and add addresses is this:
foreach($options['emails'] as $email){
$mmail->AddAddress($email[0], $email[1]);
}
if (!$mmail->Send()) {
echo "error";
}else {
echo "sent";
}
Thanks in advance
Take a look at filter_var to validate the syntax:
if (filter_var($email[0], FILTER_VALIDATE_EMAIL)) {
// email address is considered valid
Note that there are ways to connect to the recipients SMTP server and ask if the email actually exists (see https://code.google.com/p/php-smtp-email-validation/ for example) however many email servers won't honor these queries anymore, due to spammer abuse.

PHP email Validation of IBM email only, (World wide)

I am pretty new to PHP, How do I validate an email address to have an IBM domain only? Valid address are:
XXXXX#us.ibm.com
XXXXX#in.ibm.com
XXXXX#ro.ibm.com
XXXXX#ibm.com
The PHP should be able to accept any of the above.
Please help
Thanks
Split on # then verify with a regex.
list($username,$domain) = explode('#',$email);
if (preg_match('/ibm\.com$/',$domain))
{
echo "yup it's ibm.";
}
First thing to check, is if the email address you got from the email headers is valid i.e.:
John Adams <john#us.ibm.com>
"John Adams" <john#us.ibm.com>
john#us.ibm.com
Then you can verify if it came from an IBM domain by:
if(preg_match('/#([a-z]{2}\.)?ibm.com/i', $emailaddress)) {
# email is from an ibm domain
}
Finally and this is a hard part, make sure that the email was sent from a server owned by IBM, because even me can send you an email with "arvin#ibm.com" as the email address indicated in the From field.
You can list all the IP addresses of IBM's email servers then check if the email originated from them using the email's header fields. Or if your server does SPF checking you can check if the Received-SPF field of the email is "pass".

Get the correct response from Yahoo SMTP

I try to send a mail via php to an yahoo recipient.
Every time I connect to yahoo I get a 250 status code for the recipient address, even if it doesn't exist. I found a script which get the correct status code from yahoo, but I cannot find the differences or mistakes I did in my script. I tried to send different commands and run the script on several servers, but I always get a 250 response for the RCPT-TO-command.
Why do I don't get the correct response? I want to stop my script when a recipient doesn't exist!
Log of verify-email.org which gets the correct response:
MX record about yahoo.com exists.
Connection succeeded to g.mx.mail.yahoo.com SMTP.
=220 mta1062.mail.sp2.yahoo.com ESMTP YSmtp service ready
> HELO verify-email.org
=250 mta1062.mail.sp2.yahoo.com
> MAIL FROM: <check#verify-email.org>
=250 sender <check#verify-email.org> ok
> RCPT TO: <sdjrfvn3r#yahoo.com>
=554 delivery error: dd This user doesn't have a yahoo.com account (sdjrfvn3r#yahoo.com) [0] - mta1062.mail.sp2.yahoo.com
Log of my script which gets the wrong response:
C Connect to h.mx.mail.yahoo.com
S 220 mta1144.mail.mud.yahoo.com ESMTP YSmtp service ready
C HELO my-domain.com
S 250 mta1144.mail.mud.yahoo.com (152.70 ms)
C MAIL FROM: <existing-address#my-domain.com>
S 250 sender <existing-address#my-domain.com> ok (723.29 ms)
C RCPT TO: <sdjrfvn3r#yahoo.com>
S 250 recipient <sdjrfvn3r#yahoo.com> ok (152.67 ms)
C Close socket connection
S Connection closed gracefully
You can find the script which works properly here: http://verify-email.org
My script:
while(preg_match('/^\d\d\d-/', $r = fgets($sock))) {
$response .= $r;
}
$response .= $r;
return $response;
}
$mxRecord = "a.mx.mail.yahoo.com";
$domain = 'example.com';
$mailFrom = 'mailfrom#example.com';
$rcptTo = 'doesntexist2011#yahoo.com';
$commands = array(
"HELO ".$domain."\r\n",
"MAIL FROM: <".$mailFrom.">\r\n",
"RCPT TO: <".$rcptTo.">\r\n",
// "DATA\r\n",
// ... email subject and content
// ".\r\n",
"QUIT\r\n"
);
if($sock = fsockopen($mxRecord, 25, $errno, $errstr, 30)) {
foreach($array as $cmd) {
echo htmlentities($cmd);
echo '<br />';
fwrite($sock, $cmd);
echo htmlentities(getResponse($sock));
echo '<hr />';
}
fclose($sock);
}
else {
echo 'no connection';
}
?>
Some information:
I used my own domain (not example.com)
The script is located on the server where my domain refers to
The server isn't on any blacklist like spamhaus.org
The used mail address in "Mail From" does exist
I use getmxrr() to get the mx entries of yahoo.com
I tried HELO and EHLO -> always the same response
Do NOT waste your money on verify-email.org. I had written a class that works quite well at verifying email addresses, but had been having problems for days trying to return anything from Yahoo other than a 250 Recipient OK message. I finally came up with a work around which I would share here by unfortunately after hitting their servers about 10 times or so they blocked me for 12 hours. I then moved the class from my dev server to a live server with a good domain name, rDNS configured and everything that would allow me to send emails without getting blacklisted minus domain keys. Again, I got nothing but 250 responses with SMTP and again I got my IP blocked with my work around. I finally decided to break down and buy the script to "see what they're doing different". The answer: They aren't doing anything different. In fact, the script was garbage and almost identical to any rudimentary script you can find online. I loaded it on 2 different server and with two different configurations, followed the directions of the script to the letter ( it was only 1 or 2 instructions) and yet, got the same 250 response for the exact same email address that I received a 554 on the site. Digging a little deeper I found that it was potentially an email marketing company selling the script. They either have a relationship with Yahoo and others or its calling some other backend system, i dont know but I do know the sccript does not work. Furthermore, an emails sent to the seller and SWREG (a digital river company) have gone unanswered as well as a request for a refund. I sent screenshots of my results versus what they display on the site. I am now filing a dispute with my Credit Card company. Point being, DO NOT BUY from verify-email.org. Its a scam. That is unless you feel like pissing away $45.
My only advice is to form business relationships with the majors or go through a company like ReturnPath (very very expensive.) Or, send confirmation emails to each subscriber. I unfortunately work for a marketing company that can't send confirmation emails based on rules they have with their affiliate partners so I have to use a third party service (expensive) or come up with another solution. Good luck.
Did you read the FAQ of verify-email.org? "For some domains you can't verify whether the address is good or not, because their mail servers don't cooperate. For example: yahoo.com"
This is because these mail servers don't want spammers harvesting known-good email addresses.

Bounce Email handling with PHP?

Here is my scenario:
I have 2 email accounts: admin#domain.com and bounce#domain.com.
I want to send email to all my users with admin#domain.com but then "reply to" bounce#domain.com (until here, my PHP script can handle it).
When, the email can't be sent, it's sent to bounce#domain.com, the error message could be 553 (non existent email ...) etc.
My question is: How do I direct all those bounce emails (couldn't-sent emails) to bounce#domain.com through a handling script to check for the bounce error codes?
What programming language should I be using for the "handling script"?
What would the "handling script" look like? Can you give a sample?
in other words:
What are the procedures I should follow to handle the bounce email ?
The best scenario is be able to classify the type of bounce: soft, hard...
what we use is BounceStudio. You need to compile it and add the php libraries... not hard at all. You have the free and paid version of that product
once we detect the kind of bounce we use PEAR::MAIL::MIME to search for custom headers that we added previously to the email, lets say:
X-user-id: XXXXX
X-campaign-id: YYYYYY
X-recipient-id: SSSSSSSSS
in this way we can know the real recipient that we sent the email to.
hope this help you! so you can help me to get to the 500 points :P
Why not create a bounce#domain.com and use php to read those emails and do what ever you want?
Edit After your comment : Please chec my link whcih has a php script which will teach you how to open and email box using php and read the emails. You can use this scrip to check the error messages.
Let the emails bounce to an address that is really an emailadress (with login details etc.).
Make a php script which runs ever x minutes (for example with a cron job). This php script must do the following.
- Retrieve all email from the box (use for example Zend Mail)
- Check for the error in the message (e.g. by searching it with regular expressions)
- Do what ever is necessary.
If you want to know specifically who has bounced back you can use user specific bounce addresses. (See for example this site)
Maybe it's a little late for the answer, but you can always try something new.
I had the last week a task like this, and used BOUNCE HANDLER Class, by Chris Fortune, which chops up the bounce into associative arrays - http://www.phpclasses.org/browse/file/11665.html
This will be used after you connect to the POP3 with some mailer to get the bounces from it, then parse it into pieces with this, and if has the status you searched for, do the necessary actions.
Cheers.
If you've got a POP3 mailbox set up for bounce#domain.com, you could use a POP3 client script written in PHP to retrieve the messages and check for undeliverable messages.
You can use imap_open to access your mails from PHP.
This functions also works for POP3 but not every function may work here. However I guess in 2018 most email-clients should support IMAP.
This function can also be used to open streams to POP3 and NNTP
servers, but some functions and features are only available on IMAP
servers.
Here is a little example, how to iterate through your emails:
/* connect to server */
$hostname = "{$your-server:$your-port}INBOX";
$username = 'my-username';
$password = '123';
/* try to connect */
$inbox = imap_open($hostname,$username,$password) or die('Cannot connect to mailbox: ' . imap_last_error());
/* grab emails */
$emails = imap_search($inbox,'ALL');
/* if emails are returned, cycle through each... */
if($emails) {
/* for every email... */
foreach($emails as $email_number) {
$message = imap_body($inbox,$email_number,2);
$head = imap_headerinfo($inbox, $email_number,2);
// Here you can handle your emails
// ...
// ...
}
}
In my case, I know that I always get my mail delivery failed from Mailer-Daemon#myserver.com. So I could identify bounces like that:
if($head->from[0]->mailbox == 'Mailer-Daemon')
{
// We have a bounce mail here!
}
You said:
When, the email can't be sent, it's sent to bounce#domain.com, the
error message could be 553 (non existent email ...) etc.
So if your bounce emails have the subject "Mail delivery failed: Error 553" then you could identify them by the subject like this:
if($head->subject == 'Mail delivery failed: Error 553')
{
// We have a bounce mail here!
}
The failed email address is not in the header, so you need to parse it from the $message variable with some smart code.
You could always use something like http://cloudmailin.com to forward the bounced emails on to your php server via http however you may be better with a service dedicated to sending emails and using their api to retrieve the bounce details.
i have had pretty bad luck looking for a PHP solution for this, but i ran across this product that does just what i needed.
it runs as a native app mac/win but it does the job.
http://www.maxprog.com/site/software/internet-marketing/email-bounce-handler_sheet_us.php
I was searching for the answer to the same question. There are more parts of the question, and more options.
For handling the bounced e-mail, I found a PHP class, purely in PHP, no compile or additional software installation needed if you have a PHP powered site. It is very easy to use.
If you are using cPanel, or InterWorx/SiteWorx, you can configure some of the addresses to handle the received e-mails with a script, for example a PHP script, so you can write your own handling with the aid of the mentioned class. Or of course still you can create ordinary e-mail accounts and retrieve the mails via POP3 or IMAP, and then interpret them. I think the first one is better, because it's direct, you don't have to use additional channels, like IMAP. Of course if you can't configure your mail server, or don't know how to do it, then the former is better for you.
Good luck! :)
In the php mail command http://php.net/mail
you use the fifth parameter and add "-f" to it.
So, you use "-f mybouncebox#mydomain.com" as the parameter
the phpList newsletter manager uses this to manage bounces.
Once the bounces fill up in the mailbox, you can POP them, and process them. That's the easiest way to deal with them, as opposed to handling them when they arrive.
Here is a canned solution to process bounces using IMAP.
I changed the Return-Path header of my Mail instance to a dedicated bounce#xxxxxx.us
The only method easy enough for me to consider viable is the following, which checks via POP3 the dedicated inbox and can handle each email based on the message received.
$inst=pop3_login('mail.xxxxxx.us','110','bounce#xxxxxx.us','pass');
$stat=pop3_stat($inst);
//print_r($stat);
if($stat['Unread']>0){
echo "begin process<br><br>";
$list=pop3_list($inst);
//print_r($list);
foreach($list as $row){
if(strpos($row['from'],'MAILER-DAEMON')!==FALSE){
$msg=imap_fetchbody($inst,$row['msgno'],'1');
if(strpos($msg,'550')!==FALSE){
echo "handle hard bounce".$msg."<br><br>";
//WHATEVER HERE TO PROCESS BOUNCE
}
}
else{
$msg=imap_fetchbody($inst,$row['msgno'],'1');
echo "not from my server. could be spam, etc.".$msg."<br><br>";
//PROBABLY NO ACTION IS NEEDED
}
//AFTER PROCESSING
//imap_delete ( resource $imap_stream , int $msg_number [, int $options = 0 ] )
//commented out because I havent implemented yet. see IMAP documentation
}
}
else{
echo "no unread messages";
}
//imap_close ( resource $imap_stream [, int $flag = 0 ] )
//commented out because I havent implemented yet. see IMAP documentation.
//flag: If set to CL_EXPUNGE, the function will silently expunge the mailbox before closing, removing all messages marked for deletion. You can achieve the same thing by using imap_expunge()
function pop3_login($host,$port,$user,$pass,$folder="INBOX",$ssl=false)
{
$ssl=($ssl==false)?"/novalidate-cert":"";
return (imap_open("{"."$host:$port/pop3$ssl"."}$folder",$user,$pass));
}
function pop3_stat($connection)
{
$check = imap_mailboxmsginfo($connection);
return ((array)$check);
}
function pop3_list($connection,$message="")
{
if ($message)
{
$range=$message;
} else {
$MC = imap_check($connection);
$range = "1:".$MC->Nmsgs;
}
$response = imap_fetch_overview($connection,$range);
foreach ($response as $msg) $result[$msg->msgno]=(array)$msg;
return $result;
}
function pop3_retr($connection,$message)
{
return(imap_fetchheader($connection,$message,FT_PREFETCHTEXT));
}
function pop3_dele($connection,$message)
{
return(imap_delete($connection,$message));
}
We are using Procmail to filter these kind of mails. After examining some of the solutions already mentioned here, we ended up with a simple Procmail recipe to detect bounce messages. Depending on the accuracy you need, this might be applicable to your situation.
For details, check this blog entry.
I had the same problem, exact situation. By default my mail server, is sending all my returned mails to the same account that it was originally sent from, with automatic msg "Mail delivery failed: returning message to sender".
I dont really want to know why it was returned, had so many mails transactions that I just want to remove the bad ones. Dont have time to check specific rule such as Doestn Exist, Unavailable, etc ,,, Just want to flag for deletion and go on.
Bounce mails are so trivial as you need to deal with a lot of different servers and responses types. Each anti spam software or operating system scenario can send a different error code with the bounced email.
I recomend you to read and download this fixed debugged version of Handling Bounced Email - USING PHPMAILER-BMH AND AUTHSMTP from KIDMOSES here http://www.kidmoses.com/blog-article.php?bid=40 if you want to setup IMAP and and send your own custom headers, send them to your bounce#domain.com and then cross your fingers to see if the script catches the headers you sent written in the bounced mail. I tried it, works.
But if you want to follow my quick and easy fix that resolved my problem, here is the secret.
1 - Download the better version from KIDMOSES site or from my site, just in case KIDMOSES want to move somewhere else http://chasqui.market/downloads/KIDMOSES-phpmailer-bmh.zip
2 - The variable that contains the text of your returned mail is $body and itself contains the bad returned email (SO ITS AN MULTIDIMENSIONAL ARRAY ). (Also contains your servers mail and other DNS mails stuff, but we are looking for the BAD MAIL BOUNCED.
3 - Since your OWN SERVICE is sending you back the bounced email, then its not likely to change its format and own headers, sending back bounced emails, so you are safe to pick the order of bounced email array returned. In my case was always the same format template. (Unless you change systems or providers)
4 - We look into that $body and search for all email string variables and extract them positioning them into a two dimensional array called $matches
5 - We select the array position, by printing the array using print_r( array_values( $matches ));
6 - This is the code that you need to modify. Its around line 500 from class.phpmailer-bmh.php file
// process bounces by rules
$result = bmhDSNRules($dsn_msg,$dsn_report,$this->debug_dsn_rule);
} elseif ($type == 'BODY') {
$structure = imap_fetchstructure($this->_mailbox_link,$pos);
switch ($structure->type) {
case 0: // Content-type = text
$body = imap_fetchbody($this->_mailbox_link,$pos,"1");
$result = bmhBodyRules($body,$structure,$this->debug_body_rule);
//MY RULE IT WORKS at least on my return mail system..
$pattern = '/[a-z0-9_\-\+]+#[a-z0-9\-]+\.([a-z]{2,3})(?:\.[a-z]{2})?/i';
preg_match_all($pattern, $body, $matches);
//print_r( array_values( $matches )); //To select array number of bad returned mail desired, usually is 1st array $matches[0][0]
echo "<font color = red>".$matches[0][0]."</font><br>";
break;
So we forget about returned headers and concentrate on the bad emails. You can excel them, you can MySQL them, or process to whatever you want to do.
IMPORTANT
Comment the echos in callback_echo.php in the samples directory otherwise you get all the junk before printed.
function callbackAction ($msgnum, $bounce_type, $email, $subject, $xheader, $cheader, $remove, $rule_no=false, $rule_cat=false, $rule_msg='', $totalFetched=0) {
$displayData = prepData($email, $bounce_type, $remove);
$bounce_type = $displayData['bounce_type'];
$emailName = $displayData['emailName'];
$emailAddy = $displayData['emailAddy'];
$remove = $displayData['remove'];
//echo "<br>".$msgnum . ': ' . $rule_no . ' | ' . $rule_cat . ' | ' . $bounce_type . ' | ' . $remove . ' | ' . $email . ' | ' . $subject . ' | ';
//echo 'Custom Header: ' . $cheader . " | ";
//echo 'Bounce Message: ' . $rule_msg . " | ";
return true;
}
MY OUTPUT
Connected to: mail.chasqui.market (bounce#chasqui.market)
Total: 271 messages
Running in disable_delete mode, not deleting messages from mailbox
kty2001us#starmedia.com
...
entv#nuevoface.com
Closing mailbox, and purging messages
Read: 271 messages
0 action taken
271 no action taken
0 messages deleted
0 messages moved
You should look at SwiftMailer. It's completely written in PHP and has support for "bounce" emails.
http://swiftmailer.org/

Categories