blob: c8cb8549ec262a14ca073bddbd80247d3e768d22 [file] [log] [blame]
Derek Jones37f4b9c2011-07-01 17:56:50 -05001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Greg Aker741de1c2010-11-10 14:52:57 -06005 * An open source application development framework for PHP 5.1.6 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
7 * @package CodeIgniter
8 * @author ExpressionEngine Dev Team
Greg Aker0711dc82011-01-05 10:49:40 -06009 * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
Derek Allard2067d1a2008-11-13 22:59:24 +000010 * @license http://codeigniter.com/user_guide/license.html
11 * @link http://codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * CodeIgniter Email Class
20 *
21 * Permits email to be sent using Mail, Sendmail, or SMTP.
22 *
23 * @package CodeIgniter
24 * @subpackage Libraries
25 * @category Libraries
26 * @author ExpressionEngine Dev Team
27 * @link http://codeigniter.com/user_guide/libraries/email.html
28 */
29class CI_Email {
30
31 var $useragent = "CodeIgniter";
32 var $mailpath = "/usr/sbin/sendmail"; // Sendmail path
33 var $protocol = "mail"; // mail/sendmail/smtp
Derek Jones37f4b9c2011-07-01 17:56:50 -050034 var $smtp_host = ""; // SMTP Server. Example: mail.earthlink.net
Derek Allard2067d1a2008-11-13 22:59:24 +000035 var $smtp_user = ""; // SMTP Username
36 var $smtp_pass = ""; // SMTP Password
37 var $smtp_port = "25"; // SMTP Port
38 var $smtp_timeout = 5; // SMTP Timeout in seconds
Derek Jones37f4b9c2011-07-01 17:56:50 -050039 var $wordwrap = TRUE; // TRUE/FALSE Turns word-wrap on/off
Derek Allard2067d1a2008-11-13 22:59:24 +000040 var $wrapchars = "76"; // Number of characters to wrap at.
Derek Jones37f4b9c2011-07-01 17:56:50 -050041 var $mailtype = "text"; // text/html Defines email formatting
Derek Allard2067d1a2008-11-13 22:59:24 +000042 var $charset = "utf-8"; // Default char set: iso-8859-1 or us-ascii
43 var $multipart = "mixed"; // "mixed" (in the body) or "related" (separate)
44 var $alt_message = ''; // Alternative message for HTML emails
Derek Jones37f4b9c2011-07-01 17:56:50 -050045 var $validate = FALSE; // TRUE/FALSE. Enables email validation
Derek Allard2067d1a2008-11-13 22:59:24 +000046 var $priority = "3"; // Default priority (1 - 5)
47 var $newline = "\n"; // Default newline. "\r\n" or "\n" (Use "\r\n" to comply with RFC 822)
Derek Jones37f4b9c2011-07-01 17:56:50 -050048 var $crlf = "\n"; // The RFC 2045 compliant CRLF for quoted-printable is "\r\n". Apparently some servers,
Derek Allard2067d1a2008-11-13 22:59:24 +000049 // even on the receiving end think they need to muck with CRLFs, so using "\n", while
50 // distasteful, is the only thing that seems to work for all environments.
Derek Jones37f4b9c2011-07-01 17:56:50 -050051 var $send_multipart = TRUE; // TRUE/FALSE - Yahoo does not like multipart alternative, so this is an override. Set to FALSE for Yahoo.
52 var $bcc_batch_mode = FALSE; // TRUE/FALSE Turns on/off Bcc batch feature
Derek Allard2067d1a2008-11-13 22:59:24 +000053 var $bcc_batch_size = 200; // If bcc_batch_mode = TRUE, sets max number of Bccs in each batch
54 var $_safe_mode = FALSE;
55 var $_subject = "";
56 var $_body = "";
57 var $_finalbody = "";
58 var $_alt_boundary = "";
59 var $_atc_boundary = "";
60 var $_header_str = "";
61 var $_smtp_connect = "";
62 var $_encoding = "8bit";
63 var $_IP = FALSE;
64 var $_smtp_auth = FALSE;
65 var $_replyto_flag = FALSE;
66 var $_debug_msg = array();
67 var $_recipients = array();
68 var $_cc_array = array();
69 var $_bcc_array = array();
70 var $_headers = array();
71 var $_attach_name = array();
72 var $_attach_type = array();
73 var $_attach_disp = array();
74 var $_protocols = array('mail', 'sendmail', 'smtp');
75 var $_base_charsets = array('us-ascii', 'iso-2022-'); // 7-bit charsets (excluding language suffix)
76 var $_bit_depths = array('7bit', '8bit');
77 var $_priorities = array('1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)');
78
79
80 /**
81 * Constructor - Sets Email Preferences
82 *
83 * The constructor can be passed an array of config values
84 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +000085 public function __construct($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000086 {
87 if (count($config) > 0)
88 {
89 $this->initialize($config);
90 }
91 else
92 {
93 $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE;
94 $this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE;
95 }
96
97 log_message('debug', "Email Class Initialized");
98 }
99
100 // --------------------------------------------------------------------
101
102 /**
103 * Initialize preferences
104 *
105 * @access public
106 * @param array
107 * @return void
108 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000109 public function initialize($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000110 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000111 foreach ($config as $key => $val)
112 {
113 if (isset($this->$key))
114 {
115 $method = 'set_'.$key;
116
117 if (method_exists($this, $method))
118 {
119 $this->$method($val);
120 }
121 else
122 {
123 $this->$key = $val;
124 }
125 }
126 }
Eric Barnes6113f542010-12-29 13:36:12 -0500127 $this->clear();
Derek Allard2067d1a2008-11-13 22:59:24 +0000128
129 $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE;
130 $this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE;
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000131
132 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000133 }
Barry Mienydd671972010-10-04 16:33:58 +0200134
Derek Allard2067d1a2008-11-13 22:59:24 +0000135 // --------------------------------------------------------------------
136
137 /**
138 * Initialize the Email Data
139 *
140 * @access public
Bo-Yi Wu83320eb2011-09-15 13:28:02 +0800141 * @param bool
Derek Allard2067d1a2008-11-13 22:59:24 +0000142 * @return void
143 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000144 public function clear($clear_attachments = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000145 {
146 $this->_subject = "";
147 $this->_body = "";
148 $this->_finalbody = "";
149 $this->_header_str = "";
150 $this->_replyto_flag = FALSE;
151 $this->_recipients = array();
Derek Jonesd1606352010-09-01 11:16:07 -0500152 $this->_cc_array = array();
153 $this->_bcc_array = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000154 $this->_headers = array();
155 $this->_debug_msg = array();
156
157 $this->_set_header('User-Agent', $this->useragent);
158 $this->_set_header('Date', $this->_set_date());
159
160 if ($clear_attachments !== FALSE)
161 {
162 $this->_attach_name = array();
163 $this->_attach_type = array();
164 $this->_attach_disp = array();
165 }
Eric Barnes6113f542010-12-29 13:36:12 -0500166
Greg Akera769deb2010-11-10 15:47:29 -0600167 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000168 }
Barry Mienydd671972010-10-04 16:33:58 +0200169
Derek Allard2067d1a2008-11-13 22:59:24 +0000170 // --------------------------------------------------------------------
171
172 /**
173 * Set FROM
174 *
175 * @access public
176 * @param string
177 * @param string
178 * @return void
179 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000180 public function from($from, $name = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000181 {
182 if (preg_match( '/\<(.*)\>/', $from, $match))
183 {
184 $from = $match['1'];
185 }
186
187 if ($this->validate)
188 {
189 $this->validate_email($this->_str_to_array($from));
190 }
191
192 // prepare the display name
193 if ($name != '')
194 {
195 // only use Q encoding if there are characters that would require it
196 if ( ! preg_match('/[\200-\377]/', $name))
197 {
198 // add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes
Derek Jonesc630bcf2008-11-17 21:09:45 +0000199 $name = '"'.addcslashes($name, "\0..\37\177'\"\\").'"';
Derek Allard2067d1a2008-11-13 22:59:24 +0000200 }
201 else
202 {
203 $name = $this->_prep_q_encoding($name, TRUE);
204 }
205 }
206
207 $this->_set_header('From', $name.' <'.$from.'>');
208 $this->_set_header('Return-Path', '<'.$from.'>');
Eric Barnes6113f542010-12-29 13:36:12 -0500209
Greg Akera769deb2010-11-10 15:47:29 -0600210 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000211 }
Barry Mienydd671972010-10-04 16:33:58 +0200212
Derek Allard2067d1a2008-11-13 22:59:24 +0000213 // --------------------------------------------------------------------
214
215 /**
216 * Set Reply-to
217 *
218 * @access public
219 * @param string
220 * @param string
221 * @return void
222 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000223 public function reply_to($replyto, $name = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000224 {
225 if (preg_match( '/\<(.*)\>/', $replyto, $match))
226 {
227 $replyto = $match['1'];
228 }
229
230 if ($this->validate)
231 {
232 $this->validate_email($this->_str_to_array($replyto));
233 }
234
235 if ($name == '')
236 {
237 $name = $replyto;
238 }
239
240 if (strncmp($name, '"', 1) != 0)
241 {
242 $name = '"'.$name.'"';
243 }
244
245 $this->_set_header('Reply-To', $name.' <'.$replyto.'>');
246 $this->_replyto_flag = TRUE;
Greg Akera769deb2010-11-10 15:47:29 -0600247
248 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000249 }
Barry Mienydd671972010-10-04 16:33:58 +0200250
Derek Allard2067d1a2008-11-13 22:59:24 +0000251 // --------------------------------------------------------------------
252
253 /**
254 * Set Recipients
255 *
256 * @access public
257 * @param string
258 * @return void
259 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000260 public function to($to)
Derek Allard2067d1a2008-11-13 22:59:24 +0000261 {
262 $to = $this->_str_to_array($to);
263 $to = $this->clean_email($to);
264
265 if ($this->validate)
266 {
267 $this->validate_email($to);
268 }
269
270 if ($this->_get_protocol() != 'mail')
271 {
272 $this->_set_header('To', implode(", ", $to));
273 }
274
275 switch ($this->_get_protocol())
276 {
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000277 case 'smtp' :
278 $this->_recipients = $to;
Derek Allard2067d1a2008-11-13 22:59:24 +0000279 break;
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000280 case 'sendmail' :
281 case 'mail' :
282 $this->_recipients = implode(", ", $to);
Derek Allard2067d1a2008-11-13 22:59:24 +0000283 break;
284 }
Eric Barnes6113f542010-12-29 13:36:12 -0500285
Greg Akera769deb2010-11-10 15:47:29 -0600286 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000287 }
Barry Mienydd671972010-10-04 16:33:58 +0200288
Derek Allard2067d1a2008-11-13 22:59:24 +0000289 // --------------------------------------------------------------------
290
291 /**
292 * Set CC
293 *
294 * @access public
295 * @param string
296 * @return void
297 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000298 public function cc($cc)
Derek Allard2067d1a2008-11-13 22:59:24 +0000299 {
300 $cc = $this->_str_to_array($cc);
301 $cc = $this->clean_email($cc);
302
303 if ($this->validate)
304 {
305 $this->validate_email($cc);
306 }
307
308 $this->_set_header('Cc', implode(", ", $cc));
309
310 if ($this->_get_protocol() == "smtp")
311 {
312 $this->_cc_array = $cc;
313 }
Eric Barnes6113f542010-12-29 13:36:12 -0500314
Greg Akera769deb2010-11-10 15:47:29 -0600315 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000316 }
Barry Mienydd671972010-10-04 16:33:58 +0200317
Derek Allard2067d1a2008-11-13 22:59:24 +0000318 // --------------------------------------------------------------------
319
320 /**
321 * Set BCC
322 *
323 * @access public
324 * @param string
325 * @param string
326 * @return void
327 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000328 public function bcc($bcc, $limit = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000329 {
330 if ($limit != '' && is_numeric($limit))
331 {
332 $this->bcc_batch_mode = TRUE;
333 $this->bcc_batch_size = $limit;
334 }
335
336 $bcc = $this->_str_to_array($bcc);
337 $bcc = $this->clean_email($bcc);
338
339 if ($this->validate)
340 {
341 $this->validate_email($bcc);
342 }
343
344 if (($this->_get_protocol() == "smtp") OR ($this->bcc_batch_mode && count($bcc) > $this->bcc_batch_size))
345 {
346 $this->_bcc_array = $bcc;
347 }
348 else
349 {
350 $this->_set_header('Bcc', implode(", ", $bcc));
351 }
Eric Barnes6113f542010-12-29 13:36:12 -0500352
Greg Akera769deb2010-11-10 15:47:29 -0600353 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000354 }
Barry Mienydd671972010-10-04 16:33:58 +0200355
Derek Allard2067d1a2008-11-13 22:59:24 +0000356 // --------------------------------------------------------------------
357
358 /**
359 * Set Email Subject
360 *
361 * @access public
362 * @param string
363 * @return void
364 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000365 public function subject($subject)
Derek Allard2067d1a2008-11-13 22:59:24 +0000366 {
367 $subject = $this->_prep_q_encoding($subject);
368 $this->_set_header('Subject', $subject);
Greg Akera769deb2010-11-10 15:47:29 -0600369 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000370 }
Barry Mienydd671972010-10-04 16:33:58 +0200371
Derek Allard2067d1a2008-11-13 22:59:24 +0000372 // --------------------------------------------------------------------
373
374 /**
375 * Set Body
376 *
377 * @access public
378 * @param string
379 * @return void
380 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000381 public function message($body)
Derek Allard2067d1a2008-11-13 22:59:24 +0000382 {
383 $this->_body = stripslashes(rtrim(str_replace("\r", "", $body)));
Greg Akera769deb2010-11-10 15:47:29 -0600384 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000385 }
Barry Mienydd671972010-10-04 16:33:58 +0200386
Derek Allard2067d1a2008-11-13 22:59:24 +0000387 // --------------------------------------------------------------------
388
389 /**
390 * Assign file attachments
391 *
392 * @access public
393 * @param string
394 * @return void
395 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000396 public function attach($filename, $disposition = 'attachment')
Derek Allard2067d1a2008-11-13 22:59:24 +0000397 {
398 $this->_attach_name[] = $filename;
Phil Sturgeon0aaf42b2011-08-10 08:06:37 -0600399 $this->_attach_type[] = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION));
Derek Jones37f4b9c2011-07-01 17:56:50 -0500400 $this->_attach_disp[] = $disposition; // Can also be 'inline' Not sure if it matters
Greg Akera769deb2010-11-10 15:47:29 -0600401 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000402 }
403
404 // --------------------------------------------------------------------
405
406 /**
407 * Add a Header Item
408 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600409 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000410 * @param string
411 * @param string
412 * @return void
413 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600414 protected function _set_header($header, $value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000415 {
416 $this->_headers[$header] = $value;
417 }
Barry Mienydd671972010-10-04 16:33:58 +0200418
Derek Allard2067d1a2008-11-13 22:59:24 +0000419 // --------------------------------------------------------------------
420
421 /**
422 * Convert a String to an Array
423 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600424 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000425 * @param string
426 * @return array
427 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600428 protected function _str_to_array($email)
Derek Allard2067d1a2008-11-13 22:59:24 +0000429 {
430 if ( ! is_array($email))
431 {
432 if (strpos($email, ',') !== FALSE)
433 {
434 $email = preg_split('/[\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY);
435 }
436 else
437 {
438 $email = trim($email);
439 settype($email, "array");
440 }
441 }
442 return $email;
443 }
Barry Mienydd671972010-10-04 16:33:58 +0200444
Derek Allard2067d1a2008-11-13 22:59:24 +0000445 // --------------------------------------------------------------------
446
447 /**
448 * Set Multipart Value
449 *
450 * @access public
451 * @param string
452 * @return void
453 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000454 public function set_alt_message($str = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000455 {
Dan Horrigand0ddeaf2011-08-21 09:07:27 -0400456 $this->alt_message = (string) $str;
Greg Akera769deb2010-11-10 15:47:29 -0600457 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000458 }
Barry Mienydd671972010-10-04 16:33:58 +0200459
Derek Allard2067d1a2008-11-13 22:59:24 +0000460 // --------------------------------------------------------------------
461
462 /**
463 * Set Mailtype
464 *
465 * @access public
466 * @param string
467 * @return void
468 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000469 public function set_mailtype($type = 'text')
Derek Allard2067d1a2008-11-13 22:59:24 +0000470 {
471 $this->mailtype = ($type == 'html') ? 'html' : 'text';
Greg Akera769deb2010-11-10 15:47:29 -0600472 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000473 }
Barry Mienydd671972010-10-04 16:33:58 +0200474
Derek Allard2067d1a2008-11-13 22:59:24 +0000475 // --------------------------------------------------------------------
476
477 /**
478 * Set Wordwrap
479 *
480 * @access public
Dan Horrigan628e6602011-08-21 09:08:31 -0400481 * @param bool
Derek Allard2067d1a2008-11-13 22:59:24 +0000482 * @return void
483 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000484 public function set_wordwrap($wordwrap = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000485 {
Dan Horrigan628e6602011-08-21 09:08:31 -0400486 $this->wordwrap = (bool) $wordwrap;
Greg Akera769deb2010-11-10 15:47:29 -0600487 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000488 }
Barry Mienydd671972010-10-04 16:33:58 +0200489
Derek Allard2067d1a2008-11-13 22:59:24 +0000490 // --------------------------------------------------------------------
491
492 /**
493 * Set Protocol
494 *
495 * @access public
496 * @param string
497 * @return void
498 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000499 public function set_protocol($protocol = 'mail')
Derek Allard2067d1a2008-11-13 22:59:24 +0000500 {
501 $this->protocol = ( ! in_array($protocol, $this->_protocols, TRUE)) ? 'mail' : strtolower($protocol);
Greg Akera769deb2010-11-10 15:47:29 -0600502 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000503 }
Barry Mienydd671972010-10-04 16:33:58 +0200504
Derek Allard2067d1a2008-11-13 22:59:24 +0000505 // --------------------------------------------------------------------
506
507 /**
508 * Set Priority
509 *
510 * @access public
511 * @param integer
512 * @return void
513 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000514 public function set_priority($n = 3)
Derek Allard2067d1a2008-11-13 22:59:24 +0000515 {
516 if ( ! is_numeric($n))
517 {
518 $this->priority = 3;
519 return;
520 }
521
522 if ($n < 1 OR $n > 5)
523 {
524 $this->priority = 3;
525 return;
526 }
527
528 $this->priority = $n;
Greg Akera769deb2010-11-10 15:47:29 -0600529 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000530 }
Barry Mienydd671972010-10-04 16:33:58 +0200531
Derek Allard2067d1a2008-11-13 22:59:24 +0000532 // --------------------------------------------------------------------
533
534 /**
535 * Set Newline Character
536 *
537 * @access public
538 * @param string
539 * @return void
540 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000541 public function set_newline($newline = "\n")
Derek Allard2067d1a2008-11-13 22:59:24 +0000542 {
543 if ($newline != "\n" AND $newline != "\r\n" AND $newline != "\r")
544 {
545 $this->newline = "\n";
546 return;
547 }
548
549 $this->newline = $newline;
Eric Barnes6113f542010-12-29 13:36:12 -0500550
Greg Akera769deb2010-11-10 15:47:29 -0600551 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000552 }
Barry Mienydd671972010-10-04 16:33:58 +0200553
Derek Allard2067d1a2008-11-13 22:59:24 +0000554 // --------------------------------------------------------------------
555
556 /**
557 * Set CRLF
558 *
559 * @access public
560 * @param string
561 * @return void
562 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000563 public function set_crlf($crlf = "\n")
Derek Allard2067d1a2008-11-13 22:59:24 +0000564 {
565 if ($crlf != "\n" AND $crlf != "\r\n" AND $crlf != "\r")
566 {
567 $this->crlf = "\n";
568 return;
569 }
570
571 $this->crlf = $crlf;
Eric Barnes6113f542010-12-29 13:36:12 -0500572
Greg Akera769deb2010-11-10 15:47:29 -0600573 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000574 }
Barry Mienydd671972010-10-04 16:33:58 +0200575
Derek Allard2067d1a2008-11-13 22:59:24 +0000576 // --------------------------------------------------------------------
577
578 /**
579 * Set Message Boundary
580 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600581 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000582 * @return void
583 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600584 protected function _set_boundaries()
Derek Allard2067d1a2008-11-13 22:59:24 +0000585 {
586 $this->_alt_boundary = "B_ALT_".uniqid(''); // multipart/alternative
587 $this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary
588 }
Barry Mienydd671972010-10-04 16:33:58 +0200589
Derek Allard2067d1a2008-11-13 22:59:24 +0000590 // --------------------------------------------------------------------
591
592 /**
593 * Get the Message ID
594 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600595 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000596 * @return string
597 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600598 protected function _get_message_id()
Derek Allard2067d1a2008-11-13 22:59:24 +0000599 {
600 $from = $this->_headers['Return-Path'];
601 $from = str_replace(">", "", $from);
602 $from = str_replace("<", "", $from);
603
Derek Jones37f4b9c2011-07-01 17:56:50 -0500604 return "<".uniqid('').strstr($from, '@').">";
Derek Allard2067d1a2008-11-13 22:59:24 +0000605 }
Barry Mienydd671972010-10-04 16:33:58 +0200606
Derek Allard2067d1a2008-11-13 22:59:24 +0000607 // --------------------------------------------------------------------
608
609 /**
610 * Get Mail Protocol
611 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600612 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000613 * @param bool
614 * @return string
615 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600616 protected function _get_protocol($return = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000617 {
618 $this->protocol = strtolower($this->protocol);
619 $this->protocol = ( ! in_array($this->protocol, $this->_protocols, TRUE)) ? 'mail' : $this->protocol;
620
621 if ($return == TRUE)
622 {
623 return $this->protocol;
624 }
625 }
Barry Mienydd671972010-10-04 16:33:58 +0200626
Derek Allard2067d1a2008-11-13 22:59:24 +0000627 // --------------------------------------------------------------------
628
629 /**
630 * Get Mail Encoding
631 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600632 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000633 * @param bool
634 * @return string
635 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600636 protected function _get_encoding($return = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000637 {
638 $this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '8bit' : $this->_encoding;
639
640 foreach ($this->_base_charsets as $charset)
641 {
642 if (strncmp($charset, $this->charset, strlen($charset)) == 0)
643 {
644 $this->_encoding = '7bit';
645 }
646 }
647
648 if ($return == TRUE)
649 {
650 return $this->_encoding;
651 }
652 }
653
654 // --------------------------------------------------------------------
655
656 /**
657 * Get content type (text/html/attachment)
658 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600659 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000660 * @return string
661 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600662 protected function _get_content_type()
Derek Allard2067d1a2008-11-13 22:59:24 +0000663 {
Derek Jones37f4b9c2011-07-01 17:56:50 -0500664 if ($this->mailtype == 'html' && count($this->_attach_name) == 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000665 {
666 return 'html';
667 }
Derek Jones37f4b9c2011-07-01 17:56:50 -0500668 elseif ($this->mailtype == 'html' && count($this->_attach_name) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000669 {
670 return 'html-attach';
671 }
Derek Jones37f4b9c2011-07-01 17:56:50 -0500672 elseif ($this->mailtype == 'text' && count($this->_attach_name) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000673 {
674 return 'plain-attach';
675 }
676 else
677 {
678 return 'plain';
679 }
680 }
Barry Mienydd671972010-10-04 16:33:58 +0200681
Derek Allard2067d1a2008-11-13 22:59:24 +0000682 // --------------------------------------------------------------------
683
684 /**
685 * Set RFC 822 Date
686 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600687 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000688 * @return string
689 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600690 protected function _set_date()
Derek Allard2067d1a2008-11-13 22:59:24 +0000691 {
692 $timezone = date("Z");
693 $operator = (strncmp($timezone, '-', 1) == 0) ? '-' : '+';
694 $timezone = abs($timezone);
695 $timezone = floor($timezone/3600) * 100 + ($timezone % 3600 ) / 60;
696
697 return sprintf("%s %s%04d", date("D, j M Y H:i:s"), $operator, $timezone);
698 }
Barry Mienydd671972010-10-04 16:33:58 +0200699
Derek Allard2067d1a2008-11-13 22:59:24 +0000700 // --------------------------------------------------------------------
701
702 /**
703 * Mime message
704 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600705 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000706 * @return string
707 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600708 protected function _get_mime_message()
Derek Allard2067d1a2008-11-13 22:59:24 +0000709 {
710 return "This is a multi-part message in MIME format.".$this->newline."Your email application may not support this format.";
711 }
Barry Mienydd671972010-10-04 16:33:58 +0200712
Derek Allard2067d1a2008-11-13 22:59:24 +0000713 // --------------------------------------------------------------------
714
715 /**
716 * Validate Email Address
717 *
718 * @access public
719 * @param string
720 * @return bool
721 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000722 public function validate_email($email)
Derek Allard2067d1a2008-11-13 22:59:24 +0000723 {
724 if ( ! is_array($email))
725 {
patworkb0707982011-04-08 15:10:05 +0200726 $this->_set_error_message('lang:email_must_be_array');
Derek Allard2067d1a2008-11-13 22:59:24 +0000727 return FALSE;
728 }
729
730 foreach ($email as $val)
731 {
732 if ( ! $this->valid_email($val))
733 {
patworkb0707982011-04-08 15:10:05 +0200734 $this->_set_error_message('lang:email_invalid_address', $val);
Derek Allard2067d1a2008-11-13 22:59:24 +0000735 return FALSE;
736 }
737 }
738
739 return TRUE;
740 }
Barry Mienydd671972010-10-04 16:33:58 +0200741
Derek Allard2067d1a2008-11-13 22:59:24 +0000742 // --------------------------------------------------------------------
743
744 /**
745 * Email Validation
746 *
747 * @access public
748 * @param string
749 * @return bool
750 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000751 public function valid_email($address)
Derek Allard2067d1a2008-11-13 22:59:24 +0000752 {
753 return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $address)) ? FALSE : TRUE;
754 }
Barry Mienydd671972010-10-04 16:33:58 +0200755
Derek Allard2067d1a2008-11-13 22:59:24 +0000756 // --------------------------------------------------------------------
757
758 /**
759 * Clean Extended Email Address: Joe Smith <joe@smith.com>
760 *
761 * @access public
762 * @param string
763 * @return string
764 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000765 public function clean_email($email)
Derek Allard2067d1a2008-11-13 22:59:24 +0000766 {
767 if ( ! is_array($email))
768 {
769 if (preg_match('/\<(.*)\>/', $email, $match))
770 {
Barry Mienydd671972010-10-04 16:33:58 +0200771 return $match['1'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000772 }
Barry Mienydd671972010-10-04 16:33:58 +0200773 else
Derek Allard2067d1a2008-11-13 22:59:24 +0000774 {
Barry Mienydd671972010-10-04 16:33:58 +0200775 return $email;
Derek Allard2067d1a2008-11-13 22:59:24 +0000776 }
777 }
778
779 $clean_email = array();
780
781 foreach ($email as $addy)
782 {
783 if (preg_match( '/\<(.*)\>/', $addy, $match))
784 {
Barry Mienydd671972010-10-04 16:33:58 +0200785 $clean_email[] = $match['1'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000786 }
Barry Mienydd671972010-10-04 16:33:58 +0200787 else
Derek Allard2067d1a2008-11-13 22:59:24 +0000788 {
Barry Mienydd671972010-10-04 16:33:58 +0200789 $clean_email[] = $addy;
Derek Allard2067d1a2008-11-13 22:59:24 +0000790 }
791 }
792
793 return $clean_email;
794 }
Barry Mienydd671972010-10-04 16:33:58 +0200795
Derek Allard2067d1a2008-11-13 22:59:24 +0000796 // --------------------------------------------------------------------
797
798 /**
799 * Build alternative plain text message
800 *
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000801 * This public function provides the raw message for use
Derek Allard2067d1a2008-11-13 22:59:24 +0000802 * in plain-text headers of HTML-formatted emails.
803 * If the user hasn't specified his own alternative message
804 * it creates one by stripping the HTML
805 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600806 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000807 * @return string
808 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600809 protected function _get_alt_message()
Derek Allard2067d1a2008-11-13 22:59:24 +0000810 {
811 if ($this->alt_message != "")
812 {
813 return $this->word_wrap($this->alt_message, '76');
814 }
815
816 if (preg_match('/\<body.*?\>(.*)\<\/body\>/si', $this->_body, $match))
817 {
818 $body = $match['1'];
819 }
820 else
821 {
822 $body = $this->_body;
823 }
824
825 $body = trim(strip_tags($body));
826 $body = preg_replace( '#<!--(.*)--\>#', "", $body);
827 $body = str_replace("\t", "", $body);
828
829 for ($i = 20; $i >= 3; $i--)
830 {
831 $n = "";
832
833 for ($x = 1; $x <= $i; $x ++)
834 {
Barry Mienydd671972010-10-04 16:33:58 +0200835 $n .= "\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000836 }
837
838 $body = str_replace($n, "\n\n", $body);
839 }
840
841 return $this->word_wrap($body, '76');
842 }
Barry Mienydd671972010-10-04 16:33:58 +0200843
Derek Allard2067d1a2008-11-13 22:59:24 +0000844 // --------------------------------------------------------------------
845
846 /**
847 * Word Wrap
848 *
849 * @access public
850 * @param string
851 * @param integer
852 * @return string
853 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000854 public function word_wrap($str, $charlim = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000855 {
856 // Se the character limit
857 if ($charlim == '')
858 {
859 $charlim = ($this->wrapchars == "") ? "76" : $this->wrapchars;
860 }
861
862 // Reduce multiple spaces
863 $str = preg_replace("| +|", " ", $str);
864
865 // Standardize newlines
866 if (strpos($str, "\r") !== FALSE)
867 {
868 $str = str_replace(array("\r\n", "\r"), "\n", $str);
869 }
870
871 // If the current word is surrounded by {unwrap} tags we'll
872 // strip the entire chunk and replace it with a marker.
873 $unwrap = array();
874 if (preg_match_all("|(\{unwrap\}.+?\{/unwrap\})|s", $str, $matches))
875 {
876 for ($i = 0; $i < count($matches['0']); $i++)
877 {
878 $unwrap[] = $matches['1'][$i];
879 $str = str_replace($matches['1'][$i], "{{unwrapped".$i."}}", $str);
880 }
881 }
882
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000883 // Use PHP's native public function to do the initial wordwrap.
Derek Allard2067d1a2008-11-13 22:59:24 +0000884 // We set the cut flag to FALSE so that any individual words that are
Derek Jones37f4b9c2011-07-01 17:56:50 -0500885 // too long get left alone. In the next step we'll deal with them.
Derek Allard2067d1a2008-11-13 22:59:24 +0000886 $str = wordwrap($str, $charlim, "\n", FALSE);
887
888 // Split the string into individual lines of text and cycle through them
889 $output = "";
890 foreach (explode("\n", $str) as $line)
891 {
892 // Is the line within the allowed character count?
893 // If so we'll join it to the output and continue
894 if (strlen($line) <= $charlim)
895 {
896 $output .= $line.$this->newline;
897 continue;
898 }
899
900 $temp = '';
Pascal Kriete14287f32011-02-14 13:39:34 -0500901 while ((strlen($line)) > $charlim)
Derek Allard2067d1a2008-11-13 22:59:24 +0000902 {
903 // If the over-length word is a URL we won't wrap it
904 if (preg_match("!\[url.+\]|://|wwww.!", $line))
905 {
906 break;
907 }
908
909 // Trim the word down
910 $temp .= substr($line, 0, $charlim-1);
911 $line = substr($line, $charlim-1);
912 }
913
914 // If $temp contains data it means we had to split up an over-length
915 // word into smaller chunks so we'll add it back to our current line
916 if ($temp != '')
917 {
918 $output .= $temp.$this->newline.$line;
919 }
920 else
921 {
922 $output .= $line;
923 }
924
925 $output .= $this->newline;
926 }
927
928 // Put our markers back
929 if (count($unwrap) > 0)
930 {
931 foreach ($unwrap as $key => $val)
932 {
933 $output = str_replace("{{unwrapped".$key."}}", $val, $output);
934 }
935 }
936
937 return $output;
938 }
Barry Mienydd671972010-10-04 16:33:58 +0200939
Derek Allard2067d1a2008-11-13 22:59:24 +0000940 // --------------------------------------------------------------------
941
942 /**
943 * Build final headers
944 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600945 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000946 * @param string
947 * @return string
948 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600949 protected function _build_headers()
Derek Allard2067d1a2008-11-13 22:59:24 +0000950 {
951 $this->_set_header('X-Sender', $this->clean_email($this->_headers['From']));
952 $this->_set_header('X-Mailer', $this->useragent);
953 $this->_set_header('X-Priority', $this->_priorities[$this->priority - 1]);
954 $this->_set_header('Message-ID', $this->_get_message_id());
955 $this->_set_header('Mime-Version', '1.0');
956 }
Barry Mienydd671972010-10-04 16:33:58 +0200957
Derek Allard2067d1a2008-11-13 22:59:24 +0000958 // --------------------------------------------------------------------
959
960 /**
961 * Write Headers as a string
962 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600963 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000964 * @return void
965 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600966 protected function _write_headers()
Derek Allard2067d1a2008-11-13 22:59:24 +0000967 {
968 if ($this->protocol == 'mail')
969 {
970 $this->_subject = $this->_headers['Subject'];
971 unset($this->_headers['Subject']);
972 }
973
974 reset($this->_headers);
975 $this->_header_str = "";
976
Pascal Kriete14287f32011-02-14 13:39:34 -0500977 foreach ($this->_headers as $key => $val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000978 {
979 $val = trim($val);
980
981 if ($val != "")
982 {
983 $this->_header_str .= $key.": ".$val.$this->newline;
984 }
985 }
986
987 if ($this->_get_protocol() == 'mail')
988 {
Derek Jones1d890882009-02-10 20:32:14 +0000989 $this->_header_str = rtrim($this->_header_str);
Derek Allard2067d1a2008-11-13 22:59:24 +0000990 }
991 }
Barry Mienydd671972010-10-04 16:33:58 +0200992
Derek Allard2067d1a2008-11-13 22:59:24 +0000993 // --------------------------------------------------------------------
994
995 /**
996 * Build Final Body and attachments
997 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600998 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000999 * @return void
1000 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001001 protected function _build_message()
Derek Allard2067d1a2008-11-13 22:59:24 +00001002 {
Derek Jones37f4b9c2011-07-01 17:56:50 -05001003 if ($this->wordwrap === TRUE AND $this->mailtype != 'html')
Derek Allard2067d1a2008-11-13 22:59:24 +00001004 {
1005 $this->_body = $this->word_wrap($this->_body);
1006 }
1007
1008 $this->_set_boundaries();
1009 $this->_write_headers();
1010
1011 $hdr = ($this->_get_protocol() == 'mail') ? $this->newline : '';
Brandon Jones485d7412010-11-09 16:38:17 -05001012 $body = '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001013
1014 switch ($this->_get_content_type())
1015 {
1016 case 'plain' :
1017
1018 $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1019 $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding();
1020
1021 if ($this->_get_protocol() == 'mail')
1022 {
1023 $this->_header_str .= $hdr;
1024 $this->_finalbody = $this->_body;
Derek Allard2067d1a2008-11-13 22:59:24 +00001025 }
Brandon Jones485d7412010-11-09 16:38:17 -05001026 else
1027 {
1028 $this->_finalbody = $hdr . $this->newline . $this->newline . $this->_body;
1029 }
Eric Barnes6113f542010-12-29 13:36:12 -05001030
Derek Allard2067d1a2008-11-13 22:59:24 +00001031 return;
1032
1033 break;
1034 case 'html' :
1035
1036 if ($this->send_multipart === FALSE)
1037 {
1038 $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
1039 $hdr .= "Content-Transfer-Encoding: quoted-printable";
1040 }
1041 else
1042 {
Derek Jonesa45e7612009-02-10 18:33:01 +00001043 $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001044
Brandon Jones485d7412010-11-09 16:38:17 -05001045 $body .= $this->_get_mime_message() . $this->newline . $this->newline;
1046 $body .= "--" . $this->_alt_boundary . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001047
Brandon Jones485d7412010-11-09 16:38:17 -05001048 $body .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1049 $body .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
1050 $body .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
1051
1052 $body .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
1053 $body .= "Content-Transfer-Encoding: quoted-printable" . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001054 }
Eric Barnes6113f542010-12-29 13:36:12 -05001055
Brandon Jones485d7412010-11-09 16:38:17 -05001056 $this->_finalbody = $body . $this->_prep_quoted_printable($this->_body) . $this->newline . $this->newline;
Eric Barnes6113f542010-12-29 13:36:12 -05001057
1058
Derek Allard2067d1a2008-11-13 22:59:24 +00001059 if ($this->_get_protocol() == 'mail')
1060 {
1061 $this->_header_str .= $hdr;
Brandon Jones485d7412010-11-09 16:38:17 -05001062 }
1063 else
1064 {
1065 $this->_finalbody = $hdr . $this->_finalbody;
Derek Allard2067d1a2008-11-13 22:59:24 +00001066 }
1067
Derek Allard2067d1a2008-11-13 22:59:24 +00001068
1069 if ($this->send_multipart !== FALSE)
1070 {
Brandon Jones485d7412010-11-09 16:38:17 -05001071 $this->_finalbody .= "--" . $this->_alt_boundary . "--";
Derek Allard2067d1a2008-11-13 22:59:24 +00001072 }
1073
Derek Allard2067d1a2008-11-13 22:59:24 +00001074 return;
1075
1076 break;
1077 case 'plain-attach' :
1078
Derek Jonesa45e7612009-02-10 18:33:01 +00001079 $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001080
1081 if ($this->_get_protocol() == 'mail')
1082 {
1083 $this->_header_str .= $hdr;
Eric Barnes6113f542010-12-29 13:36:12 -05001084 }
1085
Brandon Jones485d7412010-11-09 16:38:17 -05001086 $body .= $this->_get_mime_message() . $this->newline . $this->newline;
1087 $body .= "--" . $this->_atc_boundary . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001088
Brandon Jones485d7412010-11-09 16:38:17 -05001089 $body .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1090 $body .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001091
Brandon Jones485d7412010-11-09 16:38:17 -05001092 $body .= $this->_body . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001093
1094 break;
1095 case 'html-attach' :
1096
Derek Jonesa45e7612009-02-10 18:33:01 +00001097 $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline . $this->newline;
Eric Barnes6113f542010-12-29 13:36:12 -05001098
Derek Allard2067d1a2008-11-13 22:59:24 +00001099 if ($this->_get_protocol() == 'mail')
1100 {
1101 $this->_header_str .= $hdr;
Derek Allard2067d1a2008-11-13 22:59:24 +00001102 }
1103
Brandon Jones485d7412010-11-09 16:38:17 -05001104 $body .= $this->_get_mime_message() . $this->newline . $this->newline;
1105 $body .= "--" . $this->_atc_boundary . $this->newline;
1106
1107 $body .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline .$this->newline;
1108 $body .= "--" . $this->_alt_boundary . $this->newline;
1109
1110 $body .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1111 $body .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
1112 $body .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
1113
1114 $body .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
1115 $body .= "Content-Transfer-Encoding: quoted-printable" . $this->newline . $this->newline;
1116
1117 $body .= $this->_prep_quoted_printable($this->_body) . $this->newline . $this->newline;
1118 $body .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001119
1120 break;
1121 }
1122
1123 $attachment = array();
1124
1125 $z = 0;
1126
1127 for ($i=0; $i < count($this->_attach_name); $i++)
1128 {
1129 $filename = $this->_attach_name[$i];
1130 $basename = basename($filename);
1131 $ctype = $this->_attach_type[$i];
1132
1133 if ( ! file_exists($filename))
1134 {
patworkb0707982011-04-08 15:10:05 +02001135 $this->_set_error_message('lang:email_attachment_missing', $filename);
Derek Allard2067d1a2008-11-13 22:59:24 +00001136 return FALSE;
1137 }
1138
Derek Jones37f4b9c2011-07-01 17:56:50 -05001139 $h = "--".$this->_atc_boundary.$this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001140 $h .= "Content-type: ".$ctype."; ";
1141 $h .= "name=\"".$basename."\"".$this->newline;
1142 $h .= "Content-Disposition: ".$this->_attach_disp[$i].";".$this->newline;
1143 $h .= "Content-Transfer-Encoding: base64".$this->newline;
1144
1145 $attachment[$z++] = $h;
1146 $file = filesize($filename) +1;
1147
1148 if ( ! $fp = fopen($filename, FOPEN_READ))
1149 {
patworkb0707982011-04-08 15:10:05 +02001150 $this->_set_error_message('lang:email_attachment_unreadable', $filename);
Derek Allard2067d1a2008-11-13 22:59:24 +00001151 return FALSE;
1152 }
1153
1154 $attachment[$z++] = chunk_split(base64_encode(fread($fp, $file)));
1155 fclose($fp);
1156 }
1157
Brandon Jones485d7412010-11-09 16:38:17 -05001158 $body .= implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--";
Eric Barnes6113f542010-12-29 13:36:12 -05001159
Brandon Jones485d7412010-11-09 16:38:17 -05001160
Derek Allard2067d1a2008-11-13 22:59:24 +00001161 if ($this->_get_protocol() == 'mail')
1162 {
Brandon Jones485d7412010-11-09 16:38:17 -05001163 $this->_finalbody = $body;
Derek Allard2067d1a2008-11-13 22:59:24 +00001164 }
Brandon Jones485d7412010-11-09 16:38:17 -05001165 else
1166 {
1167 $this->_finalbody = $hdr . $body;
1168 }
Eric Barnes6113f542010-12-29 13:36:12 -05001169
Derek Allard2067d1a2008-11-13 22:59:24 +00001170 return;
1171 }
Barry Mienydd671972010-10-04 16:33:58 +02001172
Derek Allard2067d1a2008-11-13 22:59:24 +00001173 // --------------------------------------------------------------------
1174
1175 /**
1176 * Prep Quoted Printable
1177 *
1178 * Prepares string for Quoted-Printable Content-Transfer-Encoding
1179 * Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt
1180 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001181 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001182 * @param string
1183 * @param integer
1184 * @return string
1185 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001186 protected function _prep_quoted_printable($str, $charlim = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001187 {
1188 // Set the character limit
1189 // Don't allow over 76, as that will make servers and MUAs barf
1190 // all over quoted-printable data
1191 if ($charlim == '' OR $charlim > '76')
1192 {
1193 $charlim = '76';
1194 }
1195
1196 // Reduce multiple spaces
1197 $str = preg_replace("| +|", " ", $str);
1198
1199 // kill nulls
1200 $str = preg_replace('/\x00+/', '', $str);
1201
1202 // Standardize newlines
1203 if (strpos($str, "\r") !== FALSE)
1204 {
1205 $str = str_replace(array("\r\n", "\r"), "\n", $str);
1206 }
1207
1208 // We are intentionally wrapping so mail servers will encode characters
1209 // properly and MUAs will behave, so {unwrap} must go!
1210 $str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str);
1211
1212 // Break into an array of lines
1213 $lines = explode("\n", $str);
1214
1215 $escape = '=';
1216 $output = '';
1217
1218 foreach ($lines as $line)
1219 {
1220 $length = strlen($line);
1221 $temp = '';
1222
1223 // Loop through each character in the line to add soft-wrap
1224 // characters at the end of a line " =\r\n" and add the newly
1225 // processed line(s) to the output (see comment on $crlf class property)
1226 for ($i = 0; $i < $length; $i++)
1227 {
1228 // Grab the next character
1229 $char = substr($line, $i, 1);
1230 $ascii = ord($char);
1231
1232 // Convert spaces and tabs but only if it's the end of the line
1233 if ($i == ($length - 1))
1234 {
1235 $char = ($ascii == '32' OR $ascii == '9') ? $escape.sprintf('%02s', dechex($ascii)) : $char;
1236 }
1237
1238 // encode = signs
1239 if ($ascii == '61')
1240 {
Derek Jones37f4b9c2011-07-01 17:56:50 -05001241 $char = $escape.strtoupper(sprintf('%02s', dechex($ascii))); // =3D
Derek Allard2067d1a2008-11-13 22:59:24 +00001242 }
1243
1244 // If we're at the character limit, add the line to the output,
1245 // reset our temp variable, and keep on chuggin'
1246 if ((strlen($temp) + strlen($char)) >= $charlim)
1247 {
1248 $output .= $temp.$escape.$this->crlf;
1249 $temp = '';
1250 }
1251
1252 // Add the character to our temporary line
1253 $temp .= $char;
1254 }
1255
1256 // Add our completed line to the output
1257 $output .= $temp.$this->crlf;
1258 }
1259
1260 // get rid of extra CRLF tacked onto the end
1261 $output = substr($output, 0, strlen($this->crlf) * -1);
1262
1263 return $output;
1264 }
1265
1266 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001267
Derek Allard2067d1a2008-11-13 22:59:24 +00001268 /**
1269 * Prep Q Encoding
1270 *
Derek Jones37f4b9c2011-07-01 17:56:50 -05001271 * Performs "Q Encoding" on a string for use in email headers. It's related
Derek Allard2067d1a2008-11-13 22:59:24 +00001272 * but not identical to quoted-printable, so it has its own method
1273 *
1274 * @access public
1275 * @param str
1276 * @param bool // set to TRUE for processing From: headers
1277 * @return str
1278 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001279 protected function _prep_q_encoding($str, $from = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001280 {
1281 $str = str_replace(array("\r", "\n"), array('', ''), $str);
1282
1283 // Line length must not exceed 76 characters, so we adjust for
1284 // a space, 7 extra characters =??Q??=, and the charset that we will add to each line
1285 $limit = 75 - 7 - strlen($this->charset);
1286
1287 // these special characters must be converted too
1288 $convert = array('_', '=', '?');
1289
1290 if ($from === TRUE)
1291 {
1292 $convert[] = ',';
1293 $convert[] = ';';
1294 }
1295
1296 $output = '';
1297 $temp = '';
1298
1299 for ($i = 0, $length = strlen($str); $i < $length; $i++)
1300 {
1301 // Grab the next character
1302 $char = substr($str, $i, 1);
1303 $ascii = ord($char);
1304
1305 // convert ALL non-printable ASCII characters and our specials
1306 if ($ascii < 32 OR $ascii > 126 OR in_array($char, $convert))
1307 {
1308 $char = '='.dechex($ascii);
1309 }
1310
1311 // handle regular spaces a bit more compactly than =20
1312 if ($ascii == 32)
1313 {
1314 $char = '_';
1315 }
1316
1317 // If we're at the character limit, add the line to the output,
1318 // reset our temp variable, and keep on chuggin'
1319 if ((strlen($temp) + strlen($char)) >= $limit)
1320 {
1321 $output .= $temp.$this->crlf;
1322 $temp = '';
1323 }
1324
1325 // Add the character to our temporary line
1326 $temp .= $char;
1327 }
1328
1329 $str = $output.$temp;
1330
1331 // wrap each line with the shebang, charset, and transfer encoding
1332 // the preceding space on successive lines is required for header "folding"
1333 $str = trim(preg_replace('/^(.*)$/m', ' =?'.$this->charset.'?Q?$1?=', $str));
1334
1335 return $str;
1336 }
1337
1338 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001339
Derek Allard2067d1a2008-11-13 22:59:24 +00001340 /**
1341 * Send Email
1342 *
1343 * @access public
1344 * @return bool
1345 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +00001346 public function send()
Derek Allard2067d1a2008-11-13 22:59:24 +00001347 {
1348 if ($this->_replyto_flag == FALSE)
1349 {
1350 $this->reply_to($this->_headers['From']);
1351 }
1352
Derek Jones37f4b9c2011-07-01 17:56:50 -05001353 if (( ! isset($this->_recipients) AND ! isset($this->_headers['To'])) AND
Derek Allard2067d1a2008-11-13 22:59:24 +00001354 ( ! isset($this->_bcc_array) AND ! isset($this->_headers['Bcc'])) AND
1355 ( ! isset($this->_headers['Cc'])))
1356 {
patworkb0707982011-04-08 15:10:05 +02001357 $this->_set_error_message('lang:email_no_recipients');
Derek Allard2067d1a2008-11-13 22:59:24 +00001358 return FALSE;
1359 }
1360
1361 $this->_build_headers();
1362
Derek Jones37f4b9c2011-07-01 17:56:50 -05001363 if ($this->bcc_batch_mode AND count($this->_bcc_array) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001364 {
1365 if (count($this->_bcc_array) > $this->bcc_batch_size)
1366 return $this->batch_bcc_send();
1367 }
1368
1369 $this->_build_message();
1370
1371 if ( ! $this->_spool_email())
1372 {
1373 return FALSE;
1374 }
1375 else
1376 {
1377 return TRUE;
1378 }
1379 }
Barry Mienydd671972010-10-04 16:33:58 +02001380
Derek Allard2067d1a2008-11-13 22:59:24 +00001381 // --------------------------------------------------------------------
1382
1383 /**
Derek Jones37f4b9c2011-07-01 17:56:50 -05001384 * Batch Bcc Send. Sends groups of BCCs in batches
Derek Allard2067d1a2008-11-13 22:59:24 +00001385 *
1386 * @access public
1387 * @return bool
1388 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +00001389 public function batch_bcc_send()
Derek Allard2067d1a2008-11-13 22:59:24 +00001390 {
1391 $float = $this->bcc_batch_size -1;
1392
1393 $set = "";
1394
1395 $chunk = array();
1396
1397 for ($i = 0; $i < count($this->_bcc_array); $i++)
1398 {
1399 if (isset($this->_bcc_array[$i]))
1400 {
1401 $set .= ", ".$this->_bcc_array[$i];
1402 }
1403
1404 if ($i == $float)
1405 {
1406 $chunk[] = substr($set, 1);
1407 $float = $float + $this->bcc_batch_size;
1408 $set = "";
1409 }
1410
1411 if ($i == count($this->_bcc_array)-1)
1412 {
1413 $chunk[] = substr($set, 1);
1414 }
1415 }
1416
1417 for ($i = 0; $i < count($chunk); $i++)
1418 {
1419 unset($this->_headers['Bcc']);
1420 unset($bcc);
1421
1422 $bcc = $this->_str_to_array($chunk[$i]);
1423 $bcc = $this->clean_email($bcc);
1424
1425 if ($this->protocol != 'smtp')
1426 {
1427 $this->_set_header('Bcc', implode(", ", $bcc));
1428 }
1429 else
1430 {
1431 $this->_bcc_array = $bcc;
1432 }
1433
1434 $this->_build_message();
1435 $this->_spool_email();
1436 }
1437 }
Barry Mienydd671972010-10-04 16:33:58 +02001438
Derek Allard2067d1a2008-11-13 22:59:24 +00001439 // --------------------------------------------------------------------
1440
1441 /**
1442 * Unwrap special elements
1443 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001444 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001445 * @return void
1446 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001447 protected function _unwrap_specials()
Derek Allard2067d1a2008-11-13 22:59:24 +00001448 {
1449 $this->_finalbody = preg_replace_callback("/\{unwrap\}(.*?)\{\/unwrap\}/si", array($this, '_remove_nl_callback'), $this->_finalbody);
1450 }
Barry Mienydd671972010-10-04 16:33:58 +02001451
Derek Allard2067d1a2008-11-13 22:59:24 +00001452 // --------------------------------------------------------------------
1453
1454 /**
1455 * Strip line-breaks via callback
1456 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001457 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001458 * @return string
1459 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001460 protected function _remove_nl_callback($matches)
Derek Allard2067d1a2008-11-13 22:59:24 +00001461 {
1462 if (strpos($matches[1], "\r") !== FALSE OR strpos($matches[1], "\n") !== FALSE)
1463 {
1464 $matches[1] = str_replace(array("\r\n", "\r", "\n"), '', $matches[1]);
1465 }
1466
1467 return $matches[1];
1468 }
Barry Mienydd671972010-10-04 16:33:58 +02001469
Derek Allard2067d1a2008-11-13 22:59:24 +00001470 // --------------------------------------------------------------------
1471
1472 /**
1473 * Spool mail to the mail server
1474 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001475 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001476 * @return bool
1477 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001478 protected function _spool_email()
Derek Allard2067d1a2008-11-13 22:59:24 +00001479 {
1480 $this->_unwrap_specials();
1481
1482 switch ($this->_get_protocol())
1483 {
1484 case 'mail' :
1485
1486 if ( ! $this->_send_with_mail())
1487 {
patworkb0707982011-04-08 15:10:05 +02001488 $this->_set_error_message('lang:email_send_failure_phpmail');
Derek Allard2067d1a2008-11-13 22:59:24 +00001489 return FALSE;
1490 }
1491 break;
1492 case 'sendmail' :
1493
1494 if ( ! $this->_send_with_sendmail())
1495 {
patworkb0707982011-04-08 15:10:05 +02001496 $this->_set_error_message('lang:email_send_failure_sendmail');
Derek Allard2067d1a2008-11-13 22:59:24 +00001497 return FALSE;
1498 }
1499 break;
1500 case 'smtp' :
1501
1502 if ( ! $this->_send_with_smtp())
1503 {
patworkb0707982011-04-08 15:10:05 +02001504 $this->_set_error_message('lang:email_send_failure_smtp');
Derek Allard2067d1a2008-11-13 22:59:24 +00001505 return FALSE;
1506 }
1507 break;
1508
1509 }
1510
patworkb0707982011-04-08 15:10:05 +02001511 $this->_set_error_message('lang:email_sent', $this->_get_protocol());
Derek Allard2067d1a2008-11-13 22:59:24 +00001512 return TRUE;
1513 }
Barry Mienydd671972010-10-04 16:33:58 +02001514
Derek Allard2067d1a2008-11-13 22:59:24 +00001515 // --------------------------------------------------------------------
1516
1517 /**
1518 * Send using mail()
1519 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001520 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001521 * @return bool
1522 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001523 protected function _send_with_mail()
Derek Allard2067d1a2008-11-13 22:59:24 +00001524 {
1525 if ($this->_safe_mode == TRUE)
1526 {
1527 if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str))
1528 {
1529 return FALSE;
1530 }
1531 else
1532 {
1533 return TRUE;
1534 }
1535 }
1536 else
1537 {
1538 // most documentation of sendmail using the "-f" flag lacks a space after it, however
1539 // we've encountered servers that seem to require it to be in place.
Eric Barnes6113f542010-12-29 13:36:12 -05001540
Derek Allard2067d1a2008-11-13 22:59:24 +00001541 if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, "-f ".$this->clean_email($this->_headers['From'])))
1542 {
1543 return FALSE;
1544 }
1545 else
1546 {
1547 return TRUE;
1548 }
1549 }
1550 }
Barry Mienydd671972010-10-04 16:33:58 +02001551
Derek Allard2067d1a2008-11-13 22:59:24 +00001552 // --------------------------------------------------------------------
1553
1554 /**
1555 * Send using Sendmail
1556 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001557 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001558 * @return bool
1559 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001560 protected function _send_with_sendmail()
Derek Allard2067d1a2008-11-13 22:59:24 +00001561 {
1562 $fp = @popen($this->mailpath . " -oi -f ".$this->clean_email($this->_headers['From'])." -t", 'w');
1563
Derek Jones4cefaa42009-04-29 19:13:56 +00001564 if ($fp === FALSE OR $fp === NULL)
1565 {
1566 // server probably has popen disabled, so nothing we can do to get a verbose error.
1567 return FALSE;
1568 }
Derek Jones71141ce2010-03-02 16:41:20 -06001569
Derek Jonesc630bcf2008-11-17 21:09:45 +00001570 fputs($fp, $this->_header_str);
1571 fputs($fp, $this->_finalbody);
1572
Barry Mienydd671972010-10-04 16:33:58 +02001573 $status = pclose($fp);
Eric Barnes6113f542010-12-29 13:36:12 -05001574
Derek Jonesc630bcf2008-11-17 21:09:45 +00001575 if (version_compare(PHP_VERSION, '4.2.3') == -1)
1576 {
1577 $status = $status >> 8 & 0xFF;
Barry Mienydd671972010-10-04 16:33:58 +02001578 }
Derek Jones71141ce2010-03-02 16:41:20 -06001579
Derek Jones604873f2008-11-18 15:57:24 +00001580 if ($status != 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001581 {
patworkb0707982011-04-08 15:10:05 +02001582 $this->_set_error_message('lang:email_exit_status', $status);
1583 $this->_set_error_message('lang:email_no_socket');
Derek Allard2067d1a2008-11-13 22:59:24 +00001584 return FALSE;
1585 }
1586
Derek Allard2067d1a2008-11-13 22:59:24 +00001587 return TRUE;
1588 }
Barry Mienydd671972010-10-04 16:33:58 +02001589
Derek Allard2067d1a2008-11-13 22:59:24 +00001590 // --------------------------------------------------------------------
1591
1592 /**
1593 * Send using SMTP
1594 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001595 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001596 * @return bool
1597 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001598 protected function _send_with_smtp()
Derek Allard2067d1a2008-11-13 22:59:24 +00001599 {
1600 if ($this->smtp_host == '')
1601 {
patworkb0707982011-04-08 15:10:05 +02001602 $this->_set_error_message('lang:email_no_hostname');
Derek Allard2067d1a2008-11-13 22:59:24 +00001603 return FALSE;
1604 }
1605
1606 $this->_smtp_connect();
1607 $this->_smtp_authenticate();
1608
1609 $this->_send_command('from', $this->clean_email($this->_headers['From']));
1610
Pascal Kriete14287f32011-02-14 13:39:34 -05001611 foreach ($this->_recipients as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001612 {
1613 $this->_send_command('to', $val);
1614 }
1615
1616 if (count($this->_cc_array) > 0)
1617 {
Pascal Kriete14287f32011-02-14 13:39:34 -05001618 foreach ($this->_cc_array as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001619 {
1620 if ($val != "")
1621 {
1622 $this->_send_command('to', $val);
1623 }
1624 }
1625 }
1626
1627 if (count($this->_bcc_array) > 0)
1628 {
Pascal Kriete14287f32011-02-14 13:39:34 -05001629 foreach ($this->_bcc_array as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001630 {
1631 if ($val != "")
1632 {
1633 $this->_send_command('to', $val);
1634 }
1635 }
1636 }
1637
1638 $this->_send_command('data');
1639
1640 // perform dot transformation on any lines that begin with a dot
1641 $this->_send_data($this->_header_str . preg_replace('/^\./m', '..$1', $this->_finalbody));
1642
1643 $this->_send_data('.');
1644
1645 $reply = $this->_get_smtp_data();
1646
1647 $this->_set_error_message($reply);
1648
1649 if (strncmp($reply, '250', 3) != 0)
1650 {
patworkb0707982011-04-08 15:10:05 +02001651 $this->_set_error_message('lang:email_smtp_error', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001652 return FALSE;
1653 }
1654
1655 $this->_send_command('quit');
1656 return TRUE;
1657 }
Barry Mienydd671972010-10-04 16:33:58 +02001658
Derek Allard2067d1a2008-11-13 22:59:24 +00001659 // --------------------------------------------------------------------
1660
1661 /**
1662 * SMTP Connect
1663 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001664 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001665 * @param string
1666 * @return string
1667 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001668 protected function _smtp_connect()
Derek Allard2067d1a2008-11-13 22:59:24 +00001669 {
1670 $this->_smtp_connect = fsockopen($this->smtp_host,
1671 $this->smtp_port,
1672 $errno,
1673 $errstr,
1674 $this->smtp_timeout);
1675
Pascal Kriete14287f32011-02-14 13:39:34 -05001676 if ( ! is_resource($this->_smtp_connect))
Derek Allard2067d1a2008-11-13 22:59:24 +00001677 {
patworkb0707982011-04-08 15:10:05 +02001678 $this->_set_error_message('lang:email_smtp_error', $errno." ".$errstr);
Derek Allard2067d1a2008-11-13 22:59:24 +00001679 return FALSE;
1680 }
1681
1682 $this->_set_error_message($this->_get_smtp_data());
1683 return $this->_send_command('hello');
1684 }
Barry Mienydd671972010-10-04 16:33:58 +02001685
Derek Allard2067d1a2008-11-13 22:59:24 +00001686 // --------------------------------------------------------------------
1687
1688 /**
1689 * Send SMTP command
1690 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001691 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001692 * @param string
1693 * @param string
1694 * @return string
1695 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001696 protected function _send_command($cmd, $data = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001697 {
1698 switch ($cmd)
1699 {
1700 case 'hello' :
1701
1702 if ($this->_smtp_auth OR $this->_get_encoding() == '8bit')
1703 $this->_send_data('EHLO '.$this->_get_hostname());
1704 else
1705 $this->_send_data('HELO '.$this->_get_hostname());
1706
1707 $resp = 250;
1708 break;
1709 case 'from' :
1710
1711 $this->_send_data('MAIL FROM:<'.$data.'>');
1712
1713 $resp = 250;
1714 break;
1715 case 'to' :
1716
1717 $this->_send_data('RCPT TO:<'.$data.'>');
1718
1719 $resp = 250;
1720 break;
1721 case 'data' :
1722
1723 $this->_send_data('DATA');
1724
1725 $resp = 354;
1726 break;
1727 case 'quit' :
1728
1729 $this->_send_data('QUIT');
1730
1731 $resp = 221;
1732 break;
1733 }
1734
1735 $reply = $this->_get_smtp_data();
1736
1737 $this->_debug_msg[] = "<pre>".$cmd.": ".$reply."</pre>";
1738
1739 if (substr($reply, 0, 3) != $resp)
1740 {
patworkb0707982011-04-08 15:10:05 +02001741 $this->_set_error_message('lang:email_smtp_error', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001742 return FALSE;
1743 }
1744
1745 if ($cmd == 'quit')
1746 {
1747 fclose($this->_smtp_connect);
1748 }
1749
1750 return TRUE;
1751 }
Barry Mienydd671972010-10-04 16:33:58 +02001752
Derek Allard2067d1a2008-11-13 22:59:24 +00001753 // --------------------------------------------------------------------
1754
1755 /**
Derek Jones37f4b9c2011-07-01 17:56:50 -05001756 * SMTP Authenticate
Derek Allard2067d1a2008-11-13 22:59:24 +00001757 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001758 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001759 * @return bool
1760 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001761 protected function _smtp_authenticate()
Derek Allard2067d1a2008-11-13 22:59:24 +00001762 {
1763 if ( ! $this->_smtp_auth)
1764 {
1765 return TRUE;
1766 }
1767
Derek Jones37f4b9c2011-07-01 17:56:50 -05001768 if ($this->smtp_user == "" AND $this->smtp_pass == "")
Derek Allard2067d1a2008-11-13 22:59:24 +00001769 {
patworkb0707982011-04-08 15:10:05 +02001770 $this->_set_error_message('lang:email_no_smtp_unpw');
Derek Allard2067d1a2008-11-13 22:59:24 +00001771 return FALSE;
1772 }
1773
1774 $this->_send_data('AUTH LOGIN');
1775
1776 $reply = $this->_get_smtp_data();
1777
1778 if (strncmp($reply, '334', 3) != 0)
1779 {
patworkb0707982011-04-08 15:10:05 +02001780 $this->_set_error_message('lang:email_failed_smtp_login', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001781 return FALSE;
1782 }
1783
1784 $this->_send_data(base64_encode($this->smtp_user));
1785
1786 $reply = $this->_get_smtp_data();
1787
1788 if (strncmp($reply, '334', 3) != 0)
1789 {
patworkb0707982011-04-08 15:10:05 +02001790 $this->_set_error_message('lang:email_smtp_auth_un', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001791 return FALSE;
1792 }
1793
1794 $this->_send_data(base64_encode($this->smtp_pass));
1795
1796 $reply = $this->_get_smtp_data();
1797
1798 if (strncmp($reply, '235', 3) != 0)
1799 {
patworkb0707982011-04-08 15:10:05 +02001800 $this->_set_error_message('lang:email_smtp_auth_pw', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001801 return FALSE;
1802 }
1803
1804 return TRUE;
1805 }
Barry Mienydd671972010-10-04 16:33:58 +02001806
Derek Allard2067d1a2008-11-13 22:59:24 +00001807 // --------------------------------------------------------------------
1808
1809 /**
1810 * Send SMTP data
1811 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001812 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001813 * @return bool
1814 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001815 protected function _send_data($data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001816 {
1817 if ( ! fwrite($this->_smtp_connect, $data . $this->newline))
1818 {
patworkb0707982011-04-08 15:10:05 +02001819 $this->_set_error_message('lang:email_smtp_data_failure', $data);
Derek Allard2067d1a2008-11-13 22:59:24 +00001820 return FALSE;
1821 }
1822 else
1823 {
1824 return TRUE;
1825 }
1826 }
Barry Mienydd671972010-10-04 16:33:58 +02001827
Derek Allard2067d1a2008-11-13 22:59:24 +00001828 // --------------------------------------------------------------------
1829
1830 /**
1831 * Get SMTP data
1832 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001833 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001834 * @return string
1835 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001836 protected function _get_smtp_data()
Derek Allard2067d1a2008-11-13 22:59:24 +00001837 {
1838 $data = "";
1839
1840 while ($str = fgets($this->_smtp_connect, 512))
1841 {
1842 $data .= $str;
1843
1844 if (substr($str, 3, 1) == " ")
1845 {
1846 break;
1847 }
1848 }
1849
1850 return $data;
1851 }
Barry Mienydd671972010-10-04 16:33:58 +02001852
Derek Allard2067d1a2008-11-13 22:59:24 +00001853 // --------------------------------------------------------------------
1854
1855 /**
1856 * Get Hostname
1857 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001858 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001859 * @return string
1860 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001861 protected function _get_hostname()
Derek Allard2067d1a2008-11-13 22:59:24 +00001862 {
1863 return (isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain';
1864 }
Barry Mienydd671972010-10-04 16:33:58 +02001865
Derek Allard2067d1a2008-11-13 22:59:24 +00001866 // --------------------------------------------------------------------
1867
1868 /**
1869 * Get IP
1870 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001871 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001872 * @return string
1873 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001874 protected function _get_ip()
Derek Allard2067d1a2008-11-13 22:59:24 +00001875 {
1876 if ($this->_IP !== FALSE)
1877 {
1878 return $this->_IP;
1879 }
1880
1881 $cip = (isset($_SERVER['HTTP_CLIENT_IP']) AND $_SERVER['HTTP_CLIENT_IP'] != "") ? $_SERVER['HTTP_CLIENT_IP'] : FALSE;
1882 $rip = (isset($_SERVER['REMOTE_ADDR']) AND $_SERVER['REMOTE_ADDR'] != "") ? $_SERVER['REMOTE_ADDR'] : FALSE;
1883 $fip = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND $_SERVER['HTTP_X_FORWARDED_FOR'] != "") ? $_SERVER['HTTP_X_FORWARDED_FOR'] : FALSE;
1884
Barry Mienydd671972010-10-04 16:33:58 +02001885 if ($cip && $rip) $this->_IP = $cip;
Derek Allard2067d1a2008-11-13 22:59:24 +00001886 elseif ($rip) $this->_IP = $rip;
1887 elseif ($cip) $this->_IP = $cip;
1888 elseif ($fip) $this->_IP = $fip;
1889
Robin Sowell76b369e2010-03-19 11:15:28 -04001890 if (strpos($this->_IP, ',') !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001891 {
1892 $x = explode(',', $this->_IP);
1893 $this->_IP = end($x);
1894 }
1895
1896 if ( ! preg_match( "/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $this->_IP))
1897 {
1898 $this->_IP = '0.0.0.0';
1899 }
1900
1901 unset($cip);
1902 unset($rip);
1903 unset($fip);
1904
1905 return $this->_IP;
1906 }
Barry Mienydd671972010-10-04 16:33:58 +02001907
Derek Allard2067d1a2008-11-13 22:59:24 +00001908 // --------------------------------------------------------------------
1909
1910 /**
1911 * Get Debug Message
1912 *
1913 * @access public
1914 * @return string
1915 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +00001916 public function print_debugger()
Derek Allard2067d1a2008-11-13 22:59:24 +00001917 {
1918 $msg = '';
1919
1920 if (count($this->_debug_msg) > 0)
1921 {
1922 foreach ($this->_debug_msg as $val)
1923 {
1924 $msg .= $val;
1925 }
1926 }
1927
1928 $msg .= "<pre>".$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".htmlspecialchars($this->_finalbody).'</pre>';
1929 return $msg;
1930 }
Barry Mienydd671972010-10-04 16:33:58 +02001931
Derek Allard2067d1a2008-11-13 22:59:24 +00001932 // --------------------------------------------------------------------
1933
1934 /**
1935 * Set Message
1936 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001937 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001938 * @param string
1939 * @return string
1940 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001941 protected function _set_error_message($msg, $val = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001942 {
1943 $CI =& get_instance();
1944 $CI->lang->load('email');
1945
patworkb0707982011-04-08 15:10:05 +02001946 if (substr($msg, 0, 5) != 'lang:' || FALSE === ($line = $CI->lang->line(substr($msg, 5))))
Derek Allard2067d1a2008-11-13 22:59:24 +00001947 {
1948 $this->_debug_msg[] = str_replace('%s', $val, $msg)."<br />";
1949 }
1950 else
1951 {
1952 $this->_debug_msg[] = str_replace('%s', $val, $line)."<br />";
1953 }
1954 }
Barry Mienydd671972010-10-04 16:33:58 +02001955
Derek Allard2067d1a2008-11-13 22:59:24 +00001956 // --------------------------------------------------------------------
1957
1958 /**
1959 * Mime Types
1960 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001961 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001962 * @param string
1963 * @return string
1964 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001965 protected function _mime_types($ext = "")
Derek Allard2067d1a2008-11-13 22:59:24 +00001966 {
1967 $mimes = array( 'hqx' => 'application/mac-binhex40',
1968 'cpt' => 'application/mac-compactpro',
1969 'doc' => 'application/msword',
1970 'bin' => 'application/macbinary',
1971 'dms' => 'application/octet-stream',
1972 'lha' => 'application/octet-stream',
1973 'lzh' => 'application/octet-stream',
1974 'exe' => 'application/octet-stream',
1975 'class' => 'application/octet-stream',
1976 'psd' => 'application/octet-stream',
1977 'so' => 'application/octet-stream',
1978 'sea' => 'application/octet-stream',
1979 'dll' => 'application/octet-stream',
1980 'oda' => 'application/oda',
1981 'pdf' => 'application/pdf',
1982 'ai' => 'application/postscript',
1983 'eps' => 'application/postscript',
1984 'ps' => 'application/postscript',
1985 'smi' => 'application/smil',
1986 'smil' => 'application/smil',
1987 'mif' => 'application/vnd.mif',
1988 'xls' => 'application/vnd.ms-excel',
1989 'ppt' => 'application/vnd.ms-powerpoint',
1990 'wbxml' => 'application/vnd.wap.wbxml',
1991 'wmlc' => 'application/vnd.wap.wmlc',
1992 'dcr' => 'application/x-director',
1993 'dir' => 'application/x-director',
1994 'dxr' => 'application/x-director',
1995 'dvi' => 'application/x-dvi',
1996 'gtar' => 'application/x-gtar',
1997 'php' => 'application/x-httpd-php',
1998 'php4' => 'application/x-httpd-php',
1999 'php3' => 'application/x-httpd-php',
2000 'phtml' => 'application/x-httpd-php',
2001 'phps' => 'application/x-httpd-php-source',
2002 'js' => 'application/x-javascript',
2003 'swf' => 'application/x-shockwave-flash',
2004 'sit' => 'application/x-stuffit',
2005 'tar' => 'application/x-tar',
2006 'tgz' => 'application/x-tar',
2007 'xhtml' => 'application/xhtml+xml',
2008 'xht' => 'application/xhtml+xml',
2009 'zip' => 'application/zip',
2010 'mid' => 'audio/midi',
2011 'midi' => 'audio/midi',
2012 'mpga' => 'audio/mpeg',
2013 'mp2' => 'audio/mpeg',
2014 'mp3' => 'audio/mpeg',
2015 'aif' => 'audio/x-aiff',
2016 'aiff' => 'audio/x-aiff',
2017 'aifc' => 'audio/x-aiff',
2018 'ram' => 'audio/x-pn-realaudio',
2019 'rm' => 'audio/x-pn-realaudio',
2020 'rpm' => 'audio/x-pn-realaudio-plugin',
2021 'ra' => 'audio/x-realaudio',
2022 'rv' => 'video/vnd.rn-realvideo',
2023 'wav' => 'audio/x-wav',
2024 'bmp' => 'image/bmp',
2025 'gif' => 'image/gif',
2026 'jpeg' => 'image/jpeg',
2027 'jpg' => 'image/jpeg',
2028 'jpe' => 'image/jpeg',
2029 'png' => 'image/png',
2030 'tiff' => 'image/tiff',
2031 'tif' => 'image/tiff',
2032 'css' => 'text/css',
2033 'html' => 'text/html',
2034 'htm' => 'text/html',
2035 'shtml' => 'text/html',
2036 'txt' => 'text/plain',
2037 'text' => 'text/plain',
2038 'log' => 'text/plain',
2039 'rtx' => 'text/richtext',
2040 'rtf' => 'text/rtf',
2041 'xml' => 'text/xml',
2042 'xsl' => 'text/xml',
2043 'mpeg' => 'video/mpeg',
2044 'mpg' => 'video/mpeg',
2045 'mpe' => 'video/mpeg',
2046 'qt' => 'video/quicktime',
2047 'mov' => 'video/quicktime',
2048 'avi' => 'video/x-msvideo',
2049 'movie' => 'video/x-sgi-movie',
2050 'doc' => 'application/msword',
2051 'word' => 'application/msword',
2052 'xl' => 'application/excel',
2053 'eml' => 'message/rfc822'
2054 );
2055
2056 return ( ! isset($mimes[strtolower($ext)])) ? "application/x-unknown-content-type" : $mimes[strtolower($ext)];
2057 }
2058
2059}
2060// END CI_Email class
2061
2062/* End of file Email.php */
patworkb0707982011-04-08 15:10:05 +02002063/* Location: ./system/libraries/Email.php */