return-receipt 1pxl img hack

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

tgavin
Forum Newbie
Posts: 15
Joined: Sun Aug 26, 2007 3:13 pm

return-receipt 1pxl img hack

Post by tgavin »

I'm trying to insert the 1pxl gif return-receipt image hack into my newsletter system, but I'm not sure which way to go. Here's the way things function now.

1. Admin clicks on Send
2. The newsletter is assembled from multiple (user definable) template files (header, body, footer, etc) and then written to a .txt file for caching
3. All of the subscribers are inserted into a queue table in mysql
4. The newsletter is then sent out in batches using the cached .txt file

Now, this certainly worked well because the newsletter was assembled once before sending, so the only things that changed with Swift was the recipient's email address. It would read in the .txt file and cache it as well.

The problem now seems to be implementing the hack. I need to put the following into each email, with the newsletter's id and the subscriber's id.

Code: Select all

<img src="http://www.mysite.com/ssi/return_receipt.php?nid=".$_GET['news_id']."&sid=".$_GET['sub_id']."" /> 
I've managed to do this, but it's assembling the file each time, and I received multiple emails for each recipient. Obviously I've goofed somewhere.

Am I better off rewriting my scripts and functions? Or is there an easy way to do this?

If I have to rewrite, do you have an outline that is a best-practice? I rewrote this once before when I dumped phpmailer and it's painful to think that I'd have to do it again...

Thanks!
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: return-receipt 1pxl img hack

Post by Weirdan »

I've managed to do this, but it's assembling the file each time
Since the content of your messages is different for each message, it's necessary to construct new message body for every message (or implement some kind of message templating).
and I received multiple emails for each recipient. Obviously I've goofed somewhere.
You'll have to post the code. The information you provided is not enough to tell you anything about your script.
tgavin
Forum Newbie
Posts: 15
Joined: Sun Aug 26, 2007 3:13 pm

Re: return-receipt 1pxl img hack

Post by tgavin »

Thanks.
I figured I'd have to rebuild. I was just hoping there might be something in the class that would let me insert. Better to ask first... :)
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Re: return-receipt 1pxl img hack

Post by Chris Corbyn »

There's a plugin called the Decorator plugin, but a bug was discovered in it recently so I'm not really advising you use it until the next version of Swift. It doesn't do anything which you couldn't do just as fast though ;)

You don't need to rebuild the entire message for example.

Code: Select all

foreach ($recipients as $address) {
  $message->setBody( ... your custom body ...);
  $swift->send($message, ...);
}
If you have a multipart message, don't re-attach each part which changes neither... just change the body for that part:

Code: Select all

$part = new Swift_Message_Part();
$message->attach($part); //attach it once
 
foreach ($recipients as $address) {
  $part->setBody(... your custom body ...);
  $swift->send($message, ....);
}
tgavin
Forum Newbie
Posts: 15
Joined: Sun Aug 26, 2007 3:13 pm

Re: return-receipt 1pxl img hack

Post by tgavin »

I was playing around with the decorator plugin and was receiving errors. Thanks for the heads up.

The problem that I'm encountering is that my cached .txt file (what I *think* you're calling the custom body) is the entire message - from <html> to </html> - with all of the settings defined, done and done. I've spent a lot of time defining this system so that it's very easy for the end user to add and customize their templates, letting my program do all of the hard work. Rebuilding this would be a real blow.

If there is a way for me to just insert my <img> tag without having to edit the .txt file I'm golden. Would an email client read the img tag, even if it's not within <html></html>? Somehow I think it would, but would like confirmation.

Code: Select all

//Try to connect using /usr/sbin/sendmail -bs
$swift =& new Swift(new Swift_Connection_Sendmail());
 
// build the HTML part of the message
write_file(SITE_PATH.'/data/cache/files/cache_html.php',file_get_contents(SITE_URL.'/index.php?id='.urlencode(escape($id,1)).'&sending=1&sid='.$sid.''));
$html_message = file_get_contents('../data/cache/files/cache_html.php');
 
// build the text part of the message
$text_message .= file_get_contents('../data/cache/files/cache_text.php');
 
$message =& new Swift_Message($subject);
 
//Add the "parts"
$message->setEncoding("8bit");
$message->attach(new Swift_Message_Part($text_message));
$message->attach(new Swift_Message_Part($html_message, "text/html"));
$message->headers->set("id: $id",$id);
 
// build the recipients list
$recipients =& new Swift_RecipientList();
$recipients->addTo($to);
 
// bounce address
$message->setReturnPath(new Swift_Address($reply_address));
 
//And send like usual
if ($swift->batchSend($message, $recipients, new Swift_Address($reply_address, $from_name))) {
    $sent = true;
} else {
    $sent = false; 
}
//var_dump($sent);
//$log =& Swift_LogContainer::getLog();
//var_dump($log->getFailedRecipients());
 
$swift->disconnect();
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Re: return-receipt 1pxl img hack

Post by Chris Corbyn »

str_replace() ?
tgavin
Forum Newbie
Posts: 15
Joined: Sun Aug 26, 2007 3:13 pm

Re: return-receipt 1pxl img hack

Post by tgavin »

Chris Corbyn wrote:str_replace() ?
where do you suggest?

In this line

Code: Select all

