First of all, I would like to thank StackOVerflow and its users for helping me solve a number of technical problems. I created this account today since I could not see similar problem being addressed.
The problem - I am stuck with a problem with sending emails in PHP CodeIgniter. The function $this->email->send() is taking around 3-4 seconds each time to execute.
We have a social platform where users come and post things. Every time the user uploads a new update we want to send an email to him/her.
The problem is the send email function takes around 3-4 seconds and we would love to bring it down under 1 second.
IS there any way wherein we can execute the send email process in parallel ? Say a python code which runs continuously to fetch new updates and send emails to those users. Any better method than that ?
Technology stack - PHP CI, MySQL, Apache, Windows
This is the email code that gets called on every new update -
$config = Array(
'protocol' => 'smtp',
'smtp_host' => 'smtp.gmail.com',
'smtp_port' => 587,
'smtp_user' => 'mailid#gmail.com',
'smtp_pass' => 'password',
'mailtype' => 'html',
'charset' => 'utf-8',
'smtp_crypto' => "tls"
);
$this->load->library('email', $config);
$this->email->set_newline("\r\n");
$this->email->set_mailtype("html");
$this->email->from('mailid#gmail.com', 'Support');
$this->email->to($this->session->userdata['email']);
$this->email->subject('You have posted a new update');
$this->email->message('Please login to check your new update. Do not reply to this email. For any issues reach out to email#emailid.com');
if (!$this->email->send())
{
show_error($this->email->print_debugger());
}
else
{
echo true;
}
If your function is working faster but email sending is slower, it must be problem for your smtp connection. Either your server is not much faster to connect SMTP quickly or the SMTP you are using bit slower to response.
In that case, try with a gmail SMTP and see the result.
It's my suggestion to store the emails in a database and send the emails using a cron job.
The uploading user should not wait to send emails one at a time .
If you need code for a cron job or an smtp mailer, add a comment to this answer.
Related
I have created a codeigniter 3 helper to send mails from different modules of application. I am using my gmail account to send all the mails and it works perfectly fine except that i have to store my gmail password inside the helper php file.
$config = Array(
'protocol' => 'smtp',
'smtp_host' => 'ssl://smtp.googlemail.com',
'smtp_port' => 465,
'smtp_user' => 'saurabh#gmail.com',
'smtp_pass' => 'my password',
'mailtype' => 'html',
'charset' => 'iso-8859-1'
);
$this->load->library('email', $config);
$this->email->set_newline("\r\n");
$result = $this->email->send();
How can i avoid storing the plain text password in the above code while still able to use my gmail account. Same is true for my database password, I am storing plaintext database password in the codeigniter's database.php configuration file. How this can be avoided ?
Database password cannot be hidden or connvert it in other way. But how ever no one can access your config files with the browser.
And in email password can be done. You can keep it in database and on mail sending place you can call it.
FYI - your project files cant access with browser or any other. Thats the reason we use frameworks. Bcz its security level is higher than normal oop pograms.
So your password and other stuff will not be public at any how.
The only way I see it possible is to use Gmails OAUTH mechanism instead of smtp method. here's the link to the api https://developers.google.com/identity/protocols/OAuth2 and some examples https://developers.google.com/gmail/xoauth2_libraries#php_sample. Rest assured you will have to put your plain password somewhere in your app (either in DB or at a location in file system which no one has access to except apache) or write a crypt function (even this function requires/ outputs the plain password)
I'm trying to send email using codeIgniter's email library.
Below is my code
$config = Array(
'protocol' => 'smtp',
'smtp_host' => 'smtp.myserver.com',
'smtp_user' => 'xxx#myserver.com',
'smtp_pass' => '********',
'mailtype' => 'html',
'wordwrap' => false,
'charset' => 'utf-8'
);
$this->email->initialize($config);
$this->email->set_newline("\r\n");
$this->email->from('xxx#yourserver.com', 'xxx');
$this->email->subject('blah blah');
$this->email->message('a simple html message');
$this->email->to('any#validemail.com');
$this->email->send();
Code is on diffrent server & it is using different server's mail (Yes, two different domains)
For example code is on yourserver.com and it is using smtp of myserver.com
It was working fine till morning. but now i'm getting
554 SMTP synchronisation error (see attachment for full print_debugger() output, I hide some sensitive information. i can trust you guys but not all)
Thanks.
I tried very hard to get the issue, but i have not enough access to get details of error log or mail logs, So i changed my code as below and it worked
$config = Array(
'mailtype' => 'html',
'wordwrap' => false,
'charset' => 'utf-8'
);
$this->email->initialize($config);
$this->email->set_newline("\r\n");
$this->email->from('xxx#yourserver.com', 'xxx');
$this->email->subject('blah blah');
$this->email->message('a simple html message');
$this->email->to('any#validemail.com');
$this->email->send();
I would like to say thanks to #cherrysoft for his help offering. I'm posting it here so it may help someone.
thanks to all.
This isn't really a CodeIgniter problem and there could be quite a few things going on here but the first thing I would do is to make sure that the hostname on the web server is set correctly and that your mail server recognises this host. You should tail the mail.log on your mail server (if you have access to do this) whilst you are sending mail from your web server and you will get some more insight as to what is going on. When you have the mail log entries post here and we can look at the issue in more depth.
I have created a web application as such in the application I require to send to send users their passwords if they have forgotten them. Now I use a gmail account to send the email. When I send the email locally from my machine using XAMPP everything works fine and it delivers as expected. When I look to put the php script onto a Hostgator server and try send the user their password I can't. But the reason I think this is happening is because Gmail immediately send me the following:
Someone recently used your password to try to sign in to your Google Account myemail#gmail.com. This person was using an application such as an email client or mobile device.
We prevented the sign-in attempt in case this was a hijacker trying to access your account. Please review the details of the sign-in attempt:
Tuesday, January 21, 2014 1:42:56 PM UTC
IP Address: 198.57.247.245 (gator3281.hostgator.com.)
Location: Los Angeles, CA, USA
If you do not recognize this sign-in attempt, someone else might be trying to access your account. You should sign in to your account and reset your password immediately
Based on this email I would assume that Gmail is touchy that hostgator is trying to send an email via them. My problem is I don't know how to fix this problem (This is my first time doing something like this) As such I was using a PHP framework called codeigniter and here is the code used to send the email (Note this code works more than fine locally i.e. I dont think there is anything wrong with the code):
public function SendEmailValidate($email,$subject,$message,$type)
{
$config = array(
'protocol' => 'smtp',
'smtp_host' => 'ssl://smtp.googlemail.com',
'smtp_port' => 465,
'smtp_user' => 'myemail#gmail.com',
'smtp_pass' => 'mypassword',
'smtp_timeout' => 30,
'mailtype' => $type
);
$CI = &get_instance();
$CI->load->library('email',$config);
$CI->email->set_newline("\r\n");
$CI->email->from('myemail#gmail.com','Book Bay');
$CI->email->to($email);
$CI->email->subject($subject);
$CI->email->message($message);
if($CI->email->send())
{
return true;
}
else
{
return false;
}
}
Any help on this matter would really help, thanks
its in your gmail settings; you need to allow your website to send emails;
to do so go to https://accounts.google.com/DisplayUnlockCaptcha and click continue; then useyour website to send email an email; and google will detect your login attempt and allow you.
Im using swiftmailer for sending mails via PHP. Most times it works fine. But sometimes, my mail Mails are landing in Spam-Folder.
Here my code, which sends the mails
function sendMail2($from,$to,$subject,$body,$attachment=NULL) {
require_once 'include_apth/swiftmailer/swift_required.php';
$transport = Swift_MailTransport::newInstance();
$mailer = Swift_Mailer::newInstance($transport);
$message = Swift_Message::newInstance($subject);
$message->setFrom($from);
$message->setTo($to);
$message->setBody($body, 'text/html');
if($attachment) {
$message->attach(Swift_Attachment::fromPath($attachment));
}
if(#$mailer->send($message)) {
return true;
}
else {
return false;
}
}
any ideas, why its landing sometimes in spam-folder?
I was having the same issues with deliver-ability of emails. Getting all of the correct DNS settings, headers and the like isn't enough.
Most, if not all cloud-hosting, and home-ISPs IP ranges are on various lists of IPs from where emails are not expected to be sent from - and so they are more likely to be marked as spam.
The easiest way to solve that is to use a dedicated service where emails are well known to come from, and that the company spends a great deal of effort to get email delivery properly configured.
There are a number of well known such companies, many of which offer significant free tiers, as long as you are well behaved and send appropriate emails that aren't being marked as spam, or bounce. If you are hosted on Amazon EC2 for example, you can get over 60,000 emails delivered per month via AWS/SES. My my own systems, I have an account, currently free, with Mailgun, and a 'limit' of 10,000 email sends per month.
For Swiftmailer, there are a number of plugins that can, for example, use a HTTP API to send email to the service, which then is sent over SMTP in the usual way - with greatly improved deliverabilty.
Add the below code and it will work perfectly
$headers =& $message->getHeaders();
$headers->addIdHeader('Message-ID', "b3eb7202-d2f1-11e4-b9d6-1681e6b88ec1#domain.com");
$headers->addTextHeader('MIME-Version', '1.0');
$headers->addTextHeader('X-Mailer', 'PHP v' . phpversion());
$headers->addParameterizedHeader('Content-type', 'text/html', ['charset' => 'utf-8']);
Solution get from the below question
Swiftmailer mails go into SPAM Folder
i am trying to send something like news letter Via Zend_Mail but after 12 mail i got this message
Fatal error: Maximum execution time of 30 seconds exceeded in C:\Program Files\Zend\Apache2\htdocs\forga\library\Zend\Mail\Protocol\Abstract.php on line 321
my Code is like:
$smtpHost = 'smtp.gmail.com';
$smtpConf = array(
'auth' => 'login',
'ssl' => 'tls',
'port' => '587',
'username' =>'xxxxx#xxxxx.com',
'password' => 'xxxxxxxx'
);
$transport = new Zend_Mail_Transport_Smtp($smtpHost, $smtpConf);
foreach($users as $user)
{
$mail = new Zend_Mail();
$mail->setFrom("noreply#forga.com", 'Forga');
$mail->setSubject($subject);
if($html=='on')
$mail->setBodyHtml($message);
else
$mail->setBodyText($message);
$mail->addto($user);
$transport->send($mail);
}
From the script timeout you get I'd assume your host is slow to send eMails and simply cannot handle bulk sending of eMails. You could increase the time until a script times out with
set_time_limit — Limits the maximum execution time
A more elegant way would be to send the eMails in separate processes asynchronously. Check out
Mysteries of Asynchronous Processing by Padraic Brady Part 1, 2 and 3.
Part 3 deals with eMails specifically.
Check out my answer on another posting on parallel processing in PHP Multithreading/Parallel Processing in PHP. I think it's relevant. If you need something to be done outside of the individual request it should probably be passed to some kind of queue.
Do you manage the web server yourself?
Up to version 5.3.0, set_time_limit() only works in safe mode. (deprecated in recent PHP).
You can set safe mode in php.ini.
See also max_execution_time in php.ini.
By the looks of your code your sending a single email to each on individually from your server.. Try doing the following.
$smtpHost = 'smtp.gmail.com';
$smtpConf = array(
'auth' => 'login',
'ssl' => 'tls',
'port' => '587',
'username' =>'xxxxx#xxxxx.com',
'password' => 'xxxxxxxx'
);
$transport = new Zend_Mail_Transport_Smtp($smtpHost, $smtpConf);
$mail = new Zend_Mail();
$mail->setFrom("noreply#forga.com", 'Forga');
$mail->setSubject($subject);
$html=='on' ?$mail->setBodyHtml($message) : $mail->setBodyText($message);
foreach($users as $user)
{
$mail->addto($user);
}
$transport->send($mail);
No i might actually be wrong with this because the other email addresses may be visible to all recipients, im not sure if that's only the concerning section of the email.
Regards