Page 4 of 5
Posted: Sun Jul 23, 2006 4:30 pm
by lorenww
Chris,
The batch did the trick, Thank you. And I am using a foreach loop to customize the mail as it was easiest to implement.
Just a note:
I was testing it with 23 addresses and sending 3 in a batch . . . all worked ok.
I set it up for 20 in a batch and then only 10 would come in, awhile later I would get 3 more and later another one would trickle in, all in all they came in but some were 3-4 hrs late. (I tested and tested this to get a handle on what was happening and am now getting inundated with the test e-mails lol!)
10 seemed to be the magic number, so I found that if batch was set to 10 at 10 seconds apart the emails came in like clockwork
It seems my hosting provider doesn't like bulk mailings.
The only oddity is that when hitting submit from the form that has the body text, it just hangs there like it was not submitted until the mail script finishes (I'm guessing) and then the header redirect sends me back to the admin section.
My original mailing script sent me back to the admin Immediately so not sure what is going on.
That is only a minor problem. I then added this to the submit button - alert and attempt redirect.
onclick=
"alert('Only press -Send Mail- one time and mail will be sent');window.location = ('admin.php')"
and
onclick=
"alert('Only press -Send Mail- one time and mail will be sent');document.location.href='admin.php'"
the window.location seems to be trying to work as I briefly see an hourglass but it just stays there, I know little when it comes to javascript.
Anyway Thank you very much for the help in this and it is very workable and clean.
Cheers
Loren
Posted: Sun Jul 23, 2006 6:33 pm
by Chris Corbyn
That 10 emails thing will be a mail server configuration. Some servers won't process more than 10 emails at a time, so as to avoid being spammed. This is common on shared hosts.
Glad you got it working anyway

Posted: Mon Jul 31, 2006 1:57 pm
by lorenww
Well, The "send in small batches" was timing out since I was running it in a loop so that did not work.
I now have the bulk e-mail script working with only one problem, I can get either the name or the e-mail address to appear in the message body but not both.
I even tried making Swift_Template_Plugin2.php
here is an idea of what I am trying to accomplish
Code: Select all
// ========== get the names and addresses
$mailto = file_get_contents('subscribers.php');
$dest = explode("\n", $mailto);
foreach ($dest as $key => $vallist){ // at this point $dest has email@email.com|username
$nameaddress = explode("|", $vallist); //seperate email from name
// this formats the addresses
$nameaddressN[0] = str_replace("\r", "", $nameaddressN[0]);
$nameaddressN[0] = str_replace("\n", "", $nameaddressN[0]);
$nameaddressN[0] = "'$nameaddressN[0]',
";
$recipients[] = $nameaddress[0]; // This goes into the "send to" field
$TplMail[] = array('MailtoAddress' => "$nameaddress[0]
"); // This has address to be displayed in the body
$TplName[] = array('MailtoName' => "$nameaddress[1]
"); // This has name to be displayed in the body
}
//========= end of getting names an addresses
// I can get one or the other to work but not both
$mailer->loadPlugin(new Swift_Template_Plugin($TplMail));
$mailer->loadPlugin(new Swift_Template_Plugin($TplName));
//Add as many parts as you need here
$mailer->addPart("Good Morning {MailtoName} this is your {MailtoAddress}");
$mailer->addPart("<b>Good Morning {MailtoName} this is your {MailtoAddress} </b> ", 'text/html');
Thank you for looking at this and I am so close to getting this working and all I need is add their e-mail address for unsubscribe.
Cheers
Loren
Posted: Mon Jul 31, 2006 2:30 pm
by lorenww
For now I have it solved . . . I made a copy and called it Swift_Template_Plugin2.php
Then changed instances of template to template 2 and it works.
Is this the (a) proper way to fix this?
Posted: Mon Jul 31, 2006 3:25 pm
by Chris Corbyn
lorenww wrote:For now I have it solved . . . I made a copy and called it Swift_Template_Plugin2.php
Then changed instances of template to template 2 and it works.
Is this the (a) proper way to fix this?
You shoudn't need to load the template plugin twice...
Code: Select all
$TplMail[] = array('MailtoAddress' => "$nameaddress[0]
",
'MailtoName' => "$nameaddress[1]
");
// .... snip .....
$mailer->loadPlugin(new Swift_Template_Plugin($TplMail));

Posted: Mon Jul 31, 2006 4:47 pm
by lorenww
I just tried it verbatim to your example and get.
Good Morning loren this is your {MailtoAddress}
I will use the second template until sorted out.
To change the subject a bit
I wanted to try sendmail and phpinfo.php has
/usr/sbin/sendmail -t -i
which I changed in
Swift_Sendmail_Connection.php
which gives me this
Code: Select all
require('./Swift/Swift_Sendmail_Connection.php');
$connection = new Swift_Sendmail_Connection;
$mailer = new Swift($connection, $_SERVER['SERVER_NAME']);
basically just changed the smtp stuff
The mailer failed to connect. Errors: Array
(
[0] => Array
(
[num] => 0
[time] => 0.00585600 1154381016
[message] => Connection to the given MTA failed.
)
)
. Log: Array
(
)
hope I posted that right
I have no clue as to what is happening here or if I need to change something else.
I just want to tell you your swiftmailer just rocks . . . . I'm obsessed with it for the time being and learning a lot as I go.
cheers
Loren
Posted: Wed Sep 20, 2006 11:33 am
by mango
I recently discovered swift and think its great!
I want to be able to customise each email and have followed this thread but have run into the same problem as lorenww in that if you are trying to replace two portions of the email body only one part gets replaced. The plugin does loop around the array (see test page output below), but only the last replacement seems to be implemented! I am a novice with oop, so any help would be appreciated.
My plugin code (as previously posted by Chris, but with a slightly different echo in the for loop):
Code: Select all
<?php
class Swift_Plugin_CustomiseEachEmail
{
var $pluginName = 'CustomiseEachEmail';
var $templateVars = array();
var $swiftInstance;
var $template = '';
var $count = 0;
//2-dimensional
// First level MUST be numerically indexed starting at zero
// Second level contains the replacements
function Swift_Plugin_CustomiseEachEmail($template_vars=array())
{
$this->templateVars = $template_vars;
}
function loadBaseObject(&$object)
{
$this->swiftInstance =& $object;
}
//Split the headers from the mail body
function getTemplate()
{
return substr($this->swiftInstance->currentMail[3], strpos($this->swiftInstance->currentMail[3], "\r\n\r\n"));
}
function getHeaders()
{
return substr($this->swiftInstance->currentMail[3], 0, strpos($this->swiftInstance->currentMail[3], "\r\n\r\n"));
}
function onBeforeSend()
{
if (empty($this->template)) $this->template = $this->getTemplate();
foreach ($this->templateVars[$this->count] as $key => $replacement)
{
$this->swiftInstance->currentMail[3] = $this->getHeaders().str_replace('{'.$key.'}', $replacement, $this->template);
echo 'key='.$key.' replacement='.$replacement.'<br />';
}
$this->count++;
}
}
?>
My test page code:
Code: Select all
<?php
// get data from db
$recipients = array();
while($row = mysql_fetch_assoc($results)) {
$recipients[] = array($row['title'].' '.$row['surname'], $row['email']);
$tpl[] = array ( 'email' => $row['email'],'name' => $row['title'].' '.$row['surname']);
}
echo '<pre>';
print_r($recipients);
echo '</pre>';
echo '<pre>';
print_r($tpl);
echo '</pre>';
require('Swift.php');
require('Swift/Connection/SMTP.php');
require('Swift/Plugin/CustomiseEachEmail.php');
require('Swift/Plugin/Verbose.php');
$mailer = new Swift(new Swift_Connection_SMTP('smtp_info_removed'));
$mailer->loadPlugin(new Swift_Plugin_CustomiseEachEmail($tpl));
$mailer->loadPlugin(new Swift_Plugin_Verbose());
$mailer->send(
$recipients,
'"Swift Test" <sender@example.co.uk>',
'Some Subject '. gmdate("H:i:s"),
"Dear {name} your email address is: {email} "
);
$mailer->close();
?>
The test page output is:
Code: Select all
Array
(
[0] => Array
(
[0] => Mr K11
[1] => xxx@example.co.uk
)
[1] => Array
(
[0] => Mr k14
[1] => yyy@example.co.uk
)
)
Array
(
[0] => Array
(
[email] => xxx@example.co.uk
[name] => Mr K11
)
[1] => Array
(
[email] => yyy@example.co.uk
[name] => Mr k14
)
)
key=email replacement=xxx@example.co.uk
key=name replacement=Mr K11
OK Recipient (1): xxx@example.co.uk
key=email replacement=yyy@example.co.uk
key=name replacement=Mr k14
OK Recipient (2): yyy@example.co.uk
And the emails arrive looking like this:
Code: Select all
Dear Mr k14 your email address is: {email}
If you swap the $tpl array to do the name before the email then you get:
Code: Select all
Dear {name} your email address is: yyy@example.co.uk
???
Also does anyone know of a text only webmail account which I can use to veiw the text part of a multipart email? Hotmail doesn't seem to let you turn off html emails! I am a little concerned about all the "=0a"s in the text part - is this OK?
Thanks
Chaman
Posted: Wed Sep 20, 2006 12:36 pm
by Weirdan
That's easy, here's fixed plugin:
Code: Select all
<?php
class Swift_Plugin_CustomiseEachEmail
{
var $pluginName = 'CustomiseEachEmail';
var $templateVars = array();
var $swiftInstance;
var $template = '';
var $count = 0;
//2-dimensional
// First level MUST be numerically indexed starting at zero
// Second level contains the replacements
function Swift_Plugin_CustomiseEachEmail($template_vars=array())
{
$this->templateVars = $template_vars;
}
function loadBaseObject(&$object)
{
$this->swiftInstance =& $object;
}
//Split the headers from the mail body
function getTemplate()
{
return substr($this->swiftInstance->currentMail[3], strpos($this->swiftInstance->currentMail[3], "\r\n\r\n"));
}
function getHeaders()
{
return substr($this->swiftInstance->currentMail[3], 0, strpos($this->swiftInstance->currentMail[3], "\r\n\r\n"));
}
function onBeforeSend()
{
if (empty($this->template)) $this->template = $this->getTemplate();
$mailBody = $this->template;
foreach ($this->templateVars[$this->count] as $key => $replacement)
{
$mailBody = str_replace('{' . $key . '}', $replacement, $mailBody);
echo 'key=' . $key . ' replacement=' . $replacement . '<br />';
}
$this->swiftInstance->currentMail[3] = $this->getHeaders() . $mailBody;
$this->count++;
}
}
?>
Posted: Wed Sep 20, 2006 12:51 pm
by Chris Corbyn
Yeah the plugin code posted here was broken. The code in the latest packages should be correct (i think

).

Posted: Thu Sep 21, 2006 4:33 am
by mango
That sorted it - thanks!
Yeah the plugin code posted here was broken. The code in the latest packages should be correct (i think Confused).
I only download the php4 gz version from swiftmailer.org a couple of days ago...
Posted: Thu Sep 21, 2006 5:02 am
by ibbo
Weirdan | Please use Code: Select all
and [syntax="..."] tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read: [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]
I used to run into this problem using php and had to resort to Dear user,
Which is no good realy.
I send about 8000 newsletters out per week all personalised with Dear NAME, in batches of 1000 (your mail server can probably take more but keep your eye on bandwidth usage).
I scapped php for this though and resorted to perl and postfix (and a reverse MX for my machine).
If anyone has a functioning mail server running then give this a try.
[syntax="perl"]
#!/usr/bin/perl
# email newsletter script
# grabs a list of users in the form of (username, email)
# grabs the current newsletter
use Time::Local;
use Mail::RFC822::Address qw(valid validlist);
$port = 25;
$them = 'localhost';
$subject = 'Newsletter';
$to = '';
$name = '';
$from = 'webmaster@host.com';
$AF_INET = 2;
$SOCK_STREAM = 1;
$i = 0;
$SIG{'INT'} = 'dokill';
$sockaddr = 'S n a4 x8';
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime (time);
@Days = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
@Months = ("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
$day = $Days[$wday];
$date = $mday + 0;
$year = 1900 + $year;
$month = $Months[$mon];
$tmp='';
sub dokill { kill 9,$child if $child; }
sub read_file {
my ( $f ) = @_;
open F, "< $f" or die "Can't open $f : $!";
my @f = <F>;
close F;
return wantarray ? @f : \@f;
}
sub reduce_space {
my $email = shift;
$email =~ s/(\w) @ (\w)/$1\@$2/g;
return $email;
}
# requires a hook up to the user_details and members tables
# to grab a list of usernames and email addresses
# where the user wants a newsletter
($name,$aliases,$proto) = getprotobyname('tcp');
($name,$aliases,$port) = getservbyname($port,'tcp') unless $port =~ /^\d+$/;
($name,$aliases,$type,$len,$thisaddr) = gethostbyname($hostname);
($name,$aliases,$type,$len,$thataddr) = gethostbyname($them);
$this = pack($sockaddr, $AF_INET, 0, $thisaddr);
$that = pack($sockaddr, $AF_INET, $port, $thataddr);
socket(S, $AF_INET, $SOCK_STREAM, $proto) ? print "socket ok\n" : die $!;
bind(S, $this) ? print "bind \033[31mok\033[0m\n" : die $!;
connect(S,$that) ? print "connect \033[31mok\033[0m\n" : die $!;
select(S); $| = 1; select(STDOUT);
# grab our list of users
@list = read_file($ARGV[0]);
# how many users is there
$lines = 0;
open(FILE, $ARGV[0]) or die "Can't open `$filename': $!";
while (sysread FILE, $buffer, 4096) {
$lines += ($buffer =~ tr/\n//);
}
close FILE;
# handshake with postfix
#$a=<S>;print "$a";
print S "EHLO localhost\n";
#$a=<S>;print "$a\n";
print "\n-------------------------- Session started ----------------------\n\n";
# start mailing
while ($i < $lines){
#print "$i\n";
# get the newsletter
@newsletter = read_file('/path/to/newsletter'); // make sure your newsletter end with a . on a line of its own
# split current user row on ,
@users = split(',',$list[$i]);
$name = $users[0]; # name
$to = reduce_space($users[1]); # email
if(valid($users[1])){
#print "$users[1] is valid\n";
foreach $value (@newsletter){
# replace newsletter {NAME} with $name (personalisation)
$value =~ s/{NAME}/$name/;
$value =~ s/{DATE}/$month $date $year/;
$value =~ s/{EMAIL}/$to/;
}
print S "MAIL FROM: $from\n";
#$a=<S>;print "$i=> MAIL FROM $a\n";
print S "RCPT TO: $to\n";
#$a=<S>;print "$i=> RCPT TO $a\n";
print S "DATA \n";
print S "Subject: $subject\n";
print S "MIME-Version: 1.0\n";
print S "Content-Type: text/html; charset=\"iso-8859-1\"\n";
print S "From: $from\n";
print S "To: $to\n";
foreach $value (@newsletter){
print S $value;
}
sleep(1);
#$a=<S>;print "$i=> DATA $a\n";
}
#print "\n-------------------------- Done ----------------------\n\n";
$i++;
}
print S "QUIT";
#$a=<S>;print "$a\n";
exit 1;
You need a list of users in the format
<username>, <email>
Then simply run ./pmail list_of_users.txt
And away they will go.
As i have a few servers in house I can run it from the office using a mail server in here but I see no reson why it could not be uploaded to your ISP (providing they have PERL) and a working mail server.
This script opens a socket to the server and uses that socket to acheive true bulk mailing. Something php just cannot do as well.
ibbo
Weirdan | Please use[/syntax]Code: Select all
and [syntax="..."] tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read: [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]
Posted: Thu Sep 21, 2006 7:04 am
by Weirdan
Something php just cannot do as well.
<sarcasm>Oh, really?!</sarcasm>
Posted: Thu Sep 21, 2006 8:32 am
by ibbo
<sarcasm>Oh, really?!</sarcasm>
Prove it to me and write a php bulk mailing script then that can bulk mail from a web page, or even from the shell.
Do that and you can be as sarcastic as you like.
Ive been coding in both perl and php for years, and each has its place. And judging by the length of this thread I can tell that this guy is having very little luck. And its not just him for this is a common problem when bulk mailing with php.
The problem been who wants to sit there and refresh a web page every 10 mins or so to send out approx 100 emails. I say approx as may ISP's restrict how many you can send at once (even if BCC'd).

Posted: Thu Sep 21, 2006 8:55 am
by mango
ibbo
if you take a look at my first post you will see some basic code that you can use for bulk mailing using php (you of course need to use the corrected plugin script posted by wierdan and the class code from swiftmailer.org)
Posted: Thu Sep 21, 2006 10:14 am
by Weirdan
Prove it to me and write a php bulk mailing script then that can bulk mail from a web page, or even from the shell.
Your PERL script is a basic bulk-mailer with rudimentary support for templating, isn't it? What is in it that can't be duplicated using PHP?
Do that and you can be as sarcastic as you like.
Thanks you for allowing me to be sarcastic
You're discussing alleged PHP's inability to bulk-mail in the thread about PHP library especially suited for bulk-mailing... that's funny
