Show
Ignore:
Timestamp:
05/23/06 03:30:12 (6 years ago)
Author:
john
Message:

ActionMailer? rewrite to add mailer views/models

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/trax/vendor/trax/action_mailer.php

    r162 r200  
    4242 
    4343    private 
    44         $mail_mime,  // Mail_mime object 
    45         $to_addresses, 
    46         $cc_addresses, 
    47         $bcc_addresses, 
    48         $replyto_addresses; 
     44        $mail_mime = null,  # Mail_mime object 
     45        $mail = null, # Mail object to deliver mail 
     46        $mime_params = array(), # params for charset 
     47        $errors = array(); # array to hold any errors 
    4948    public 
    50         $crlf = "\r\n", 
    51         $smtp_params = array("host"=>"localhost", "port"=>"25"), 
    52         $send_type = "mail", // smtp or mail 
    53         $subject = null, // email subject 
    54         $from_address = "no-reply@nodomain.com", 
    55         $from_name = null, 
    56         $error = null; 
    57  
    58     function __construct($crlf = null) { 
    59         if(!is_null($crlf)) { 
    60             $this->crlf = $crlf; 
    61         } 
    62         $this->mail_mime = new Mail_mime(); 
    63     } 
    64  
    65     function add_to_address($address, $name = null) { 
    66         $cur = count($this->to_addresses); 
    67         $this->to_addresses[$cur][0] = trim($address); 
    68         $this->to_addresses[$cur][1] = trim($name); 
    69     } 
    70  
    71     function add_cc_address($address, $name = null) { 
    72         $cur = count($this->cc); 
    73         $this->cc_addresses[$cur][0] = trim($address); 
    74         $this->cc_addresses[$cur][1] = trim($name); 
    75     } 
    76  
    77     function add_bcc_address($address, $name = null) { 
    78         $cur = count($this->bcc); 
    79         $this->bcc_addresses[$cur][0] = trim($address); 
    80         $this->bcc_addresses[$cur][1] = trim($name); 
    81     } 
    82  
    83     function add_replyto_address($address, $name = null) { 
    84         $cur = count($this->ReplyTo); 
    85         $this->replyto_addresses[$cur][0] = trim($address); 
    86         $this->replyto_addresses[$cur][1] = trim($name); 
    87     } 
    88  
    89     function set_from_address($address, $name = null) { 
    90         $this->from_address = trim($address); 
    91         if(!is_null($name)) 
    92             $this->from_name = trim($name); 
    93     } 
    94  
    95     function set_text_body($text) { 
    96         if(strlen($text) > 0) 
     49        $smtp_settings = array(  
     50            'host'      => 'localhost', # The server to connect. 
     51            'port'      => 25,  # The port to connect. 
     52            'persist'   => false, # Indicates whether or not the SMTP connection should persist over multiple sends. 
     53            'auth'      => false, # Whether or not to use SMTP authentication. 
     54            'username'  => null, # The username to use for SMTP authentication. 
     55            'password'  => null, # The password to use for SMTP authentication.             
     56        ), 
     57        $sendmail_settings = array( 
     58            'path' => '/usr/sbin/sendmail', 
     59            'args' => '-i -t' 
     60        ), 
     61        $views_file_extention = TRAX_VIEWS_EXTENTION, 
     62        $delivery_method = "mail", # mail | sendmail | smtp | test 
     63        $perform_deliveries = true, # true will attempt to deliver mail | false will not deliver mail 
     64        $default_charset = "utf-8", # default charset for email. 
     65        $head_charset = null, # charset for email headers. 
     66        $html_charset = null, # charset for html email body. 
     67        $text_charset = null, # charset for text email body. 
     68        $template = null, # view file to use for body of email. 
     69        $template_root = null, # template_root determines the base from which template references will be made. 
     70        $deliveries = array(), # if delivery_method is "test" it will not deliver but store emails in this array. 
     71        $recipients = null, # to address(es) 
     72        $subject = null, # email subject 
     73        $from = null, # from email address 
     74        $default_from = null, # if no from specified use this as the from. 
     75        $body = array(), # array set in child class of values for view template. 
     76        $preparse_body = array(), # holder for orginal body array from child class 
     77        $headers = array(), # email headers 
     78        $crlf = "\r\n", # linefeed char 
     79        $content_type = "text"; # text | html | both 
     80 
     81    /** 
     82     *  ActionMailer constructor. 
     83     *  @todo Document this API 
     84     */  
     85    function __construct() { 
     86        $this->mail_mime = new Mail_mime($this->crlf);                
     87    } 
     88 
     89    /** 
     90     *  Override call() to do some magic where you can call create_*() and deliver_*(). 
     91     *  @todo Document this API 
     92     */      
     93    function __call($method_name, $parameters) { 
     94        if(method_exists($this, $method_name)) { 
     95            # If the method exists, just call it 
     96            $result = call_user_func_array(array($this,$method_name), $parameters); 
     97        } else { 
     98            if(preg_match("/^create_([_a-z]\w*)/", $method_name, $matches)) { 
     99                $result = $this->create_mail($matches[1], $parameters); 
     100            } elseif(preg_match("/^deliver_([_a-z]\w*)/", $method_name, $matches)) {               
     101                $result = $this->create_mail($matches[1], $parameters); 
     102                if(!$this->deliver($result)) { 
     103                    $result = false;     
     104                } 
     105            } 
     106        } 
     107        return $result; 
     108    } 
     109 
     110    /** 
     111     *  Set all the necessary email headers 
     112     *  @todo Document this API 
     113     */      
     114    private function set_headers() { 
     115        if(!is_null($this->recipients)) { 
     116            $recipients = $this->format_emails($this->recipients, "To"); 
     117            $this->set_header_line("To", $recipients);             
     118        } 
     119         
     120        if(!is_null($this->cc)) { 
     121            $cc = $this->format_emails($this->cc, "Cc"); 
     122            $this->set_header_line("Cc", $cc);             
     123        } 
     124 
     125        if(!is_null($this->bcc)) { 
     126            $bcc = $this->format_emails($this->bcc, "Bcc"); 
     127            $this->set_header_line("Bcc", $bcc);             
     128        } 
     129 
     130        if(!is_null($this->reply_to)) { 
     131            $reply_to = $this->format_emails($this->reply_to, "Reply-To"); 
     132            $this->set_header_line("Reply-To", $reply_to);             
     133        } 
     134         
     135        if(!is_null($this->from)) { 
     136            $this->from = $this->default_from;             
     137        }  
     138        $from = $this->format_emails($this->from, "From"); 
     139        $this->set_header_line("From", $from); 
     140         
     141        if(!is_null($this->subject))  { 
     142            $this->set_header_line("Subject", $this->subject); 
     143        } else { 
     144            $this->set_header_line("Subject", ""); 
     145        } 
     146 
     147        if(!array_key_exists("Date", $this->headers)) { 
     148            $this->set_header_line("Date", date("r")); 
     149        } 
     150         
     151        if(!array_key_exists("Return-Path", $this->headers) && !is_null($this->from_address)) { 
     152            $this->set_header_line("Return-Path", $this->from_address); 
     153        }   
     154           
     155        if(!array_key_exists("Reply-To", $this->headers) && !is_null($this->from_address)) { 
     156            $this->set_header_line("Reply-To", $this->from_address);             
     157        } 
     158    } 
     159 
     160    /** 
     161     *  Format an array of emails into a correct string / validate emails. 
     162     *  @todo Document this API 
     163     */     
     164    private function format_emails($emails, $type = null) { 
     165      
     166        $email_addresses = null;      
     167        if(!is_null($emails) && is_string($emails)) { 
     168            if(strstr($emails, ",")) { 
     169                $emails = explode(",", $emails);         
     170            } else { 
     171                $emails = array($emails);     
     172            }     
     173        }         
     174        if(is_array($emails)) { 
     175            foreach($emails as $email) { 
     176                if($this->validate_email($email)) { 
     177                    $email_addresses[] = $email; 
     178                } else { 
     179                    if($type) { 
     180                        $type = "$type ";     
     181                    } 
     182                    $this->errors[] = "Invalid ".$type."email address: ".$email;     
     183                } 
     184            } 
     185            if(is_array($email_addresses)) { 
     186                $email_addresses = implode(",", $email_addresses); 
     187            }                      
     188        }       
     189 
     190        return $email_addresses;            
     191    } 
     192 
     193    /** 
     194     *  Set the text body of the email. 
     195     *  @todo Document this API 
     196     */     
     197    private function set_text_body($text) { 
     198        if(strlen($text) > 0) { 
    97199            $this->mail_mime->setTxtBody($text); 
    98     } 
    99  
    100     function set_html_body($html) { 
    101         if(strlen($html) > 0) 
     200        } 
     201    } 
     202 
     203    /** 
     204     *  Set the html body of the email. 
     205     *  @todo Document this API 
     206     */ 
     207    private function set_html_body($html) { 
     208        if(strlen($html) > 0) { 
    102209            $this->mail_mime->setHTMLBody($html); 
    103     } 
    104      
    105     function set_subject($subject) { 
    106         $this->subject = $subject;     
    107     } 
    108  
     210        } 
     211    }     
     212 
     213    /** 
     214     *  Sets up default class variables for this mailer.  Classes extending 
     215     *  ActionMailer can override these values. 
     216     *  @todo Document this API 
     217     */ 
     218    private function initialize_defaults($method_name) {        
     219        $this->template_root = TRAX_ROOT . $GLOBALS['TRAX_INCLUDES']['views']; 
     220        $this->template_path = "{$this->template_root}/".Inflector::underscore(get_class($this)); 
     221        $this->template = $this->template ? $this->template : $method_name;         
     222        $this->headers = $this->headers ? $this->headers : array(); 
     223        $this->body = $this->body ? $this->body : array(); 
     224        $this->default_from = "nobody@".$_SERVER['HTTP_HOST']; 
     225        $this->head_charset = $this->head_charset ? $this->head_charset : $this->default_charset; 
     226        $this->html_charset = $this->html_charset ? $this->html_charset : $this->default_charset; 
     227        $this->text_charset = $this->text_charset ? $this->text_charset : $this->default_charset; 
     228        $this->mime_params = array( 
     229            'head_charset' => $this->head_charset,  
     230            'html_charset' =>  $this->html_charset, 
     231            'text_charset' =>  $this->text_charset 
     232        );          
     233    } 
     234 
     235    /** 
     236     *  Sets up and creates the email for deliver(). 
     237     *  @todo Document this API 
     238     */ 
     239    private function create_mail($method_name, $parameters = array()) {   
     240        $this->initialize_defaults($method_name); 
     241        if(method_exists($this, $method_name)) { 
     242            //echo "calling $method_name<br>"; 
     243            call_user_func_array(array($this, $method_name), $parameters);    
     244        }    
     245        $this->set_headers(); 
     246        $body = $this->preparse_body = $this->body; 
     247        if(!is_string($body)) { 
     248            $body = $this->render_message($method_name, $body); 
     249        } 
     250        if($this->content_type == "html") { 
     251            $this->set_html_body($body);        
     252        } elseif($this->content_type == "both") { 
     253            $this->set_html_body($body);  
     254            $this->set_text_body($body);    
     255        } else { 
     256            $this->set_text_body($body);         
     257        } 
     258            
     259        $this->body = $this->mail_mime->get($this->mime_params);       
     260        $this->headers = $this->mail_mime->headers($this->headers);   
     261        $this->headers['Subject'] = ereg_replace("[\n\r]", "", $this->headers['Subject']);  
     262 
     263        if($this->delivery_method == "sendmail") { 
     264            $this->mail =& Mail::factory("sendmail", $this->sendmail_settings); 
     265        } elseif($this->delivery_method == "smtp") { 
     266            $this->mail =& Mail::factory("smtp", $this->smtp_settings); 
     267        } else { 
     268            $this->mail =& Mail::factory("mail");     
     269        } 
     270 
     271        return $this; 
     272    } 
     273 
     274    /** 
     275     *  Load the template view file for the body of the email. 
     276     *  @todo Document this API 
     277     */ 
     278    function render_message($method_name, $body = array()) { 
     279        if(strstr($method_name, "/")) { 
     280            $template = "{$this->template_root}/{$method_name}.{$this->views_file_extention}"; 
     281        } else { 
     282            $template = "{$this->template_path}/{$method_name}.{$this->views_file_extention}"; 
     283        } 
     284 
     285        if(file_exists($template)) { 
     286            # start to buffer output 
     287            ob_start();  
     288            if(count($body)) { 
     289                extract($body);   
     290            } 
     291            include($template); 
     292            $result = ob_get_contents(); 
     293            ob_end_clean(); 
     294        } 
     295        return $result;         
     296    } 
     297 
     298    /** 
     299     *  Uses ActionControllers render_partial method. 
     300     *  @todo Document this API 
     301     */       
     302    function render_partial($path, $options = array()) { 
     303        $locals = $this->preparse_body; 
     304        if(is_array($options['locals']) && is_array($locals)) { 
     305            $options['locals'] = array_merge($locals, $options['locals']); 
     306        } elseif(is_array($locals)) { 
     307            $options['locals'] = $locals;     
     308        } 
     309        $ar = new ActionController(); 
     310        $ar->views_path = $this->template_path; 
     311        $ar->render_partial($path, $options);                      
     312    } 
     313 
     314    /** 
     315     *  Return a text version of the email currently loaded. 
     316     *  @todo Document this API 
     317     */     
     318    function encoded($add_pre_tags = false) {                    
     319        if(!count($this->errors)) { 
     320            list(, $text_headers) = $this->mail->prepareHeaders($this->headers); 
     321            $email = $text_headers.$this->crlf.$this->crlf.$this->body; 
     322            if($add_pre_tags) { 
     323                $email = "<pre>".$email."</pre>";     
     324            } 
     325        } else { 
     326            $email = $this->get_errors_as_string("\n");     
     327        } 
     328        return $email; 
     329    } 
     330 
     331    /** 
     332     *  Sends the email loaded into this object via create_mail(). 
     333     *  @todo Document this API 
     334     */     
     335    function deliver($mail = null) { 
     336        if(is_null($mail)) { 
     337            $mail =& $this;                
     338        }  
     339        if($this->perform_deliveries) { 
     340            if($this->delivery_method == "test") { 
     341                $this->deliveries[] = $mail->encoded(); 
     342                return true;     
     343            } 
     344            if(!count($this->errors)) {  
     345                $result = $mail->mail->send(null, $mail->headers, $mail->body); 
     346                if(is_object($result)) {  
     347                    $this->errors[] = $result->getMessage(); 
     348                    return false; 
     349                }  
     350            } else { 
     351                return false; 
     352            } 
     353        } 
     354        return true; 
     355    } 
     356 
     357    /** 
     358     *  Add an attachment to an email. 
     359     *  @todo Document this API 
     360     */ 
    109361    function add_attachment($file, $content_type ='application/octet-stream', $file_name = '', $is_file = true, $encoding = 'base64') { 
    110362        $this->mail_mime->addAttachment($file, $content_type, $file_name, $is_file, $encoding); 
    111363    } 
    112364 
    113     function format_address($address) { 
    114         if(empty($address[1])) 
    115             $formatted = $address[0]; 
    116         else 
    117             $formatted = sprintf('"%s" <%s>', $address[1], $address[0]); 
    118  
    119         // now validate if the email address 
    120         if(!$this->validate_email($address[0])) { 
    121             $this->error .= "Invalid email address: ".$address[0]."<br>"; 
    122         } 
    123  
    124         return $formatted; 
    125     } 
    126  
     365    /** 
     366     *  Validates a single email address 
     367     * 
     368     *  @param string $email 
     369     *    Validates the input $email is in format: 
     370     *      user@domain.com or "John Smith <user@domain.com>" 
     371     *  @return boolean  
     372     *    <ul> 
     373     *      <li>true => Valid email, no errors found. 
     374     *      <li>false => Email not valid</li> 
     375     *    </ul> 
     376     */ 
    127377    function validate_email($email) { 
    128         if(eregi("^[a-zA-Z0-9._-]+@([a-zA-Z0-9._-]+\.)+([a-zA-Z0-9_-]){2,4}$", $email)) { 
     378        if(eregi("^[a-zA-Z0-9._-]+@([a-zA-Z0-9._-]+\.)+([a-zA-Z0-9_-]){2,4}$", $email) || 
     379           eregi("^([ '_a-zA-Z0-9]\w*)+<[a-zA-Z0-9._-]+@([a-zA-Z0-9._-]+\.)+([a-zA-Z0-9_-]){2,4}>$", $email)) { 
    129380            return true; 
    130381        } 
     
    132383    } 
    133384 
     385    /** 
     386     *  Set a single line for the header of an email 
     387     * 
     388     *  @uses $headers 
     389     *  @param string $header_key 
     390     *    key for the header line (To:, From:, Subject:, etc) 
     391     *  @param string $header_value 
     392     *    value for the $header_key  
     393     */ 
    134394    function set_header_line($header_key, $header_value) { 
    135395        if($header_key && $header_value) { 
     
    137397        } 
    138398    } 
    139  
    140     function set_headers($extra_headers = null) { 
    141         if(is_array($this->to_addresses)) { 
    142             foreach($this->to_addresses as $to_address) { 
    143                 $to_addresses[] = $this->format_address($to_address); 
    144             } 
    145             if(is_array($to_addresses)) $to_addresses = implode(",", $to_addresses); 
    146             if(!empty($to_addresses)) 
    147             $this->set_header_line("To", $to_addresses); 
    148         } 
    149  
    150         if(is_array($this->cc_addresses)) { 
    151             foreach($this->cc_addresses as $cc_address) { 
    152                 $cc_addresses[] = $this->format_address($cc_address); 
    153             } 
    154             if(is_array($cc_addresses)) $cc_addresses = implode(",", $cc_addresses); 
    155             if(!empty($cc_addresses)) 
    156             $this->set_header_line("Cc", $cc_addresses); 
    157         } 
    158  
    159         if(is_array($this->bcc_addresses)) { 
    160             foreach($this->bcc_addresses as $bcc_address) { 
    161                 $bcc_addresses[] = $this->format_address($bcc_address); 
    162             } 
    163             if(is_array($bcc_addresses)) $bcc_addresses = implode(",", $bcc_addresses); 
    164             if(!empty($bcc_addresses)) 
    165             $this->set_header_line("Bcc", $bcc_addresses); 
    166         } 
    167  
    168         if(is_array($this->replyto_addresses)) { 
    169             foreach($this->replyto_addresses as $replyto_address) { 
    170                 $replyto_addresses[] = $this->format_address($replyto_address); 
    171             } 
    172             if(is_array($replyto_addresses)) $replyto_addresses = implode(",", $replyto_addresses); 
    173             if(!empty($replyto_addresses)) 
    174             $this->set_header_line("Reply-To", $replyto_addresses); 
    175         } 
    176  
    177         if(!is_null($this->subject))  { 
    178             $this->set_header_line("Subject", $this->subject); 
    179         }  else { 
    180             $this->set_header_line("Subject", ""); 
    181         } 
    182  
    183         if(!is_null($this->from_address)) { 
    184             $from_address = $this->format_address(array("0"=>$this->from_address, "1"=>$this->from_name)); 
    185             $this->set_header_line("From", $from_address); 
    186         } 
    187  
    188         if(is_array($extra_headers)) { 
    189             foreach($extra_headers as $extra_key => $extra_value) { 
    190                 if(!empty($extra_key) && !empty($extra_value)) 
    191                 $this->set_header_line($extra_key, $extra_value); 
    192             } 
    193         } 
    194  
    195         if(!array_key_exists("Date", $this->headers)) 
    196             $this->set_header_line("Date", date("r")); 
    197          
    198         if(!array_key_exists("Return-Path", $this->headers) && !is_null($this->from_address)) 
    199             $this->set_header_line("Return-Path", $this->from_address); 
    200              
    201         if(!array_key_exists("Reply-To", $this->headers) && !is_null($this->from_address)) 
    202             $this->set_header_line("Reply-To", $this->from_address);             
    203     } 
    204  
    205     function send($to_address = null, $subject = null, $text_body = null, $html_body = null, $extra_headers = null) { 
    206         if(!is_null($to_address)) $this->add_to_address($to_address); 
    207         if(!is_null($subject)) $this->set_subject($subject); 
    208         if(!is_null($html_body)) $this->set_html_body($html_body); 
    209         if(!is_null($text_body)) $this->set_text_body($text_body); 
    210  
    211         $body = $this->mail_mime->get(); 
    212         $this->set_headers($extra_headers); 
    213         $headers = $this->mail_mime->headers($this->headers);        
    214  
    215         if($this->send_type == "smtp") { 
    216             $mail =& Mail::factory("smtp", $this->smtp_params); 
    217         } else { 
    218             $mail =& Mail::factory("mail"); 
    219         } 
    220  
    221         if(!$this->error) { 
    222             $result = $mail->send(null, $headers, $body); 
    223             if(is_object($result)) { 
    224                 $this->error = $result->getMessage(); 
    225                 return false; 
    226             } else { 
    227                 return true; 
    228             } 
    229         } else { 
    230             return false; 
    231         } 
     399     
     400    /** 
     401     *  Return description of non-fatal errors 
     402     * 
     403     *  @uses $errors 
     404     *  @param boolean $return_string 
     405     *    <ul> 
     406     *      <li>true => Concatenate all error descriptions into a string 
     407     *        using $seperator between elements and return the 
     408     *        string</li> 
     409     *      <li>false => Return the error descriptions as an array</li> 
     410     *    </ul> 
     411     *  @param string $seperator  String to concatenate between error 
     412     *    descriptions if $return_string == true 
     413     *  @return mixed Error description(s), if any 
     414     */ 
     415    function get_errors($return_string = false, $seperator = "<br>") { 
     416        if($return_string && count($this->errors) > 0) { 
     417            return implode($seperator, $this->errors); 
     418        } else { 
     419            return $this->errors; 
     420        } 
     421    } 
     422 
     423    /** 
     424     *  Return errors as a string. 
     425     * 
     426     *  Concatenate all error descriptions into a stringusing 
     427     *  $seperator between elements and return the string. 
     428     *  @param string $seperator  String to concatenate between error 
     429     *    descriptions 
     430     *  @return string Concatenated error description(s), if any 
     431     */ 
     432    function get_errors_as_string($seperator = "<br>") { 
     433        return $this->get_errors(true, $seperator); 
    232434    } 
    233435