4

The goal

I am trying to create a PHP script which emails a rather large (6MB) PDF file to users on a website that request it. A user enters their email address into a form, submits the form, and the file is sent to them via a PHP Mailer instance. The user is displayed a success page on submitting of the form.

The problem

After the data is submitted via the POST method, there is a long pause and the server eventually returns a 404. However, the email is received perfectly fine with the PDF attachment after a few minutes.

Troubleshooting / attempted solutions

I attribute the problem to PHP Mailer simply taking too long a time to send the email because of the large attachment. The server times out and resorts to returning a 404. In the mean time, the script eventually finishes processing and the email is thereafter received.

If I remove the attachment and just send a blank email, the script loads very quickly and shows the success/confirmation page.

I have considered creating a redirect, but everywhere that I have found explanations on how to achieve a redirect in PHP, it is said that you should kill the original script (which I do not want to do).

The question

How do I allow the email script to take its time to run, while immediately displaying a success message to the user so they are not left confused?

Community
  • 1
  • 1
JacksonHunt
  • 582
  • 6
  • 21

5 Answers5

1

This is a task for a message queue. Store all information needed to send the mail in a queue and have a background task taking this information and sending your mails. If the insertion to the message queue succeeded, display the success message to the user.

If you do not have access to background scripts (e.g. shared hosting), you can still have a direct response. Just use ignore_user_abort(true) and send a correct Content-Length header. Browsers will trust that header and show the response, while your script can continue running and send the mail.

kelunik
  • 6,750
  • 2
  • 41
  • 70
1

Another solution: Do a quick trick instead of attaching a big file in the email instantly. Give them the download link of the PDF File. Thus the content becomes too short. But no attachment.

You can effort to create unique URL to download the same PDF file by different users.

Otherwise, email queuing is good, as discussed.

Bimal Poudel
  • 1,214
  • 2
  • 18
  • 41
0

Instead of emailing the file immediately, store the request in a database with all the details you need in order to send it. Then you can use a cronjob/scheduled task to regularly (every minute if you like) check the database for any outstanding requests and send the emails in the background.

rjdown
  • 9,162
  • 3
  • 32
  • 45
0

As no codes were provided, you can use AJAX to call your script and show a success message wherever you want. The script will be called, the user will get the message and as soon the script finish, the user will receive the email.

Of course, the success message shouldn't be implemented in the AJAX handlers, otherwise the message will be delayed as well.

Berriel
  • 12,659
  • 4
  • 43
  • 67
0

This is a good use case for an asynchronous job queue such as Gearman or Beanstalk.

You have to run an external worker process that will wait for tasks from the job server.
On the web server side, just create the task, send it to the job server to dispatch it to the worker process, and exit the PHP script.
The worker process will then proceed to send the mails while the web server can continue serving HTTP requests.

SirDarius
  • 41,440
  • 8
  • 86
  • 100