Slow mail() function workarounds - php

I have a php script which sends user a mail if his purchase is successful. The problem is it the page loads slow due to mail(). I know there are ways like putting the mails in a database table and then using a cron job to send them but the frequency of purchase can be high and I want the mail to be sent right away, so that doesn't look like a good option.
The purchase request gets processed by the same page from where he purchased and he can only do so once. The user doesn't control any part of mail other than the purchase details. I thought of using Ajax, the script would send the data to client side and call a ajax function which then calls another mail script but this would let user know what is being sent and can be tampered. Is there any other way I can use Ajax safely without letting user know whats being sent and where? And are there any better workarounds?

mail() should return immediately upon queuing the message to your mail server, which (generally) should take no time at all, so I think your problem here is definitely the mail server and not your PHP. I'm guessing that the mail server you're submitting to is running some anti-spam checks, like reverse DNS lookups. It might also be throttling you based on usage. Can you try sending through another mail server to verify?
Also, if you have shell access, try sending a message from the shell (e.g., echo test | mail -v -s test me#whatever.com) to see what it's doing and how long it takes.
Edit: Just noticed your comment re: Windows. In this case, at least you can try a telnet from the PHP server to port 25 on the mail host to see how long it takes to connect and get the 220 greeting header. (I bet you'll connect immediately but won't get the 220 header for a while.)

You're on to the right idea. Here's what I would do in this scenario:
The user makes a purchase (no ajax unless you want to at this point)
In processing that purchase an email is inserted into the email table with an "id" & "sent" column plus all the other stuff.
User is brought to a success page
The success page kicks off ajax in the background to send the email with that id from the db - and doesn't care about the result
The php page in charge of emailing sends the email and marks the sent column
If someone ever makes a call to your database with an id that's not sent, that email needed to get sent out anyway, so it's ok. If the id doesn't match or the sent column is marked true, you can ignore it. No worries about people trying to send spam using your system.

Related

Laravel functions time out and Jquery scripts response take along time

I build an online shop when my customers buy something from the shop, when they reach checkout, I use hyperpay API, so when they pay by visa, its a request from my server to hyperpay server then I have the result if it the success I send an email message to customer and store payment and products data in another server with api.
not always but sometimes, my server stop after sending emails, or stop before sending data to the second server, or I get a response from hyperpay and the operation cut, I don't know why.
So I think it's a time-out problem, but I am still not sure.
and another problem, my jquery scripts response take a long time.
so I want to know, the problem with my codes or from my server?
There could numerous reason behind for that to happen. As per your info, it looks like the time to send the email is taking longer or sometime it halts. Then you can do this things step by step:
Check laravel.log inside storage directory to check if any relevant information.
If the SMTP or whatever means of connection you are using to send the email needs to debugged.
You should send heavy tasks such as email sending to queue: https://laravel.com/docs/8.x/mail#queueing-mail so the other tasks can be executed without any problem while the SMTP call is being made.
If none of this help, you should look into your both web server and mail server

Do I need to whitelist any IPs to use Mandrill API?

I am trying to send mail using Mandrill API and I have got following responses :
[{"email":"_emailid_","status":"queued","_id":"772237d78ce74e5c9bd8ccbd9a1cfb8c"}]
{"email":"_emailid_","status":"scheduled","_id":"10a0b596a95e44ddb5e8cf504e3899ce","reject_reason":null},
{"email":"_emailid_","status":"scheduled","_id":"b699d58f021b43b2a0b25d801d1b4f91","reject_reason":null}
But I am not getting any mail on the email addresses sent. Please help.
Do I need to whitelist the IP of the system from where I am doing the curl call ?
You do not need to whitelist any ip addresses, you however do have to configure the DNS records for your email domain properly, head over to the domain settings page in the mandrill control panel for more information.
Everything seems fine.Either your you are not providing correct email to api or mail are coming to your spam folder.You need to check mail from address which you give to the api.
It looks like at least the last two were scheduled, which means they won't send immediately, but rather at the scheduled time in the future. You'll probably want to double check the time and date that they were scheduled to be sure.
For the first one, there are a number of reasons that emails are queued, including if they have attachments that need to be scanned, or if they're part of a large/batch API call. We'd need more information about the API parameters that you passed to determine the reason for it being queued and/or what happened once it was queued.
You can search your Outbound Activity by the recipient email address, subject line, sender, and a number of other criteria for emails that have been sent. Messages that are scheduled but haven't sent yet cannot be searched since they've not been processed. For any messages that have sent, click on the word "Delivered" on the Outbound Activity page to see more details about the response that Mandrill got from the receiving server when delivering the message.

How can I make email transactional in PHP and MySQL?

I want to send email to my app users ensuring that every email is sent only once.
I will be recording the email transmission in a database.
If I use this order of operations:
Insert into database
Send email
Commit
There is a chance that script times out just after sending the email (step #2) and before doing the commit (step #3). In that case the change in step #1 will not be committed and email sending job won't be able to know that the email was successfully sent last time so the same email will be sent again.
Is there a way out or do I have to live with occasional duplicate emails?
To make a long story short: you can't make email transactional.
At best you know that your smtp server recieved your request to sent the message. You have however no way of knowing whether it got sent, was received or bounced.
So your best bet, as you already suggested, is to live occasional duplicate emails. It will be a very rare event anyway.
You can use MySQL transactions for this, basically it prepares all your queries and executes them when you tell it to do so.
So you prepare the queries before sending the mail, then commit it after sending it.
More info
http://dev.mysql.com/doc/refman/5.0/en/commit.html
Alternatively you could set the mail as pending, and afterwards update it as completed. Then run a cron job that kills pending jobs that have been running for a certain amount of time, or try to reprocess them.
well you can make a column status which can be enum or int with values representing sending, failed, sent_successfully
Now, you do this:
Insert the data before sending the mail. And set status to sending
Send the mail
based on the result in step (2), update the row either failed or sent_successfully.
You might also like to have a column tries and a batch process that sends failed mails at every 30 minutes, if tries < TRY_THRESHOLD. And then, set status to failed_permanently or sent_successfully and log the error.
Just got some time to think over my own question. Here is what I think now:
The email sending steps in question were:
Insert into database
Send email
Commit
Email cannot be made transactional because the step #2 (above) is not part of the transaction even though it is done while the transaction is active.
These steps can help ensure that any failed email-sending attempts is retried but cannot guarantee that an email is not sent more than once. This situation could only be improved if the email sending engine is transaction-aware. Such an engine would (atleast) do the following:
Accept email job submission but don't send the email until the commit is performed
Make the commit fail if the email is not sent.
Cancel the submitted job if the transaction is rolled-back
I am not aware of any such email server.
Nishant, in his answer suggested following steps:
Insert the data before sending the mail. And set status to sending
Send the mail
based on the result in step (2), update the row either failed or sent_successfully.
These steps also cannot ensure duplicate sending of email due to script timeout for the same reason as noted above.
So far, I think, I will just have to live with occasional duplicate emails.

PHP Pear Mail on reception

I would like to know if there's any way I can send a automatic answer to client when I open them mail who's comming from my website ?
Anybody have sugestion ?
Has asked here is more information:
I Have a online cart who send me a
e-mail when I receive order, I would
like that when I open the order
there's a email automaticly been sent
to the client to tell him that i've
took his order. Like when you open a
e-mail and that tell you that the
sender asked to receive a confirmation
that you've received the mail.
For resume I would like that when I receive a order mail, and open it there anoter email who's sent directly to the client telling him that i've openned his order and processing it.
You can create a script on your website, for example 'mysite.com/confirmread.php'. In this script you can write code to send an e-mail to the customer.
Then, in the e-mail that is sent to you on the customer's order, you can create a link towards this script. You can click the link then, for example: 'mysite.com/confirmread.php?ordernr=2883992' or 'mysite.com/confirmread.php?mail=customer#domain.com'.
Another way might be an automatic script that is fired once you open your e-mail. I'm thinking of a javascript / ajax script, which calls the same script (confirmread.php), but without you having to click the link. I'm not sure to which extent scripting is supported in e-mail clients (think of the difference between online vs offline mail clients).
You can, of course, also reply the e-mail to another address of your own. For example sale#mysite.com. This address can then be read by the PHP script. But I guess that's more complex.
You have to hook into the IMAP server and check the status of the emails periodically. And when on changes its status from unread to read you can send an email. But this means you have to track the status of the emails in a separate database against this DB you have to check then if the email was already read.
Better solution:
Add into your order mail a link at the bottom which links to a script which sends an email to the customer. So, you have to manually trigger this email but its very easy to implement.
Example in pseudo code:
Link at the bottom of the order email:
yourserver.com/sendEmailThatOrderWasReceived.php?orderid=123&customerEmail=test#example.com
Script on your server:
<?php
mail($_REQUEST['customerEmail'], 'Order '.$_REQUEST['oderId'].' is confirmed', 'Thank you for your order, we had a look at it.');

How to handle mail delivery errors with PHP

I am building a symfony module for sending newsletters. the idea is to build a queue list of adreeses to receice the mail and then ,with a cron job, send let's say 50 at a time.
What i don't now how to do is to read the Mail Delivery reports that are sent back by the server when an email adress doesn't exist or the mail is full. The idea is to store these error reports an clean the adress list.
Any ideea how to implement that?
When reading the "bounced inbox", you can use a class like this to actually parse the mail and see what status was returned (e.g. permanent or temporary error):
http://www.phpclasses.org/browse/package/2691.html
To really parse a mail accurately will give you a hard time, as not all mailservers are alike and some will send you a "mailbox full"-error marked with a "permanent" flag while others may tell you that the error "user doesn't exist" is "temporary".
I tried a solution for this once and ended up setting up my own parser connected to a huge database containing possible server replies (and their "real" meaning :).
You can use a reply to address while sending. So bouned emails will be sent to this id. You can also create another PHP script which will read this "reply to" email inbox and get the id from it. You can then remove this id from the list you have.

Categories