email is not sent when using a loop

Swift Mailer is a fantastic library for sending email with php. Discuss this library or ask any questions about it here.

Moderators: Chris Corbyn, General Moderators

Post Reply
choubix
Forum Commoner
Posts: 42
Joined: Tue Nov 06, 2007 12:21 pm

email is not sent when using a loop

Post by choubix »

hello,
i am trying to send an email to many recipients.
it returns a blank page...

I guess it comes from the decorator or from the email field...

can someone tell me what's wrong there please?
is there any possibility to better the code so it doesnt load the server too much please?

thanks!

Code: Select all

//sends an email to clients having won points (uses tables: winners && clients)

$query = (" SELECT winners.id_winner, SUM(winning_numbers), clients.fname, clients.lname, clients.email 
			FROM winners, clients 
			WHERE winners.id_winner = clients.id_clients 
			AND mailsent = 0 
			GROUP BY id_winner ");
$result = mysql_query($query) or die('Query failed. ' . mysql_error());




while($row = mysql_fetch_array($result))
{ 

//Start Swift
$smtp =& new Swift_Connection_SMTP("smtp.xxxxx.com");
$smtp->attachAuthenticator(new Swift_Authenticator_LOGIN());
$smtp->setUsername("xxxxxx");
$smtp->setPassword("xxxxxxx");

$swift =& new Swift($smtp);
		
//Create the message
$message =& new Swift_Message("Dear {fname} {lname} you have won!", "Congratulations, you have played on http://www.xxxxxxx.com and won {points} points! Please log on xxxxxx.com and check if you can redeem your points for exclusive gifts. You can also convert your points into more chances to win excluse prizes offered by our partners! Have a great day!");
		
$message->setTo("undisclosed-recipients:;");

$replacements = array(
"$row['email']" => array("{fname}" => "$row['fname']", "{lname}" => "$row['lname']", "{points}" => "$row['SUM(winning_numbers)']*200")
);
 
//Load the plugin with these replacements
$swift->attachPlugin(new Swift_Plugin_Decorator($replacements), "decorator");
	
	 
//Now check if Swift actually sends it
$swift->send($message, "$row['email']", "admin@xxxxx.com");


print "ok";
}

$swift->disconnect();
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Move all the connection stuff outside the loop.You're opening a crap load of connections then only closing the last one. ;)
choubix
Forum Commoner
Posts: 42
Joined: Tue Nov 06, 2007 12:21 pm

Post by choubix »

hi Chris,

I have tried that. indeed i would make the connection faster but still: it doesnt send anything.

I remember managing to get swift to send emails by removing all decorator stuff earlier today.
but of course none of the tags {fname}, {lname} and {points} worked at that time (the $query is ok though)

by the way:
- will {points} be correctly interpreted or will it show a*200 (where a is a number) ??
- is it correct to use the batchsend in that case? (this will be a cron job, sent to quite a few persons so I quite dont want to disclose other users emails ;) )



here is the current code:

Code: Select all

$query = (" SELECT winners.id_winner, SUM(winning_numbers), clients.fname, clients.lname, clients.email 
			FROM winners, clients 
			WHERE winners.id_winner = clients.id_clients 
			AND mailsent = 0 
			GROUP BY id_winner ");
$result = mysql_query($query) or die('Query failed. ' . mysql_error());


//Start Swift
$smtp =& new Swift_Connection_SMTP("smtp.xxxxx.com");
$smtp->attachAuthenticator(new Swift_Authenticator_LOGIN());
$smtp->setUsername("xxxxxx");
$smtp->setPassword("xxxxxx");


while($row = mysql_fetch_array($result))
{ 
$swift =& new Swift($smtp);
		
//Create the message
$message =& new Swift_Message("Dear {fname} {lname} you have won!", "Congratulations, you have played on http://www.xxxxxx.com and won {points} points! Please log on xxxxx.com and check if you can redeem your points for exclusive gifts. You can also convert your points into more chances to win excluse prizes offered by our partners! Have a great day!");

$replacements = array(
"$row['email']" => array("{fname}" => "$row['fname']", "{lname}" => "$row['lname']", "{points}" => "$row['SUM(winning_numbers)']*200")
);
 
//Load the plugin with these replacements
$swift->attachPlugin(new Swift_Plugin_Decorator($replacements), "decorator");
	
	 
//Now check if Swift actually sends it
$swift->batchSend($message, "$row['email']", "admin@xxxxxxx.com");


print "ok";
}

$swift->disconnect();
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Lose all the double quotes -- they're not needed and indeed will make "$a*200" appear as a string rather than a computed number.

You're still doing way too much inside the loop (overwriting $swift, overwriting $replacements etc).

Try this.

Code: Select all

$query = (" SELECT winners.id_winner, SUM(winning_numbers), clients.fname, clients.lname, clients.email
         FROM winners, clients
         WHERE winners.id_winner = clients.id_clients
         AND mailsent = 0
         GROUP BY id_winner ");
$result = mysql_query($query) or die('Query failed. ' . mysql_error());


//Start Swift
$smtp =& new Swift_Connection_SMTP("smtp.xxxxx.com");
$smtp->attachAuthenticator(new Swift_Authenticator_LOGIN());
$smtp->setUsername("xxxxxx");
$smtp->setPassword("xxxxxx");

$swift =& new Swift($smtp);
      
//Create the message
$message =& new Swift_Message("Dear {fname} {lname} you have won!", "Congratulations, you have played on http://www.xxxxxx.com and won {points} points! Please log on xxxxx.com and check if you can redeem your points for exclusive gifts. You can also convert your points into more chances to win excluse prizes offered by our partners! Have a great day!");

$recipients =& new Swift_RecipientList();

$replacements = array();

while($row = mysql_fetch_array($result))
{

  $replacements[$row['email']] = array("{fname}" => $row['fname'], "{lname}" => $row['lname'], "{points}" => $row['SUM(winning_numbers)']*200);

  $recipients->addTo($row['email']);
}

//Load the plugin with these replacements
$swift->attachPlugin(new Swift_Plugin_Decorator($replacements), "decorator");

//Now check if Swift actually sends it
if ($swift->batchSend($message, $recipients, "admin@xxxxxxx.com"))
{
  echo "OK";
}

$swift->disconnect();
choubix
Forum Commoner
Posts: 42
Joined: Tue Nov 06, 2007 12:21 pm

Post by choubix »

hi chris,

thanks for your message.
i managed to make it work yesterday (i noticed that my quotes were not placed correctly... shame on me...)

thanks for helping me making the script run faster!!
seems to be better that way.

I will read more thoroughly the wiki to make sure my emails are not sent directly into the trash box of the recipients now :)

Thanks! :)
choubix
Forum Commoner
Posts: 42
Joined: Tue Nov 06, 2007 12:21 pm

