Safe way to send mail via PHP to many users - php

Let me explain what I mean in my title. Let's say, that for example I'm creating a small e-commerce system for one web shop/catalog. There's a possibility for customers to choose, do they wish to receive newsletters or not. If they do, then logically thinking the newsletters should be send immediately as the newsletter is formed and ready.
Of course it can be done simple by fetching all specified user e-mails from database and using for cycle to send mail via mail function in loop, but problem is that I was told, that this is bad practice. The simple and not cheap way would be purchasing internet service for sending newsletters, but what for the php programmer is needed, then?
So I ask you humble comrades, what from your point of view might be a solution?
NB! You probably won't believe me, but it is not for spamming.
UPD: I might have explained myself wrong, but I would like to hear a solution not only about the correct way to send mail, but also about the correct delivery. Since not every mail send is always delivered.
Of course there are some reasons, which are unpredictable. For example someplace along the way something broke and mail was lost (if such thing is possible), but there are also other reasons which are influenced maybe from server or elsewhere. Maybe there is need to talk with hoster about it?

There is no reason why you couldn't write it in PHP, although I would not make it a part of a webrequest / HTTP process. I've successfully implemented for give or take 500,000 subscribers per mailing (depending on local data available, as this was a location-specific project). It was an in-house project, so unfortunately no code/package for you, but some pointers I came across:
Setting up delivery
Started out with phpmailer itself, to take care of formatting, encoding of contents and headers, adding of attachments etc. That portion of it works well, and I wouldn't want to write that from scratch.
The 'sending' of an email itself is just setting some flag in a database whether / how / what should be sent to (a portion of) the subscribers.
After this flag is set, it will automatically be picked up by a cronjob, no more webserver involved.
I started out with a heavily polluted database with millions of email addresses, of which a lot were obvious not valid, so first thing was to validate all email addresses for format, then for host:
filter_var($email, FILTER_VALIDATE_EMAIL); over the subscribers (and storing the result obviously) got rid of the first few hundred thousand invalid emails.
Splitting out the host (and storing the host name) from the emails, and validating that (does it have an MX or at least an A record in DNS, but keep in mind: you can send email to an IP-address foo#[255.255.255.255], so do keep those valid)) got rid of a good portion more. The emailaddresses here are not permanently disabled, but with a status flag that indicates they're disabled because of the domain name / ip.
Scripts were changed to require valid emailaddresses on subscription / before insertion, this nonsense of 'you aint gonna get it#anywhere' subscription-pollution in the database was just ridiculous.
Now I ended up with a list of email addresses that had the potential of being valid. There are in essence 3 ways to detect invalid addresses (keep in mind, the all can be temporary):
They are denied immediately by the server.
The earlier determined server just doesn't listen to traffic.
They are bounced long after you thought you delivered them.
Strange thing, the bounces, which every emailserver seems to have another format forand were a hell to parse at first, ended up actually pretty easy to capture using VERP. Rather then parsing whole emails, a dedicated email address (let's call it mailer#example.com) was configured to rather then deliver to mailbox, to pipe it through a command, and if we sent email to user#server.tld, the Return-Path was set for mailer+user=server.tld#example.com. Easily parsed on receipt, and after how many bounces (mailbox could not exist, mailbox may be full (yes, still!), etc.) you declare an emailaddress unusable is up to you.
Now, the direct denial by the server. Probably we could have gone with properly configuring some MTA and/or writing plugins for those, but as the emails were time-sensitive, and we had to have absolute configurable control per mailing over last usable delivery time (after which the email was not longer of interest to the user), throttling per receiving server, and generally everything, it would take about the same time writing a mailer in PHP which we knew better, that used the SMTP protocol directly to socket 25 on receiving servers. With a minimum amount of effort the possibility of another transport then the default choices in PHPMailer was built-in. The SMTP protocol is actually quite simple, but there are some caveats:
A lot of receiving server apply Grey Listing: most spambots will not really care if a specific mail arrives, they just churn them out. So, if an unknown / not yet trusted sender send mail, it will be temporarily rejected. Catch that (usually code 451), and place the email in the queue for later retry.
A mailserver, especially of the larger ISP's and free services (gmail, hotmail/msn/live, etc.) will not stand for a torrent of mail without fighting back: after the first couple of hundred / thousand, they start rejecting you. More about that later.
Getting speed
Now, we had a delivery system that worked, but it needed to be fast. Sending a 10,000 emails in an hour is all fine if you only have 10,000 addresses to send to, but the minimum we required was about 200,000 per hour. Start of it was a dedicated server (which can actually be pretty low powered, no matter what you do, most of time taken in delivery of email is in the network, not on your server).
Caching of IP's: remember all those IP's we requested from hostnames in email addresses? We stored those obviously, and looking up their IP's again and again causes considerable lag. However, IPs may change: a DNS record there, another MX at another place... the data gets stale fast. Most of the time the server isn't actually sending anything (subscription newslettters come in bursts obviously), a low-priority cronjob is running checking all hostnames with a stale IP (we chose older then 1 day as being stale) for an IP address, including those which previously had none (new domains get registered all the time, so why shouldn't a domain become available the day after someone already enthusiastically subscribed with his/her brand new email address? Or server problems with some domain are solved, etc.). Actually sending the emails now required no more domain lookups.
Reuse of the SMTP connection: setting up a connection to a server takes relatively a large portion of the time to deliver an email when you're talking directly to port 25. You don't have to setup a new connection for every email, you can just send the next over the same connection. A bit of trail-and-error has resulted in setting the default here to about 50 emails per connection (assuming you have that many or more for the domain). However, on failure of an emailaddress closing and reopening the connection for a retry sometimes helped. All in all, this really helped to speed things along.
Some obvious one, so obvious I almost forgot to mention it: it would be a waste to have to create the body of the email on the spot: if it's a general mail, have the body ready (I altered PHPMailer somewhat to be able to use a cached email), possibly days before (if you know you're going to send a mail on Friday, and your server is idling, why not prepare them on Wednesday already? If it's personalized, you could still prepare it beforehand given enough time, if not, at least have the non-personalized portions waiting to go.
Multiple processes. Did I mention much of the time it takes to deliver email is spend on the network? One mailing process is not nearly getting the most from your emailserver, barely noticable load and the mails are trickling out. Play around with a number of processes mailing different portions of the queue to see what's right for your server/connection, but remember 2 very important things:
Different processes make you very vulnerable to race conditions: be freaking absolutely sure you have a fullproof system that will never send the same mail twice (thrice, of even more). Not only does it seriously annoy users, your spamrating goes up a notch.
Keep domains together where possible: randomly picking from the queue you will lose the advantage of keeping an open connection to the server receiving email for the domain.
Avoiding rejects
You're going to send a lot of mail. That's exactly what spammers do. However, you don't want to be seen as a spammer (after all, you aren't, are you)? There are a number of mechanisms in place which will thoroughly increase your trustworthiness to receiving servers:
Have a proper reverse DNS: processes checking the DNS belonging to the IP that is sending the email like it very much if the second level domains match: are you sending mail on behalf of example.com? Make sure your server's reverse DNS is something like somename.example.com.
Publish SPF records for your domain: explicitly indicate the machine used to send your bulk email is allowed & expected to send mail with that From / Return-Path headers.
remember rejects: servers don't like it to tell you again and again that different email addresses don't exist. Either automated mechanisms, and even human admins, blocked our server while we worked through all non-validated email addresses that did (no longer) exist. We didn't employ a double opt-in until later, so the database was polluted with typos, people switching IPs and thereby email address, prank email addresses and so on. Be sure to capture those invalids, and given enough or sever enough failures, unsubscribe them. They're doing you no good, they're hogging resources, and if they really want you mail and the mailbox becomes available later, they'll just have to resubscribe.
DKIM is another mechanism that may increase your trustworthiness, but as we haven't implemented it (yet), I cannot tell you much about that.
MX records: some servers still like it if your sending server is also the receiving server for the domain. As it was at the time, we had only 1 MX, and as the mailing server was still not that very busy, we dubbed it the fallback MX server for the domain. The normal MX server was not the server sending the subscriptions, as it is very irritating to be temporarily blocked by a server you're trying to send an important email to (clients etc.) because you already sent a load of less important mail. It does have the highest preference as receiving MX, but in the event it would fail we had the nice bonus that our subscription sending server would still be fallback for delivery, so in crisis we could still get to it, preventing awkward bounces to customers trying to reach us.
Tell them about you. Seriously. A lot of major players in free email addresses like live.com offer you the opportunity to sign up in some way, or have some point of contact to go to for help & support if your emails get rejected. I you have a legitimate reason to send so many emails, and it is believable you have that many subscribers, chances are they seriously up the number of emails you can send to their server per hour. A meager 1,000 may become somewhere in the ten-thousands or even higher if you are persuasive and honest enough. There may be contracts, requirements you have to fulfill, and promises you must make (and keep) to be allowed this. ISP's are a brand apart, and every other player is different. Don't bother calling them usually, because 99% of the time the only numbers you can find will only have people willing to troubleshoot your internet connection, which understand (or are allowed) little else. An abuse# email address is a good place to start, but see if you can delve up a more to-the-point email address up from somewhere. Be precise, honest and complete: roughly how many subscribers of you have an emailaddress with that ISP, how often are you trying to mail them, what are the errors or denials you receive, how is the subscribe & unscubscribe process like, and what is the service you actually provide to their customers. Also, be nice: how vital sending those mails may be to your business, panicking about it and claiming terrible losses does not concern them. A polite statement of facts and wishes, and asking whether they can help rather then demanding a solution goes a very long way.
Throttling: as much as you tried, some server will accept only a certain amount of mail per hour and/or day from you. Learn those numbers (we're logging successes & failures anyway), set them to a reasonable default for the normal domains, set them to agreed upon limits for bigger players.
Avoiding being tagged as spam
First rule: don't spam!
Second rule: ever! Not a 'once off', not a 'they haven't subscribed but this may be the deal of a lifetime to them', not with the best intentions, people have had to ask for your emails.
Obviously set up a correct double opt-in subscription mechanism.
PHPMailer does set proper headers on its own,
Set up an easy unsubscribe mechanism, by web (include a link to it in every mail), possibly also email and customerservice if you have it. Make sure the customerservice can unsubscribe people directly.
As said earlier: unsubscribe (excessive) fails & bounces.
Avoid spammy 'deal of a lifetime' wordings.
Use url's in your emails sparingly.
Avoid adding links to domains outside your control, unless you are absolutely sure you can trust them not to spam, if even then...
Provide value to the user: being tagged as spam by user-interaction in google/yahoo/live webmail clients seriously hurts future successes (on a site note: if you sign up for it, live/msn/hotmail will forward all mail to you send by your domain which is tagged as spam by users. Learn to love it, and as always: unsubscribe them, they clearly don't want your mall and are hurting your spam rating).
Monitor blacklists for your IP. If you appear on one of those, it's bye bye, so immidiate action in both clearing your name and determining the case is required.
Measuring success rate
With the whole process under your control, you are reasonably sure the email ended up somewhere (although it could be the MX's bitbucket or a spam folder), or you have logged a failure & the reason why. That takes care of the 'actually delivered' numbers.
Some people will try to convince you to add links to online images to your emails (either real or the famous 1x1 transparent gif) to measure how many people actually read your email. As a high percentage blocks those images, these numbers are shaky at best, and our believe is we just shouldn't bother with them, their numbers are utterly unreliable.
Your best bet for measuring actual success rate are a lot easier if you want the users to do something. Add parameters to links in the mail, so you can measure how many users arrive at the site you linked, whether they performed desired actions (watched a video, left a comment, purchased goods).
All in all, with all the logging, the user-interface, configurable settings per domain / email / user etc. It took us about 1,5 man-month to build & iron out the quirks. That may be quite an investment compared to outsourcing the emails, it may be not, it all depends on the volume & business itself.
Now, let the flaming begin that I was a fool to write an MTA in PHP, I for one thoroughly enjoyed it (which is one reason I wrote this huge amount of text), and the extremely versatile logging & settings capabilities, per-host alerts based on failure percentage etc. are making live oh so easy ;)

Using something like Swiftmailer, PHPmailer or Zend_mail are much better alternatives to using the simple mail() function as it can be easily marked as spam. There are simply too many issues with mailing that need to be considered - most of these are solved by using pre-existing libraries.
Just a few problems that need to be addressed when sending mass emails manually:
Using incorrect headers.
Processing bounced messages
Timing out of script due to an influx of emails.
Edit:
Probably not the answer you're looking for. But, I would strongly suggest you invest in something like Campaign Monitor or Mail Chimp. Since this process is not for educational purposes, but commercial, I would strongly suggest the above services.

I got your question, but before replying, let's me go to usual considerations. First, I strongly recommend using a service like Mail Chimp. It's kinda free for small jobs, and has many cool features, like tracking back how many emails were open, how many were clicked, how many failed on deliver... Think about make a favor to yourself and don't reinvent the wheel.
Now, for getting to know purpose, let's go to the reply to your question.
First thing to have in mind is to enforce your list to be a good one. How to do that? Well, for a good list, I mean a valid email addresses list. Simple put a newsletter form on your page, with just one field (maybe a captcha, but I don't think it is necessary).
Save all input to a database table, with a field "isValid" set as false by default, and any kind of unique hash. Then you send a confirmation email, with a link (with the hash generated) for confimation which when clicked will make the "isValid" flag true, and a link for cancelation (ALWAYS send this cancelation link within all your emails).
This is what stores and serious sites do. Anything that force your customers/visitors to receive is a bad moral practice (ie, spam).
Second thing, use a good hosting service. Too cheap services usually are used by spammers, and major email services blacklist everything coming from those addresses.
I know, you should be asking yourself if I get your question wrong. No, I don't, technical stuff comes now.
Why is a bad practice put a mail function inside a for loop? Simple. Because function mail do several operations everytime it is called. PHP, will open a connection to mail server, send data to be parsed, ask for sending, register mail server status, close connection, bubble up status to finish the mail function you called and clean up the memory mess.
This connection overhead is the problem people state as bad practice from programming point of view. Using a SMTP/IMAP solution is better because it optimizes this process.
A little bit down on tech stuff I see your questions about delivery. Well, as I said, you have some ways to ensure you emails list is good enough. But what if another exception occurs, like having a blackout + no-break failures on customer server?
Well, PHP keeps the status of "asking mail server to send, mail server sent". If the mail server sent your message, PHP will return true. Period.
If client was unable to receive, or reject, you should check email headers and email status. These are on email server. Once again, these informations can be accessed with SMTP/POP/IMAP extensions, not with mail function.
If you wanna go further, read IMAP docs, search for email classes (phpclasses.org, pear and pecl are best places to look into).
Extra tip: RFCs can be useful, as you can understand better what email servers really talks to each other.
Extra tip 2: Access you gmail or ymail and check for your sent/received messages for their "full version" and read its headers. You can learn a lot with them.

Via SMTP Authentication: http://www.cyberciti.biz/tips/howto-php-send-email-via-smtp-authentication.html

Just use PHP Mail and study IMF and how to build custom headers you can attach the fourth parameter, exmaple follows
<?php
// multiple recipients
$to = 'aidan#example.com' . ', '; // note the comma
$to .= 'wez#example.com';
// subject
$subject = 'Birthday Reminders for August';
// message
$message = '
<html>
...
</html>
';
// To send HTML mail, the Content-type header must be set
$headers = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
// Additional headers
$headers .= 'To: Mary <mary#example.com>, Kelly <kelly#example.com>' . "\r\n";
$headers .= 'From: Birthday Reminder <birthday#example.com>' . "\r\n";
$headers .= 'Cc: birthdayarchive#example.com' . "\r\n";
$headers .= 'Bcc: birthdaycheck#example.com' . "\r\n";
// Mail it
mail($to, $subject, $message, $headers);
?>
Source: http://php.net/manual/en/function.mail.php

create a mail queue subsystem which might include tables such as mail_queue, mail_status, mail_attachments, mail_recipients and mail_templates etc...

You might consider PHPMailer
http://phpmailer.worxware.com/index.php?pg=exampleasendmail
You can add multiple recipients and a special callback function for handling the returning messages for every single mail sent. (for an example visit the link)
I Don't think that catching a "mail delivery failed" error mail is possible via php except that you are using PHPMailer via SMTP and once in a while watch for any returning message form any recipient in from your outgoing email collection.

Related

How can I make sure that I don't send any email to customers from testing site in php

I have to make the copy of my existing site for testing purposes at home. I have got the permission from the company.
But in the database I have the more than 10,000 customer records with email.
I don't want to accidentally send any emails to them while i make some mess with site during various tests.
whats the best way to avoid that
I do need the email functionality for testing other stuff
The most idiot-proof method you can use is often the best for these things as we all have those days where anything that can go wrong will. It's best to be careful, even borderline paranoid, when a mistake could really ruin your day.
Here's a few methods that might work:
Impotent Configuration by Default
The absolutely safest system is to keep the SMTP server configuration for the production server on the production server and only on the production server. Your development copy would have some other SMTP configuration, like to a testing GMail SMTP account. Usually GMail limits you to 500 emails per day on ordinary accounts so you'll quickly hit this limit if you really screw things up somehow.
Replace Customer Emails in Database
Another thing to consider is scrubbing all of the customer emails in your database, removing them and replacing them with mytestaccount+0000#gmail.com and mytestaccount0001#gmail.com if you care to actually receive and inspect them, taking advantage of the fact that the + and subsequent content is ignored for delivery to GMail, effectively giving you unlimited potential email addresses.
As an example:
UPDATE customers SET email=CONCAT('mytestaccount+', customer.id, '#gmail.com')
You'll have to customize this to be whatever email address you want. One advantage to doing this is that you won't have a valuable list of customer email addresses sitting on your development drive and any associated back-ups of it. To be thorough you should probably scramble the hashed passwords as well just so the database is basically worthless to potential hackers. Too many times passwords get scraped from backups that aren't secured properly.
Render Customer Emails Undeliverable
The next best approach is to add ".test" to the end of every email in the system you don't want to send so that it will hard bounce instead of going to someone's inbox.
This is basically a one-liner:
UPDATE customers SET email=CONCAT(email, '.test')
Over-Ride Email at Delivery Time
You can always include some conditional logic like where you will deliberately substitute the recipient of the email message. This can be risky because there's a chance that you might disable that switch by accident, though, so as always, be careful.
In practice this looks something like:
if ($i_should_not_spam_customer_accounts_accidentally)
{
$mail->to = "nobody#nowhere"
}
Use an API Driven Service
Some Mail Service Providers have an API that can help you when testing email messages. I'm a co-founder at PostageApp and the service was designed so you can send messages using an API key that's specifically configured to receive but not deliver emails. Other services like MailGun can be used in a similar fashion.
No Single Point of Failure
It isn't a good feeling being one logical test away from tragedy, though. You should make sure there's several things that have to go wrong before you have a fiasco.
If you don't want to change your code or the data in the database, and if you are using postfix in your local machine, you can rewrite all the outgoing mail to your addres. More info: http://www.postfix.org/ADDRESS_REWRITING_README.html
Change All the Email Address, For Example email#domain.com to email#domain.com. After the test completes you can replace # with #.

PHP E-mail Efficiency (BCC vs individual e-mails)

Our web-based PHP software currently sends out a newsletter to anywhere between 1-2000 recipients. Often the newsletter has a PDF attachment (15KB-5MB). The newsletter does not need to be customized to the individual recipients.
Question: Is it better to send one e-mail that has each recipient blind carbon copied (BCC) or to generate a unique e-mail message for each recipient?
Considerations:
- Which option puts less stress on the mail transfer agent?
- Which option is more efficient programmatically?
- Which option is less resource intensive?
- Are there any limitations to either option? (e.g. BCC having a maximum number)
I've tried Google and I just can't find anyone that has a definitive opinion based on empirical evidence. It's actually hard to find anyone that has an opinion at all.
THANKS: To everyone who contributed to answering this question. Greatly appreciate the feedback from people to ensure we're doing things properly!
Generate a single email per recipient. Use the To field instead of BCC to make it personal.
Advantages
The mail queue will accurately reflect what is happening.
You can distribute the load to multiple email servers.
You can personalize the "To" "Subject" "Body" etc.
You can use tracking URL's.
Mail servers often have a BCC limit per message. You will not hit a limit if you send a single message at a time.
BCC emails typically remain in the queue until all deliveries are complete. It is rare, but we have experienced (with the latest qmail) that sometimes a single recipient will respond with an error that confuses the mail server to send it again, fail, again, fail...until we remove it from the queue. This gets people very upset.
Disadvantages
PHP script has to work harder to generate the individual requests.
There are surely other advantages and disadvantages, but that is the list I follow.
UPDATE: Regarding the PDF attachment, I would recommend providing a download link unless it is crucial to include it with the email.
PDF attachments make an email look more suspicious to spam/virus scanners, because spam is known to try to exploit vulnerable versions of Acrobat. Those PDF attachments might make your newsletter more likely to end up in the recipient's Spam folder.
Large PDF's (1+mb) are not friendly to people checking their email with slow connections or constrained devices such as smartphones.
A link is much smaller than the attachment. You will save upwards to 13GB of bandwidth if you leave off that 5MB attachment!
It depends on MTA infrastructure at your site. If the box that is running your web app is set up to forward all e-mails to some e-mail hub at your ISP then BCC is definitely the advantage. Otherwise, it may save some bandwidth for you but not necessarily (it depends on the actual addresses you send to) Also, I would recommend you not to attach the pdf to the message but place it on the web server and include hyperlink in e-mail. As I got your message is a bulk message. I believe that many people do not read your messages even they opted in to receive.
Instead of attaching such a large file (which might also be rejected by some MTAs because of the size) upload it somewhere on a publicly accessible place (i.e. a web server) and send a simple link to all of the email recipients which they can use to view the PDF.
The good thing about this approach is that you save loads of bandwidth and even if you need different PDFs for every recipient you could still use it.

PHP - Bulk mailing and checking for server responses

We send a lot of emails to a lot of our users (ranges in 20k+ per day). One of the major problems we face are invalid or dead emails - sometimes our users delete their accounts, change their email address without updating their profile, or our email database builders simply caught emails that are invalid or no longer active. These unresolved returned status messages keep not only piling up on our webmaster account, but also waste precious server resources and flag us as spam more often because of the repeated attempts.
Now, while our mail server is set up to keep trying to send an email to an address that returns "temporarily unavailable", I would like to be able to receive status messages into PHP immediately after sending. For example, when my Sender class sends an email, I would like to know the status message that was returned - whether the email is no longer active, or the server does not exist, or the email was simply moved to another address.
Naturally, I want to be able to receive a status message of a delayed email as well. So if an email does not get sent because the recipient email address is temporarily unavailable, I would like to get the "temporarily unavailable" message back into Php, but I would also like the real one to get passed back once the sending succeeds (for example, if the email does go through 2 days later).
Is there a library that would help me achieve this? What are the most common approaches to this problem, if any?
Like most questions about PHP and mail this is mainly about the MTA.
Bulk emailing is a science in its own right (OK, so more like a black art) and at these kinds of volumes you need to up your game a lot if you want reasonable rates of deliverability.
But back to the question.
An awful lot of this is about how you configure your mail server. AFAIK, most MTAs will only send back a failure message when the message is removed from the queue (e.g. after the last attempt at delivery). Which gives 2 options for tracking each attempt:
1) parse the log files
2) set the number of attempts to 1 (and optionally handle re-queueing yourself).
Given that a message can fail to be delivered after it has successfully departed from your server, it makes a lot of sense to use delivery status notifications (i.e. bounce emails) to track the progress of messages - so using option 2 avoids having to build different code for handling different scenarios.
Without knowing what OS this is running on, nor which MTA, it's impossible to give more specific recommendations.
symcbean's answer gives many theorical inputs and several means to handle your case.
Besides, maybe you could have a look on how other libs or builtin functions work. For instance, you can have a look at :
PHPList
Extended PHP Mailer
i used PHPList some times ago but it was already a reliable solution. I don't know the PHP Mailer class but i may be worth a try (or a least a look on how they deal with similar issues).
Regards,
Max

php bulk mail limit

I need to send about ~20k emails to potential clients and need the best way to avoid:
server crash
being put in spammers list
I've searched a few forums and people said it's best to send mails in 1k packages
but my question is what delay between sending each 1k should I set? I mean 1k/day or 1k/hour or 1k/min etc.
I recently had to build system to do so, here is the solution we chose :
1- The management system setup emails and store them in a database.
2- We setup a no-reply account on our mail server to get the bounces back.
3- We build a small code over the great mailing library swiftmailer (swiftmailer.org).
4- We run the script we build through a cron and send mails in packages of 50 per minute (hotmail will most likely flag email as spam if too much emails are sent from the same adresse/server in the same minute). We store each swiftId i the mail database
5- At the runtime of the mail sending script we check for bounces or other errors in our no-reply mailbox and flag our messages in our mail table accordingly (status : 1 - success, 2 - invalid email, 3 - bounces)
6- We sync back our data (upon user accessing the section of the system) in the main system when they have a status and that the last change was made at least 10 minutes in the past to limit the change of states in the system. (the synchronisation script can change the status of an item in the main system, but the 10 minutes delay reduce the risk of changes)
I think your 1K thing is a red herring. There have been a number of similar questions asked with good answers, have a look though these:
How do you make sure email you send programmatically is not automatically marked as spam?
Avoid being blocked by web mail companies for mass/bulk emailing?
Sending solicited mass email
Note that the primary requirement to avoid being your mail being marked as spam is NOT TO SEND SPAM. Your description sounds a lot like spam, in which case no amount of clever tricks will help you.
Providing you are not actually sending spam, a professional organisation such as http://www.campaignmonitor.com/ or http://www.mailchimp.com/ is probably cheaper than the amount of time you will require to do this properly.
Your best bet is to farm it out to specialists.
There's a whole load of subtleties about mass mailing that are easy to get wrong.
Best case is that your server gets put on an email blacklist - meaning all your mails from now on get binned as spam. Worst case is fines and/or jail time, depending n your local laws and the laws where the recipients live.
When it comes down to being put in spammers lists, the question is, how many (very) similar mails from the same sender reach a certain host. If you flood yahoo-mail-accounts with thousands of mails within a short period of time, you can be sure to be on their list shortly.
What you can do: pay a professional service to send out the mails for you. They usually have contracts with the big providers so you don't end up on anyones blacklist (will cost you money, though).If you're sending them out from your server, make sure the "reverse DNS lookup" for your server is activated - I don't know if that's checked any more but it gave me a hard time once.
If your mails don't need to be sent out at a certain time, I'd send the mails in very small packages, e.g. not more than one mail per second, not too much in a row. Then wait for a certain amount of time and repeat until all mails have been sent.A company I used to work for would send out not more than 200 and then wait half an hour before the program proceeded. As far as I know, we never ended up on some blacklist.
The spam list has been well answered, but as far as not bombing out your server, the answer is generally the same. Use a service that does this for you.
If you absolutely must send this volume of e-mail on your own, you want to do it with some sort of background service. This can be written in anything (provided that you don't simply buy one of the many pieces of software off the shelf), but ideally it should be multi-threaded.
Your management application should not be sending these e-mails... only queuing them up in a database or something.
Again though, why reinvent the wheel? You'll save yourself a lot of time by going with something off-the-shelf.

Emails are put into spam - wrong headers problem

this is my first question on StackOverflow, but I think that we'll both come to the happy end. :) The problem is: I've got newsletter script written in PHP and when I send those emails to the various accounts they are put in the spam folder. Here is what I get in mail headers:
X-Spam-status: Yes, score=5.01 tagged_above=1 required=4.5
tests=[HTML_FONT_SIZE_LARGE=0.001, HTML_MESSAGE=0.001,
HTML_TAG_BALANCE_BODY=0.712, MIME_HTML_ONLY=1.105, MISSING_DATE=1.396,
MISSING_MID=0.14, RCVD_IN_BRBL_LASTEXT=1.644,TO_EQ_FM_DOM_HTML_ONLY=0.001,
T_FRT_CONTACT=0.01] autolearn=no
And here are my questions:
What is that and how to fix status RCVD_IN_BRBL_LASTEXT? I haven't found anything informative googling that phrase.
How to fix MISSING_DATE status? I've put in the code generating whole email:
$mailHeaders[] = "Date: ".date('Y-m-d H:i:s', time());
but with no success. "Date" fields comes only as H:i (13:45, for example) - Thunderbird 3.1.3 FYI. Searching on SO didn't help me. I have also tried adding Delivery-Date status - still nothing.
RCVD_IN_BRBL_LASTEXT indicates that your email has been flagged by the Baracuda RBL, which is a service which tracks IP addresses that have been known to send spam.
Possibly your newsletter has been flagged up as spam in the past? or possibly its the ISP you're using to route your email which has been responsible for some spam. Either way, this particular point isn't an issue with your mail headers.
The missing date is the important one which will bring your points below the threshold.
The date format you need looks like this: Date: Wed, 15 SEP 2010 14:12:27 +0100
Most of that is self explanatory (the last bit is the time zone), and it looks like you know your way around the PHP date function, so hopefully that should sort you out. But I found this page helpful as a walk-through of a legitimate email header format.
The challenge with bulk email sending is that there's so many different factors that could throw you off and get you blocked as spam. Headers tell you what's going on, but in the grand scheme of things they're not one of the biggest challenges.
My company sends 50000+ emails per week, sometimes that many per day. Here's what we've learned:
1) If your server hasn't established "reputation" with email hosts, you're more likely to get flagged. There's no great way to establish it, though sites like Socket Labs simply throttle down new clients in the beginning and after 60-90 days release that throttle to allow more email to go through. As many emails as Socket Labs processes, it tells me it's a valid practice.
1a) Monitor the RBL list to ensure you're not on it. If you do get flagged (happens to just about everyone at some time or another) aggressively work to get yourself off ASAP. Contact the RBL in question and work with them to quickly right the situation.
2) The "big guys" including Gmail, Yahoo, AOL, and MSN are sensitive to being rapidly hit by the same host in succession. My company has chosen to overcome this by keeping track of who our email processes are sending to via a "log" If the next email has the same domain as the previous sent, we wait a period of time. If not, we fire at will. It prevents our system from sending more than 1 email per X seconds to the same host, and has meant our emails are getting through at a very high rate.
3) AOL mail is borderline worthless. I saw a stat once that someone had proven something like 20% of email sent to AOL just "disappears" I'm not sure if it's that high, but I know we have nothing but problems with getting AOL email through...it's the nature of the beast. The good news is that AOL is on its way out, so we shouldn't have to deal with it on this level too much longer.
4) The obvious step is to ensure that you're doing the best you can to stay CAN-Spam compliant. Include a real-time opt-out, company information in the footer, and don't try to deceive with your message.
5) Finally, don't send email to people who haven't requested it. It seems like a silly easy step, but it's abused SO much. You won't be flagged as spam if you send to people who want your email...it's that easy. If you get a bounce, process it out of your list immediately so that you're not trying to resend to a bad account.
Good luck.
The X-Spam-Status header is being added by a Barracuda spam filter, and what you're seeing is diagnostic information it attaches to explain why it marked the message as spam.
Barracuda is a rules-based engine, and as you guessed, the score you're getting (5.01 in the example above, though you say you fixed the date so your score may be lower) is above the allowed threshold.
Since the highest-weighted signal is the RCVD_IN_BRBL_LASTEXT field, you're likely getting dinged primarily because your IP address is in their Real-time Block List (RBL). It's possible you can find the data source that hates your IP -- check http://www.spamhaus.org/lookup.lasso to see if it's Spamhaus that has tagged you -- and convince them to remove you, but more likely the best path is to use an IP that's already been groomed to have a good reputation. Two providers you may wish to check out are http://sendgrid.com and http://authsmtp.com, both of whom will allow you to proxy your traffic through their servers (assuming your content isn't likely to be voted as spam).
Hope that is helpful.

Categories