Webylon 3.1 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • auth
  • Booking
  • cart
    • shipping
    • steppedcheckout
  • Catalog
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • Email
  • Email_BounceHandler
  • Email_BounceRecord
  • Mailer
  • NewsletterEmailBlacklist
  • QueuedEmail
  • QueuedEmailDispatchTask
  • TestMailer
  1 <?php
  2 
  3 /**
  4  * @package sapphire
  5  * @subpackage email
  6  */
  7 
  8 if(isset($_SERVER['SERVER_NAME'])) {
  9     /**
 10      * X-Mailer header value on emails sent
 11      */
 12     define('X_MAILER', 'SilverStripe Mailer - version 2006.06.21 (Sent from "'.$_SERVER['SERVER_NAME'].'")');
 13 } else {
 14     /**
 15      * @ignore
 16      */
 17     define('X_MAILER', 'SilverStripe Mailer - version 2006.06.21');
 18 }
 19 // Note: The constant 'BOUNCE_EMAIL' should be defined as a valid email address for where bounces should be returned to.
 20 
 21 /**
 22  * Class to support sending emails.
 23  * @package sapphire
 24  * @subpackage email
 25  */
 26 class Email extends ViewableData {
 27     
 28     /**
 29      * @param string $from Email-Address
 30      */
 31     protected $from;
 32     
 33     /**
 34      * @param string $to Email-Address. Use comma-separation to pass multiple email-addresses.
 35      */
 36     protected $to;
 37     
 38     /**
 39      * @param string $subject Subject of the email
 40      */
 41     protected $subject;
 42     
 43     /**
 44      * @param string $body HTML content of the email.
 45      * Passed straight into {@link $ss_template} as $Body variable.
 46      */
 47     protected $body;
 48     
 49     /**
 50      * @param string $plaintext_body Optional string for plaintext emails.
 51      * If not set, defaults to converting the HTML-body with {@link Convert::xml2raw()}.
 52      */
 53     protected $plaintext_body;
 54     
 55     /**
 56      * @param string $cc
 57      */
 58     protected $cc;
 59     
 60     /**
 61      * @param string $bcc
 62      */
 63     protected $bcc;
 64     
 65     /**
 66      * @param Mailer $mailer Instance of a {@link Mailer} class.
 67      */
 68     protected static $mailer;
 69     
 70     /**
 71      * This can be used to provide a mailer class other than the default, e.g. for testing.
 72      * 
 73      * @param Mailer $mailer
 74      */
 75     static function set_mailer(Mailer $mailer) {
 76         self::$mailer = $mailer;
 77     }
 78     
 79     /**
 80      * Get the mailer.
 81      * 
 82      * @return Mailer
 83      */
 84     static function mailer() {
 85         if(!self::$mailer) self::$mailer = new Mailer();
 86         return self::$mailer;
 87     }
 88     
 89     /**
 90      * @param array $customHeaders A map of header-name -> header-value
 91      */
 92     protected $customHeaders = array();
 93 
 94     /**
 95      * @param array $attachements Internal, use {@link attachFileFromString()} or {@link attachFile()}
 96      */
 97     protected $attachments = array();
 98     
 99     /**
100      * @param boolean $
101      */
102     protected $parseVariables_done = false;
103     
104     /**
105      * @param string $ss_template The name of the used template (without *.ss extension)
106      */
107     protected $ss_template = "GenericEmail";
108     
109     /**
110      * @param array $template_data Additional data available in a template.
111      * Used in the same way than {@link ViewableData->customize()}.
112      */
113     protected $template_data = null;
114     
115     /**
116      * @param string $bounceHandlerURL
117      */
118     protected $bounceHandlerURL = null;
119     
120     /**
121      * @param sring $admin_email_address The default administrator email address. 
122      * This will be set in the config on a site-by-site basis
123      */
124     static $admin_email_address = '';
125 
126     /**
127      * @param string $send_all_emails_to Email-Address
128      */
129     protected static $send_all_emails_to = null;
130     
131     /**
132      * @param string $bcc_all_emails_to Email-Address
133      */
134     protected static $bcc_all_emails_to = null;
135     
136     /**
137      * @param string $cc_all_emails_to Email-Address
138      */
139     protected static $cc_all_emails_to = null;
140         
141     /**
142      * Create a new email.
143      */
144     public function __construct($from = null, $to = null, $subject = null, $body = null, $bounceHandlerURL = null, $cc = null, $bcc = null) {
145         if($from != null) $this->from = $from;
146         if($to != null) $this->to = $to;
147         if($subject != null) $this->subject = $subject;
148         if($body != null) $this->body = $body;
149         if($cc != null) $this->cc = $cc;
150         if($bcc != null) $this->bcc = $bcc;
151         if($bounceHandlerURL != null) $this->setBounceHandlerURL($bounceHandlerURL);
152         parent::__construct();
153     }
154     
155     public function attachFileFromString($data, $filename, $mimetype = null) {
156         $this->attachments[] = array(
157             'contents' => $data,
158             'filename' => $filename,
159             'mimetype' => $mimetype,
160         );
161     }
162     
163     public function setBounceHandlerURL( $bounceHandlerURL ) {
164         if($bounceHandlerURL) {
165             $this->bounceHandlerURL = $bounceHandlerURL;
166         } else {
167             $this->bounceHandlerURL = $_SERVER['HTTP_HOST'] . Director::baseURL() . 'Email_BounceHandler';
168         }
169     }
170     
171     public function attachFile($filename, $attachedFilename = null, $mimetype = null) {
172         $absoluteFileName = Director::getAbsFile($filename);
173         if(file_exists($absoluteFileName)) {
174             $this->attachFileFromString(file_get_contents($absoluteFileName), $attachedFilename, $mimetype);
175         } else {
176             user_error("Could not attach '$absoluteFileName' to email. File does not exist.", E_USER_NOTICE);
177         }
178     }
179 
180     public function Subject() {
181         return $this->subject;
182     }
183     
184     public function Body() {
185         return $this->body;
186     }
187     
188     public function To() {
189         return $this->to;
190     }
191     
192     public function From() {
193         return $this->from;
194     }
195     
196     public function Cc() {
197         return $this->cc;
198     }
199     
200     public function Bcc() {
201         return $this->bcc;
202     }
203     
204     public function setSubject($val) { 
205         $this->subject = $val; 
206     }
207     
208     public function setBody($val) { 
209         $this->body = $val; 
210     }
211     
212     public function setTo($val) { 
213         $this->to = $val; 
214     }
215     
216     public function setFrom($val) { 
217         $this->from = $val; 
218     }
219     
220     public function setCc($val) {
221         $this->cc = $val;
222     }
223     
224     public function setBcc($val) {
225         $this->bcc = $val;
226     }
227     
228     /**
229      * Set the "Reply-To" header with an email address.
230      * @param string $email The email address of the "Reply-To" header
231      */
232     public function replyTo($email) { 
233         $this->addCustomHeader('Reply-To', $email); 
234     }
235     
236     /**
237      * Add a custom header to this value.
238      * Useful for implementing all those cool features that we didn't think of.
239      * 
240      * @param string $headerName
241      * @param string $headerValue
242      */
243     public function addCustomHeader($headerName, $headerValue) {
244         if($headerName == 'Cc') $this->cc = $headerValue;
245         else if($headerName == 'Bcc') $this->bcc = $headerValue;
246         else {
247             if(isset($this->customHeaders[$headerName])) $this->customHeaders[$headerName] .= ", " . $headerValue;
248             else $this->customHeaders[$headerName] = $headerValue;
249         }
250     }
251 
252     public function BaseURL() {
253         return Director::absoluteBaseURL();
254     }
255     
256     /**
257      * Debugging help
258      */
259     public function debug() {
260         $this->parseVariables();
261 
262         return "<h2>Email template $this->class</h2>\n" . 
263             "<p><b>From:</b> $this->from\n" .
264             "<b>To:</b> $this->to\n" . 
265             "<b>Cc:</b> $this->cc\n" . 
266             "<b>Bcc:</b> $this->bcc\n" . 
267             "<b>Subject:</b> $this->subject</p>" . 
268             $this->body;
269     }
270 
271     /**
272      * Set template name (without *.ss extension).
273      * 
274      * @param string $template
275      */
276     public function setTemplate($template) {
277         $this->ss_template = $template;
278     }
279     
280     /**
281      * @return string
282      */
283     public function getTemplate() {
284         return $this->ss_template;
285     }
286 
287     protected function templateData() {
288         if($this->template_data) {
289             return $this->template_data->customise(array(
290                 "To" => $this->to,
291                 "Cc" => $this->cc,
292                 "Bcc" => $this->bcc,
293                 "From" => $this->from,
294                 "Subject" => $this->subject,
295                 "Body" => $this->body,
296                 "BaseURL" => $this->BaseURL(),
297                 "IsEmail" => true,
298             ));
299         } else {
300             return $this;
301         }
302     }
303     
304     /**
305      * Used by {@link SSViewer} templates to detect if we're rendering an email template rather than a page template
306      */
307     public function IsEmail() {
308         return true;
309     }
310     
311     /**
312      * Populate this email template with values.
313      * This may be called many times.
314      */
315     function populateTemplate($data) {
316         if($this->template_data) {
317             $this->template_data = $this->template_data->customise($data);  
318         } else {
319             if(is_array($data)) $data = new ArrayData($data);
320             $this->template_data = $this->customise($data);
321         }
322         $this->parseVariables_done = false;
323     }
324     
325     /**
326      * Load all the template variables into the internal variables, including
327      * the template into body.  Called before send() or debugSend()
328      * $isPlain=true will cause the template to be ignored, otherwise the GenericEmail template will be used
329      * and it won't be plain email :) 
330      */
331     protected function parseVariables($isPlain = false) {
332         SSViewer::set_source_file_comments(false);
333         
334         if(!$this->parseVariables_done) {
335             $this->parseVariables_done = true;
336 
337             // Parse $ variables in the base parameters
338             $data = $this->templateData();
339             
340             // Process a .SS template file
341             $fullBody = $this->body;
342             if($this->ss_template && !$isPlain) {
343                 // Requery data so that updated versions of To, From, Subject, etc are included
344                 $data = $this->templateData();
345                 
346                 $template = new SSViewer($this->ss_template);
347                 
348                 if($template->exists()) {
349                     $fullBody = $template->process($data);
350                 }
351             }
352             
353             // Rewrite relative URLs
354             $this->body = HTTP::absoluteURLs($fullBody);
355         }
356     }
357     
358     /**
359      * @desc Validates the email address. Returns true of false
360      */
361     static function validEmailAddress($address) {
362         return ereg('^([a-zA-Z0-9_+\.\-]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$', $address);
363     }
364     
365     /**
366      * Send the email in plaintext.
367      * 
368      * @see send() for sending emails with HTML content.
369      * @uses Mailer->sendPlain()
370      * 
371      * @param string $messageID Optional message ID so the message can be identified in bounces etc.
372      * @return bool Success of the sending operation from an MTA perspective. 
373      * Doesn't actually give any indication if the mail has been delivered to the recipient properly)
374      */
375     function sendPlain($messageID = null) {
376         Requirements::clear();
377         
378         $this->parseVariables(true);
379         
380         if(empty($this->from)) $this->from = Email::getAdminEmail();
381                         
382         $this->setBounceHandlerURL($this->bounceHandlerURL);
383         
384         $headers = $this->customHeaders;
385         
386         $headers['X-SilverStripeBounceURL'] = $this->bounceHandlerURL;
387                         
388         if($messageID) $headers['X-SilverStripeMessageID'] = project() . '.' . $messageID;
389                         
390         if(@$_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1') 
391             $headers['X-SilverStripeClientIP'] = $_SERVER['REMOTE_ADDR'];
392 
393         $to = $this->to;
394         $subject = $this->subject;
395         if(self::$send_all_emails_to) {
396             $subject .= " [addressed to $to";
397             $to = self::$send_all_emails_to;
398             if($this->cc) $subject .= ", cc to $this->cc";
399             if($this->bcc) $subject .= ", bcc to $this->bcc";
400             $subject .= ']';
401         } else {
402             if($this->cc) $headers['Cc'] = $this->cc;
403             if($this->bcc) $headers['Bcc'] = $this->bcc;
404         }
405     
406         if(self::$cc_all_emails_to) {
407             if(!empty($headers['Cc']) && trim($headers['Cc'])) {
408                 $headers['Cc'] .= ', ' . self::$cc_all_emails_to;       
409             } else {
410                 $headers['Cc'] = self::$cc_all_emails_to;
411             }
412         }
413 
414         if(self::$bcc_all_emails_to) {
415             if(!empty($headers['Bcc']) && trim($headers['Bcc'])) {
416                 $headers['Bcc'] .= ', ' . self::$bcc_all_emails_to;
417             } else {
418                 $headers['Bcc'] = self::$bcc_all_emails_to;
419             }
420         }
421 
422         Requirements::restore();
423         
424         return self::mailer()->sendPlain($to, $this->from, $subject, $this->body, $this->attachments, $headers);
425     }
426     
427     /**
428      * Send an email with HTML content.
429      *
430      * @see sendPlain() for sending plaintext emails only.
431      * @uses Mailer->sendHTML()
432      * 
433      * @param string $messageID Optional message ID so the message can be identified in bounces etc.
434      * @return bool Success of the sending operation from an MTA perspective. 
435      * Doesn't actually give any indication if the mail has been delivered to the recipient properly)
436      */
437     public function send($messageID = null) {
438         Requirements::clear();
439     
440         $this->parseVariables();
441 
442         if(empty($this->from)) $this->from = Email::getAdminEmail();
443 
444         $this->setBounceHandlerURL( $this->bounceHandlerURL );
445 
446         $headers = $this->customHeaders;
447 
448         $headers['X-SilverStripeBounceURL'] = $this->bounceHandlerURL;
449 
450         if($messageID) $headers['X-SilverStripeMessageID'] = project() . '.' . $messageID;
451 
452         if(@$_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1') 
453             $headers['X-SilverStripeClientIP'] = $_SERVER['REMOTE_ADDR'];
454 
455         $to = $this->to;
456         $subject = $this->subject;
457         if(self::$send_all_emails_to) {
458             $subject .= " [addressed to $to";
459             $to = self::$send_all_emails_to;
460             if($this->cc) $subject .= ", cc to $this->cc";
461             if($this->bcc) $subject .= ", bcc to $this->bcc";
462             $subject .= ']';
463             unset($headers['Cc']);
464             unset($headers['Bcc']);
465         } else {
466             if($this->cc) $headers['Cc'] = $this->cc;
467             if($this->bcc) $headers['Bcc'] = $this->bcc;
468         }
469 
470         if(self::$cc_all_emails_to) {
471             if(!empty($headers['Cc']) && trim($headers['Cc'])) {
472                 $headers['Cc'] .= ', ' . self::$cc_all_emails_to;       
473             } else {
474                 $headers['Cc'] = self::$cc_all_emails_to;
475             }
476         }
477         
478         if(self::$bcc_all_emails_to) {
479             if(!empty($headers['Bcc']) && trim($headers['Bcc'])) {
480                 $headers['Bcc'] .= ', ' . self::$bcc_all_emails_to;     
481             } else {
482                 $headers['Bcc'] = self::$bcc_all_emails_to;
483             }
484         }
485         
486         Requirements::restore();
487         
488         return self::mailer()->sendHTML($to, $this->from, $subject, $this->body, $this->attachments, $headers, $this->plaintext_body);
489     }
490 
491     /**
492      * Used as a default sender address in the {@link Email} class
493      * unless overwritten. Also shown to users on live environments
494      * as a contact address on system error pages.
495      * 
496      * Used by {@link Email->send()}, {@link Email->sendPlain()}, {@link Debug->friendlyError()}.
497      * 
498      * @param string $newEmail
499      */
500     public static function setAdminEmail($newEmail) {
501         self::$admin_email_address = $newEmail;
502     }
503     
504     /**
505      * @return string
506      */
507     public static function getAdminEmail() {
508         return self::$admin_email_address;
509     }
510 
511     /**
512      * Send every email generated by the Email class to the given address.
513      * It will also add " [addressed to (email), cc to (email), bcc to (email)]" to the end of the subject line
514      * This can be used when testing, by putting a command like this in your _config.php file
515      * 
516      * if(!Director::isLive()) Email::send_all_emails_to("someone@example.com")
517      */
518     public static function send_all_emails_to($emailAddress) {
519         self::$send_all_emails_to = $emailAddress;
520     }
521     
522     /**
523      * CC every email generated by the Email class to the given address.
524      * It won't affect the original delivery in the same way that send_all_emails_to does.  It just adds a CC header 
525      * with the given email address.    Note that you can only call this once - subsequent calls will overwrite the configuration
526      * variable.
527      *
528      * This can be used when you have a system that relies heavily on email and you want someone to be checking all correspondence.
529      * 
530      * if(Director::isLive()) Email::cc_all_emails_to("supportperson@example.com")
531      */
532     public static function cc_all_emails_to($emailAddress) {
533         self::$cc_all_emails_to = $emailAddress;
534     }
535 
536     /**
537      * BCC every email generated by the Email class to the given address.
538      * It won't affect the original delivery in the same way that send_all_emails_to does.  It just adds a BCC header 
539      * with the given email address.    Note that you can only call this once - subsequent calls will overwrite the configuration
540      * variable.
541      *
542      * This can be used when you have a system that relies heavily on email and you want someone to be checking all correspondence.
543      * 
544      * if(Director::isLive()) Email::cc_all_emails_to("supportperson@example.com")
545      */
546     public static function bcc_all_emails_to($emailAddress) {
547         self::$bcc_all_emails_to = $emailAddress;
548     }
549     
550     /**
551      * Checks for RFC822-valid email format.
552      * 
553      * @param string $str
554      * @return boolean
555      * 
556      * @see http://code.iamcal.com/php/rfc822/rfc822.phps
557      * @copyright Cal Henderson <cal@iamcal.com> 
558      *  This code is licensed under a Creative Commons Attribution-ShareAlike 2.5 License 
559      *  http://creativecommons.org/licenses/by-sa/2.5/
560      */
561     function is_valid_address($email){
562         $qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
563         $dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
564         $atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c'.
565             '\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
566         $quoted_pair = '\\x5c[\\x00-\\x7f]';
567         $domain_literal = "\\x5b($dtext|$quoted_pair)*\\x5d";
568         $quoted_string = "\\x22($qtext|$quoted_pair)*\\x22";
569         $domain_ref = $atom;
570         $sub_domain = "($domain_ref|$domain_literal)";
571         $word = "($atom|$quoted_string)";
572         $domain = "$sub_domain(\\x2e$sub_domain)*";
573         $local_part = "$word(\\x2e$word)*";
574         $addr_spec = "$local_part\\x40$domain";
575 
576         return preg_match("!^$addr_spec$!", $email) ? 1 : 0;
577     }
578 
579     /**
580      * Encode an email-address to protect it from spambots.
581      * At the moment only simple string substitutions,
582      * which are not 100% safe from email harvesting.
583      * 
584      * @todo Integrate javascript-based solution
585      * 
586      * @param string $email Email-address
587      * @param string $method Method for obfuscating/encoding the address
588      *  - 'direction': Reverse the text and then use CSS to put the text direction back to normal
589      *  - 'visible': Simple string substitution ('@' to '[at]', '.' to '[dot], '-' to [dash])
590      *  - 'hex': Hexadecimal URL-Encoding - useful for mailto: links
591      * @return string
592      */
593     public static function obfuscate($email, $method = 'visible') {
594         switch($method) {
595             case 'direction' :
596                 Requirements::customCSS(
597                     'span.codedirection { unicode-bidi: bidi-override; direction: rtl; }',
598                     'codedirectionCSS'
599                 );
600                 return '<span class="codedirection">' . strrev($email) . '</span>';
601             case 'visible' :
602                 $obfuscated = array('@' => ' [at] ', '.' => ' [dot] ', '-' => ' [dash] ');
603                 return strtr($email, $obfuscated);
604             case 'hex' :
605                 $encoded = '';
606                 for ($x=0; $x < strlen($email); $x++) $encoded .= '&#x' . bin2hex($email{$x}).';';
607                 return $encoded;
608             default:
609                 user_error('Email::obfuscate(): Unknown obfuscation method', E_USER_NOTICE);
610                 return $email;
611         }
612     }
613 }
614 
615 /**
616  * Base class that email bounce handlers extend
617  * @package sapphire
618  * @subpackage email
619  */
620 class Email_BounceHandler extends Controller {
621     
622     function init() {
623         BasicAuth::protect_entire_site(false);
624         parent::init();
625     }
626     
627     function index() {
628         $subclasses = ClassInfo::subclassesFor( $this->class );
629         unset($subclasses[$this->class]);
630         
631         if( $subclasses ) { 
632             $subclass = array_pop( $subclasses ); 
633             $task = new $subclass();
634             $task->index();
635             return;
636         }    
637                 
638         // Check if access key exists
639         if( !isset($_REQUEST['Key']) ) {
640             echo 'Error: Access validation failed. No "Key" specified.';
641             return;
642         }
643 
644         // Check against access key defined in sapphire/_config.php
645         if( $_REQUEST['Key'] != EMAIL_BOUNCEHANDLER_KEY) {
646             echo 'Error: Access validation failed. Invalid "Key" specified.';
647             return;
648         }
649 
650         if( !$_REQUEST['Email'] ) {
651             echo "No email address\n";
652             return;     
653         }
654         
655         $this->recordBounce( $_REQUEST['Email'], $_REQUEST['Date'], $_REQUEST['Time'], $_REQUEST['Message'] );
656     }
657         
658     private function recordBounce( $email, $date = null, $time = null, $error = null ) {
659         if(ereg('<(.*)>', $email, $parts)) $email = $parts[1];
660         
661         if( !$date )
662             $date = date( 'Y-m-d' );
663         else
664             $date = date( 'Y-m-d', strtotime( $date ) );
665         
666         if( !$time )
667             $time = date( 'H:i:s' );
668         else
669             $time = date( 'H:i:s', strtotime( $time ) );
670 
671         $SQL_email = Convert::raw2sql($email);
672         $SQL_bounceTime = Convert::raw2sql("$date $time");
673 
674         $duplicateBounce = DataObject::get_one("Email_BounceRecord", "\"BounceEmail\" = '$SQL_email' AND (\"BounceTime\"+INTERVAL 1 MINUTE) > '$SQL_bounceTime'");
675         
676         if(!$duplicateBounce) {
677             $record = new Email_BounceRecord();
678             
679             $member = DataObject::get_one( 'Member', "\"Email\"='$SQL_email'" );
680             
681             if( $member ) {
682                 $record->MemberID = $member->ID;
683 
684                 // If the SilverStripeMessageID (taken from the X-SilverStripeMessageID header embedded in the email) is sent,
685                 // then log this bounce in a Newsletter_SentRecipient record so it will show up on the 'Sent Status Report' tab of the Newsletter
686                 if( isset($_REQUEST['SilverStripeMessageID'])) {
687                     // Note: was sent out with: $project . '.' . $messageID;
688                     $message_id_parts = explode('.', $_REQUEST['SilverStripeMessageID']);
689                     // Note: was encoded with: base64_encode( $newsletter->ID . '_' . date( 'd-m-Y H:i:s' ) );
690                     $newsletter_id_date_parts = explode ('_', base64_decode($message_id_parts[1]) );
691         
692                     // Escape just in case
693                     $SQL_memberID = Convert::raw2sql($member->ID);
694                     $SQL_newsletterID = Convert::raw2sql($newsletter_id_date_parts[0]);
695                     
696                     // Log the bounce
697                     $oldNewsletterSentRecipient = DataObject::get_one("Newsletter_SentRecipient", "\"MemberID\" = '$SQL_memberID' AND \"ParentID\" = '$SQL_newsletterID' AND \"Email\" = '$SQL_email'");
698                     
699                     // Update the Newsletter_SentRecipient record if it exists
700                     if($oldNewsletterSentRecipient) {           
701                         $oldNewsletterSentRecipient->Result = 'Bounced';
702                         $oldNewsletterSentRecipient->write();
703                     } else {
704                         // For some reason it didn't exist, create a new record
705                         $newNewsletterSentRecipient = new Newsletter_SentRecipient();
706                         $newNewsletterSentRecipient->Email = $SQL_email;
707                         $newNewsletterSentRecipient->MemberID = $member->ID;
708                         $newNewsletterSentRecipient->Result = 'Bounced';
709                         $newNewsletterSentRecipient->ParentID = $newsletter_id_date_parts[0];
710                         $newNewsletterSentRecipient->write();
711                     }
712 
713                     // Now we are going to Blacklist this member so that email will not be sent to them in the future.
714                     // Note: Sending can be re-enabled by going to 'Mailing List' 'Bounced' tab and unchecking the box under 'Blacklisted'
715                     $member->setBlacklistedEmail(TRUE);
716                     echo '<p><b>Member: '.$member->FirstName.' '.$member->Surname.' <'.$member->Email.'> was added to the Email Blacklist!</b></p>'."\n";
717                 }
718             } 
719             $record->BounceEmail = $email;
720             $record->BounceTime = $date . ' ' . $time;
721             $record->BounceMessage = $error;
722             $record->write();
723             
724             echo "Handled bounced email to address: $email\n";
725         } else {
726             echo "Sorry, this bounce report has already been logged, not logging this duplicate bounce.\n";
727         }
728     }   
729         
730 }
731 
732 /**
733  * Database record for recording a bounced email
734  * @package sapphire
735  * @subpackage email
736  */
737 class Email_BounceRecord extends DataObject {
738     static $db = array(
739             'BounceEmail' => 'Varchar',
740             'BounceTime' => 'SS_Datetime',
741             'BounceMessage' => 'Varchar'
742     );
743     
744     static $has_one = array(
745             'Member' => 'Member'
746     );   
747 
748     static $has_many = array();
749     
750     static $many_many = array();
751     
752     static $defaults = array();
753     
754     static $singular_name = 'Email Bounce Record';
755     
756     
757     /** 
758     * a record of Email_BounceRecord can't be created manually. Instead, it should be   
759     * created though system. 
760     */ 
761     public function canCreate($member = null) { 
762         return false; 
763     }
764 }
765 
766 ?>
767 
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -
Webylon 3.1 API Docs API documentation generated by ApiGen 2.8.0