When using PHPMailer on localhost (Windows, XAMPP), email sends ok but the script hangs forever -- no refresh.
php's own mail() function works fine, and PHPMailer works fine using sendmail, so this is only a problem in SMTP mode.
Strangely, when stepping through with Xdebug,
I get "Fatal error: Maximum execution time of 0 seconds exceeded" in the console when I reach __destruct()
though I can step through this, which gives me the refresh and the error reflected in the browser. Also, once I've done this, I can refresh the browser and new emails will be sent normally and with no error and no hanging. Exit out of debugging mode and I return to the hanging behaviour.
Note: in php.ini:
max_execution_time=60
max_input_time=60
require_once "PHPMailerAutoload.php";
$to = "myemail#gmail.com";
$to_name = "Me";
$from_name = "fromName";
$from = "from#name.com";
$subject = "This is a test email from php " . strftime("%T", time());
$message = "phpmailer using smtp";
$mail = new PHPMailer();
$mail->IsSMTP();
$mail->SMTPDebug = 2;
$mail->Host = "# censored #";
$mail->Port = 587;
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'tls';
$mail->Hostname = "myhost";
$mail->Username = '# censored #';
$mail->Password = '# censored #!';
$mail->FromName = $from_name;
$mail->From = $from;
$mail->addAddress($to, $to_name);
$mail->Subject = $subject;
$mail->Body = $message;
$result = $mail->send();
echo $result ? 'Sent' : 'Error: ' . $mail->ErrorInfo;
I have had similar issues when working on a development localhost server with PHPMailer. After much research the way that I overcome this was to manually require both the PHPMailer class and the SMTP class like:
require('../vendor/phpmailer/phpmailer/class.phpmailer.php');
require("../vendor/phpmailer/phpmailer/class.smtp.php");
As using the PHPMailerAutoload.php didn't fully require all the class needed and threw exceptions. Do you have a live server to test as I found a lot of answers like "works fine when live and fully deployed", this is a risky choice though.
I managed to overcome the "maximum execution time" by requiring the files manually. But the hanging is intermittent whilst using windows and XAMPP where sometimes it send straight away and other times it may take a while for the script to process. Not sure if this will work but it's worth a shot.
Further to this I investigated the "class.smtp.php" file within PHPMailer and found this:
$this->edebug('Connection: opened', self::DEBUG_CONNECTION);
// SMTP server can take longer to respond, give longer timeout for first read
// Windows does not have support for this timeout function
if (substr(PHP_OS, 0, 3) != 'WIN') {
$max = ini_get('max_execution_time');
// Don't bother if unlimited
if ($max != 0 && $timeout > $max) {
#set_time_limit($timeout);
}
stream_set_timeout($this->smtp_conn, $timeout, 0);
}
Which defined in the comments above it states that "Windows does not support the timeout function". Maybe from this understanding it could help you eliminate possibilities?
Related
So as the title implies
Im trying to send an email (one email) but the problem I'm facing is bizarre.
Whenever debug is turned on, email is sent only once.
But when debug is turned off, around 3 to 4 emails are sent at once.
NOTE: I'm using localhost not an actual server.
to diagnose the problem, I did the following:
1- used a md5 to generate random string in the "subject" to check whether email is sent with same contents or different. and the results were totally different. meaning, emails weren't duplicate but actually being sent couple of times.
2- opened the project in a browser with no extensions to make sure the problem wasn't in an extension loading my project page more than once. and the results were also similar to number 1, different "subject" also.
so, long story shot. i have no idea what causes this problem to happen. and why it only stop happening when debug is turned on.
NOTE: this is not my first time to use PHP mailer, but my first time to face this problem. I'm also using the latest version of PHP mailer (6.5.1)
Here is my entire code:
in PHP mailer file:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;
require ABSPATH.'inc/phpmailer/script/src/PHPMailer.php';
require ABSPATH.'inc/phpmailer/script/src/Exception.php';
require ABSPATH.'inc/phpmailer/script/src/SMTP.php';
function SendEmail(){
$mail = new PHPMailer(true);
try {
//Server settings
$mail->SMTPDebug = SMTP::DEBUG_OFF;
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'ssl';
$mail->isSMTP();
$mail->Host = '*****';
$mail->SMTPAuth = true;
$mail->Username = '*****';
$mail->Password = '*****';
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mail->Port = 465;
$mail->SMTPAutoTLS = false;
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
$mail->ClearAllRecipients();
$mail->clearAttachments();
//Recipients
$mail->setFrom('*****', '******');
$mail->addAddress('*******', '*****');
$mail->addReplyTo('******', '******');
//Attachments
$mail->addAttachment(ABSPATH.'upload/dog.jpg', 'new.jpg');
//Content
$mail->isHTML(true);
$mail->Subject = md5(rand()); //This is how I'm checking whether it sends same email with same subject header or different ones. and it does send different ones
$mail->Body = 'This is the HTML message body <b>in bold!</b>'. md5(rand());
$mail->AltBody = "To view the message, please use an HTML compatible email viewer!";
$mail->ContentType = 'text/html; charset=utf-8\r\n';
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
}
and here is the file I'm using to call the function
<?PHP
// NO LOOP here
require_once(ABSPATH.'inc/phpmailer/phpmailer.php');
SendEmail();
As always, the first place to check is the docs.
Since you've already tried the random hash in the subject trick (well done on your logic!), you know that the problem is not that your script is sending more than one message, but that your script is being called repeatedly, and you should see evidence of that in your web server logs too. The usual reason for this is browser extensions which have a nasty habit of doing multiple submissions. Test that by using a clean browser with no extensions (e.g. use a browser you don't normally use, like Opera, Brave, or Chrome Canary).
Any requests that your browser is making should appear in the network tab of the dev console. On the server side you can either set up remote debugging to trigger breakpoints (tricky), or var_dump every request to a log so you get full details of what's calling the script.
BTW, you really shouldn't be disabling TLS verification. Fix the problem properly instead of hiding it; the troubleshooting guide has lots on that subject.
I had the same issue and solved by upgrading to the latest version of PHPMailer.
I am writing a script to send birthday messages automatically to employees. For now I have taken hard-coded email ids. Now the problem is that these scripts are working perfectly well on my laptop Windows 10 Wampserver3.0.6. But now when I am transfering these files to the main desktop in the office(Windows 7 Wampserver3.1.3), the email sending based scripts crash the computer when you embed or attach an image. If I remove the attachment and send only the text, the email gets sent. But on attaching an image the computer crashes directly. The code is as follows:
require("PHPMailer-master\src\PHPMailer.php");
require("PHPMailer-master\src\SMTP.php");
require("PHPMailer-master\src\Exception.php");
$mail = new PHPMailer\PHPMailer\PHPMailer();
$mail->IsSMTP();
$mail->SMTPDebug = 1;
$mail->SMTPAuth = true;
$mail->SMTPSecure = 'ssl';
$mail->Host = "smtp.gmail.com";
$mail->Port = 465;
$mail->IsHTML(true);
$mail->Username = "abc#gmail.com";
$mail->Password = "********";
$mail->SetFrom("abc#gmail.com");
$mail->Subject = "Happy birthday!";
$mail->AddEmbeddedImage('compressed.jpg', 'compressed');
$mail->Body = "<h1>Happy Birthday!</h1><br>Have a wonderful day!";
$mail->AddAddress("abc#gmail.com","def#hotmail.com");
if(!$mail->send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo "Message has been sent";
}
I have tried so many things. I have increased the memory_limit of wamp server.
An additional thing, debug=1 displays the process on chrome. So if i embed an image, it stops halfway, it does not display the process completely and crashes in the middle.
NOTE: addAttachment() works well but addEmbeddedImage() crashes the computer
It works perfectly well on my laptop. Please help.
I've been trying to get my PhpMailer to work for over a week now.
I'm on a Windows machines, so I set up a "droplet" server with DigitalOcean (because they seem to have good step-by-step instructions) and then set up fake email accounts with ZohoMail (because it's free and I just need to test this.)
I've got breaks all over the three PhpMailer files I need (PhpMailerAutoload.php, class.phpmailer.php, and class.smtp.php). What I figured out is that I'm getting hung up on this line:
class.smtp.php line 1060 (or about since I've got breaks in there)
inside function get_lines:
$str = #fgets($this->smtp_conn, 515);
I put in more breaks, as below:
//*********Debug Code here
$test = $this->smtp_conn;
echo "\nContents of test var: \n";
var_dump($test);
echo "about to set str var \n";
$str = #fgets($test, 515);
echo "Contents of str var \n";
var_dump($str);
echo "\n out of debug code";
//***********End of debug code
After two minutes (2 minutes and 5 seconds to be precise) $test var_dumps just fine and "about to set str var" prints just fine.
But that's it. No more code executes.
I don't know what #fgets is. I don't see any documentation in the PHP manual for that, so I'm not sure where to go from here.
FIRST IDEA:
I checked on my php versions:
- server is running 5.5.9
- my PC is running 5.6.12
I'm guessing those are close enough.
SECOND IDEA:
I found that in the past there are a "==" vs "=" issue with this line of code, but that's clearly not the issue here.
THIRD IDEA:
I also read that some people fixed this problem by making sure that "php_openssl.dll" is enabled in their php.ini file.
In mine I have a line that reads:
extension = php_openssl.dll
So I think that's OK.
FOURTH IDEA:
Is my configuration wrong?
I'm using the following:
SMTP Host: smtp.zoho.com (should I get the IP address instead?)
SMTP Port: 465
and I think I have encryption and authentication turned on. (My code is at the end if that helps.)
FIFTH IDEA:
Start over using gmail to see if that gives me any clues, unless someone has a better idea.
function send_SMTP_email($email, $name, $subject, $msg) {
//SMTP needs accurate times, and the PHP time zone MUST be set
//This should be done in your php.ini, but this is how to do it if you don't have access to that
date_default_timezone_set('Etc/UTC');
require_once '/inc/phpmailer/PHPMailerAutoload.php'; // will load class.phpmailer.php and class.smtp.php itself
require_once '/inc/config.php';
//Create a new PHPMailer instance
$mail = new PHPMailer;
//Tell PHPMailer to use SMTP
$mail->isSMTP();
//Enable SMTP debugging, TO DO: Disable for production
// 0 = off (for production use)
// 1 = client messages
// 2 = client and server messages
$mail->SMTPDebug = 2;
//Ask for HTML-friendly debug output
$mail->Debugoutput = 'html';
//Set the hostname of the mail server
$mail->Host = SMTP_HOST;
//Set the SMTP port number - likely to be 25, 465 or 587
$mail->Port = SMTP_PORT;
//Whether to use SMTP authentication
$mail->SMTPAuth = true;
//Username to use for SMTP authentication
$mail->Username = SYSTEM_EMAIL;
//Password to use for SMTP authentication
$mail->Password = SYSTEM_PASSWORD;
//Set who the message is to be sent from
$mail->setFrom(SYSTEM_EMAIL, SYSTEM_NAME);
//Set an alternative reply-to address
$mail->addReplyTo(SYSTEM_EMAIL, SYSTEM_NAME);
//Set who the message is to be sent to
$mail->addAddress($email, $name);
//Set the subject line
$mail->Subject = $subject;
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
//$mail->msgHTML(file_get_contents('contents.html'), dirname(__FILE__));
//Send HTML OR Plain Text
$mail->isHTML(true);
//Set body
$mail->Body = "<p>" . $msg . "</p>";
//Include plain text if non-HTML email reader
$mail->AltBody = $msg;
//Attach an image file
//$mail->addAttachment('images/phpmailer_mini.png');
$result = $mail->send();
//send the message, check for errors
//if (!$mail->send()) {
if (!$result) {
$return_val = "Mailer Error: " . $mail->ErrorInfo;
} else {
$return_val = "";
}
return $return_val;
}
I just had the same problem and finally found the problem. The default is set to TLS. Once I changed it to SSL with
$mail->SMTPSecure = 'ssl';
everything worked fine. Hopes this helps, if anyone else faces the same issue.
I have written a class in PHP which I use for sending mails making use of a Gmail account. This class in turn uses the PHPMailer library. The setup is WAMP 2.4 on Windows Vista. Using the microtime() function in PHP, I see that it takes anywhere between 5 to 6 seconds to send a single mail. Is it normal for a PHP script running on the kind of set up that I have to take as much as 5-6 seconds for a single mail going out. Here is code for the class.
<?php
require_once("phpmailer/class.phpmailer.php");
require_once("phpmailer/class.smtp.php");
class Mailer {
// Needs to be set per object
public $subject;
public $message;
public $to_name;
public $to;
private $mail; // This is the main mail object that'll be initialized
public function __construct() {
// Need to create a PHPMailer object in the constuctor and return it for use in this class.
$mail = new PHPMailer();
$from_name = "bleh";
$from = "bleh#gmail.com";
$username = "bleh";
$password = "bleh";
$mail->FromName = $from_name;
$mail->From = $from;
$mail->Username = $username;
$mail->Password = $password;
$mail->IsSMTP();
$mail->Host = "smtp.gmail.com";
// $mail->Port = 587; // Turns out, I dont need this one.
$mail->SMTPAuth = true; // gmail requires this
$mail->SMTPSecure = 'tls'; // gmail requires this
$this->mail = $mail;
}
function send() {
$mail = $this->mail; // The mail object
$mail->Subject = $this->subject;
$mail->Body = $this->message;
$mail->AddAddress($this->to, $this->to_name);
$result = $mail->Send();
return $result;
}
}
?>
Code used to test this -
$startTime = microtime(true);
require_once("mailer.php");
$mailer = new Mailer();
$mailer->subject = "Test";
$mailer->message = "Test";
$mailer->to_name = "My Name";
$mailer->to = "anemail#address";
$mailer->send();
echo "Time: " . number_format(( microtime(true) - $startTime), 4) . " Seconds\n";
It is very common for SMTP to take a long time - it's even used as an anti-spam measure in the form of greetdelay/tarpit mechanisms. RFC2821 section 4.5.3.2 allows up to a 5 minute delay before traffic starts. SMTP is not intended for interactive use (since it can't queue in that situation), and sending via SMTP during web page submission can suffer because of that. Sendmail or SMTP via an async process would avoid the issue.
In PHPMailer you can enable SMTP debug output and it will show you what's happening so you'll be able to see what's taking the time:
$mail->SMTPDebug = 2;
As mentioned in my comment, Gmail may be rate limiting you. There could also be some aspect of your network communication with Gmail that is causing the issue.
You can manually begin an SMTP conversation with Gmail from the command line. Watch for how long each step takes, and check for any codes / messages that may come back from Gmail indicating a problem.
For details on how to create a manual SMTP conversation see
Connecting to smtp.gmail.com via command line
Messages that come back will be Base64 encoded as indicated in that answer. You can use an online Base64 decoder to convert back to plain text.
Note: The link shows instructions for Linux. If you don't have a Linux server to test from, you can use Cygwin (for windows) or an OpenSSH for Windows package that does not require a full Cygwin install
I have faced to same problem and its getting around 30s to send the email.
The problem was system running PHP server got hang until the email is sent.
I tried many solutions but easiest way was start another PHP server locally on different port for handle the mail sending.
The main PHP server (system running server) will handed over the mail sending request to the mail PHP server and continue no the process.
Still 30s will take to send the email, but not effect to the main PHP server.
I recently moved from windows shared hosting to a VPS. I'm struggling to get phpmailer to work for a contact form on my website.
The code for my site the sets up the email to send is:
$mail->IsSMTP(); // set mailer to use SMTP
$mail->Host = "smtp.gmail.com"; // specify main and backup server or localhost
$mail->SMTPAuth = true; // turn on SMTP authentication
$mail->SMTPSecure = "tls";
$mail->SMTPDebug = 1; // can vary the amount of debug info given on error
$mail->Username = "mail#mydomain.com"; // SMTP username
$mail->Password = "########"; // SMTP password
$mail->Port = 587;
This code worked on the old windows shared hosting. Also everything else is identical too with the site (the class.phpmailer.php file etc)
So I'm guessing it's something to do with my setup of iis or the server itself.
Connecting out works on port 587 according to my webhosts who checked that for me
I installed php using the Microsoft tool that does everything for you. the site is in php and is working, and it looks to my untrained eye like all is fine there.
I've checked that php_openssl.dll is enabled.
I've spent a long time reading around and fiddling with no luck. I'm really at a loss as what to look at next. Any ideas what it could be or what I should try?
thanks!
Phil.
EDIT:
The action on the php form is to go to contactprocessor.php.
That file contains this code:
<?
ob_start();
if(isset($_POST['btnSubmit']))
{
require("class.phpmailer.php");
$mail = new PHPMailer();
//Your SMTP servers details
$mail->IsSMTP(); // set mailer to use SMTP
$mail->Host = "smtp.gmail.com"; // specify main and backup server or localhost
$mail->SMTPAuth = true; // turn on SMTP authentication
$mail->SMTPSecure = "tls";
$mail->SMTPDebug = 1; // can vary the amount of debug info given on error
$mail->Username = "mail#mydomain.com"; // SMTP username
$mail->Password = "########"; // SMTP password
$mail->Port = 587;
$redirect_url = "http://www.mydomain.com/contact/contact_success.php"; //Redirect URL after submit the form
$mail->From = $mail->Username; //Default From email same as smtp user
$mail->FromName = "Website Contact Form";
$mail->AddAddress("mail#mydomain.com", "From Contact Form"); //Email address where you wish to receive/collect those emails.
$mail->WordWrap = 50; // set word wrap to 50 characters
$mail->IsHTML(true); // set email format to HTML
$mail->Subject = "From Contact Form";
$message = "FullName: ".htmlspecialchars($_POST['fullname'])." <br> <br>
\r\n <br>EmailAddress: ".htmlspecialchars($_POST['email'])." <br> <br>
\r\n <br>Phone Number: ".htmlspecialchars($_POST['mobile'])." <br> <br>
\r\n <br> Message: <br>".htmlspecialchars($_POST['message']);
$mail->Body = $message;
if(!$mail->Send())
{
echo "Sorry the message could not be sent. Please email mail#mydomain.com instead. Thanks<p>";
echo "Mailer Error: " . $mail->ErrorInfo;
exit;
}
echo "Message has been sent";
header("Location: $redirect_url");
}
?>
Instead of actually sending the email, it just seems to print the above to screen of the user as if it's a webpage. it's as if the server thinks it's a html page and is just serving it.
You wrote:
Instead of actually sending the email, it just seems to print the above [code] to screen of the user as if it's a webpage. it's as if the server thinks it's a html page and is just serving it.
I think your problem is unrelated to phpMailer, or indeed email at all.
This is almost certain to be simply a small difference between the PHP configuration on your old and new servers.
Your PHP code is using the short-style PHP tags -- ie starting with <?.
Many PHP servers are configured not to allow this short-style tag, and only run PHP code that starts with the full <?php tag.
Given what you stated in the remark I quoted above, I suspect this is your problem, because what you describe is exactly the symptom I would expect from that.
You have two options:
Change your code to use the long style <?php tag.
Change your server config to allow the short <? tag.
I would recommend taking option (1) if possible, because the long-form tags are considered best practice (the short form is not recommended because it can have a potential clash with the <?xml marker at the start of most XML documents).
If you have a lot of short-form <? tags (and assuming you're allowed to do so), changing the server config may be worth considering, but if it's easy enough to fix the problem by switching to long tags, I'd say that would be better.
Hope that helps.
Thanks to Spudley for the answer. I had <? at the start (which is a shorthand that doesn't work on new php installations apparently). It should be <?php that's made it work. Thanks again.