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

Packages

  • 1c
    • exchange
      • catalog
  • auth
  • Booking
  • building
    • company
  • cart
    • shipping
    • steppedcheckout
  • Catalog
    • monument
  • 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
  • SimpleOrderPage_SubmittedFormEmail
  • 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 setPlainBody($val) { 
213         $this->plaintext_body = $val; 
214     }
215     
216     public function setTo($val) { 
217         $this->to = $val; 
218     }
219     
220     public function setFrom($val) { 
221         $this->from = $val; 
222     }
223     
224     public function setCc($val) {
225         $this->cc = $val;
226     }
227     
228     public function setBcc($val) {
229         $this->bcc = $val;
230     }
231     
232     /**
233      * Set the "Reply-To" header with an email address.
234      * @param string $email The email address of the "Reply-To" header
235      */
236     public function replyTo($email) { 
237         $this->addCustomHeader('Reply-To', $email); 
238     }
239     
240     /**
241      * Add a custom header to this value.
242      * Useful for implementing all those cool features that we didn't think of.
243      * 
244      * @param string $headerName
245      * @param string $headerValue
246      */
247     public function addCustomHeader($headerName, $headerValue) {
248         if($headerName == 'Cc') $this->cc = $headerValue;
249         else if($headerName == 'Bcc') $this->bcc = $headerValue;
250         else {
251             if(isset($this->customHeaders[$headerName])) $this->customHeaders[$headerName] .= ", " . $headerValue;
252             else $this->customHeaders[$headerName] = $headerValue;
253         }
254     }
255 
256     public function BaseURL() {
257         return Director::absoluteBaseURL();
258     }
259     
260     /**
261      * Debugging help
262      */
263     public function debug() {
264         $this->parseVariables();
265 
266         return "<h2>Email template $this->class</h2>\n" . 
267             "<p><b>From:</b> $this->from\n" .
268             "<b>To:</b> $this->to\n" . 
269             "<b>Cc:</b> $this->cc\n" . 
270             "<b>Bcc:</b> $this->bcc\n" . 
271             "<b>Subject:</b> $this->subject</p>" . 
272             $this->body;
273     }
274 
275     /**
276      * Set template name (without *.ss extension).
277      * 
278      * @param string $template
279      */
280     public function setTemplate($template) {
281         $this->ss_template = $template;
282     }
283     
284     /**
285      * @return string
286      */
287     public function getTemplate() {
288         return $this->ss_template;
289     }
290 
291     protected function templateData() {
292         if($this->template_data) {
293             return $this->template_data->customise(array(
294                 "To" => $this->to,
295                 "Cc" => $this->cc,
296                 "Bcc" => $this->bcc,
297                 "From" => $this->from,
298                 "Subject" => $this->subject,
299                 "Body" => $this->body,
300                 "BaseURL" => $this->BaseURL(),
301                 "IsEmail" => true,
302             ));
303         } else {
304             return $this;
305         }
306     }
307     
308     /**
309      * Used by {@link SSViewer} templates to detect if we're rendering an email template rather than a page template
310      */
311     public function IsEmail() {
312         return true;
313     }
314     
315     /**
316      * Populate this email template with values.
317      * This may be called many times.
318      */
319     function populateTemplate($data) {
320         if($this->template_data) {
321             $this->template_data = $this->template_data->customise($data);  
322         } else {
323             if(is_array($data)) $data = new ArrayData($data);
324             $this->template_data = $this->customise($data);
325         }
326         $this->parseVariables_done = false;
327     }
328     
329     /**
330      * Load all the template variables into the internal variables, including
331      * the template into body.  Called before send() or debugSend()
332      * $isPlain=true will cause the template to be ignored, otherwise the GenericEmail template will be used
333      * and it won't be plain email :) 
334      */
335     protected function parseVariables($isPlain = false) {
336         SSViewer::set_source_file_comments(false);
337         
338         if(!$this->parseVariables_done) {
339             $this->parseVariables_done = true;
340 
341             // Parse $ variables in the base parameters
342             $data = $this->templateData();
343             
344             // Process a .SS template file
345             $fullBody = $this->body;
346             if ($this->getTemplate()) {
347 
348                 $template = new SSViewer(($isPlain) ? $this->getTemplate() . '_plain' : $this->getTemplate());
349                 if ($template->exists()) {
350                 // Requery data so that updated versions of To, From, Subject, etc are included
351                     $fullBody = $template->process($this->templateData());
352                 }
353             }
354             // Rewrite relative URLs
355             $this->body = HTTP::absoluteURLs($fullBody);
356         }
357     }
358 
359     function renderWith($template, $customFields = null) {
360         return $this->templateData()->renderWith($template, $customFields);
361     }
362     
363     /**
364      * @desc Validates the email address. Returns true of false
365      */
366     static function validEmailAddress($address) {
367         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);
368     }
369     
370     /**
371      * Send the email in plaintext.
372      * 
373      * @see send() for sending emails with HTML content.
374      * @uses Mailer->sendPlain()
375      * 
376      * @param string $messageID Optional message ID so the message can be identified in bounces etc.
377      * @return bool Success of the sending operation from an MTA perspective. 
378      * Doesn't actually give any indication if the mail has been delivered to the recipient properly)
379      */
380     function sendPlain($messageID = null) {
381         Requirements::clear();
382         
383         $this->parseVariables(true);
384         
385         if(empty($this->from)) $this->from = Email::getAdminEmail();
386                         
387         $this->setBounceHandlerURL($this->bounceHandlerURL);
388         
389         $headers = $this->customHeaders;
390         
391         $headers['X-SilverStripeBounceURL'] = $this->bounceHandlerURL;
392                         
393         if($messageID) $headers['X-SilverStripeMessageID'] = project() . '.' . $messageID;
394                         
395         if(@$_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1') 
396             $headers['X-SilverStripeClientIP'] = $_SERVER['REMOTE_ADDR'];
397 
398         $to = $this->to;
399         $subject = $this->subject;
400         if(self::$send_all_emails_to) {
401             $subject .= " [addressed to $to";
402             $to = self::$send_all_emails_to;
403             if($this->cc) $subject .= ", cc to $this->cc";
404             if($this->bcc) $subject .= ", bcc to $this->bcc";
405             $subject .= ']';
406         } else {
407             if($this->cc) $headers['Cc'] = $this->cc;
408             if($this->bcc) $headers['Bcc'] = $this->bcc;
409         }
410     
411         if(self::$cc_all_emails_to) {
412             if(!empty($headers['Cc']) && trim($headers['Cc'])) {
413                 $headers['Cc'] .= ', ' . self::$cc_all_emails_to;       
414             } else {
415                 $headers['Cc'] = self::$cc_all_emails_to;
416             }
417         }
418 
419         if(self::$bcc_all_emails_to) {
420             if(!empty($headers['Bcc']) && trim($headers['Bcc'])) {
421                 $headers['Bcc'] .= ', ' . self::$bcc_all_emails_to;
422             } else {
423                 $headers['Bcc'] = self::$bcc_all_emails_to;
424             }
425         }
426 
427         Requirements::restore();
428         
429         return self::mailer()->sendPlain($to, $this->from, $subject, ($this->plaintext_body) ? $this->plaintext_body : $this->body, $this->attachments, $headers);
430     }
431     
432     /**
433      * Send an email with HTML content.
434      *
435      * @see sendPlain() for sending plaintext emails only.
436      * @uses Mailer->sendHTML()
437      * 
438      * @param string $messageID Optional message ID so the message can be identified in bounces etc.
439      * @return bool Success of the sending operation from an MTA perspective. 
440      * Doesn't actually give any indication if the mail has been delivered to the recipient properly)
441      */
442     public function send($messageID = null) {
443         Requirements::clear();
444     
445         $this->parseVariables();
446 
447         if(empty($this->from)) $this->from = Email::getAdminEmail();
448 
449         $this->setBounceHandlerURL( $this->bounceHandlerURL );
450 
451         $headers = $this->customHeaders;
452 
453         $headers['X-SilverStripeBounceURL'] = $this->bounceHandlerURL;
454 
455         if($messageID) $headers['X-SilverStripeMessageID'] = project() . '.' . $messageID;
456 
457         if(@$_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1') 
458             $headers['X-SilverStripeClientIP'] = $_SERVER['REMOTE_ADDR'];
459 
460         $to = $this->to;
461         $subject = $this->subject;
462         if(self::$send_all_emails_to) {
463             $subject .= " [addressed to $to";
464             $to = self::$send_all_emails_to;
465             if($this->cc) $subject .= ", cc to $this->cc";
466             if($this->bcc) $subject .= ", bcc to $this->bcc";
467             $subject .= ']';
468             unset($headers['Cc']);
469             unset($headers['Bcc']);
470         } else {
471             if($this->cc) $headers['Cc'] = $this->cc;
472             if($this->bcc) $headers['Bcc'] = $this->bcc;
473         }
474 
475         if(self::$cc_all_emails_to) {
476             if(!empty($headers['Cc']) && trim($headers['Cc'])) {
477                 $headers['Cc'] .= ', ' . self::$cc_all_emails_to;       
478             } else {
479                 $headers['Cc'] = self::$cc_all_emails_to;
480             }
481         }
482         
483         if(self::$bcc_all_emails_to) {
484             if(!empty($headers['Bcc']) && trim($headers['Bcc'])) {
485                 $headers['Bcc'] .= ', ' . self::$bcc_all_emails_to;     
486             } else {
487                 $headers['Bcc'] = self::$bcc_all_emails_to;
488             }
489         }
490         
491         Requirements::restore();
492         
493         return self::mailer()->sendHTML($to, $this->from, $subject, $this->body, $this->attachments, $headers, $this->plaintext_body);
494     }
495 
496     /**
497      * Used as a default sender address in the {@link Email} class
498      * unless overwritten. Also shown to users on live environments
499      * as a contact address on system error pages.
500      * 
501      * Used by {@link Email->send()}, {@link Email->sendPlain()}, {@link Debug->friendlyError()}.
502      * 
503      * @param string $newEmail
504      */
505     public static function setAdminEmail($newEmail) {
506         self::$admin_email_address = $newEmail;
507     }
508     
509     /**
510      * @return string
511      */
512     public static function getAdminEmail() {
513         return self::$admin_email_address;
514     }
515 
516     /**
517      * Send every email generated by the Email class to the given address.
518      * It will also add " [addressed to (email), cc to (email), bcc to (email)]" to the end of the subject line
519      * This can be used when testing, by putting a command like this in your _config.php file
520      * 
521      * if(!Director::isLive()) Email::send_all_emails_to("someone@example.com")
522      */
523     public static function send_all_emails_to($emailAddress) {
524         self::$send_all_emails_to = $emailAddress;
525     }
526     
527     /**
528      * CC every email generated by the Email class to the given address.
529      * It won't affect the original delivery in the same way that send_all_emails_to does.  It just adds a CC header 
530      * with the given email address.    Note that you can only call this once - subsequent calls will overwrite the configuration
531      * variable.
532      *
533      * This can be used when you have a system that relies heavily on email and you want someone to be checking all correspondence.
534      * 
535      * if(Director::isLive()) Email::cc_all_emails_to("supportperson@example.com")
536      */
537     public static function cc_all_emails_to($emailAddress) {
538         self::$cc_all_emails_to = $emailAddress;
539     }
540 
541     /**
542      * BCC every email generated by the Email class to the given address.
543      * It won't affect the original delivery in the same way that send_all_emails_to does.  It just adds a BCC header 
544      * with the given email address.    Note that you can only call this once - subsequent calls will overwrite the configuration
545      * variable.
546      *
547      * This can be used when you have a system that relies heavily on email and you want someone to be checking all correspondence.
548      * 
549      * if(Director::isLive()) Email::cc_all_emails_to("supportperson@example.com")
550      */
551     public static function bcc_all_emails_to($emailAddress) {
552         self::$bcc_all_emails_to = $emailAddress;
553     }
554     
555     /**
556      * Checks for RFC822-valid email format.
557      * 
558      * @param string $str
559      * @return boolean
560      * 
561      * @see http://code.iamcal.com/php/rfc822/rfc822.phps
562      * @copyright Cal Henderson <cal@iamcal.com> 
563      *  This code is licensed under a Creative Commons Attribution-ShareAlike 2.5 License 
564      *  http://creativecommons.org/licenses/by-sa/2.5/
565      */
566     function is_valid_address($email){
567         $qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
568         $dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
569         $atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c'.
570             '\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
571         $quoted_pair = '\\x5c[\\x00-\\x7f]';
572         $domain_literal = "\\x5b($dtext|$quoted_pair)*\\x5d";
573         $quoted_string = "\\x22($qtext|$quoted_pair)*\\x22";
574         $domain_ref = $atom;
575         $sub_domain = "($domain_ref|$domain_literal)";
576         $word = "($atom|$quoted_string)";
577         $domain = "$sub_domain(\\x2e$sub_domain)*";
578         $local_part = "$word(\\x2e$word)*";
579         $addr_spec = "$local_part\\x40$domain";
580 
581         return preg_match("!^$addr_spec$!", $email) ? 1 : 0;
582     }
583 
584     /**
585      * Encode an email-address to protect it from spambots.
586      * At the moment only simple string substitutions,
587      * which are not 100% safe from email harvesting.
588      * 
589      * @todo Integrate javascript-based solution
590      * 
591      * @param string $email Email-address
592      * @param string $method Method for obfuscating/encoding the address
593      *  - 'direction': Reverse the text and then use CSS to put the text direction back to normal
594      *  - 'visible': Simple string substitution ('@' to '[at]', '.' to '[dot], '-' to [dash])
595      *  - 'hex': Hexadecimal URL-Encoding - useful for mailto: links
596      * @return string
597      */
598     public static function obfuscate($email, $method = 'visible') {
599         switch($method) {
600             case 'direction' :
601                 Requirements::customCSS(
602                     'span.codedirection { unicode-bidi: bidi-override; direction: rtl; }',
603                     'codedirectionCSS'
604                 );
605                 return '<span class="codedirection">' . strrev($email) . '</span>';
606             case 'visible' :
607                 $obfuscated = array('@' => ' [at] ', '.' => ' [dot] ', '-' => ' [dash] ');
608                 return strtr($email, $obfuscated);
609             case 'hex' :
610                 $encoded = '';
611                 for ($x=0; $x < strlen($email); $x++) $encoded .= '&#x' . bin2hex($email{$x}).';';
612                 return $encoded;
613             default:
614                 user_error('Email::obfuscate(): Unknown obfuscation method', E_USER_NOTICE);
615                 return $email;
616         }
617     }
618 }
619 
620 /**
621  * Base class that email bounce handlers extend
622  * @package sapphire
623  * @subpackage email
624  */
625 class Email_BounceHandler extends Controller {
626     
627     function init() {
628         BasicAuth::protect_entire_site(false);
629         parent::init();
630     }
631     
632     function index() {
633         $subclasses = ClassInfo::subclassesFor( $this->class );
634         unset($subclasses[$this->class]);
635         
636         if( $subclasses ) { 
637             $subclass = array_pop( $subclasses ); 
638             $task = new $subclass();
639             $task->index();
640             return;
641         }    
642                 
643         // Check if access key exists
644         if( !isset($_REQUEST['Key']) ) {
645             echo 'Error: Access validation failed. No "Key" specified.';
646             return;
647         }
648 
649         // Check against access key defined in sapphire/_config.php
650         if( $_REQUEST['Key'] != EMAIL_BOUNCEHANDLER_KEY) {
651             echo 'Error: Access validation failed. Invalid "Key" specified.';
652             return;
653         }
654 
655         if( !$_REQUEST['Email'] ) {
656             echo "No email address";
657             return;     
658         }
659         
660         $this->recordBounce( $_REQUEST['Email'], $_REQUEST['Date'], $_REQUEST['Time'], $_REQUEST['Message'] );           
661     }
662         
663     private function recordBounce( $email, $date = null, $time = null, $error = null ) {
664         if(ereg('<(.*)>', $email, $parts)) $email = $parts[1];
665         
666         $SQL_email = Convert::raw2sql($email);
667         $SQL_bounceTime = Convert::raw2sql("$date $time");
668 
669         $duplicateBounce = DataObject::get_one("Email_BounceRecord", "\"BounceEmail\" = '$SQL_email' AND (\"BounceTime\"+INTERVAL 1 MINUTE) > '$SQL_bounceTime'");
670         
671         if(!$duplicateBounce) {
672             $record = new Email_BounceRecord();
673             
674             $member = DataObject::get_one( 'Member', "\"Email\"='$SQL_email'" );
675             
676             if( $member ) {
677                 $record->MemberID = $member->ID;
678 
679                 // If the SilverStripeMessageID (taken from the X-SilverStripeMessageID header embedded in the email) is sent,
680                 // then log this bounce in a Newsletter_SentRecipient record so it will show up on the 'Sent Status Report' tab of the Newsletter
681                 if( isset($_REQUEST['SilverStripeMessageID'])) {
682                     // Note: was sent out with: $project . '.' . $messageID;
683                     $message_id_parts = explode('.', $_REQUEST['SilverStripeMessageID']);
684                     // Note: was encoded with: base64_encode( $newsletter->ID . '_' . date( 'd-m-Y H:i:s' ) );
685                     $newsletter_id_date_parts = explode ('_', base64_decode($message_id_parts[1]) );
686         
687                     // Escape just in case
688                     $SQL_memberID = Convert::raw2sql($member->ID);
689                     $SQL_newsletterID = Convert::raw2sql($newsletter_id_date_parts[0]);
690                     
691                     // Log the bounce
692                     $oldNewsletterSentRecipient = DataObject::get_one("Newsletter_SentRecipient", "\"MemberID\" = '$SQL_memberID' AND \"ParentID\" = '$SQL_newsletterID' AND \"Email\" = '$SQL_email'");
693                     
694                     // Update the Newsletter_SentRecipient record if it exists
695                     if($oldNewsletterSentRecipient) {           
696                         $oldNewsletterSentRecipient->Result = 'Bounced';
697                         $oldNewsletterSentRecipient->write();
698                     } else {
699                         // For some reason it didn't exist, create a new record
700                         $newNewsletterSentRecipient = new Newsletter_SentRecipient();
701                         $newNewsletterSentRecipient->Email = $SQL_email;
702                         $newNewsletterSentRecipient->MemberID = $member->ID;
703                         $newNewsletterSentRecipient->Result = 'Bounced';
704                         $newNewsletterSentRecipient->ParentID = $newsletter_id_date_parts[0];
705                         $newNewsletterSentRecipient->write();
706                     }
707 
708                     // Now we are going to Blacklist this member so that email will not be sent to them in the future.
709                     // Note: Sending can be re-enabled by going to 'Mailing List' 'Bounced' tab and unchecking the box under 'Blacklisted'
710                     $member->setBlacklistedEmail(TRUE);
711                     echo '<p><b>Member: '.$member->FirstName.' '.$member->Surname.' <'.$member->Email.'> was added to the Email Blacklist!</b></p>';
712                 }
713             } 
714                         
715             if( !$date )
716                     $date = date( 'd-m-Y' );
717             /*else
718                     $date = date( 'd-m-Y', strtotime( $date ) );*/
719                     
720             if( !$time )
721                     $time = date( 'H:i:s' );
722             /*else
723                     $time = date( 'H:i:s', strtotime( $time ) );*/
724                     
725             $record->BounceEmail = $email;
726             $record->BounceTime = $date . ' ' . $time;
727             $record->BounceMessage = $error;
728             $record->write();
729             
730             echo "Handled bounced email to address: $email";    
731         } else {
732             echo 'Sorry, this bounce report has already been logged, not logging this duplicate bounce.';
733         }
734     }   
735         
736 }
737 
738 /**
739  * Database record for recording a bounced email
740  * @package sapphire
741  * @subpackage email
742  */
743 class Email_BounceRecord extends DataObject {
744     static $db = array(
745             'BounceEmail' => 'Varchar',
746             'BounceTime' => 'SS_Datetime',
747             'BounceMessage' => 'Varchar'
748     );
749     
750     static $has_one = array(
751             'Member' => 'Member'
752     );   
753 
754     static $has_many = array();
755     
756     static $many_many = array();
757     
758     static $defaults = array();
759     
760     static $singular_name = 'Email Bounce Record';
761     
762     
763     /** 
764     * a record of Email_BounceRecord can't be created manually. Instead, it should be   
765     * created though system. 
766     */ 
767     public function canCreate($member = null) { 
768         return false; 
769     }
770 }
771 
772 ?>
773 
[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.2 API Docs API documentation generated by ApiGen 2.8.0