| 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) { |
| 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 | */ |
| 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); |