Page 1 of 2
personalized mass mailing
Posted: Thu Apr 24, 2008 10:53 am
by nonsii
Hi!
First of all, i want to say that i am amazed about your system. We have our own small content management system and now want to expand the system with a newsletter tool, so that everybody can send out personalized mass mailings.
most of the work is done, even the check mail to admin works fine and goes through everywhere.
now i have to do the last step - the sending mechanism. i read through the forum and did not find any appropriate solution, and maybe ia ma too dumb to understand the decorator plugin thing.
short for understanding: the content and the recipients come from a database. the newsletter ist fully generated and stored in a variable.
the personalized infos are gender, title, name, and some data for user statistics (userid, newsletterid, linkid,...) which have to be integrated in every single mail. so is it a good way to send it in a loop, where i replace the infos via php?
maybe the plugin way is much better...but actually i don't see how i should do that...
the last step, dealing with bounces and failed recipients would be the best idea if i save the data to db? so that it can be overworked at anytime after the sending?
thanks a lot in advance!
nonsii
Re: personalized mass mailing
Posted: Thu Apr 24, 2008 4:53 pm
by gmbzcode
This sort of thing is best done by an email list server. Unfortunately, the one I am most familiar with is PHPlist and it currently uses PHPmailer so you sacrifice functionality to go with that.
Re: personalized mass mailing
Posted: Fri Apr 25, 2008 2:33 am
by nonsii
thanks for that...
i know PHPList, but that's not really the solution i want. most things are allready done - just the final persoanlisation and sending has to be done...customizing a ready software to our needs and to the simple user interface we have (for all non technicians) would be much more work i fear.
Re: personalized mass mailing
Posted: Fri Apr 25, 2008 3:05 am
by s.dot
Right now the best scenario is to send in a loop using str_replace() on variables. This is due to a bug in SwiftMailer in the decorator plugin. It will be fixed in the new version (don't know if it's out already, check the website!).
As far as bounced emails go, that has to be done manually. What I do is have a field called `bounced` in my database. I set it to 1 if the email bounces. I only send to email addresses that have `bounced` = 0.
I'm sure this isn't the only solution for handling bounced emails. Perhaps you could set up some sort of system on a cron job to pipe bounced emails to a script to update the database automatically.
SwiftMailer is just for sending emails though, it is not a total email solution. You'll have to roll the bounced emails code yourself.
Hope this helps!

Re: personalized mass mailing
Posted: Fri Apr 25, 2008 3:16 am
by Chris Corbyn
scottayy wrote:Right now the best scenario is to send in a loop using str_replace() on variables. This is due to a bug in SwiftMailer in the decorator plugin. It will be fixed in the new version (don't know if it's out already, check the website!).
3.3.3 fixed that bug
Otherwise I agree with everything else you said

Take a look at the IMAP functions to access a dedicated mailbox set to handle bounces.
Re: personalized mass mailing
Posted: Fri Apr 25, 2008 11:11 am
by s.dot
Chris Corbyn wrote:3.3.3 fixed that bug

Suhweeet!!
Geez, I should stay more updated on things.
Re: personalized mass mailing
Posted: Sun Apr 27, 2008 3:18 pm
by s.dot
Chris, the decorator plugin works beautifully now.