Post by choubix »

it's a bit "off topic" but"

as we are using smtp.domain.com with swiftmailer:
do we need a MX record for smtp.domain.com along with the SPF record?
chuckl
Forum Commoner
Posts: 61
Joined: Wed May 23, 2007 7:36 am

Post by chuckl »

Your domain setup is probably as, if not more, important than correct mail formatting in ensuring that your emails are actually delivered. Remember that all Swiftmailer does in effect is ensure that the mail is handed to the email system.

Since the mail server is sending mail for your domain it must be referenced in the SPF record. Also make sure it has a valid DNS entry and reverse DNS.
choubix
Forum Commoner
Posts: 42
Joined: Tue Nov 06, 2007 12:21 pm

Post by choubix »

hi chuckl,

what i read was that i had to setup a SPF record myself.
when you are talking about DNS and reverse DNS can you please be a bit more precise ?

I already have set up the website using A records mainly and 1 MX record.

they are like this:

A records:

webmail.mydomain.com
mx1.mydomain.com
pop3.mydomain.com
webmail.mydomain,com
smtp.mydomain.com
mydomain.com

MX record:
mail.mydomain.com

Is this domain configuration ok since
- I am using admin@mydomain.com (this address exists) in swift mailer.
- I am using smtp.mydomain.com to send the emails (using my login credentials)

I know that from here http://old.openspf.org/wizard.html I can generate a SPF record for the domain.

thanks! :)
chuckl
Forum Commoner
Posts: 61
Joined: Wed May 23, 2007 7:36 am

Post by chuckl »

I'm not quite sure how to be more precise, but I'll try.

If the server that sends the mail identifies itself as smtp.mydomain.com when sending mail, then there must be a DNS entry for machine/subdomain 'smtp' in the DNS record for mydomain.com pointing to the IP address of that server.

There should also be a reverse DNS entry containing that IP address (reversed obviously) referring to machine/subdomain 'smtp'.

Your domain SPF record should cover ALL servers that originate or send mail for your domain. It's almost impossible to give advice on how to do this, since there are so many ways of setting up an SPF record.

The other common trap often mentioned here is that when sending from a website, the mail is sent as originating from Apache user 'nobody' or 'www-data', rather than the domain of the website.

Hope that helps,
choubix
Forum Commoner
Posts: 42
Joined: Tue Nov 06, 2007 12:21 pm

Post by choubix »

hi chuckl,

just wanted to make myself more explicit:

with swift mailer:
- I am sending my emails using smtp.mydomain.com
- I also use an existing email address with login// password in my php script.

- all the records in my previous post are redirected to the ip address of my server (both A and MX records)
BUT: when I try a reverse lookup here: http://remote.12dt.com/lookup.php
my IP address redirects to my server in this way:
IP address resolves to wpccXXXX.myhost.com, top level domain myhost.com

according to the common trap you mentionned:
doesnt swift prevent us from this as we need to use a smtp + login/password? (i use an existing email address)


could you advise me on what to do in order to configure my DNS correctly please?

thanks :)
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Yep, most likely you're on a shared server and there's not really a lot you can do about reverse mappings when you're not authoritative for the IP address.

The SMTP server DOES NOT need to have a MX record held against it no. The SMTP server DOES need to have a reverse DNS entry configured however -- ideally one that responds to pings.

The domain of the sender (i.e. the From: address or the Return-Path: address) DOES need to have a MX record. Well, technically many server wall fallback to trying an A record but a large portion of servers will actually try a lookup of your MX record before accepting mail.

SPF is very important too. The SMTP server you're sending from must be in the SPF record list for the domain of your sender (i.e. the SMTP server must be allowed to send mail From: your domain).

To summarise:

SMTP does not need MX.
SMTP does need reverse DNS.
Sender address needs a MX record.
SMTP server needs to be in SPF record for sender.
choubix
Forum Commoner
Posts: 42
Joined: Tue Nov 06, 2007 12:21 pm

Post by choubix »

thanks Chris.

I get what you are saying and I believe this explanation find it's place in a Sticky :)

Just want to make sure it is crystal clear on my side:

when you say: Sender address needs a MX record
does it mean:
- mydomain.com must have a MX record pointing to my IP address OR
- email_used_to_send_emails@mydomain.com must have a MX record pointing to my IP address?



funny that you mention this: I actually am on a dedicated server (well: it is what I pay for...)
I have a Plesk dashboard + access to apache etcetc

I have to check with the guys how I can get the REVERSE DNS to point to my SMTP server.
Post Reply