write_file(SITE_PATH.'/data/cache/files/cache_html.php',file_get_contents(SITE_URL.'/index.php?id='.urlencode(escape($id,1)).'&sending=1&sid='.$sid.''));
I'm placing the recipients id (sid) and the newsletter id (id). The only problem? I have to rewrite the entire cache file for each recipient. Maybe I'm mistaken, but there wouldn't be anything for Swift to cache, since it's a total rewrite with each recipient. Am I wrong?
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Re: return-receipt 1pxl img hack

Post by Chris Corbyn »

I was thinking about calling str_replace() on $html_message and $text_message. I don't know the specifics of why you write to a file then read back out of that file, but all you need are placeholders like {id} in the message, the str_replace() those placeholders for each recipient as you send. It may not tie into your existing system without a little bit of rewriting but it shouldn't be much work I imagine.
tgavin
Forum Newbie
Posts: 15
Joined: Sun Aug 26, 2007 3:13 pm

Re: return-receipt 1pxl img hack

Post by tgavin »

When a newsletter is created it's written to a file for two reasons: so that mysql doesn't need to be queried every time somebody reads the newsletter, and for SEO (ie: /2008/01/28/my-newsletter-title/index.php), where index.php is the cached newsletter.

When a newsletter is created, this is what happens

Code: Select all

include(SITE_PATH.'/ssi/header1.php');
include(SITE_PATH.'/ssi/header2.php');
include(SITE_PATH.'/data/templates/'.$template.'/header.php');
include(SITE_PATH.'/ssi/template_query.php');
articles();
include(SITE_PATH.'/data/templates/'.$template.'/footer.php');
include(SITE_PATH.'/ssi/footer.php');
// now write the file to disk
That file is never changed, unless the admin edits and updates the newsletter.

Now, If i were to just do this when sending

Code: Select all

// build the HTML part of the message
ob_start();
include(SITE_PATH.'/ssi/header1.php');
include(SITE_PATH.'/ssi/header2.php');
echo "<img src=\"".SITE_URL."/ssi/return_receipt.php?nid={$id}&sid={$sid}\" width=\"1\" height=\"1\" border=\"0\" />\n";
include(SITE_PATH.'/data/templates/'.$template.'/header.php');
include(SITE_PATH.'/ssi/template_query.php');
articles();
include(SITE_PATH.'/data/templates/'.$template.'/footer.php');
include(SITE_PATH.'/ssi/footer.php');
$html_message = ob_get_contents();
ob_end_clean();
I wouldn't have to rewrite anything (almost).
Would everything except for the line with the <img> be cached?
Is there a way that I can see what Swift has cached, or will cache so that I can run tests?
tgavin
Forum Newbie
Posts: 15
Joined: Sun Aug 26, 2007 3:13 pm

Re: return-receipt 1pxl img hack

Post by tgavin »

I think I see where you were going before. Instead of

Code: Select all

$html_message = file_get_contents('../data/cache/files/cache_html.php');
do this

Code: Select all

$html_message = file_get_contents('../data/cache/files/cache_html.php?id=&nid&sid=$sid');
and then in the template files, have the variables, $_GET['nid']; etc.?

Wouldn't that still constitute a rewrite?
tgavin
Forum Newbie
Posts: 15
Joined: Sun Aug 26, 2007 3:13 pm

Re: return-receipt 1pxl img hack

Post by tgavin »

Here's what I decided to do.

When creating my cache file I include the code for the <img>, with GET vars.
When sending the newsletter, the info sent to Switf is:

Code: Select all

// build the HTML part of the message
$html_message = file_get_contents(SITE_URL."/data/cache/files/cache_html.php?nid={$id}&sid={$sid}");
$message->attach(new Swift_Message_Part($html_message, "text/html"));
Then, each subscriber gets a personalized email with their own sub id, etc. I've tested this and it works.

Since I'm still a little sketchy on what Swift caches, my question is: Is Swift caching everything *except* the newsletter id and subscriber id - the only 2 things that change in each email? I just want to make sure that I'm not spending too much on each email. I have some users that are sending upwards of 60k emails per week to their lists! (no, it's not spam) :D

Thanks for such a great class! I'll be donating once I'm finished with this. There's still more of the world for you to see!
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Re: return-receipt 1pxl img hack

Post by Chris Corbyn »

Swift caches:

* Each individual header (on the main message, and on any entities attached to it).
* The body of each separate mime entity attached to it (i.e. each mime part, attachment or image)

If anything changes, it only clears the cache a re-generates content for the specific part which changed. In the case of changing something in the body of the message this will mean the body gets rebuilt, but the headers (and other body parts) will remain cached.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Re: return-receipt 1pxl img hack

Post by Chris Corbyn »

Just FYI, it may surprise you to know that the heaviest work done on the message is potentially in the headers.
tgavin
Forum Newbie
Posts: 15
Joined: Sun Aug 26, 2007 3:13 pm

Re: return-receipt 1pxl img hack

Post by tgavin »

Hey, thanks!

I had no idea that you posted a reply. I never received an email!

I went to donate last week, but it looks like I need to be a member of sourceforge? Can't I donate directly via Paypal?
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Re: return-receipt 1pxl img hack

Post by Chris Corbyn »

tgavin wrote:Hey, thanks!

I had no idea that you posted a reply. I never received an email!

I went to donate last week, but it looks like I need to be a member of sourceforge? Can't I donate directly via Paypal?
Hi tgavin. Thanks for being so generous :D Donations all get sent too my PayPal address which is:

chris@w3style.co.uk (can be sent to directly if you prefer)

My understanding is that if you don't have a SF account, the donation just shows up as "anonymous".

Thanks again :)
Post Reply