I sent to 10,800 members. Only one complained that their {username} wasn't replaced with their username.
If you're interested in seeing my code to see if it is my error or an error in the decorator plugin, here's my code:
Code: Select all
<?php
//OK, ok. This could take a while, so...
set_time_limit(0);
ignore_user_abort(true);
//and we sure as heck want to see any errors!
ini_set('display_errors', 'On');
error_reporting(E_ALL);
//flush everything
ob_start();
ob_implicit_flush();
//include the database connection
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/db_connect.php';
//get the site settings
require_once $_SERVER['DOCUMENT_ROOT'] . '/class/settings.class.php';
$settings = new SMPSettings();
//make sure subject and body are set
if (empty($_POST['emailSubject']) || empty($_POST['emailBody']))
{
die('Please fill in the subject and body of the email');
}
//build the message
$msg = $settings->emailHeader . stripslashes($_POST['emailBody']) . $settings->emailFooter;
$msgPlain = strip_tags($msg);
//load in the swift mailer components
require_once $_SERVER['DOCUMENT_ROOT'] . '/lib/Swift.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/lib/Swift/Connection/SMTP.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/lib/Swift/Plugin/Decorator.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/lib/Swift/Plugin/AntiFlood.php';
//instantiate Swift with the SMTP connection.
$swift = new Swift(new Swift_Connection_SMTP('localhost'));
//create the message
$message = new Swift_Message(stripslashes($_POST['emailSubject']));
//attach the html part of the body
$message->attach(new Swift_Message_Part($msg, 'text/html'));
//attach the plain text part of the body
$message->attach(new Swift_Message_Part($msgPlain));
//query for usernames and email addresses to send to
if ($settings->emailRequireNewsletter == 1)
{
$sendToResult = mysql_query("SELECT `id`, `username`, `email` FROM `users` WHERE `bounced` = 0 ORDER BY `id` ASC") or die(mysql_error());
} else
{
$sendToResult = mysql_query("SELECT `id`, `username`, `email` FROM `users` WHERE `bounced` = 0 AND `receive_newsletter` = 1 ORDER BY `id` ASC") or die(mysql_error());
}
//how many people we're sending to
$sendingTo = mysql_num_rows($sendToResult);
//see if we have anyone to send to
if ($sendingTo == 0)
{
die('We\'ve got nobody to send to. Sad, sad day, yo.');
}
//start the recipient list and replacements array
$recipients = new Swift_RecipientList();
$replacements = array();
/**
* Loop through the result set and add onto the recipients list
*/
while ($sendToArray = mysql_fetch_assoc($sendToResult))
{
$recipients->addTo($sendToArray['email']);
$replacements[$sendToArray['email']] = array('{username}' => $sendToArray['username']);
}
/**
* Attach the replacements decorator plugin
*/
$swift->attachPlugin(new Swift_Plugin_Decorator($replacements), 'decorator');
/**
* Attach the anti-flood plugin. Send 100 emails, disconnect, wait for 10 seconds, recconect
*/
$swift->attachPlugin(new Swift_Plugin_AntiFlood($settings->emailsPerBatch, $settings->emailWaitBetweenBatches), 'anti-flood');
/**
* Send the email
*/
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo '<p>Currently sending to <strong>' . $sendingTo . '</strong> email addresses. This may take a while. You will see a \'Send Complete\' message when the sending is done. Alternatively, you may
close this browser window and the email sending should continue.</p>';
$swift->batchSend($message, $recipients, $settings->noReplyEmail);
echo '<p>Send Complete</p>';
It is not a big deal to me.

However it might be to you.. so i posted it.

Might be a good reference for someone else wanting to do personalized mass mailing in the same manner.
Re: personalized mass mailing
Posted: Wed Apr 30, 2008 7:25 am
by nonsii
wow - thanks a lot for that help.
the last days i worked over the code and implemented the loop thing with the replaces.
but if the decorator plugin works also - i will also try that - thanks a lot for the code - help is allways a big thing
the other features are quite clear to me right now - i will tell you how it worked...
nonsii
Re: personalized mass mailing
Posted: Wed Apr 30, 2008 10:35 pm
by daneel
is really fixed ? ? ?
I've downloaded the last version, but I get the same error ... and is also kind of wired that in the "changes" file and in "Swift.php" says its version 3.3.2 ... I also tried downloading it from SVN...
The error that I get is that the replacement is always the same, for all the recipients...
maybe i'm doing something wrong...

Re: personalized mass mailing
Posted: Wed Apr 30, 2008 10:52 pm
by Chris Corbyn
daneel wrote:is really fixed ? ? ?
I've downloaded the last version, but I get the same error ... and is also kind of wired that in the "changes" file and in "Swift.php" says its version 3.3.2 ... I also tried downloading it from SVN...
The error that I get is that the replacement is always the same, for all the recipients...
maybe i'm doing something wrong...

