I wrote a mailing script phpmailer/swiftmail supported. Actually small campaigns works fine, all mails arrive to receivers without spam or server resouce problems.
I have question about per connection sending performance. Which way better for sending action? (Subscriber specific different mail body)
First scenario;
- Open Newsletter Data
- Catch 100 Subscriber on task list
- Replace Newsletter Data/Header For Each Subscriber and Save to New Array
- Call PhpMailer - Common SMTP Connection settings
$mail->SMTPKeepAlive = true;
foreach($newArray as $k=>$v){
$mail->AddAddress($k, $v['name']);
$mail->Subject = $v['subject'];
$mail->Body = $v['content'];
$mail->Send();
}
$mail->smtpClose();
Second scenario (Current method on my script, I've call phpmailer class into record loop);
- Open Newsletter Data
- Open Task List 100 record
while($rs = $sql->fetch_assoc()){
Replace Newsletter Data/Header
Call PhpMailer - Common SMTP Connection settings
$mail->SMTPKeepAlive = true;
$mail->AddAddress($rs['mail'], $rs['name']);
$mail->Subject = $campRs['subject'];
$mail->Body = $campRs['content'];
$mail->Send();
}
$mail->smtpClose();
I'm confused about that, if I go for large amount mailing list, any server or script problems may occur?
Best regards!
The vast majority of time spent sending an email is the SMTP communication between your web server and the SMTP server it is talking with.
Both scenarios are likely to be equivalently fast.
If you need to increase performance, look into having multiple threads sending to different email addresses concurrently.
The fastest way to send from PHPMailer is to submit all your messages to a nearby (or on localhost) mail server via SMTP. This is (surprisingly) often faster than calling mail()
, since mail calls the sendmail utility, which just opens an SMTP connection to localhost, at least in the case of postfix.
Don't send directly to recipient addresses because your generation script is not an MTA, and so will lack queueing, deferrals, error handling, subsequent bounce handling etc; use a proper mail server (such as postfix) for that.
Don't create a new PHPMailer instance every time around the loop - it's a waste of resources. Just because it's not as big as the SMTP overhead doesn't mean it's worth throwing away, though Amdahl's law applies of course. Set everything that's common to all recipients outside the loop (e.g. subject). Real threads in PHP are not simple, but you can easily fork multiple processes (more than you have CPU cores; see the pcntl extension) because they will mostly be network-bound anyway. You may find it useful to pre-queue your messages in something like beanstalkd to allow your worker processes to get on with sending as fast as they can.
In your first example, you're not clearing the recipient array between each message, so the first message will go to the first recipient, the second will go to the second and first recipient and so on. You need to call $mail->clearAllAddresses()
at the end of your loop.
You should use SMTPKeepAlive, especially if you're using a nearby relay, as it will reduce SMTP overhead substantially.
For a more complete example, see the example included with PHPMailer.
Do all that and you can easily reach hundreds of messages per second.