I'm thinking about how to handle sending large amounts of email from my web applications, and whether there are any best practices for doing so. StackOverflow is already labeling this as 'subjective', which it may be to an extent, but I need to know the most successful way to implement this system, or whether any standardized approach exists.
In my webapp, there are users who are heads of groups of 1 to 10,000 users. This user must be able to email send a message to all of these users through my system. Therefore, my system is responsible for sending up to 10,000 emails to individual users for each group head.
As far as I can tell, there is no rate limit in GMail for sending messages to individuals (although there is a 500 recipient max).
Right now, my current setup is:
When a message is sent through the system, it enters an email queue.
A cron script grabs messages from the queue every few minutes, and sends out those emails.
All email is taking place through GMail's SMTP server.
The actual application doing the mailing is PHPMailer.
This setup, as the user base grows, will probably not suffice. The questions I have are:
Should I be using a local SMTP server instead?
Should I use a mail binary on the local machine instead? I this case, I could probably skip the queue altogether?
Is there an accepted way to do this?
Thanks!
Google App Engine
I would write this in Google app engine (python) because:
It scales well.
It has a good email api.
It has a taskqueue with a good api to access it.
Because python is a real nice language.
It is (relatively) cheap.
PHP
If I would implement it in PHP I would
Find yourself a good SMTP server which allows you to sent this volume of mails because Gmail will not allow you to sent this kind of volume. I am for sure that this will cost you some money.
Find yourself a decent PHP email library to sent messages with like for example PHPMailer like you said.
Use a message queue like for example beanstalkd to put email messages in queue and sent email asynchronously. First because with this the user will have snappier page load. Second with a message queue like beanstalkd you can regulate speed of sending better which will prevent from overloading your pc with work. You will need to have ssh access to the server to compile(install) beanstalkd. You can find beanstalkd at beanstalkd
You would also need ssh access to run a PHP script in the background which will process the message queue. You can find a beanstalkd-client at php beanstalkd-client
from php/apache/webpage
This is the page from which you will sent messages out to user. From this page you will sent message to beanstalkd by coding something in the lines of this:
// register Pheanstalk class loader
require_once('pheanstalk_init.php');
$pheanstalk = new Pheanstalk('127.0.0.1');
$message = ""; // This would contain your message
$pheanstalk->put(json_encode($message);
You have to put messages in message queue using put command
From long running PHP script in background:
The code would look something like this:
// register Pheanstalk class loader
require_once('pheanstalk_init.php');
$pheanstalk = new Pheanstalk('127.0.0.1');
while(true) {
$job = $pheanstalk->reserve();
$email = json_decode($job->getData());
// Sent email using PHP mailer.
$pheanstalk->delete($job);
}
Like I am saying it is possible with both PHP and Google app engine but I would go for app engine because it is easier to implement.
With an email count as "high" as 10.000 a day, I wouldn't rely on GMail (or any other) SMTP. Not that they can't handle it, obviously they can handle A LOT more. But they possibly don't want to.
Having a local SMTP server is IMO the way to go :
It's pretty easy to set up (just DON'T let people use it without a strong authent scheme)
Most modern MTA handle sending queues very well
You won't have to deal with GMail (or others) deciding to block your account someday for quota reasons
Gmail and Google Apps limits you to around 500 emails a day. I'm not sure how that combines with the 500 recipient max, but if you want to send 10 000 emails you'll probably want to find another mail server. I personally use a local server or the ISP or datacenter's SMTP.
If you are sending that many emails, I would recommend using the queue so the user's isn't sitting there waiting for the email to be sent.
Be very careful that your domain doesn't get blacklisted as a spam domain. If it does, you can expect most of your emails to be blocked, support, sales, etc. Which could in turn be very expensive.
You may instead want to use a service like AWeber. Not only are they setup to handle these amounts of emails, but they can probably give you more metrics than you can implement on your own.
I'm not sure if it's publishe anywhere, but from experience I can tell you that Gmail will put a fifteen minute or so freeze on your account if you start sending hundreds of messages at a time. This happened to me last week. I think you should host your own SMTP server. Using the mail() function often will put your mail in someone's spam folder.
Just install Postfix on the local machine, or a machine on the same LAN for maximum access speeds. Make sure it is well secured from the outside, and quickly accessible from the inside.
Then code your PHP script to directly inject the emails to the Postfix queue. That shall dramatically increase the processing speed of mail delivery.
Related
I will start by saying that I am not having an issue with sending successful emails with PHPMailer. It is working as intended in that regard. The PHPMailer script is working and this may very well not even be a PHPMailer related issue. However, there is a 20 second "processing" delay that is happening everytime I attempt to run the very basic script.
This essentially botches any kind of front-end experience which is causing an issue for my intended use case (a contact form). Note that my testing was done solely on the provided Github recommended example code, no external code was added beyond necessary configuration.
The script is sending a basic singluar email. No batch or mass sending is required. My code and PHPMailers debug log are posted below. Please check out the debug log - after the initial connection is open, there is a 20 second delay between connection opened and the first "220" status. I am not versed enough to understand exactly what this means and I was hoping to get some clarity on that. A simple google search does provide that 220 means Domain Service is Ready. But what is really happening in these 20 seconds? What is causing the hang? 20 seconds is too long to send a single email.
I have been researching delays on SMTP and PHPMailer issues for over a week now and I cannot find any good information that provides a straight forward answer to this issue. I have however found recommendations to:
Use a localhost to recieve mail. (I cannot do this, I don't have the capability to run my own mail server 24/7)
Design a Mail Queue and batch send on a different thread(cron job, etc) - Note that I have done this before for a much larger project. But considering this use case is going to be for a basic contact form, I feel like that is a bit overkill. Maintaining a database to send a singular email should not be necessary. I also have no need for mass sending. Every email will always be a singular email and ideally it would be recieved immediately, not on timed intervals, ie. cron job.
Your Web Hosting is garbage. (It is likely bad) I don't really have experience with who is the best or the worst. I am hosted through Hostinger and unfortunately I am essentially locked in for 4 years without taking a loss.
--
Is there anyone that understands what is actually hapenning here? Maybe another person that had a similar issue? Someone that can take the debug logs at more than face value and could provide any clarity on what is causing the 20 second delay on every single of the script. Or any potential solutions that allow me to continue using SMTP but without the delay. It is almost always exactly 20-21 seconds.
(Currently when manually disabling SMTP from the script, it eliminates the 20 second delay, but it essentially reverts the code to scrictly use the php mail() function, which I hear is bad practice. I would love to be able to retain best practice, which I hear is SMTP/PHPMailer)
This is an anti-spam technique called “greetdelay”, and will be a deliberate choice implemented by your mail service provider. The SMTP spec says that clients must wait for the server to respond before starting an SMTP transaction. Badly-behaved clients (such as spam scripts) don’t wait, and the server will drop the connection and possibly block subsequent connections from that IP if they start talking too soon.
PHPMailer is well-behaved (it will wait, as you’re seeing), however this really highlights that SMTP is not a good thing to use during interactive HTTP request processing, which is mentioned in the PHPMailer docs.
The right solution to this is to run a local mail server to act as a relay. Submission will be effectively instant as far as your page is concerned, and the mail server will handle onward delivery, including the greetdelay. It will also handle more complicated problems like greylisting, network outages, mail server throttling, etc.
Mail servers like postfix are not difficult to configure to act this way, but that’s really suited to docs, tutorials, or a question on server fault. I’m not clear why you can’t do this. If you have root access to your own VM, and you already know that outbound SMTP traffic is permitted, it should not be a problem.
When an order is placed, the order details are sent via email to the customer and seller but it takes too long to send the email due to which the order placement takes time. What should be done to make the process faster?
I guess you should implement a Queue, for example [https://laravel.com/docs/5.2/queues]
Install a local mail server (I'd recommend postfix) and send to it from PHPMailer using SMTP. That is the fastest way of getting a message on its way. It means that your script does not have to deal with DNS lookups, remote connections, authentication, and it hands off control to the mail server that deals with all those things asynchronously, including queuing, retrying, bouncing etc.
You can implement queuing in PHP, but it's really the wrong tool for the job. Regardless of the implementation, it will be much, much slower and more error-prone than using a mail server, and more to the point, it's software that you will need to write, test and maintain.
I assume I will need to point MX records at my server (LAMP), -- what processes the incoming e-mail message?
Are there any existing PHP libraries to do this?
You don't want to use PHP as a mail server. You've got two options:
Set up a classic email server (postfix, sendmail, exim, etc) that delivers new messages to a local mailbox. Use IMAP or POP to access that mailbox from PHP, and pull messages out of it. Alternatively, this same method may be used with (virtually) any remote mail service as well, thus relieving you of the duty of administering a mail server. (Which you'll likely find to be not worth it for the sake of one mailbox.) This method would usually be run via cron every few minutes, so you're not going to get "instant" activation if that's a requirement.
Set up a classic email server (postfix, sendmail, exim, etc) and use procmail or similar to intercept messages at delivery time, and pipe them to a PHP script. This method will fire the script the instant the email arrives, so you'll have no lag time like in #1. However, it's more difficult to configure (especially if you haven't maintained a mail server before) and won't work with most external hosted email services.
Use a pipe alias to receive the emails.
I would recommend you to do processing in Perl (python is also ok, but Perl has very similar syntax to PHP), which is much more suitable for the task. You can also find a lot of libraries through CPAN there.
http://search.cpan.org/~rjbs/Email-Simple-2.100/lib/Email/Simple.pm
I have php script to send 1,00,000 mails everyday..
it just runs all emails in loop and invoke mail() function..
I can't use mailinglist manager because. each mail has different content, unique clickurls.
is it the proper way to send mailers?
thank you
Sending thousands of emails from a PHP script is a bit messy at best. One of the real problems is to ensure that the script keeps running as long as necessary to do the job. You can do that if you keep resetting the time out for PHP and you have permission to do that, but there's still going to be a host of other problems.
The best thing to do is to build the email message and the list of recipients in PHP then hand the task of mailing off to something else - either a shell script or some kind of application that gets spawned off and detached from PHP in some way.
Also have you tried using SwiftMailer etc?
It should be alright, as long as you provide users a link to unsubscribe from the mailing list. Make sure you're on good terms with your SMTP server provider. Otherwise, the server will get blacklisted.
EDIT: Many SMTP servers have limitations on the number of emails you can send out in an hour. Find out this limit for your SMTP server and put a small delay() in your loop after sending out each email.
php mail(...) function?
My company has a website built with PHP. We use the built-in PHP email functionality to send thousands of emails to subscribers on a daily basis.
This is a terrible idea. It chokes out our server, and takes hours to complete the whole batch.
Now I've looked at mass mailing services like MailChimp (which would replace our current system of sending the same email to many people), but what I think I'd really like to do is to set up a somewhat-sophisticated notification system.
Rather than send a mass email to each person each time something important happens, I'd like clients to be able to customize the rate and content of the emails that they receive.
Even using this new idea, we're talking about A LOT of emails being sent.
So my question is very specific: I have a rough idea of how to build the system internally, but what is the best way to send out all of these emails?
Bullet points to consider:
Sometimes emails' contents are identical across recipients, but many of them will be customized per-user (they choose what they get notified about, and sometimes it is aggregated).
I want a system that is not going to choke the server, and will complete in a decent amount of time. I don't mind going with a third-party service (even a paid one) if that is what it is going to take.
The system should hook into PHP easily, or the API or whatever should be relatively easy for me to call from your typical web server.
We have a dedicated server and full control over it (so we can install apps, services, whatever).
Any kind of detailed tracking information (opens, clicks, etc) is a huge plus.
These emails are sometimes time-sensitive (so can't take all day to send).
Thoughts? Tips? Point me in the right direction?
EDIT
To clarify:
I can do these on my own:
maintain user list
handle email content generation based on user preferences
And need something else (app, third-party service, w/e) to:
accept email content and addresses and actually send the emails out
provide tracking data (opens, clicks, etc). The more detail the better.
I'm leaning towards a third-party service, since I'm not sure any app can avoid choking the server when sending thousands of emails (though I wouldn't consider myself an email expert so I could be wrong).
We use the built-in PHP email functionality to send thousands of emails to subscribers on a daily basis.
This is a terrible idea. It chokes out our server, and takes hours to complete the whole batch.
Why do you think that your problems are anything to do with the built-in PHP email function? It's a very thin wrapper around 'mail' or a simple SMTP client depending on what platform you are running on.
When you say it chokes your server - do you mean your email server? Your web server? something else?
There's nowhere near enough information here to make a proper diagnosis but it looks like the problems are of your own making - sure, there are lots of people out there who promise to sort all your problems for you if only you buy their latest product/service. But there's a very good chance that this isn't going to solve your current problems.
Can you tell us:
what OS the PHP is running on
how you invoke the code to create the emails
what the mail config in the php.ini file is
what type of MTA are you using? On what OS?
how is youe MTA copnfigured - does it deliver directly or via a smart relay?
which server is getting "choked"?
What anti-spam measures do you have in place for outgoing mail?
Then tell us what you've done to diagnose the fault and why you think its specifically on sending mails.
C.
I'd recommend using the third party mailing service Silverpop, or something like it. We've used them for a few years and have been fairly satisfied. They already have relationships with the major email clients (AOL, Yahoo!, Gmail, etc.) and they do a good job of telling you if the stuff you're sending is likely to be classified as SPAM.
They have a fairly extensive API that uses XML HTTP/HTTPS requests that can tie in to existing systems. You can use it to remotely trigger emails, schedule mailings, customize email contents, set up, manage and query huge lists of recipients, run batch processes, etc.
It isn't a perfect service, but compared to a lot of others out there, they do pretty well. I have had very few complaints about them thus far.
I usually got around this by having a mail "sending" function that dumped the emails into a queue (database table) with a job that ran every couple of minutes, grabbed the next x emails in the queue, sent those out and marked them as succeeded. That's the simple bones of it. You can then add on handling for email failures, returned mail, etc in version 2.
Use Google AppEngine if you are worried about scalability & customization: it provides an email API and you can interface anything to it provided it is through an HTTP interface.
Of course, this is just a suggestion - disregard if this doesn't fit.
Quite possibly not ideal, but if you're looking at large scale transmission there are commercial solutions such as Port 25's PowerMTA that can be set up to effectively transmit the contents of a given folder.
As such, you'd simply use PHP to create the personalised MIME formatted raw data for each outbound email and place these in a temporary directory prior to transmission. (I've written such a system in the past and you'd be surprised at the PHP's ability to grind out the emails, even with quite complex text & HTML emails with images as inline-attachments, etc.) Once you were ready to transmit, you'd then move the files en-masse to the PowerMTA monitored folder and it would take care of the transmission.
Depending on how you look at it the benefit/problem with such a solution is that you'll need to build trust relationships with people such as AOL, MSN/Hotmail, etc. to ensure that your mail server isn't blacklisted due to user's reporting email as SPAM. (That said, this will likely be a factor with any DIY solution.)
Why not keep your PHP system and use a third party SMTP service? Some reliable companies offer the use of e-mailing-only machines at reasonable prices, e.g. Dewahost who I am planning to use.
Also see the question Third Party Email Senders and my answer there.
Check out Campaign Enterprise for a possible in-house solution.
One of my friend uses http://www.tailoredmail.com but i havn't used it personally
I know this is an older question, but I just wanted to suggest SendGrid which is essentially an "Email Server as a Service" allowing you to send emails with cost per email.