It really is fixed. Are you seeing the same replacements all the time? (i.e. have you never seen it replace the markers successfully?)
Can you show your code please?
Re: personalized mass mailing
Posted: Thu May 01, 2008 5:38 pm
by daneel
first, thanks for your quick answer !
The error was (and I say 'was' becuase I think I've solved it) that the process did actually replace the fields, but always with the same data...
I cannot post the code, 'cause it's divided in classes and would be kind of hard to read here, but I was doing something like:
-Create Swift objetct
-Load newsletter
-Load totalUsers
-While (emailsSended < totalUsers)
-Get 20 users with its data (because loading 50000 users would be too much)
-Create Decorator Plugin and add reaplcements
-Add Decorator Plugin to Swift
-Send with BatchMailer
-Remove Decorator Plugin from Swift
-Loop
What I did now is to create and add the plugin before the loop, and only call "setReplacements" method when necessary...
But thanks for your support !!
Re: personalized mass mailing
Posted: Thu May 01, 2008 10:21 pm
by Chris Corbyn
daneel wrote:What I did now is to create and add the plugin before the loop
I guessed it may have been something to do with this. You can't repeatedly add the same plugin since you'll reset its state every time you add it

Glad you got it sorted

Re: personalized mass mailing
Posted: Wed May 21, 2008 11:06 pm
by etrams
I've been trying to use the code posted in here, (of course with certain modifications, but still I am not getting the email, or error message. I am supposed to get the email since I am the last one on the list. 2k+ addresses?
It just takes forever to load the page, and prints the first message, then it stops loading but it prints no message about to how many email addresses is sending.
I am trying to run this at a shared hosting (1and1).
Any ideas?
Re: personalized mass mailing
Posted: Thu May 22, 2008 12:22 am
by s.dot
Check out this topic for real-time browser reporting on how many messages have been sent:
viewtopic.php?f=52&t=81949
And use the swift logging functions to help you find where errors are occuring:
http://www.swiftmailer.org/wikidocs/v3/misc/logging
hope this helps!
Re: personalized mass mailing
Posted: Sat May 24, 2008 1:16 am
by etrams
Please wait until the you are notified that all messages have been sent.
===========
Thats all I get. I see my browser loading and loading but I don't get to see any information out of the plug-in.
I realize that I am sending to some part of my list (I added myself to the beginning now). However it is not telling me to how many people I am sending.
Here is the code:
Code: Select all
<?
ignore_user_abort(TRUE);
mysql_connect("localhost", 'user', 'password') or die(mysql_error());;
mysql_select_db("db244368630") or die(mysql_error());
$query = "SELECT * FROM mail_list";
$emails = mysql_query($query) or die(mysql_error());
$headers = 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'From:' . $from . "\r\n" .
'Reply-To:'. $from . "\r\n" . 'X-Mailer: PHP/' . phpversion();
$message = wordwrap($body, 70);
$mess = "<pre>";
$mess .= $message;
$mess .= "</pre>";
$message = $mess;
//OK, ok. This could take a while, so...
set_time_limit(0);
ignore_user_abort(true);
//and we sure as heck want to see any errors!
ini_set('display_errors', 'On');
error_reporting(E_ALL);
//flush everything
ob_start();
ob_implicit_flush();
//include the database connection
//require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/db_connect.php';
//get the site settings
//require_once $_SERVER['DOCUMENT_ROOT'] . '/class/settings.class.php';
//$settings = new SMPSettings();
//make sure subject and body are set
if (empty($_POST['subject']) || empty($_POST['body']))
{
die('Please fill in the subject and body of the email');
}
//build the message'
$msg = "<pre>";
$msg .= wordwrap(stripslashes($_POST['body']));
$msg .= "<pre>";
$msgPlain = strip_tags($msg);
//load in the swift mailer components
require_once 'lib/Swift.php';
require_once 'lib/Swift/Connection/SMTP.php';
require_once 'lib/Swift/Plugin/Decorator.php';
require_once 'lib/Swift/Plugin/AntiFlood.php';
require_once 'lib/Swift/LogContainer.php';
$log =& Swift_LogContainer::getLog();
$log->setLogLevel(4);
//instantiate Swift with the SMTP connection.
$smtp = new Swift_Connection_SMTP('smtp.1and1.com');
$swift = new Swift($smtp);
//create the message
$message = new Swift_Message(stripslashes($_POST['subject']));
//attach the html part of the body
$message->attach(new Swift_Message_Part($msg, 'text/html'));
//attach the plain text part of the body
$message_clean = wordwrap($_REQUEST['body'], 70);
$message->attach(new Swift_Message_Part("<pre>"));
$message->attach(new Swift_Message_Part($msgPlain));
$message->attach(new Swift_Message_Part("</pre>"));
//query for usernames and email addresses to send to
$sendToResult = mysql_query("SELECT `email` FROM `mail_list` ORDER BY `id` ASC ") or die(mysql_error());
//how many people we're sending to
$sendingTo = mysql_num_rows($sendToResult);
//see if we have anyone to send to
if ($sendingTo == 0)
{
die('We\'ve got nobody to send to. Sad, sad day, yo.');
}
//start the recipient list and replacements array
$recipients = new Swift_RecipientList();
$replacements = array();
/**
* Loop through the result set and add onto the recipients list
*/
while ($sendToArray = mysql_fetch_assoc($sendToResult))
{
$recipients->addTo($sendToArray['email']);
//$replacements[$sendToArray['email']] = array('{username}' => $sendToArray['username']);
}
/**
* Attach the replacements decorator plugin
*/
//$swift->attachPlugin(new Swift_Plugin_Decorator($replacements), 'decorator');
/**
* Attach the anti-flood plugin. Send 100 emails, disconnect, wait for 10 seconds, recconect
*/
$swift->attachPlugin(new Swift_Plugin_AntiFlood(90, 10), "anti-flood");
class SendCounterPlugin implements Swift_Events_SendListener
{
private $_count = 0;
public function sendPerformed(Swift_Events_SendEvent $e)
{
$this->_count += $e->getNumSent();
echo "{$this->_count} Messages sent<br />";
}
}
$swift->attachPlugin(new SendCounterPlugin(), 'counter');
/**
* Send the email
*/
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo str_repeat(' ', 100) . '<br />';
echo '<p>Currently sending to <strong>' . $sendingTo . '</strong> email addresses. This may take a while. You will see a \'Send Complete\' message when the sending is done. Alternatively, you may
close this browser window and the email sending should continue.</p>';
$swift->batchSend($message, $recipients,new Swift_Address("test@test.com", "test"));
echo '<p>Send Complete</p>';
?>