Laravel Imap connect() slow | reuse? - php

I am using laravel-imap to connect to my email server and get all mailboxes and messages.
I noticed that the connect() method is slow, it takes 4-5 sec.:
$start = microtime(true);
$oClient = new Client([
'host' => env('MAIL_HOST_IN'),
'port' => env('MAIL_PORT_IN'),
'encryption' => env('MAIL_ENCRYPTION_IN'),
'validate_cert' => true,
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'protocol' => 'imap'
]);
// Connect to the IMAP Server
$oClient->connect();
\Log::info('Connect: ' . strval(microtime(true) - $start));
Thats it, there is no additional code. I also use getFolders() and loop through them to get messages.
I count/get unseen messages and do more operations, but they are all fast.
I am asking this, because if I login into my mailbox through the website, the performance is much better 1-2 sec. And the operation is the same, I get the mailboxes and a count on unseen messages. So why it is slow via script?
In case it simply is like that and I cant change it, what are some possible solutions? The only idea I have right now it to reuse the connection in multple functions, so at least I connect only once.

Thanks #everyone who commented.
I can confirm now that there is no issue with the code/package.
It seems that something on my local machine was responsible for the slow connect time.
I dont know exactly what it was, maybe a broken firewall.
I uploaded the code to my server. The performance was much better, it connected immediately.

Related

MS_MAX_CONCURRENT_REQ - VIES VAT Validation

I want to confirm multiple addresses by using https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl.
For some reason, I keep getting the MS_MAX_CONCURRENT_REQ error. I understand the meaning of the error, but I can't understand why it keeps occurring so randomly. I have a sleep of 15 seconds after each call. I could filter out so far that the error occurs mainly with German VAT ID's.
How can I minimize this error without increasing the sleep time?
This is my current SOAPClient Setup.
$client = new SoapClient('https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl', ['trace' => false,'keep_alive' => false]);
$result = $client->checkVatApprox([
'countryCode' => $countryCode,
'vatNumber' => $vatNumber,
'traderName' => $traderName,
'traderStreet' => $traderStreet,
'traderPostcode' => $traderPostcode,
'traderCity' => $traderCity,
'requesterCountryCode' => $requesterCountryCode,
'requesterVatNumber' => $requesterVatNumber
]);
As you can find in the documentation of the WSDL of this service:
MS_MAX_CONCURRENT_REQ: Your Request for VAT validation has not been processed; the maximum number of concurrent requests for this Member State has been reached. Please re-submit your request later or contact TAXUD-VIESWEB#ec.europa.eu for further information": Your request cannot be processed due to high traffic towards the Member State you are trying to reach. Please try again later.
There is nothing you can do about it yourself except periodically trying again until it succeeds. Make sure to use a friendly back-off strategy, such as doubling the sleep time between each request in case of failure (also known as "exponential backoff").

slow php imap email fetching ( >10 seconds )

