I'm using PHPMailer to send a newsletter out from a list of emails in a database. The script queries the database, puts the data into an array with a while loop, and in the while loop creates and sends the email.
It works fine until after 150 or so emails are sent, then it randomly stops. As an example, email blast #1 failed after 161 sent emails, email blast #2 failed after 165 sent emails, and email blast #3 failed after 182 sent emails.
I have been researching and researching and cannot find the cause to this. Right now I send each email in it's on To: message, and don't send them using the BCC: route. Could it be settings on my server? If so, what should I be looking for?
I also have a little bit of debugging built in. The sql script at the end adds the email to the database, along with the specific time it was sent, so that I can tell exactly how many get sent, which email stops the process, and how long it takes.
The emails it stops on show no pattern (meaning they are different email providers) and it only takes around 10 - 12 minutes to send out that many. My script timeout on the server is way high than that so that isn't the cause.
My code is as follows:
$mail = new PHPMailer();
$mail->IsSMTP(); // set mailer to use SMTP
$mail->Host = "*server ip here*"; // specify main and backup server
$mail->SMTPKeepAlive = true; // SMTP connection will not close after each email sent
$mail->SMTPAuth = false; // turn on SMTP authentication
$mail->Username = "*user*"; // SMTP username
$mail->Password = "*pass*"; // SMTP password
while($select2 = sqlsrv_fetch_array($select)) {
$email = $select2['email'];
$unid = $select2['id'];
$unemail = $select2['email'];
$to = $email;
$from = "newsletter#site.com";
$new_date = date("n/j/y - g:i:s a");
$headers = "From: $from\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
$message2 = "<html><body>";
$message2 .= $message;
$message2 .= "</body></html>";
$mail->From = "newsletter#site.com";
$mail->FromName = "Newsletter";
$mail->AddAddress($to);
$mail->AddReplyTo("newsletter#site.com", "Website.com");
$mail->IsHTML(true); // set email format to HTML
$mail->Subject = $subject;
$mail->Body = $message2;
if(!$mail->Send()) {
die("mail() Failed to send email to $to.");
echo "<br><br>Mailer Error: " . $mail->ErrorInfo;
exit;
} else {
$make_sent_query = "INSERT INTO emailssent (email_signup_id, email, datesent) VALUES (?, ?, ?)";
$params_sent = array($unid, $to, $new_date);
$add_to_sent = sqlsrv_query($conn, $make_sent_query, $params_sent);
if($add_to_sent) {
echo "Message sent for email $to<br>";
} else {
die("Mail sent, but failed to insert into Sent Emails database.");
}
}
$mail->ClearAddresses(); //clear addresses for next loop
}
Could this be being caused by your local mail server? If you're sending out 150 emails in a short space of time, it might be assuming that it's spamming, and stop once you reach a certain amount.
You could try slowing it down with a sleep() after sending each mail? Just a second or two should be enough if that is the cause....
Is there a reason why you want to avoid using BCC? You can send email to multiple recipients and reduce the number of emails you're sending to a fraction of what you're sending now, though it is at the cost of not being able to individualise each email.
I think it's timeout problem. And crontab can solve your problem http://en.wikipedia.org/wiki/Cron . You can write script to send your emails and set your crontab to run this script every minutes. Then you have never had a timeout.
One of the potential reasons can be PHP timing out the script. Every script gets to run for a limited amount of time. If your script takes more time than that then PHP will simply kill the script. Typically that should cause an error being reported in the error logs. Check your apache error log messages - they might contain a hint.
it is caused by the max_execution_time in XAMPP,
so, the script of sending emails will stop when the script is running above the max_execution_time.
the default max_execution_time is 120seconds.
sending many emails takes much times.
you can change it by adding this script
ini_set('max_execution_time', 0);
put it before your email blasting script section, it tells the php to set it to unlimited max_execution_time.
Related
I don't use PHP that often but when I do and I need to write a function to send E-Mails, I just used the mail() function. I have used it on a shared hosting service and I always received the E-Mails from a... well... not an account? A bot? It didn't even have an E-Mail address.
And that's what I want to achieve at this very moment - send an E-Mail to me without really connecting to a SMTP server or going through authentication. How can be that done with PHPMailer? Is it even possible in my case? And if you somehow got my question, how are such E-Mails even called; the ones that... aren't sent by... well... an E-Mail account?
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'PHPMailer-master\src\Exception.php';
require 'PHPMailer-master\src\PHPMailer.php';
require 'PHPMailer-master\src\SMTP.php';
$mail = new PHPMailer();
$mail->FromName = "A random name";
$mail->addAddress("myemail#gmail.com", "Recepient Name");
$mail->isHTML(true);
$mail->Subject = "Subject is here";
$mail->Body = "Hello, <br>test body ";
if(!$mail->Send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo "Message has been sent";
}
?>
This did make me laugh a bit...
No, emails can't just magically spring into existence, but there isn't necessarily a direct correlation between email user accounts and addresses.
When you send from a shared hosting account by calling mail(), the mail server knows the account you're sending from, and sometimes doesn't require authentication as a result. This for example is how GoDaddy operates. Unfortunately this approach is very prone to abuse because there is often little preventing you from flat-out lying about who you are. This is why such services are usually a) terrible and b) extremely unreliable for actually delivering messages.
If you don't specify a "from" address, the server will usually make one up from information it does have – typically your user account name, or the name of the user running the script (e.g. www-data), and the hostname of the server you're on, often something like randomnumber.hostingprovider.example.com. Look at the headers of messages you've sent before, and you'll probably see something like that.
Sometimes this address can be the same for all users on a given shared server, so your delivery reputation can depend on what others are sending, which could well be spam, phishing, malware, etc.
This vagueness is terrible for deliverability, so if you host your contact form on such a system, expect messages from it to end up in a spam folder.
If you use SMTP to send via a "proper" account you gain a lot more control and reliability, but unfortunately some hosting providers (GoDaddy again) block outbound SMTP and force you to use their mail servers. This is a way of saying that if you want to send email that will be delivered, use a decent hosting provider.
Once you get control over your sending, you can choose exactly what addresses messages are sent from, subject to authentication constraints including things like SPF, DKIM, and DMARC, but that's another story.
To my knowledge it is possible and have it work correctly each time. In the last year I found that the e-mails I sent using the mail() function would immediately go into my spam box (as well as the junk box of others) causing great confusion. I upgraded to PHPMailer to solve this and I have never set it up to use SMTP and works just fine.
The code I have is:
$mail = new PHPMailer(true);
$html = $email->get(); // This gets a standard HTML Template to use as the base of the e-mail.
$title = 'Title for Inside the HTML';
$subject = 'The E-mail Subject';
$html = str_replace('[title]',$title,$html); //Use this to replace the [title] element in my HTML Template with $title.
$html = str_replace('[date]',date("F j, Y g:i A"),$html); // Again, replaces [date] in the HTML Template with the current date and time.
$body = 'Hello My Good Friend,<br>This is just a simple <strong>HTML Message</strong><br><br>Thank you.';
$html = str_replace('[body]',$body,$html); //Add my HTML Message to the HTML Template.
try {
//Recipients
$mail->setFrom('noreply#example.com', 'My Organization');
$mail->addAddress($row["email"], $row["fullname"]); // Add a recipient
//Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = $subject;
$mail->Body = $html;
$mail->AltBody = strip_tags($html,'<br>');
$mail->send();
//Return Success Message
$rMsg .= '<div class="alert alert-success">
<strong>Success: </strong> We have e-mailed the warning.</div>';
} catch (Exception $e) {
$rMsg .= '<div class="alert alert-danger">
<strong>Error: </strong> There was an error e-mailing the warning.</div>';
}
I'm making my first site for a learning exercise as I've been a java back-end developer. I am setting up a user registration form and since this is going to be my user's first glimpse at my site, I want to make sure I handle things as robustly as possible. Through some trials I've come across and implemented almost all these solutions:
php's mail() function - this worked the first day i tested it and stopped working later. First time I realized sending mail wasn't a "given" simple task
pear mail class - implemented this tonight and is currently still working
pear smtp mail - read about this here. Makes me feel like I should be using smtp?
At this point I have realized sending email reliably is not quite as trivial as I originally thought. My question is what is the most reliable way to send mail, and what is the most robust way to handle exceptions? For instance if SMTP is the most reliable way, please explain why and provide a simple example with error handling.
For any of the errors that occur, are they errors where doing some automated retry would benefit? I understand that just because I send mail doesn't mean the person will get it, but I'm asking what the most robust solution is because I'm sure other people have done this 100 times over.
To prove I'm not just a lazy coder, this is what I've got so far which has been working - but I have no idea how robust this actually is (pear mail):
<?php } else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
include('Mail.php');
include('Mail/mime.php');
$to = urldecode($_POST['email']);
if (preg_match('(\r|\n)', $to)) {
die('No email injection for you!');
}
$headers = array(
'From'=>'tag <me#mysite.com>',
'Subject'=>'Registration for mysite.com'
);
$text_body = 'boring text message';
$html_body = '<html>
<head><title>Welcome</title></head>
<body>
<p>slightly less boring message</p>
</body>
</html>';
//Utilize the mime class to generate mime body and add mime headers
$mime = new Mail_mime();
$mime->setTXTBody($text_body);
$mime->setHTMLBody($html_body);
$body = $mime->get();
$headers = $mime->headers($headers);
//Utilize the mail class to send the mime mail
$mail = Mail::factory('mail');
$mail->send($to, $headers, $body);
echo 'mail sent maybe?';
?>
EDIT:
Code sample using SMTP with error handling
<?php } else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
include('Mail.php');
include('Mail/mime.php');
$to = $_POST['email'];
$to = urldecode($to);
if (preg_match('(\r|\n)', $to)) {
die('No email injection for you!');
}
$headers = array(
'From'=>'tag <me#mysite.com>',
'Subject'=>'Registration for mysite.com'
);
$text_body = 'boring text message';
$html_body = '<html>
<head><title>Welcome</title></head>
<body>
<p>slightly less boring message</p>
</body>
</html>';
//Utilize the mime class to generate mime body and add mime headers
$mime = new Mail_mime();
$mime->setTXTBody($text_body);
$mime->setHTMLBody($html_body);
$body = $mime->get();
$headers = $mime->headers($headers);
//Utilize the mail class to send the mime mail
$host = 'mail.mysite.com';
$port = '26';
$username = 'me#mysite.com';
$password ='myPassword';
$smtp = Mail::factory('smtp', array (
'host' => $host,
'port' => $port,
'auth' => true,
'username' => $username,
'password' => $password
));
$mail = $smtp->send($to, $headers, $body);
if (PEAR::isError($mail)) {
echo("<p>" . $mail->getMessage() . "</p>");
} else {
echo("<p>Message successfully sent!</p>");
}
?>
There are typically several steps involved in sending mail:
Application: Put mail into queue of local delivery agent
Delivery agent: Send mail to configured SMTP server
SMTP server: Send mail to destination mail server
User mail application: Fetch mail from mail server
User: Click on mail, read it
PHP's mail() function puts the mail into the queue of the local mail delivery agent on unix. You'll only get an error (return value false) if that does not work. You do not get notified when the agent cannot deliver the mail further or any of the steps 2-5.
Using a direct SMTP connection to your SMTP server at least gives you an if the mail cannot be delivered to your SMTP server, which is more information than you get with mail(). What you don't get is information if the mail does not get read or is simply filtered out into a spam folder, or if the remote mail account does not exist (3-5).
To get to know that the remote account exists, you need to either parse the error response mails ("Undelivered mail returned to sender), or implement the full remote server SMTP connection and sending yourself (step 3), which I would not recommend.
To find out if the mail has been read, you could embed a "web bug", a tiny (potentially clear) image that is displayed in the HTML mail and notifies you that the mail has been displayed. You can use this to put sent mails into a database and mark them as read when your web bug image URL gets called. Mails that did not get read in X days can be seen as "not read" or "failed" - but the user can also simply be on vacation :)
Reliability & robustness
Your own mail server (step 3) automatically tries to re-send mails when the remote user's mail server is down. If that does not work, you'll get mails like "Mail delivery delayed for 24 hours", and another mail when it stopped doing that.
So once the mail is on your mail server, you can be sure that this server will do everything it can to deliver it.
is anybody know any solution for below problem
in my project, i am send email to client using smtp and php mailer and gmail script. so when i am send mail gmail send mail to particular client. for that i am passing gmail login and user name which is valid. all mail are sending properly. but sometime it may happen that some client not receive mail and at that time i am not able to get or trace any error. so i there any way, when i am sending mail to client , and when client get it and read it at that time i got any kind of confirmation.
Please if anybody have any idea , help me out.
<?php
/**
* Simple example script using PHPMailer with exceptions enabled
* #package phpmailer
* #version $Id$
*/
require ('../class.phpmailer.php');
try {
$mail = new PHPMailer(true); //New instance, with exceptions enabled
$body = "Please return read receipt to me.";
$body = preg_replace('/\\\\/','', $body); //Strip backslashes
$mail->IsSMTP(); // tell the class to use SMTP
$mail->SMTPAuth = true; // enable SMTP authentication
$mail->Port = 25; // set the SMTP server port
$mail->Host = "SMTP SERVER IP/DOMAIN"; // SMTP server
$mail->Username = "EMAIL USER ACCOUNT"; // SMTP server username
$mail->Password = "EMAIL USER PASSWORD"; // SMTP server password
$mail->IsSendmail(); // tell the class to use Sendmail
$mail->AddReplyTo("someone#something.com","SOMEONE");
$mail->From = "someone#something.com";
$mail->FromName = "SOMEONE";
$to = "other#something.com";
$mail->AddAddress($to);
$mail->Subject = "First PHPMailer Message[Test Read Receipt]";
$mail->ConfirmReadingTo = "someone#something.com"; //this is the command to request for read receipt. The read receipt email will send to the email address.
$mail->AltBody = "Please return read receipt to me."; // optional, comment out and test
$mail->WordWrap = 80; // set word wrap
$mail->MsgHTML($body);
$mail->IsHTML(true); // send as HTML
$mail->Send();
echo 'Message has been sent.';
} catch (phpmailerException $e) {
echo $e->errorMessage();
}
?>
Some modification need to be done in above script.
Configure SMTP mail server.
Set the correct FROM & FROM Name (someone#something.com, SOMEONE)
Set the correct TO address
from
also
Delivery reports and read receipts in PHP mail
You can always add reply to mail address which will take care if there is any error so you will get email back, and for if it's read, include a picture (blank picture of 1 pixel will do) and add code in that picture like and you can see how many hits that image did recieve or recieved any at all.
You can check that things in two different ways like, by using the header "Disposition-Notification-To" to your mail function, it will not going to work in all case because most people choose not to send read receipts. If you could, from your server, influence whether or not this happened, a spammer could easily identify active and inactive email addresses quite easily.
You can set header like
$email_header .= "Disposition-Notification-To: $from";
$email_header .= "X-Confirm-Reading-To: $from";
now the another method to check is by placing an image and you can add a script to onload of that image, that script will send notification to your system that xxx user have read the mail so, in that way you can track delivery status of the mail.
In fact, I can't think of any way to confirm it's been delivered without also checking it gets read, either by including a image that is requested from your server and logged as having been accessed, or a link that the user must visit to see the full content of the message.
Neither are guaranteed (not all email clients will display images or use HTML) and not all 'delivered' messages will be read.
Though for more info https://en.wikipedia.org/wiki/Email_tracking
This question already has answers here:
Sending email with PHP from an SMTP server
(9 answers)
Closed 4 years ago.
i've got a php function which sends emails fine but I want it to use the smtp server i have specified in the ini.set function.
if i delete these 3 lines of code the email still sends fine.
the reason i want to use the smtp server is because sometimes this does not work to certain mail hosts.
connect();
$username = mysql_real_escape_string($_POST['username']);
$result = mysql_query("SELECT email FROM members WHERE username = '$_POST[username]'")
or die ("Error - Something went wrong.");
$row = mysql_fetch_array($result);
$useremail = $row['email'];
$name = "name";
$mail_from = "noreply#name.com";
$mail_to = "$useremail";
$mail_body = "Hello. Thank you for registering. Please click the link below to confirm your email address. ";
$mail_subject = "Confirm you registration".$name;
$mail_header = "From: ".$name." <".$mail_from.">\r\n";
ini_set ("SMTP", "ssl://serveraddress");
ini_set("smtp_port","465");
ini_set("sendmail_from","noreply#name.com");
$sendmail = mail($mail_to, $mail_subject, $mail_body, $mail_header);
if($sendmail == true) { mail("john#name.com", "email sent ok", "email sent to '$_POST[email]'", "yea sent ok");}
Else { mail("john#name.com", "email ERROR", "email not sent to '$_POST[email]'", "yea we got a problem");}
}
If you are serious about sending mass mailing in your web application, i'd look at the SwiftMailer library, its free and relatively easy to setup and you can set your own SMTP transporter live.
Else than that, i have had issues with sending mail to hotmail and yahoo before where the email just doesn't get there when you use the "mail()" function. Keep in mind that the web email clients are very picky about headers, structure and security and may refuse emails not written by real clients easily.
If you want to test out something like that, just use a local-address#your-domain email, this will usually not filter it out. Now if the mail doesn't get there, you know it's something else.
I've just updated a contact form to use PHPMailer to stop emails being marked as junk, with no luck.
It's a fairly straight forward setup I'm using but its still going into peoples junk mail.
Here is my script, I was wondering if anyone could tell what was wrong?
include_once('../inc/phpmailer/class.phpmailer.php');
$mail = new PHPMailer();
$name = $_POST['name'];
$email = $_POST['email'];
$body = "Name: ".$name."\r\n";
$body .= "Email: ".$email."\r\n";
$body .= "Message: ".$_POST['message'];
$mail->From = "mailer#blah.com";
$mail->FromName = "Contact BLah";
$mail->Subject = "Contact From: Blah";
$mail->Body = $body;
$mail->AddAddress("john#blah.com", "john");
$mail->AddAddress("david#blah.com", "david");
if(!$mail->Send()) {
$errorMsg .= "Error sending message, please try again later.";
} else {
$errorMsg .= "Message Sent successfully.";
}
I thought that PHPmailer normally takes care of inserting proper headers?
Any thoughts?
EDIT: Added spam score
-Spam-Status: "score=0.0 tests=none version=3.1.7 cmae=v=1.0 c=1 a=8nJEP1OIZ-IA:10
a=soyWjZv28gkhNSke5wm04A==:17 a=fqdOs_Nl9wd82e3SDigA:9 a=l-lynuxnH-gfU2bevBoA:7
a=wPNLvfGTeEIA:10 a=nymK5Bb5l1cA:10 a=_6wjLm_vFSYA:10 xcat=Undefined/Undefined"
X-Spam-Level: *
EDIT 2: I just tried the script on a different server from the clients and it has the same result. Do I have to send through the SMTP setup for it not to be classed as spam?
Some reasons your mail can get marked spam:
You're sending spam
Your IP, or a block of IPs surrounding your IP has been marked as a spam source on one or more blackhole lists
The content of the email is triggering spam filters.
The recipient has added you to their blacklist
The recipient didn't add you to their whitelist
You're sending a mixed source mail ("From: xyz#example.com", but sending it from "someotherdomain.net")
SPF records for your server are misconfigured/not configured at all
Domain keys are misconfigured/not configured at all
etc...
PHPMailer is a tool. Consider it a hammer. The hammer may have bent the nail, but only because the wielder didn't aim right.
The only way you'll solve this problem is by examining the bounce messages (if any), and whatever showed up in the recipient's mailbox. If they receive the mail, but it goes into a spam folder, then get a copy of the mail and examine its headers. Most spam filters will put their spam score/reasoning in there.
Small hint:
add in a line like so
$mail->AddReplyTo( 'mailer#blah.com', 'Contact BLah' );
It should decrease your SPAM rating significantly.
I was having the same problem using PHPMailer, and here's what fixed the problem for me: set the Sender (this is different and distinct from the "From") to a valid email account for the domain you are sending the email from. This causes PHPMailer to properly set the "envelope-from" information so that the email passes SPF and Sender-ID validation. Without doing this, the "envelope-from" is a OS user id and server combination which will not be verifiable.
Example Code:
$mail = new PHPMailer;
$mail->From = 'from_email#domain.com';
$mail->Sender = 'sender_email#domain.com';
...
It is not necessarily PHPMailer's fault, there are several possible reasons for your server to be blacklisted. You can check here to see if this happened