tags:

views:

173

answers:

5

What is the best way/class to send a lot of html e-mail?

(Every mail needs to contain information (from a mysql database) that is linked to the address to which it's sent)

+1  A: 

First I store the information I need in a transient table (not temporary, just a normal table that I drop after I'm done).

Then I generate the mails, deleting the processed records as I go, and put the generated mails into an "outbox" table.

Lastly, a script fires off every N minutes taking M records out the "outbox" table: it sends a mail, and then deletes that mail from the outbox table.

Why the transient table? Because the server on which this all happens has very strict time constraints. Using the above method allows me to partially generate the mails; you can safely re-run the generation phase without worrying about duplicate mails being generated. So in spite of the server killing the job, the script makes progress.

The sending script sends (60 / N)*M mails an hour, again to work within the constraints of the server.

Frank Shearar
+1  A: 

I would suggest using the Pear packages Mail ( http://pear.php.net/package/Mail) and Mail_Mime ( http://pear.php.net/package/Mail_Mime).

If you need a queuing system, you could try gearman ( http://gearman.org/)

Dominik
+1  A: 

I use Zend_Mail. The following example (from the docs) shows how to send multiple mails over a single SMTP connection:

// Create transport
$config = array('name' => 'sender.example.com');
$transport = new Zend_Mail_Transport_Smtp('mail.example.com', $config);

// Set From & Reply-To address and name for all emails to send.
Zend_Mail::setDefaultFrom('[email protected]', 'John Doe');
Zend_Mail::setDefaultReplyTo('[email protected]','Jane Doe');

// Loop through messages
for ($i = 0; $i < 5; $i++) {
    $mail = new Zend_Mail();
    $mail->addTo('[email protected]', 'Test');

    $mail->setSubject(
        'Demonstration - Sending Multiple Mails per SMTP Connection'
    );
    $mail->setBodyText('...Your message here...');
    $mail->send($transport);
}

// Reset defaults
Zend_Mail::clearDefaultFrom();
Zend_Mail::clearDefaultReplyTo();

You would just need to modify the loop to fetch data from your database specific to each message to send. Furthermore, you won't need the entire framework to make use of Zend_Mail.

Take a look at: http://framework.zend.com/manual/en/zend.mail.multiple-emails.html

karim79
+1  A: 

I think the first consideration is that is likely to take some time to process - so should not be done as a synchronous web request - see

http://stackoverflow.com/questions/2212635/best-way-to-manage-long-running-php-script

There are then all sorts of issues about creating HTML emails. You might want to have a look at one of the off-the-shelf packages such as phpmailer for generating the email itself. Alternatively, if the content is very complicated, you might consider setting it up as a web page, perhaps using a templating system - but remember to restrict any external access to it. e.g.

<?php
if ($_SERVER["REMOTE_ADDR"]!='127.0.0.1') {
   die ('NO ACCESS!');
}
$send_to=$_GET['email'];
$dbh=mysql_connect(...);
....

Then in your script:

....
$content=file('http://localhost/generate_email.php?email='
    . urlencode($db_row['recipient']));
mail($db_row['recipient'], $subject, $content);

HTH

C.

symcbean
A: 

I like Karim's idea, although I would put a try/catch around the $mail->send($transport) this way you can keep track of what has and what has not been sent, and log it accordingly or mark it in the relevant database.

Catharsis