I am building my own webmail client. Like Roundcube or Squirrelmail, for example. The problem is that my version is very slow, while Roundcube is fast and I cannot understand why is that (Roundcube's source ir very big and I am unable to dive in it..)
The goal - fetch last 50 messages from mailbox. My strategy:
Get number of messages in mailbox by imap_num_msg()
Make array of sequence numbers from max to (max-50)
For each sequence number I ran functions imap_header() and imap_fetchstructure()
It takes 10-15 seconds. It allows me to get each messages title, date, whether is has attachments or not, from, to and other information.
However, Roundcube displays the same info, but load time is only 3 seconds or so. My strategy seems to be very wrong. How can I do it faster? I'm pretty sure that it must be slow to ran imap_header and imap_fetchstructure for each sequence number, but I think there is no other way to get that information.. I'm doing something like this:
function getMessageBySequenceNumber($imapStream, $sequence_number){
$header = imap_header($imapStream, $sequence_number);
$structure = imap_fetchstructure($imapStream, $sequence_number);
/*
... some code parsing $structure to find out whether this emails has any attachments or not
*/
return [
'uid' => imap_uid($imapStream, $i),
'subject' => $header->subject,
'timestamp' => $header->udate,
'unseen' => $header->Unseen,
'star' => $header->Flagged,
'draft' => $header->Draft,
'size' => $header->size,
'has_attachments_bool' => $has_attachments_bool,
];
}
$imapStream = imap_open();
$first_sequence_number = imap_num_msg(); // lets imagine it returns 100
$last_sequence_number = $first_sequence_number-50;
$sequence_numbers = [100,99,88 ..., 51, 50];
$messages = [];
foreach($sequence_numbers as $sequence_number){
$messages[] = getMessageBySequenceNumber($imapStream, $sequence_number);
}
return $messages;
You are fetching the messages one-by-one. This means that your PHP code has to wait for the remote IMAP server to answer you, then your PHP code is going to process the (partial) response, send the data back to the server, etc.
Use an IMAP library which allows batched operations, and read RFC 3501 to understand how to use it.

zend smtp mail crashes after 100+ mails

While sending a newsletter-kind-of mail I came across this weird problem.
In a for loop, I loop through all the users in a database and try to send them all an HTML mail with some basic information. Now the thing is that the first 200 or so mails run fine, but then the script crashes and gives the following error:
Warning: fwrite(): SSL operation failed with code 1. OpenSSL Error messages: error:140D00CF:SSL routines:SSL_write:protocol is shutdown in /opt/zendframework2/library/Zend/Mail/Protocol/AbstractProtocol.php on line 263 Warning: fwrite(): SSL operation failed with code 1. OpenSSL Error messages: error:140D00CF:SSL routines:SSL_write:protocol is shutdown in /opt/zendframework2/library/Zend/Mail/Protocol/AbstractProtocol.php on line 263 Fatal error: Uncaught exception 'Zend\Mail\Protocol\Exception\RuntimeException' with message 'Could not read from smtp.gmail.com' in /opt/zendframework2/library/Zend/Mail/Protocol/AbstractProtocol.php:308 Stack trace: #0 /opt/zendframework2/library/Zend/Mail/Protocol/AbstractProtocol.php(339): Zend\Mail\Protocol\AbstractProtocol->_receive(300) #1 /opt/zendframework2/library/Zend/Mail/Protocol/Smtp.php(358): Zend\Mail\Protocol\AbstractProtocol->_expect(221, 300) #2 /opt/zendframework2/library/Zend/Mail/Protocol/Smtp.php(394): Zend\Mail\Protocol\Smtp->quit() #3 /opt/zendframework2/library/Zend/Mail/Protocol/AbstractProtocol.php(115): Zend\Mail\Protocol\Smtp->_disconnect() #4 [internal function]: Zend\Mail\Protocol\AbstractProtocol->__destruct() #5 {main} thrown in /opt/zendframework2/library/Zend/Mail/Protocol/AbstractProtocol.php on line 308
Now, I'm not to familiar with smtp, ssl & tls but I believe the most important line of the error is: 'Could not read from smtp.gmail.com'. Which doesn't make any sense to me.
We send emails all the time ( lost passwords, registration mails, etc ) and this always (to my knowledge) works fine. The script just crashes after it has sent too many mails in a short period of time.
Ok, that was the problem, now let me explain the setup :)
I'm running Zend 2.2.6 on a standard LAMP server ( PHP 5.3.10 ) and using standard SMTP mail scripts provided by Zend. We're using Google business apps as a mail client. The following is the first couple of lines of the mail script:
<?PHP
namespace Mail\Mails;
use Zend\Mail;
use Zend\Mail\Message;
use Zend\Mime\Message as MimeMessage;
use Zend\Mime\Part as MimePart;
use Zend\Mail\Transport\Smtp as SmtpTransport;
use Zend\Mail\Transport\SmtpOptions;
use Mail\Config\Config;
class Base
{
private $transport, $text, $html, $to, $subject;
public function __construct()
{
$config = new Config();
$transport = new SmtpTransport();
$options = new SmtpOptions(array(
'name' => 'mydomain.com',
'host' => 'smtp.gmail.com',
'port' => 587,
'connection_class' => 'login',
'connection_config' => array(
'username' => $config->username,
'password' => $config->password,
'ssl' => 'tls'
),
));
$transport->setOptions($options);
$this->transport = $transport;
// This happens in different parts of the code.
$this->subject( $subject );
$this->to( $address );
$this->html( $html );
$this->text( $text );
$this->send();
}
?>
What I've tried so far:
Running the script again
This has different outcomes: sometimes it breaks earlier, sometimes it breaks further on, but this proves the script doesn't break on a particular address. I get the feeling that the server has some kind of cooling down: the first run it processes like 200 addresses but when I rerun the script directly after, it can break after 20 addresses. When I try it like an hour later the script breaks after about 200 addresses again.
I've tried to change the ssl option to 'ssl' and the port option to '465' but this has the exact same result.
Is anybody familiar with this problem? I'm not really sure where to look for problems, maybe someone can give me a push in the right direction?
Thanks in advance!
Older site but probably your problem
http://www.serversmtp.com/en/limits-of-gmail-smtp-server
That's because Google places all sorts of limits on the use of its SMTP service by marketers. Those limits begin with a restriction on the number of recipients who can receive the same message. If Gmail's SMTP server detects that your message is going to more than 500 people, it disables your account.

Uable to connect Splunk using php sdk

I am trying to connect Splunk using PHP SDK but I am getting following errors:
https://api.9xnn-6gtz.data.splunkstorm.com:80/services/auth/login Warning: array_shift() expects parameter 1 to be array, null given in /home/u354848659/public_html/oauth/splunk/Splunk/Http.php on line 124
Warning: Invalid argument supplied for foreach() in /home/u354848659/public_html/oauth/splunk/Splunk/Http.php on line 126
Login Failed. Reason: String could not be parsed as XML
$SplunkExamples_connectArguments = array(
'host' => 'example.com',
'port' => '80',
'username' => 'xxxx',
'password' => 'xxxx',
'token' => 'xxxxxxxxxxx',
);
I passed all above details. But when I am trying to run it is not working. Kindly help me out in resolving the issue at the earliest. Thanks
You need to give more code of what you're doing with this. One of your warning messages states you're passing a null, Here you're showing us an array, which gives me some ideas of what might be wrong, but you're not showing us how you use this array. You should try putting together a SSCCE.
From the getting started guide, the example does not pass a token. The reason for this, if you dig into the documentation you'll see that if you provide a token, then the username and password is ignored and you don't need to call login().
Furthermore, using the PHP SDK (and other SDKs), you need to hit the Splunk REST API port, which by default is port 8089, not port 80. This is configurable of course, so you should double check with your Splunk Administrator.

CakePHP emails suddenly stopped working

I have been using CakePHP's email class for close to a year now. The system has been sending html emails without problems. Two days ago I received reports that customers were not receiving their notifications. I noticed as well that I wasn't receiving my admin notifications.
My first thought was something changed with my server (hosted by GoDaddy). I do not believe it is my hosting provider as I have tested a php's raw mail() function and even sent a quick text email through CakePHP's class. I also tested each debug mode and error logs, nothing to indicate an error occurred. Here is the code I have been using (successfully) since a couple days ago. This code is the same around 10 times throughout my app.
$Email = new CakeEmail();
$Email->template('order_status_change', 'default')
->emailFormat('html')
->to($order['Order']['email'])
->subject('blah blah ' . $order['Order']['id'] . ' status change: ' . $status['Status']['label'])
->from(array('myemail#gmail.com' => 'blah blah'))
->viewVars(array(
'id' => $order['Order']['id'],
'firstName' => $order['Order']['first_name'],
'statusLabel' => $status['Status']['label'],
'statusDescr' => $status['Status']['description']
))
->send();
A couple things to note:
I have confirmed that the html template 'order_status_change' and
default layout are in the correct folders (they were working before)
I have confirmed that the variables are all correctly set at the
time of email
If I have to switch to text emails I will but I cannot seem to fathom how the code would suddenly stop working. The only thing I have changed is the debug mode (which I have been doing since the beginning).
Update
Emails stopped working again so I switched over to text mail. However for some odd reason when I put a url in the body (like http://www.google.com) the mail fails. However if I remove just the .com then it will go through. What the hell is happening?
Update 2
This is my current config that will send out text emails without links in them (when I say links I mean a url string)
class EmailConfig {
public $godaddy = array(
'transport' => 'Smtp',
'host' => 'relay-hosting.secureserver.net',
'port' => 25,
'timeout' => 300,
'log' => true,
'charset' => 'utf-8',
'headerCharset' => 'utf-8'
);
}
I confirmed that Go Daddy does not need authentication and the port is 25.

Categories