The following script takes about 1.5 seconds to send an email as measured by the timers across the $mail->send() line. If I don't use smtp, it goes MUCH faster, however, some mail servers will block the incoming email.
What is causing the delay? If there is nothing that could be done about it, what would be a good solution to prevent the user from having to wait for it?
<?php
require_once ('../../application/classes_3rd/PHPMailer/PHPMailerAutoload.php');
class myPHPMailer extends PHPMailer
{
public function __construct()
{
$this->isSMTP();
$this->SMTPDebug = 0;
$this->Host = 587;
$this->Port = "smtp.gmail.com";
$this->SMTPSecure="tls";
$this->SMTPAuth = true;
$this->Username = "example#gmail.com";
$this->Password = "my_password";
}
}
try {
$mail = new myPHPMailer(true);
$mail->AddReplyTo('me#example.com');
$mail->SetFrom('me#example.com');
$mail->AddAddress('me#example.com', 'John Doe');
$mail->Subject = "My subject";
$mail->MsgHTML("Hello! Click this link https://www.google.com/");
$time=microtime(1);
$mail->Send();
echo(microtime(1)-$time);
} catch (phpmailerException $e) {
trigger_error($e->errorMessage(), E_USER_ERROR);
}
?>
When you use the isMail() or isSendmail() transport options in PHPMailer, it does not send the message immediately, but submits it to your local mail server, which frees up your web app and sends the message at its leisure. This usually incurs no network overhead, no encryption or authentication, and if it's a low-traffic server, it's probably doing little else and can accept the message very quickly.
SMTP was never really meant to be used interactively i.e. during submission of a web page, and it can indeed take a long time. It's a complex protocol with many round-trips and points where delays are likely, particularly with the likelihood of grey listing, greet delays, immediate spam filtering and more.
If you want to use SMTP and make it fast, use a nearby mail server (even localhost) as a relay that doesn't need encryption or authentication and does not apply spam filtering on outbound messages.
instead of use this:
$mail->IsSMTP();
Use this:
$mail->IsMail();
I was with same issue, SMTP can really slow you down.
Related
Currently I am using phpMailer for sending emails to my Gmail account in a form submition. the code that I used for sending email is similar to the below code:
###################
/* sendeng email */
###################
use phpMailer\PHPMailer\PHPMailer;
if ($sehat === true) {
require_once "../phpMailer/PHPMailer.php";
require_once "../phpMailer/SMTP.php";
require_once "../phpMailer/Exception.php";
$mail = new PHPMailer();
//smtp settings
$mail->isSMTP();
$mail->Host = "smtp.gmail.com";
$mail->SMTPAuth = true;
$mail->Username = "myGmail#gmail.com";
$mail->Password = 'myPassword';
$mail->Port = 465;
$mail->SMTPSecure = "ssl";
//email settings
$mail->isHTML(true);
$mail->setFrom($commEmail, $commName);
$mail->addAddress("myGmail#gmail.com");
$mail->Subject = ("$commEmail ($commTopic)");
$mail->Body = "<div style='text-align:right; direction:rtl;'>" . nl2br(strip_tags($commMess)) . "</div>";
// $mail->Body = nl2br(strip_tags($commMess));
// $mail->AltBody = nl2br(strip_tags($commMess));
// $mail->Body = $commMess;
/* for other language messages */
$mail->CharSet = 'UTF-8';
if($mail->send()){
$status = "success";
$response = "Email is sent!";
}
else
{
$status = "failed";
$response = "Something is wrong: <br>" . $mail->ErrorInfo;
}
exit(json_encode(array("status" => $status, "response" => $response)));
}
I don't have any problem with sending email. But my first question is where I am using $mail->Password = 'myPassword'; in my code. Actually I am writing and debugging the code on a localhost (WAMPSERVER), and I used my real password instead of myPassword in the code. But after finishing the app I am going to host it to a real server (deploy my app). My question is that with this code, could host provider access to my Gmail password? And if so what is the solution to that? Is it a bug in phpMailer or I am wrong?
The second question is that when I want to send form data to my Gmail account, I must change the setting of my Gmail to "lower security" in this localhost version. If I deploy my app and it becomes available online, again I must do that (lower security of Gmail) or there are better ways? Because now when I return Gmail security setting to normal state the phpMailer does not send data.
My question is that with this code, could host provider access to my Gmail password?
Yes.
And if so what is the solution to that?
Don't use a host you don't trust.
In general you need to be able to trust your host, but there is one step that can help avoid all that this implies: using XOAUTH2 for authentication.
With this mechanism you do not have to store a real ID and password on your server; you need to use them in a one-off operation to obtain a token that can be limited to gmail operations. There are code examples provided with PHPMailer for this, along with a utility script you can use to obtain your auth token, and a wiki article to help you configure it (though it could use updating; contributions welcome). However, be aware that using OAuth is generally a complicated and unpleasant experience that contains many potential ways to mess things up. In this use case, it does provide a security enhancement as it means you don't have to leave your real google credentials lying around.
A scrupulous hosting provider will allow you to encrypt your VM's disk images in a way that means they can't read your data from the hypervisor, and if they don't also have SSH access to your instance, your data should be fairly well protected from them.
everybody,
I am working on Email system to send emails via SMTP protocol with PHP,
everything goes fine and now I can send messages without a problem, I have tow problems Actually and I hope I will find a solution,
1 - I send email to users using a phpmailer library, but I can not control and get the result of sending email because I send about 10 emails at one SMTP connection.
this is my send code
$mail = new PHPMailer;
$froms=$respu['froms'];
$mail->Timeout = 3600;
$mail->SMTPDebug = 2; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = $respu['server']; // Specify main and backup SMTP servers
$mail->SMTPAuth = $respu['authentication']; // Enable SMTP authentication
$mail->Username = $respu['username']; // SMTP username
$mail->Password = $respu['password']; // SMTP password
$mail->SMTPSecure = $respu['security']; // Enable TLS encryption, `ssl` also accepted
$mail->Port = $respu['port']; // TCP port to connect to
$mail->SetFrom($respu['username'],$froms);
$mail->AddAddress($to);
$mail->Subject = $subject;
$mail->MsgHTML($message);
if(!$mail->Send()) {
//$errors=$mail->getSMTPInstance()->getError();
$date=date('Y-m-d h:i');
echo $msg= "Message Not Sent: to $to " . $mail->ErrorInfo;
$date=date('Y-m-d h:i');
$sql="insert into log (log_text,user_email,log_time,status)values ('$msg','$to','$date',0) ";
$this->query_return($sql);
exit();
} else {$date=date('Y-m-d h:i');
$sql="insert into log (log_text,user_email,log_time,status)values ( 'Message Sent Successfully ','$to','$date',1) ";
$this->query_return($sql);
}
the if(!$mail->Send()) condition return true every time even if the email is wrong . it working like to test if the SMTP connection is done or not, I want to know if the email received by users or not.
my second problem is, I have more than 3000 mail address and I want to send email to them at the same time, what is happening is the procedure take a long time and I have to wait for a long time to finish it, how can I do it faster.
For sending to lists, use the mailing list example provided with PHPMailer as a starting point. Also read the wiki article about sending to lists.
For maximum performance, you want to be submitting to a local or nearby mail server, which then takes responsibility for onward delivery. Some messages may fail to be delivered, in which case you will need to rely on bounce handlers; when a message fails to send, it will be returned to the Return-path address, which you can control by setting the Sender property in PHPMailer (by default it uses your From address). Note that as a sender you should never set a return-path header yourself; that's the receiving server's job.
Be warned though: handling bounces is very unpleasant; because bounce messages are fairly "invisible" in normal use, it means that they are extremely variable in quality. For example, it's possible for bounces from some Microsoft Exchange servers to omit the address that the message bounced for! You can handle that scenario (and many other shortcomings of badly-configured mail servers) by using VERP addressing to help you identify original recipient addresses, or even individual messages. However you deal with this, you need to be on very good speaking terms with your mail server. Using an external service to handle sends like this isn't necessarily any better, since they face exactly the same problems, though at least they may deal with much of the unpleasantness of bounce handling.
FYI I run https://smartmessages.net, an email marketing service; it's built around PHPMailer (which is partly why I'm the maintainer), and we can send at about 300 messages/second (using a very good mail server), so decent throughput is entirely possible with PHPMailer.
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 am using the following PHP CODE to send BULK MAIL .But Mails seems to Land in SPAM.I am using "phpmailer" class to send the mail.
require 'mailer/class.phpmailer.php';
$mail = new PHPMailer();
$mail->IsSMTP();
$mail->SMTPAuth = true;
$mail->SMTPSecure = "ssl";
$mail->Host = "smtp.gmail.com";
$mail->Port = 465;
$mail->Username = "info#gmail.com";
$mail->Password = "Bexwa44Puciz"; // GMAIL password
$mail->AddReplyTo('info#gmail.com', 'Info');
$Appname = 'info.com';
$_subject="Newsletter From: ".$Appname;
$ema=",";
$to_bcc=explode(",",$ema);
$mail->AddCustomHeader($headers);
foreach($to_bcc as $tb){
$mail->AddBCC($tb, $dname);
}
$_body ="News content";//$hid;
$mail->FromName = "info.com";
$mail->From="inf#gmail.com";
$mail->Subject = $_subject;
$mail->AltBody = "To view the message, please use an HTML compatible email viewer!";
$mail->MsgHTML($_body);
if($mail->Send()){
echo "Done";
}else {
echo "Failed";
}
I experienced same. My website sends requests for data confirmation to users a few times each day while I do my daily data maintenance. I sent a test message to my Gmail address and found that if you read your mail through Gmail webmail interface it will sometimes tell you Why the message was spammed. Very useful. It gave the reason "A lot of messages from hp19.hostpapa.com were spam". I am on a budget shared server and I assume a hundred other spammers have bought accounts on the same machine as mine and are using it for evil. My site is non-profit so buying a dedicated box to avoid spam is not an option. So...
My solution was to change my CMS to not use PHP mail() at all. Now my CMS simply displays the message and a mailto: link with Subject parameter set. Now my process is to hit CTRL+C, Click the link, CTRL+V, and hit send. Messages are sent from my computer's IP Address (not on any blacklist) using my mail client, Thunderbird.
This takes me just a couple of seconds longer than it did when my CMS used PHP mail() to send the message for me. However I have found I am receiving a lot more replies so I am happy that the vast majority of messages are not getting spam-binned.
I appreciate this manual solution is not appropriate for automated bulk messaging but for small non-profit sites on shared server who trigger each message with a click, I thought it was worth sharing.
There are a number of reasons you could be going into someones spam box. Your email server could be blacklisted due to either you, or another user on your server. You can check it at http://mxtoolbox.com/blacklists.aspx
Also check your SPF records in your DNS
I've used two PHP email scripts and routing it through my SMTP server, when I do this though it sends two of the same email.
When I use mail() this doesn't happen, but I'd much rather use SMTP.
Any ideas why this may be occuring?
If you're setting the 'To' and/or 'Recipient' header multiple times, the SMTP server could interpret that as separate e-mail address, thus you'll receive the multiple e-mails.
I'd recommend using the PEAR Mail class. Very simple to use, and handles much of the work for you. It supports multiple backends including SMTP. Likewise, if you want to expand your class to send HTML emails, the Mail_Mime class handles this very nicely, providing methods to set the plain-text body and the HTML body (in case the recipient doesn't support HTML).
So if you're only using PHPMailer without editing it's code, it's not your script's fault. Maybe check your SMTP server's configuration?
function send_email($from, $fromname, $to, $subject, $body, $alt = '')
{
require_once('class.phpmailer.php');
//include("class.smtp.php"); // optional, gets called from within class.phpmailer.php if not already loaded
$mail = new PHPMailer(true); // the true param means it will throw exceptions on errors, which we need to catch
$mail->IsSMTP(); // telling the class to use SMTP
try
{
$mail->Host = 'localhost'; // SMTP server
$mail->SMTPDebug = 2; // enables SMTP debug information (for testing)
//$mail->AddReplyTo($from, $fromname);
$mail->AddAddress($to);
$mail->SetFrom($from, $fromname);
$mail->Subject = $subject;
//$mail->AltBody = $alt; // optional - MsgHTML will create an alternate automatically
$mail->MsgHTML($body);
$mail->Send();
echo 'Message Sent OK';
}
catch (phpmailerException $e)
{
echo $e->errorMessage(); //Pretty error messages from PHPMailer
}
catch (Exception $e)
{
echo $e->getMessage(); //Boring error messages from anything else!
}
}
That's the current function so far
Based on your code, if it's the class which is at fault, you'd expect to get 'Message Sent OK' twice (I can't see why that would happen though). If you don't, then I'd be looking at your SMTP server (maybe via a call to support).
I'm assuming you've disabled Reply-to to rule it out as a cause in this case? Note: I'm not suggesting that would affect anything (other than you likely being classified as spam).
Incidentally, I moved from PHPMailer to Swift Mailer some time ago & have never looked back. If you don't get any joy from support then I'd try at least testing with Swift Mailer.
I agree with what da5id said, why dont you take the second error message out. Further have you checked the receiver whether they REALLY get 2 messages?