blob: c8b727c3464e521947980d127124dde09907be82 [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
141 * @return void
142 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000143 public function clear($clear_attachments = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000144 {
145 $this->_subject = "";
146 $this->_body = "";
147 $this->_finalbody = "";
148 $this->_header_str = "";
149 $this->_replyto_flag = FALSE;
150 $this->_recipients = array();
Derek Jonesd1606352010-09-01 11:16:07 -0500151 $this->_cc_array = array();
152 $this->_bcc_array = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000153 $this->_headers = array();
154 $this->_debug_msg = array();
155
156 $this->_set_header('User-Agent', $this->useragent);
157 $this->_set_header('Date', $this->_set_date());
158
159 if ($clear_attachments !== FALSE)
160 {
161 $this->_attach_name = array();
162 $this->_attach_type = array();
163 $this->_attach_disp = array();
164 }
Eric Barnes6113f542010-12-29 13:36:12 -0500165
Greg Akera769deb2010-11-10 15:47:29 -0600166 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000167 }
Barry Mienydd671972010-10-04 16:33:58 +0200168
Derek Allard2067d1a2008-11-13 22:59:24 +0000169 // --------------------------------------------------------------------
170
171 /**
172 * Set FROM
173 *
174 * @access public
175 * @param string
176 * @param string
177 * @return void
178 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000179 public function from($from, $name = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000180 {
181 if (preg_match( '/\<(.*)\>/', $from, $match))
182 {
183 $from = $match['1'];
184 }
185
186 if ($this->validate)
187 {
188 $this->validate_email($this->_str_to_array($from));
189 }
190
191 // prepare the display name
192 if ($name != '')
193 {
194 // only use Q encoding if there are characters that would require it
195 if ( ! preg_match('/[\200-\377]/', $name))
196 {
197 // add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes
Derek Jonesc630bcf2008-11-17 21:09:45 +0000198 $name = '"'.addcslashes($name, "\0..\37\177'\"\\").'"';
Derek Allard2067d1a2008-11-13 22:59:24 +0000199 }
200 else
201 {
202 $name = $this->_prep_q_encoding($name, TRUE);
203 }
204 }
205
206 $this->_set_header('From', $name.' <'.$from.'>');
207 $this->_set_header('Return-Path', '<'.$from.'>');
Eric Barnes6113f542010-12-29 13:36:12 -0500208
Greg Akera769deb2010-11-10 15:47:29 -0600209 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000210 }
Barry Mienydd671972010-10-04 16:33:58 +0200211
Derek Allard2067d1a2008-11-13 22:59:24 +0000212 // --------------------------------------------------------------------
213
214 /**
215 * Set Reply-to
216 *
217 * @access public
218 * @param string
219 * @param string
220 * @return void
221 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000222 public function reply_to($replyto, $name = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000223 {
224 if (preg_match( '/\<(.*)\>/', $replyto, $match))
225 {
226 $replyto = $match['1'];
227 }
228
229 if ($this->validate)
230 {
231 $this->validate_email($this->_str_to_array($replyto));
232 }
233
234 if ($name == '')
235 {
236 $name = $replyto;
237 }
238
239 if (strncmp($name, '"', 1) != 0)
240 {
241 $name = '"'.$name.'"';
242 }
243
244 $this->_set_header('Reply-To', $name.' <'.$replyto.'>');
245 $this->_replyto_flag = TRUE;
Greg Akera769deb2010-11-10 15:47:29 -0600246
247 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000248 }
Barry Mienydd671972010-10-04 16:33:58 +0200249
Derek Allard2067d1a2008-11-13 22:59:24 +0000250 // --------------------------------------------------------------------
251
252 /**
253 * Set Recipients
254 *
255 * @access public
256 * @param string
257 * @return void
258 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000259 public function to($to)
Derek Allard2067d1a2008-11-13 22:59:24 +0000260 {
261 $to = $this->_str_to_array($to);
262 $to = $this->clean_email($to);
263
264 if ($this->validate)
265 {
266 $this->validate_email($to);
267 }
268
269 if ($this->_get_protocol() != 'mail')
270 {
271 $this->_set_header('To', implode(", ", $to));
272 }
273
274 switch ($this->_get_protocol())
275 {
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000276 case 'smtp' :
277 $this->_recipients = $to;
Derek Allard2067d1a2008-11-13 22:59:24 +0000278 break;
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000279 case 'sendmail' :
280 case 'mail' :
281 $this->_recipients = implode(", ", $to);
Derek Allard2067d1a2008-11-13 22:59:24 +0000282 break;
283 }
Eric Barnes6113f542010-12-29 13:36:12 -0500284
Greg Akera769deb2010-11-10 15:47:29 -0600285 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000286 }
Barry Mienydd671972010-10-04 16:33:58 +0200287
Derek Allard2067d1a2008-11-13 22:59:24 +0000288 // --------------------------------------------------------------------
289
290 /**
291 * Set CC
292 *
293 * @access public
294 * @param string
295 * @return void
296 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000297 public function cc($cc)
Derek Allard2067d1a2008-11-13 22:59:24 +0000298 {
299 $cc = $this->_str_to_array($cc);
300 $cc = $this->clean_email($cc);
301
302 if ($this->validate)
303 {
304 $this->validate_email($cc);
305 }
306
307 $this->_set_header('Cc', implode(", ", $cc));
308
309 if ($this->_get_protocol() == "smtp")
310 {
311 $this->_cc_array = $cc;
312 }
Eric Barnes6113f542010-12-29 13:36:12 -0500313
Greg Akera769deb2010-11-10 15:47:29 -0600314 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000315 }
Barry Mienydd671972010-10-04 16:33:58 +0200316
Derek Allard2067d1a2008-11-13 22:59:24 +0000317 // --------------------------------------------------------------------
318
319 /**
320 * Set BCC
321 *
322 * @access public
323 * @param string
324 * @param string
325 * @return void
326 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000327 public function bcc($bcc, $limit = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000328 {
329 if ($limit != '' && is_numeric($limit))
330 {
331 $this->bcc_batch_mode = TRUE;
332 $this->bcc_batch_size = $limit;
333 }
334
335 $bcc = $this->_str_to_array($bcc);
336 $bcc = $this->clean_email($bcc);
337
338 if ($this->validate)
339 {
340 $this->validate_email($bcc);
341 }
342
343 if (($this->_get_protocol() == "smtp") OR ($this->bcc_batch_mode && count($bcc) > $this->bcc_batch_size))
344 {
345 $this->_bcc_array = $bcc;
346 }
347 else
348 {
349 $this->_set_header('Bcc', implode(", ", $bcc));
350 }
Eric Barnes6113f542010-12-29 13:36:12 -0500351
Greg Akera769deb2010-11-10 15:47:29 -0600352 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000353 }
Barry Mienydd671972010-10-04 16:33:58 +0200354
Derek Allard2067d1a2008-11-13 22:59:24 +0000355 // --------------------------------------------------------------------
356
357 /**
358 * Set Email Subject
359 *
360 * @access public
361 * @param string
362 * @return void
363 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000364 public function subject($subject)
Derek Allard2067d1a2008-11-13 22:59:24 +0000365 {
366 $subject = $this->_prep_q_encoding($subject);
367 $this->_set_header('Subject', $subject);
Greg Akera769deb2010-11-10 15:47:29 -0600368 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000369 }
Barry Mienydd671972010-10-04 16:33:58 +0200370
Derek Allard2067d1a2008-11-13 22:59:24 +0000371 // --------------------------------------------------------------------
372
373 /**
374 * Set Body
375 *
376 * @access public
377 * @param string
378 * @return void
379 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000380 public function message($body)
Derek Allard2067d1a2008-11-13 22:59:24 +0000381 {
diegorivera13095cb2011-10-19 02:56:15 -0200382 $this->_body = rtrim(str_replace("\r", "", $body));
383
Andrey Andreev75b1f392011-10-20 10:11:59 +0300384 /* strip slashes only if magic quotes is ON
385 if we do it with magic quotes OFF, it strips real, user-inputted chars.
386
387 NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and
388 it will probably not exist in future versions at all.
389 */
390 if ( ! is_php('5.4') && get_magic_quotes_gpc())
diegorivera6eab49a2011-10-19 11:18:45 -0200391 {
diegorivera13095cb2011-10-19 02:56:15 -0200392 $this->_body = stripslashes($this->_body);
diegorivera6eab49a2011-10-19 11:18:45 -0200393 }
diegorivera13095cb2011-10-19 02:56:15 -0200394
Greg Akera769deb2010-11-10 15:47:29 -0600395 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000396 }
Barry Mienydd671972010-10-04 16:33:58 +0200397
Derek Allard2067d1a2008-11-13 22:59:24 +0000398 // --------------------------------------------------------------------
399
400 /**
401 * Assign file attachments
402 *
403 * @access public
404 * @param string
405 * @return void
406 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000407 public function attach($filename, $disposition = 'attachment')
Derek Allard2067d1a2008-11-13 22:59:24 +0000408 {
409 $this->_attach_name[] = $filename;
Phil Sturgeon0aaf42b2011-08-10 08:06:37 -0600410 $this->_attach_type[] = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION));
Derek Jones37f4b9c2011-07-01 17:56:50 -0500411 $this->_attach_disp[] = $disposition; // Can also be 'inline' Not sure if it matters
Greg Akera769deb2010-11-10 15:47:29 -0600412 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000413 }
414
415 // --------------------------------------------------------------------
416
417 /**
418 * Add a Header Item
419 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600420 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000421 * @param string
422 * @param string
423 * @return void
424 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600425 protected function _set_header($header, $value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000426 {
427 $this->_headers[$header] = $value;
428 }
Barry Mienydd671972010-10-04 16:33:58 +0200429
Derek Allard2067d1a2008-11-13 22:59:24 +0000430 // --------------------------------------------------------------------
431
432 /**
433 * Convert a String to an Array
434 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600435 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000436 * @param string
437 * @return array
438 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600439 protected function _str_to_array($email)
Derek Allard2067d1a2008-11-13 22:59:24 +0000440 {
441 if ( ! is_array($email))
442 {
443 if (strpos($email, ',') !== FALSE)
444 {
445 $email = preg_split('/[\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY);
446 }
447 else
448 {
449 $email = trim($email);
450 settype($email, "array");
451 }
452 }
453 return $email;
454 }
Barry Mienydd671972010-10-04 16:33:58 +0200455
Derek Allard2067d1a2008-11-13 22:59:24 +0000456 // --------------------------------------------------------------------
457
458 /**
459 * Set Multipart Value
460 *
461 * @access public
462 * @param string
463 * @return void
464 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000465 public function set_alt_message($str = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000466 {
Frank de Jonge9aa89292011-08-21 05:45:55 +0300467 $this->alt_message = $str;
Greg Akera769deb2010-11-10 15:47:29 -0600468 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000469 }
Barry Mienydd671972010-10-04 16:33:58 +0200470
Derek Allard2067d1a2008-11-13 22:59:24 +0000471 // --------------------------------------------------------------------
472
473 /**
474 * Set Mailtype
475 *
476 * @access public
477 * @param string
478 * @return void
479 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000480 public function set_mailtype($type = 'text')
Derek Allard2067d1a2008-11-13 22:59:24 +0000481 {
482 $this->mailtype = ($type == 'html') ? 'html' : 'text';
Greg Akera769deb2010-11-10 15:47:29 -0600483 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000484 }
Barry Mienydd671972010-10-04 16:33:58 +0200485
Derek Allard2067d1a2008-11-13 22:59:24 +0000486 // --------------------------------------------------------------------
487
488 /**
489 * Set Wordwrap
490 *
491 * @access public
492 * @param string
493 * @return void
494 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000495 public function set_wordwrap($wordwrap = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000496 {
497 $this->wordwrap = ($wordwrap === FALSE) ? FALSE : TRUE;
Greg Akera769deb2010-11-10 15:47:29 -0600498 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000499 }
Barry Mienydd671972010-10-04 16:33:58 +0200500
Derek Allard2067d1a2008-11-13 22:59:24 +0000501 // --------------------------------------------------------------------
502
503 /**
504 * Set Protocol
505 *
506 * @access public
507 * @param string
508 * @return void
509 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000510 public function set_protocol($protocol = 'mail')
Derek Allard2067d1a2008-11-13 22:59:24 +0000511 {
512 $this->protocol = ( ! in_array($protocol, $this->_protocols, TRUE)) ? 'mail' : strtolower($protocol);
Greg Akera769deb2010-11-10 15:47:29 -0600513 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000514 }
Barry Mienydd671972010-10-04 16:33:58 +0200515
Derek Allard2067d1a2008-11-13 22:59:24 +0000516 // --------------------------------------------------------------------
517
518 /**
519 * Set Priority
520 *
521 * @access public
522 * @param integer
523 * @return void
524 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000525 public function set_priority($n = 3)
Derek Allard2067d1a2008-11-13 22:59:24 +0000526 {
527 if ( ! is_numeric($n))
528 {
529 $this->priority = 3;
530 return;
531 }
532
533 if ($n < 1 OR $n > 5)
534 {
535 $this->priority = 3;
536 return;
537 }
538
539 $this->priority = $n;
Greg Akera769deb2010-11-10 15:47:29 -0600540 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000541 }
Barry Mienydd671972010-10-04 16:33:58 +0200542
Derek Allard2067d1a2008-11-13 22:59:24 +0000543 // --------------------------------------------------------------------
544
545 /**
546 * Set Newline Character
547 *
548 * @access public
549 * @param string
550 * @return void
551 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000552 public function set_newline($newline = "\n")
Derek Allard2067d1a2008-11-13 22:59:24 +0000553 {
554 if ($newline != "\n" AND $newline != "\r\n" AND $newline != "\r")
555 {
556 $this->newline = "\n";
557 return;
558 }
559
560 $this->newline = $newline;
Eric Barnes6113f542010-12-29 13:36:12 -0500561
Greg Akera769deb2010-11-10 15:47:29 -0600562 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000563 }
Barry Mienydd671972010-10-04 16:33:58 +0200564
Derek Allard2067d1a2008-11-13 22:59:24 +0000565 // --------------------------------------------------------------------
566
567 /**
568 * Set CRLF
569 *
570 * @access public
571 * @param string
572 * @return void
573 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000574 public function set_crlf($crlf = "\n")
Derek Allard2067d1a2008-11-13 22:59:24 +0000575 {
576 if ($crlf != "\n" AND $crlf != "\r\n" AND $crlf != "\r")
577 {
578 $this->crlf = "\n";
579 return;
580 }
581
582 $this->crlf = $crlf;
Eric Barnes6113f542010-12-29 13:36:12 -0500583
Greg Akera769deb2010-11-10 15:47:29 -0600584 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000585 }
Barry Mienydd671972010-10-04 16:33:58 +0200586
Derek Allard2067d1a2008-11-13 22:59:24 +0000587 // --------------------------------------------------------------------
588
589 /**
590 * Set Message Boundary
591 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600592 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000593 * @return void
594 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600595 protected function _set_boundaries()
Derek Allard2067d1a2008-11-13 22:59:24 +0000596 {
597 $this->_alt_boundary = "B_ALT_".uniqid(''); // multipart/alternative
598 $this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary
599 }
Barry Mienydd671972010-10-04 16:33:58 +0200600
Derek Allard2067d1a2008-11-13 22:59:24 +0000601 // --------------------------------------------------------------------
602
603 /**
604 * Get the Message ID
605 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600606 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000607 * @return string
608 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600609 protected function _get_message_id()
Derek Allard2067d1a2008-11-13 22:59:24 +0000610 {
611 $from = $this->_headers['Return-Path'];
612 $from = str_replace(">", "", $from);
613 $from = str_replace("<", "", $from);
614
Derek Jones37f4b9c2011-07-01 17:56:50 -0500615 return "<".uniqid('').strstr($from, '@').">";
Derek Allard2067d1a2008-11-13 22:59:24 +0000616 }
Barry Mienydd671972010-10-04 16:33:58 +0200617
Derek Allard2067d1a2008-11-13 22:59:24 +0000618 // --------------------------------------------------------------------
619
620 /**
621 * Get Mail Protocol
622 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600623 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000624 * @param bool
625 * @return string
626 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600627 protected function _get_protocol($return = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000628 {
629 $this->protocol = strtolower($this->protocol);
630 $this->protocol = ( ! in_array($this->protocol, $this->_protocols, TRUE)) ? 'mail' : $this->protocol;
631
632 if ($return == TRUE)
633 {
634 return $this->protocol;
635 }
636 }
Barry Mienydd671972010-10-04 16:33:58 +0200637
Derek Allard2067d1a2008-11-13 22:59:24 +0000638 // --------------------------------------------------------------------
639
640 /**
641 * Get Mail Encoding
642 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600643 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000644 * @param bool
645 * @return string
646 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600647 protected function _get_encoding($return = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000648 {
649 $this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '8bit' : $this->_encoding;
650
651 foreach ($this->_base_charsets as $charset)
652 {
653 if (strncmp($charset, $this->charset, strlen($charset)) == 0)
654 {
655 $this->_encoding = '7bit';
656 }
657 }
658
659 if ($return == TRUE)
660 {
661 return $this->_encoding;
662 }
663 }
664
665 // --------------------------------------------------------------------
666
667 /**
668 * Get content type (text/html/attachment)
669 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600670 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000671 * @return string
672 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600673 protected function _get_content_type()
Derek Allard2067d1a2008-11-13 22:59:24 +0000674 {
Derek Jones37f4b9c2011-07-01 17:56:50 -0500675 if ($this->mailtype == 'html' && count($this->_attach_name) == 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000676 {
677 return 'html';
678 }
Derek Jones37f4b9c2011-07-01 17:56:50 -0500679 elseif ($this->mailtype == 'html' && count($this->_attach_name) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000680 {
681 return 'html-attach';
682 }
Derek Jones37f4b9c2011-07-01 17:56:50 -0500683 elseif ($this->mailtype == 'text' && count($this->_attach_name) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000684 {
685 return 'plain-attach';
686 }
687 else
688 {
689 return 'plain';
690 }
691 }
Barry Mienydd671972010-10-04 16:33:58 +0200692
Derek Allard2067d1a2008-11-13 22:59:24 +0000693 // --------------------------------------------------------------------
694
695 /**
696 * Set RFC 822 Date
697 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600698 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000699 * @return string
700 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600701 protected function _set_date()
Derek Allard2067d1a2008-11-13 22:59:24 +0000702 {
703 $timezone = date("Z");
704 $operator = (strncmp($timezone, '-', 1) == 0) ? '-' : '+';
705 $timezone = abs($timezone);
706 $timezone = floor($timezone/3600) * 100 + ($timezone % 3600 ) / 60;
707
708 return sprintf("%s %s%04d", date("D, j M Y H:i:s"), $operator, $timezone);
709 }
Barry Mienydd671972010-10-04 16:33:58 +0200710
Derek Allard2067d1a2008-11-13 22:59:24 +0000711 // --------------------------------------------------------------------
712
713 /**
714 * Mime message
715 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600716 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000717 * @return string
718 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600719 protected function _get_mime_message()
Derek Allard2067d1a2008-11-13 22:59:24 +0000720 {
721 return "This is a multi-part message in MIME format.".$this->newline."Your email application may not support this format.";
722 }
Barry Mienydd671972010-10-04 16:33:58 +0200723
Derek Allard2067d1a2008-11-13 22:59:24 +0000724 // --------------------------------------------------------------------
725
726 /**
727 * Validate Email Address
728 *
729 * @access public
730 * @param string
731 * @return bool
732 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000733 public function validate_email($email)
Derek Allard2067d1a2008-11-13 22:59:24 +0000734 {
735 if ( ! is_array($email))
736 {
patworkb0707982011-04-08 15:10:05 +0200737 $this->_set_error_message('lang:email_must_be_array');
Derek Allard2067d1a2008-11-13 22:59:24 +0000738 return FALSE;
739 }
740
741 foreach ($email as $val)
742 {
743 if ( ! $this->valid_email($val))
744 {
patworkb0707982011-04-08 15:10:05 +0200745 $this->_set_error_message('lang:email_invalid_address', $val);
Derek Allard2067d1a2008-11-13 22:59:24 +0000746 return FALSE;
747 }
748 }
749
750 return TRUE;
751 }
Barry Mienydd671972010-10-04 16:33:58 +0200752
Derek Allard2067d1a2008-11-13 22:59:24 +0000753 // --------------------------------------------------------------------
754
755 /**
756 * Email Validation
757 *
758 * @access public
759 * @param string
760 * @return bool
761 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000762 public function valid_email($address)
Derek Allard2067d1a2008-11-13 22:59:24 +0000763 {
764 return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $address)) ? FALSE : TRUE;
765 }
Barry Mienydd671972010-10-04 16:33:58 +0200766
Derek Allard2067d1a2008-11-13 22:59:24 +0000767 // --------------------------------------------------------------------
768
769 /**
770 * Clean Extended Email Address: Joe Smith <joe@smith.com>
771 *
772 * @access public
773 * @param string
774 * @return string
775 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000776 public function clean_email($email)
Derek Allard2067d1a2008-11-13 22:59:24 +0000777 {
778 if ( ! is_array($email))
779 {
780 if (preg_match('/\<(.*)\>/', $email, $match))
781 {
Barry Mienydd671972010-10-04 16:33:58 +0200782 return $match['1'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000783 }
Barry Mienydd671972010-10-04 16:33:58 +0200784 else
Derek Allard2067d1a2008-11-13 22:59:24 +0000785 {
Barry Mienydd671972010-10-04 16:33:58 +0200786 return $email;
Derek Allard2067d1a2008-11-13 22:59:24 +0000787 }
788 }
789
790 $clean_email = array();
791
792 foreach ($email as $addy)
793 {
794 if (preg_match( '/\<(.*)\>/', $addy, $match))
795 {
Barry Mienydd671972010-10-04 16:33:58 +0200796 $clean_email[] = $match['1'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000797 }
Barry Mienydd671972010-10-04 16:33:58 +0200798 else
Derek Allard2067d1a2008-11-13 22:59:24 +0000799 {
Barry Mienydd671972010-10-04 16:33:58 +0200800 $clean_email[] = $addy;
Derek Allard2067d1a2008-11-13 22:59:24 +0000801 }
802 }
803
804 return $clean_email;
805 }
Barry Mienydd671972010-10-04 16:33:58 +0200806
Derek Allard2067d1a2008-11-13 22:59:24 +0000807 // --------------------------------------------------------------------
808
809 /**
810 * Build alternative plain text message
811 *
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000812 * This public function provides the raw message for use
Derek Allard2067d1a2008-11-13 22:59:24 +0000813 * in plain-text headers of HTML-formatted emails.
814 * If the user hasn't specified his own alternative message
815 * it creates one by stripping the HTML
816 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600817 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000818 * @return string
819 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600820 protected function _get_alt_message()
Derek Allard2067d1a2008-11-13 22:59:24 +0000821 {
822 if ($this->alt_message != "")
823 {
824 return $this->word_wrap($this->alt_message, '76');
825 }
826
827 if (preg_match('/\<body.*?\>(.*)\<\/body\>/si', $this->_body, $match))
828 {
829 $body = $match['1'];
830 }
831 else
832 {
833 $body = $this->_body;
834 }
835
836 $body = trim(strip_tags($body));
837 $body = preg_replace( '#<!--(.*)--\>#', "", $body);
838 $body = str_replace("\t", "", $body);
839
840 for ($i = 20; $i >= 3; $i--)
841 {
842 $n = "";
843
844 for ($x = 1; $x <= $i; $x ++)
845 {
Barry Mienydd671972010-10-04 16:33:58 +0200846 $n .= "\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000847 }
848
849 $body = str_replace($n, "\n\n", $body);
850 }
851
852 return $this->word_wrap($body, '76');
853 }
Barry Mienydd671972010-10-04 16:33:58 +0200854
Derek Allard2067d1a2008-11-13 22:59:24 +0000855 // --------------------------------------------------------------------
856
857 /**
858 * Word Wrap
859 *
860 * @access public
861 * @param string
862 * @param integer
863 * @return string
864 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000865 public function word_wrap($str, $charlim = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000866 {
867 // Se the character limit
868 if ($charlim == '')
869 {
870 $charlim = ($this->wrapchars == "") ? "76" : $this->wrapchars;
871 }
872
873 // Reduce multiple spaces
874 $str = preg_replace("| +|", " ", $str);
875
876 // Standardize newlines
877 if (strpos($str, "\r") !== FALSE)
878 {
879 $str = str_replace(array("\r\n", "\r"), "\n", $str);
880 }
881
882 // If the current word is surrounded by {unwrap} tags we'll
883 // strip the entire chunk and replace it with a marker.
884 $unwrap = array();
885 if (preg_match_all("|(\{unwrap\}.+?\{/unwrap\})|s", $str, $matches))
886 {
887 for ($i = 0; $i < count($matches['0']); $i++)
888 {
889 $unwrap[] = $matches['1'][$i];
890 $str = str_replace($matches['1'][$i], "{{unwrapped".$i."}}", $str);
891 }
892 }
893
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000894 // Use PHP's native public function to do the initial wordwrap.
Derek Allard2067d1a2008-11-13 22:59:24 +0000895 // We set the cut flag to FALSE so that any individual words that are
Derek Jones37f4b9c2011-07-01 17:56:50 -0500896 // too long get left alone. In the next step we'll deal with them.
Derek Allard2067d1a2008-11-13 22:59:24 +0000897 $str = wordwrap($str, $charlim, "\n", FALSE);
898
899 // Split the string into individual lines of text and cycle through them
900 $output = "";
901 foreach (explode("\n", $str) as $line)
902 {
903 // Is the line within the allowed character count?
904 // If so we'll join it to the output and continue
905 if (strlen($line) <= $charlim)
906 {
907 $output .= $line.$this->newline;
908 continue;
909 }
910
911 $temp = '';
Pascal Kriete14287f32011-02-14 13:39:34 -0500912 while ((strlen($line)) > $charlim)
Derek Allard2067d1a2008-11-13 22:59:24 +0000913 {
914 // If the over-length word is a URL we won't wrap it
915 if (preg_match("!\[url.+\]|://|wwww.!", $line))
916 {
917 break;
918 }
919
920 // Trim the word down
921 $temp .= substr($line, 0, $charlim-1);
922 $line = substr($line, $charlim-1);
923 }
924
925 // If $temp contains data it means we had to split up an over-length
926 // word into smaller chunks so we'll add it back to our current line
927 if ($temp != '')
928 {
929 $output .= $temp.$this->newline.$line;
930 }
931 else
932 {
933 $output .= $line;
934 }
935
936 $output .= $this->newline;
937 }
938
939 // Put our markers back
940 if (count($unwrap) > 0)
941 {
942 foreach ($unwrap as $key => $val)
943 {
944 $output = str_replace("{{unwrapped".$key."}}", $val, $output);
945 }
946 }
947
948 return $output;
949 }
Barry Mienydd671972010-10-04 16:33:58 +0200950
Derek Allard2067d1a2008-11-13 22:59:24 +0000951 // --------------------------------------------------------------------
952
953 /**
954 * Build final headers
955 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600956 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000957 * @param string
958 * @return string
959 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600960 protected function _build_headers()
Derek Allard2067d1a2008-11-13 22:59:24 +0000961 {
962 $this->_set_header('X-Sender', $this->clean_email($this->_headers['From']));
963 $this->_set_header('X-Mailer', $this->useragent);
964 $this->_set_header('X-Priority', $this->_priorities[$this->priority - 1]);
965 $this->_set_header('Message-ID', $this->_get_message_id());
966 $this->_set_header('Mime-Version', '1.0');
967 }
Barry Mienydd671972010-10-04 16:33:58 +0200968
Derek Allard2067d1a2008-11-13 22:59:24 +0000969 // --------------------------------------------------------------------
970
971 /**
972 * Write Headers as a string
973 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600974 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000975 * @return void
976 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600977 protected function _write_headers()
Derek Allard2067d1a2008-11-13 22:59:24 +0000978 {
979 if ($this->protocol == 'mail')
980 {
981 $this->_subject = $this->_headers['Subject'];
982 unset($this->_headers['Subject']);
983 }
984
985 reset($this->_headers);
986 $this->_header_str = "";
987
Pascal Kriete14287f32011-02-14 13:39:34 -0500988 foreach ($this->_headers as $key => $val)
Derek Allard2067d1a2008-11-13 22:59:24 +0000989 {
990 $val = trim($val);
991
992 if ($val != "")
993 {
994 $this->_header_str .= $key.": ".$val.$this->newline;
995 }
996 }
997
998 if ($this->_get_protocol() == 'mail')
999 {
Derek Jones1d890882009-02-10 20:32:14 +00001000 $this->_header_str = rtrim($this->_header_str);
Derek Allard2067d1a2008-11-13 22:59:24 +00001001 }
1002 }
Barry Mienydd671972010-10-04 16:33:58 +02001003
Derek Allard2067d1a2008-11-13 22:59:24 +00001004 // --------------------------------------------------------------------
1005
1006 /**
1007 * Build Final Body and attachments
1008 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001009 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001010 * @return void
1011 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001012 protected function _build_message()
Derek Allard2067d1a2008-11-13 22:59:24 +00001013 {
Derek Jones37f4b9c2011-07-01 17:56:50 -05001014 if ($this->wordwrap === TRUE AND $this->mailtype != 'html')
Derek Allard2067d1a2008-11-13 22:59:24 +00001015 {
1016 $this->_body = $this->word_wrap($this->_body);
1017 }
1018
1019 $this->_set_boundaries();
1020 $this->_write_headers();
1021
1022 $hdr = ($this->_get_protocol() == 'mail') ? $this->newline : '';
Brandon Jones485d7412010-11-09 16:38:17 -05001023 $body = '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001024
1025 switch ($this->_get_content_type())
1026 {
1027 case 'plain' :
1028
1029 $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1030 $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding();
1031
1032 if ($this->_get_protocol() == 'mail')
1033 {
1034 $this->_header_str .= $hdr;
1035 $this->_finalbody = $this->_body;
Derek Allard2067d1a2008-11-13 22:59:24 +00001036 }
Brandon Jones485d7412010-11-09 16:38:17 -05001037 else
1038 {
1039 $this->_finalbody = $hdr . $this->newline . $this->newline . $this->_body;
1040 }
Eric Barnes6113f542010-12-29 13:36:12 -05001041
Derek Allard2067d1a2008-11-13 22:59:24 +00001042 return;
1043
1044 break;
1045 case 'html' :
1046
1047 if ($this->send_multipart === FALSE)
1048 {
1049 $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
1050 $hdr .= "Content-Transfer-Encoding: quoted-printable";
1051 }
1052 else
1053 {
Derek Jonesa45e7612009-02-10 18:33:01 +00001054 $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001055
Brandon Jones485d7412010-11-09 16:38:17 -05001056 $body .= $this->_get_mime_message() . $this->newline . $this->newline;
1057 $body .= "--" . $this->_alt_boundary . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001058
Brandon Jones485d7412010-11-09 16:38:17 -05001059 $body .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1060 $body .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
1061 $body .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
1062
1063 $body .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
1064 $body .= "Content-Transfer-Encoding: quoted-printable" . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001065 }
Eric Barnes6113f542010-12-29 13:36:12 -05001066
Brandon Jones485d7412010-11-09 16:38:17 -05001067 $this->_finalbody = $body . $this->_prep_quoted_printable($this->_body) . $this->newline . $this->newline;
Eric Barnes6113f542010-12-29 13:36:12 -05001068
1069
Derek Allard2067d1a2008-11-13 22:59:24 +00001070 if ($this->_get_protocol() == 'mail')
1071 {
1072 $this->_header_str .= $hdr;
Brandon Jones485d7412010-11-09 16:38:17 -05001073 }
1074 else
1075 {
1076 $this->_finalbody = $hdr . $this->_finalbody;
Derek Allard2067d1a2008-11-13 22:59:24 +00001077 }
1078
Derek Allard2067d1a2008-11-13 22:59:24 +00001079
1080 if ($this->send_multipart !== FALSE)
1081 {
Brandon Jones485d7412010-11-09 16:38:17 -05001082 $this->_finalbody .= "--" . $this->_alt_boundary . "--";
Derek Allard2067d1a2008-11-13 22:59:24 +00001083 }
1084
Derek Allard2067d1a2008-11-13 22:59:24 +00001085 return;
1086
1087 break;
1088 case 'plain-attach' :
1089
Derek Jonesa45e7612009-02-10 18:33:01 +00001090 $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001091
1092 if ($this->_get_protocol() == 'mail')
1093 {
1094 $this->_header_str .= $hdr;
Eric Barnes6113f542010-12-29 13:36:12 -05001095 }
1096
Brandon Jones485d7412010-11-09 16:38:17 -05001097 $body .= $this->_get_mime_message() . $this->newline . $this->newline;
1098 $body .= "--" . $this->_atc_boundary . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001099
Brandon Jones485d7412010-11-09 16:38:17 -05001100 $body .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1101 $body .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001102
Brandon Jones485d7412010-11-09 16:38:17 -05001103 $body .= $this->_body . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001104
1105 break;
1106 case 'html-attach' :
1107
Derek Jonesa45e7612009-02-10 18:33:01 +00001108 $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline . $this->newline;
Eric Barnes6113f542010-12-29 13:36:12 -05001109
Derek Allard2067d1a2008-11-13 22:59:24 +00001110 if ($this->_get_protocol() == 'mail')
1111 {
1112 $this->_header_str .= $hdr;
Derek Allard2067d1a2008-11-13 22:59:24 +00001113 }
1114
Brandon Jones485d7412010-11-09 16:38:17 -05001115 $body .= $this->_get_mime_message() . $this->newline . $this->newline;
1116 $body .= "--" . $this->_atc_boundary . $this->newline;
1117
1118 $body .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline .$this->newline;
1119 $body .= "--" . $this->_alt_boundary . $this->newline;
1120
1121 $body .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1122 $body .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
1123 $body .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
1124
1125 $body .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
1126 $body .= "Content-Transfer-Encoding: quoted-printable" . $this->newline . $this->newline;
1127
1128 $body .= $this->_prep_quoted_printable($this->_body) . $this->newline . $this->newline;
1129 $body .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001130
1131 break;
1132 }
1133
1134 $attachment = array();
1135
1136 $z = 0;
1137
1138 for ($i=0; $i < count($this->_attach_name); $i++)
1139 {
1140 $filename = $this->_attach_name[$i];
1141 $basename = basename($filename);
1142 $ctype = $this->_attach_type[$i];
1143
1144 if ( ! file_exists($filename))
1145 {
patworkb0707982011-04-08 15:10:05 +02001146 $this->_set_error_message('lang:email_attachment_missing', $filename);
Derek Allard2067d1a2008-11-13 22:59:24 +00001147 return FALSE;
1148 }
1149
Derek Jones37f4b9c2011-07-01 17:56:50 -05001150 $h = "--".$this->_atc_boundary.$this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001151 $h .= "Content-type: ".$ctype."; ";
1152 $h .= "name=\"".$basename."\"".$this->newline;
1153 $h .= "Content-Disposition: ".$this->_attach_disp[$i].";".$this->newline;
1154 $h .= "Content-Transfer-Encoding: base64".$this->newline;
1155
1156 $attachment[$z++] = $h;
1157 $file = filesize($filename) +1;
1158
1159 if ( ! $fp = fopen($filename, FOPEN_READ))
1160 {
patworkb0707982011-04-08 15:10:05 +02001161 $this->_set_error_message('lang:email_attachment_unreadable', $filename);
Derek Allard2067d1a2008-11-13 22:59:24 +00001162 return FALSE;
1163 }
1164
1165 $attachment[$z++] = chunk_split(base64_encode(fread($fp, $file)));
1166 fclose($fp);
1167 }
1168
Brandon Jones485d7412010-11-09 16:38:17 -05001169 $body .= implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--";
Eric Barnes6113f542010-12-29 13:36:12 -05001170
Brandon Jones485d7412010-11-09 16:38:17 -05001171
Derek Allard2067d1a2008-11-13 22:59:24 +00001172 if ($this->_get_protocol() == 'mail')
1173 {
Brandon Jones485d7412010-11-09 16:38:17 -05001174 $this->_finalbody = $body;
Derek Allard2067d1a2008-11-13 22:59:24 +00001175 }
Brandon Jones485d7412010-11-09 16:38:17 -05001176 else
1177 {
1178 $this->_finalbody = $hdr . $body;
1179 }
Eric Barnes6113f542010-12-29 13:36:12 -05001180
Derek Allard2067d1a2008-11-13 22:59:24 +00001181 return;
1182 }
Barry Mienydd671972010-10-04 16:33:58 +02001183
Derek Allard2067d1a2008-11-13 22:59:24 +00001184 // --------------------------------------------------------------------
1185
1186 /**
1187 * Prep Quoted Printable
1188 *
1189 * Prepares string for Quoted-Printable Content-Transfer-Encoding
1190 * Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt
1191 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001192 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001193 * @param string
1194 * @param integer
1195 * @return string
1196 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001197 protected function _prep_quoted_printable($str, $charlim = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001198 {
1199 // Set the character limit
1200 // Don't allow over 76, as that will make servers and MUAs barf
1201 // all over quoted-printable data
1202 if ($charlim == '' OR $charlim > '76')
1203 {
1204 $charlim = '76';
1205 }
1206
1207 // Reduce multiple spaces
1208 $str = preg_replace("| +|", " ", $str);
1209
1210 // kill nulls
1211 $str = preg_replace('/\x00+/', '', $str);
1212
1213 // Standardize newlines
1214 if (strpos($str, "\r") !== FALSE)
1215 {
1216 $str = str_replace(array("\r\n", "\r"), "\n", $str);
1217 }
1218
1219 // We are intentionally wrapping so mail servers will encode characters
1220 // properly and MUAs will behave, so {unwrap} must go!
1221 $str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str);
1222
1223 // Break into an array of lines
1224 $lines = explode("\n", $str);
1225
1226 $escape = '=';
1227 $output = '';
1228
1229 foreach ($lines as $line)
1230 {
1231 $length = strlen($line);
1232 $temp = '';
1233
1234 // Loop through each character in the line to add soft-wrap
1235 // characters at the end of a line " =\r\n" and add the newly
1236 // processed line(s) to the output (see comment on $crlf class property)
1237 for ($i = 0; $i < $length; $i++)
1238 {
1239 // Grab the next character
1240 $char = substr($line, $i, 1);
1241 $ascii = ord($char);
1242
1243 // Convert spaces and tabs but only if it's the end of the line
1244 if ($i == ($length - 1))
1245 {
1246 $char = ($ascii == '32' OR $ascii == '9') ? $escape.sprintf('%02s', dechex($ascii)) : $char;
1247 }
1248
1249 // encode = signs
1250 if ($ascii == '61')
1251 {
Derek Jones37f4b9c2011-07-01 17:56:50 -05001252 $char = $escape.strtoupper(sprintf('%02s', dechex($ascii))); // =3D
Derek Allard2067d1a2008-11-13 22:59:24 +00001253 }
1254
1255 // If we're at the character limit, add the line to the output,
1256 // reset our temp variable, and keep on chuggin'
1257 if ((strlen($temp) + strlen($char)) >= $charlim)
1258 {
1259 $output .= $temp.$escape.$this->crlf;
1260 $temp = '';
1261 }
1262
1263 // Add the character to our temporary line
1264 $temp .= $char;
1265 }
1266
1267 // Add our completed line to the output
1268 $output .= $temp.$this->crlf;
1269 }
1270
1271 // get rid of extra CRLF tacked onto the end
1272 $output = substr($output, 0, strlen($this->crlf) * -1);
1273
1274 return $output;
1275 }
1276
1277 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001278
Derek Allard2067d1a2008-11-13 22:59:24 +00001279 /**
1280 * Prep Q Encoding
1281 *
Derek Jones37f4b9c2011-07-01 17:56:50 -05001282 * Performs "Q Encoding" on a string for use in email headers. It's related
Derek Allard2067d1a2008-11-13 22:59:24 +00001283 * but not identical to quoted-printable, so it has its own method
1284 *
1285 * @access public
1286 * @param str
1287 * @param bool // set to TRUE for processing From: headers
1288 * @return str
1289 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001290 protected function _prep_q_encoding($str, $from = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001291 {
1292 $str = str_replace(array("\r", "\n"), array('', ''), $str);
1293
1294 // Line length must not exceed 76 characters, so we adjust for
1295 // a space, 7 extra characters =??Q??=, and the charset that we will add to each line
1296 $limit = 75 - 7 - strlen($this->charset);
1297
1298 // these special characters must be converted too
1299 $convert = array('_', '=', '?');
1300
1301 if ($from === TRUE)
1302 {
1303 $convert[] = ',';
1304 $convert[] = ';';
1305 }
1306
1307 $output = '';
1308 $temp = '';
1309
1310 for ($i = 0, $length = strlen($str); $i < $length; $i++)
1311 {
1312 // Grab the next character
1313 $char = substr($str, $i, 1);
1314 $ascii = ord($char);
1315
1316 // convert ALL non-printable ASCII characters and our specials
1317 if ($ascii < 32 OR $ascii > 126 OR in_array($char, $convert))
1318 {
1319 $char = '='.dechex($ascii);
1320 }
1321
1322 // handle regular spaces a bit more compactly than =20
1323 if ($ascii == 32)
1324 {
1325 $char = '_';
1326 }
1327
1328 // If we're at the character limit, add the line to the output,
1329 // reset our temp variable, and keep on chuggin'
1330 if ((strlen($temp) + strlen($char)) >= $limit)
1331 {
1332 $output .= $temp.$this->crlf;
1333 $temp = '';
1334 }
1335
1336 // Add the character to our temporary line
1337 $temp .= $char;
1338 }
1339
1340 $str = $output.$temp;
1341
1342 // wrap each line with the shebang, charset, and transfer encoding
1343 // the preceding space on successive lines is required for header "folding"
1344 $str = trim(preg_replace('/^(.*)$/m', ' =?'.$this->charset.'?Q?$1?=', $str));
1345
1346 return $str;
1347 }
1348
1349 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001350
Derek Allard2067d1a2008-11-13 22:59:24 +00001351 /**
1352 * Send Email
1353 *
1354 * @access public
1355 * @return bool
1356 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +00001357 public function send()
Derek Allard2067d1a2008-11-13 22:59:24 +00001358 {
1359 if ($this->_replyto_flag == FALSE)
1360 {
1361 $this->reply_to($this->_headers['From']);
1362 }
1363
Derek Jones37f4b9c2011-07-01 17:56:50 -05001364 if (( ! isset($this->_recipients) AND ! isset($this->_headers['To'])) AND
Derek Allard2067d1a2008-11-13 22:59:24 +00001365 ( ! isset($this->_bcc_array) AND ! isset($this->_headers['Bcc'])) AND
1366 ( ! isset($this->_headers['Cc'])))
1367 {
patworkb0707982011-04-08 15:10:05 +02001368 $this->_set_error_message('lang:email_no_recipients');
Derek Allard2067d1a2008-11-13 22:59:24 +00001369 return FALSE;
1370 }
1371
1372 $this->_build_headers();
1373
Derek Jones37f4b9c2011-07-01 17:56:50 -05001374 if ($this->bcc_batch_mode AND count($this->_bcc_array) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001375 {
1376 if (count($this->_bcc_array) > $this->bcc_batch_size)
1377 return $this->batch_bcc_send();
1378 }
1379
1380 $this->_build_message();
1381
1382 if ( ! $this->_spool_email())
1383 {
1384 return FALSE;
1385 }
1386 else
1387 {
1388 return TRUE;
1389 }
1390 }
Barry Mienydd671972010-10-04 16:33:58 +02001391
Derek Allard2067d1a2008-11-13 22:59:24 +00001392 // --------------------------------------------------------------------
1393
1394 /**
Derek Jones37f4b9c2011-07-01 17:56:50 -05001395 * Batch Bcc Send. Sends groups of BCCs in batches
Derek Allard2067d1a2008-11-13 22:59:24 +00001396 *
1397 * @access public
1398 * @return bool
1399 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +00001400 public function batch_bcc_send()
Derek Allard2067d1a2008-11-13 22:59:24 +00001401 {
1402 $float = $this->bcc_batch_size -1;
1403
1404 $set = "";
1405
1406 $chunk = array();
1407
1408 for ($i = 0; $i < count($this->_bcc_array); $i++)
1409 {
1410 if (isset($this->_bcc_array[$i]))
1411 {
1412 $set .= ", ".$this->_bcc_array[$i];
1413 }
1414
1415 if ($i == $float)
1416 {
1417 $chunk[] = substr($set, 1);
1418 $float = $float + $this->bcc_batch_size;
1419 $set = "";
1420 }
1421
1422 if ($i == count($this->_bcc_array)-1)
1423 {
1424 $chunk[] = substr($set, 1);
1425 }
1426 }
1427
1428 for ($i = 0; $i < count($chunk); $i++)
1429 {
1430 unset($this->_headers['Bcc']);
1431 unset($bcc);
1432
1433 $bcc = $this->_str_to_array($chunk[$i]);
1434 $bcc = $this->clean_email($bcc);
1435
1436 if ($this->protocol != 'smtp')
1437 {
1438 $this->_set_header('Bcc', implode(", ", $bcc));
1439 }
1440 else
1441 {
1442 $this->_bcc_array = $bcc;
1443 }
1444
1445 $this->_build_message();
1446 $this->_spool_email();
1447 }
1448 }
Barry Mienydd671972010-10-04 16:33:58 +02001449
Derek Allard2067d1a2008-11-13 22:59:24 +00001450 // --------------------------------------------------------------------
1451
1452 /**
1453 * Unwrap special elements
1454 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001455 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001456 * @return void
1457 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001458 protected function _unwrap_specials()
Derek Allard2067d1a2008-11-13 22:59:24 +00001459 {
1460 $this->_finalbody = preg_replace_callback("/\{unwrap\}(.*?)\{\/unwrap\}/si", array($this, '_remove_nl_callback'), $this->_finalbody);
1461 }
Barry Mienydd671972010-10-04 16:33:58 +02001462
Derek Allard2067d1a2008-11-13 22:59:24 +00001463 // --------------------------------------------------------------------
1464
1465 /**
1466 * Strip line-breaks via callback
1467 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001468 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001469 * @return string
1470 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001471 protected function _remove_nl_callback($matches)
Derek Allard2067d1a2008-11-13 22:59:24 +00001472 {
1473 if (strpos($matches[1], "\r") !== FALSE OR strpos($matches[1], "\n") !== FALSE)
1474 {
1475 $matches[1] = str_replace(array("\r\n", "\r", "\n"), '', $matches[1]);
1476 }
1477
1478 return $matches[1];
1479 }
Barry Mienydd671972010-10-04 16:33:58 +02001480
Derek Allard2067d1a2008-11-13 22:59:24 +00001481 // --------------------------------------------------------------------
1482
1483 /**
1484 * Spool mail to the mail server
1485 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001486 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001487 * @return bool
1488 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001489 protected function _spool_email()
Derek Allard2067d1a2008-11-13 22:59:24 +00001490 {
1491 $this->_unwrap_specials();
1492
1493 switch ($this->_get_protocol())
1494 {
1495 case 'mail' :
1496
1497 if ( ! $this->_send_with_mail())
1498 {
patworkb0707982011-04-08 15:10:05 +02001499 $this->_set_error_message('lang:email_send_failure_phpmail');
Derek Allard2067d1a2008-11-13 22:59:24 +00001500 return FALSE;
1501 }
1502 break;
1503 case 'sendmail' :
1504
1505 if ( ! $this->_send_with_sendmail())
1506 {
patworkb0707982011-04-08 15:10:05 +02001507 $this->_set_error_message('lang:email_send_failure_sendmail');
Derek Allard2067d1a2008-11-13 22:59:24 +00001508 return FALSE;
1509 }
1510 break;
1511 case 'smtp' :
1512
1513 if ( ! $this->_send_with_smtp())
1514 {
patworkb0707982011-04-08 15:10:05 +02001515 $this->_set_error_message('lang:email_send_failure_smtp');
Derek Allard2067d1a2008-11-13 22:59:24 +00001516 return FALSE;
1517 }
1518 break;
1519
1520 }
1521
patworkb0707982011-04-08 15:10:05 +02001522 $this->_set_error_message('lang:email_sent', $this->_get_protocol());
Derek Allard2067d1a2008-11-13 22:59:24 +00001523 return TRUE;
1524 }
Barry Mienydd671972010-10-04 16:33:58 +02001525
Derek Allard2067d1a2008-11-13 22:59:24 +00001526 // --------------------------------------------------------------------
1527
1528 /**
1529 * Send using mail()
1530 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001531 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001532 * @return bool
1533 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001534 protected function _send_with_mail()
Derek Allard2067d1a2008-11-13 22:59:24 +00001535 {
1536 if ($this->_safe_mode == TRUE)
1537 {
1538 if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str))
1539 {
1540 return FALSE;
1541 }
1542 else
1543 {
1544 return TRUE;
1545 }
1546 }
1547 else
1548 {
1549 // most documentation of sendmail using the "-f" flag lacks a space after it, however
1550 // we've encountered servers that seem to require it to be in place.
Eric Barnes6113f542010-12-29 13:36:12 -05001551
Derek Allard2067d1a2008-11-13 22:59:24 +00001552 if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, "-f ".$this->clean_email($this->_headers['From'])))
1553 {
1554 return FALSE;
1555 }
1556 else
1557 {
1558 return TRUE;
1559 }
1560 }
1561 }
Barry Mienydd671972010-10-04 16:33:58 +02001562
Derek Allard2067d1a2008-11-13 22:59:24 +00001563 // --------------------------------------------------------------------
1564
1565 /**
1566 * Send using Sendmail
1567 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001568 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001569 * @return bool
1570 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001571 protected function _send_with_sendmail()
Derek Allard2067d1a2008-11-13 22:59:24 +00001572 {
1573 $fp = @popen($this->mailpath . " -oi -f ".$this->clean_email($this->_headers['From'])." -t", 'w');
1574
Derek Jones4cefaa42009-04-29 19:13:56 +00001575 if ($fp === FALSE OR $fp === NULL)
1576 {
1577 // server probably has popen disabled, so nothing we can do to get a verbose error.
1578 return FALSE;
1579 }
Derek Jones71141ce2010-03-02 16:41:20 -06001580
Derek Jonesc630bcf2008-11-17 21:09:45 +00001581 fputs($fp, $this->_header_str);
1582 fputs($fp, $this->_finalbody);
1583
Barry Mienydd671972010-10-04 16:33:58 +02001584 $status = pclose($fp);
Eric Barnes6113f542010-12-29 13:36:12 -05001585
Derek Jonesc630bcf2008-11-17 21:09:45 +00001586 if (version_compare(PHP_VERSION, '4.2.3') == -1)
1587 {
1588 $status = $status >> 8 & 0xFF;
Barry Mienydd671972010-10-04 16:33:58 +02001589 }
Derek Jones71141ce2010-03-02 16:41:20 -06001590
Derek Jones604873f2008-11-18 15:57:24 +00001591 if ($status != 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001592 {
patworkb0707982011-04-08 15:10:05 +02001593 $this->_set_error_message('lang:email_exit_status', $status);
1594 $this->_set_error_message('lang:email_no_socket');
Derek Allard2067d1a2008-11-13 22:59:24 +00001595 return FALSE;
1596 }
1597
Derek Allard2067d1a2008-11-13 22:59:24 +00001598 return TRUE;
1599 }
Barry Mienydd671972010-10-04 16:33:58 +02001600
Derek Allard2067d1a2008-11-13 22:59:24 +00001601 // --------------------------------------------------------------------
1602
1603 /**
1604 * Send using SMTP
1605 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001606 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001607 * @return bool
1608 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001609 protected function _send_with_smtp()
Derek Allard2067d1a2008-11-13 22:59:24 +00001610 {
1611 if ($this->smtp_host == '')
1612 {
patworkb0707982011-04-08 15:10:05 +02001613 $this->_set_error_message('lang:email_no_hostname');
Derek Allard2067d1a2008-11-13 22:59:24 +00001614 return FALSE;
1615 }
1616
1617 $this->_smtp_connect();
1618 $this->_smtp_authenticate();
1619
1620 $this->_send_command('from', $this->clean_email($this->_headers['From']));
1621
Pascal Kriete14287f32011-02-14 13:39:34 -05001622 foreach ($this->_recipients as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001623 {
1624 $this->_send_command('to', $val);
1625 }
1626
1627 if (count($this->_cc_array) > 0)
1628 {
Pascal Kriete14287f32011-02-14 13:39:34 -05001629 foreach ($this->_cc_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 if (count($this->_bcc_array) > 0)
1639 {
Pascal Kriete14287f32011-02-14 13:39:34 -05001640 foreach ($this->_bcc_array as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001641 {
1642 if ($val != "")
1643 {
1644 $this->_send_command('to', $val);
1645 }
1646 }
1647 }
1648
1649 $this->_send_command('data');
1650
1651 // perform dot transformation on any lines that begin with a dot
1652 $this->_send_data($this->_header_str . preg_replace('/^\./m', '..$1', $this->_finalbody));
1653
1654 $this->_send_data('.');
1655
1656 $reply = $this->_get_smtp_data();
1657
1658 $this->_set_error_message($reply);
1659
1660 if (strncmp($reply, '250', 3) != 0)
1661 {
patworkb0707982011-04-08 15:10:05 +02001662 $this->_set_error_message('lang:email_smtp_error', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001663 return FALSE;
1664 }
1665
1666 $this->_send_command('quit');
1667 return TRUE;
1668 }
Barry Mienydd671972010-10-04 16:33:58 +02001669
Derek Allard2067d1a2008-11-13 22:59:24 +00001670 // --------------------------------------------------------------------
1671
1672 /**
1673 * SMTP Connect
1674 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001675 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001676 * @param string
1677 * @return string
1678 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001679 protected function _smtp_connect()
Derek Allard2067d1a2008-11-13 22:59:24 +00001680 {
1681 $this->_smtp_connect = fsockopen($this->smtp_host,
1682 $this->smtp_port,
1683 $errno,
1684 $errstr,
1685 $this->smtp_timeout);
1686
Pascal Kriete14287f32011-02-14 13:39:34 -05001687 if ( ! is_resource($this->_smtp_connect))
Derek Allard2067d1a2008-11-13 22:59:24 +00001688 {
patworkb0707982011-04-08 15:10:05 +02001689 $this->_set_error_message('lang:email_smtp_error', $errno." ".$errstr);
Derek Allard2067d1a2008-11-13 22:59:24 +00001690 return FALSE;
1691 }
1692
1693 $this->_set_error_message($this->_get_smtp_data());
1694 return $this->_send_command('hello');
1695 }
Barry Mienydd671972010-10-04 16:33:58 +02001696
Derek Allard2067d1a2008-11-13 22:59:24 +00001697 // --------------------------------------------------------------------
1698
1699 /**
1700 * Send SMTP command
1701 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001702 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001703 * @param string
1704 * @param string
1705 * @return string
1706 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001707 protected function _send_command($cmd, $data = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001708 {
1709 switch ($cmd)
1710 {
1711 case 'hello' :
1712
1713 if ($this->_smtp_auth OR $this->_get_encoding() == '8bit')
1714 $this->_send_data('EHLO '.$this->_get_hostname());
1715 else
1716 $this->_send_data('HELO '.$this->_get_hostname());
1717
1718 $resp = 250;
1719 break;
1720 case 'from' :
1721
1722 $this->_send_data('MAIL FROM:<'.$data.'>');
1723
1724 $resp = 250;
1725 break;
1726 case 'to' :
1727
1728 $this->_send_data('RCPT TO:<'.$data.'>');
1729
1730 $resp = 250;
1731 break;
1732 case 'data' :
1733
1734 $this->_send_data('DATA');
1735
1736 $resp = 354;
1737 break;
1738 case 'quit' :
1739
1740 $this->_send_data('QUIT');
1741
1742 $resp = 221;
1743 break;
1744 }
1745
1746 $reply = $this->_get_smtp_data();
1747
1748 $this->_debug_msg[] = "<pre>".$cmd.": ".$reply."</pre>";
1749
1750 if (substr($reply, 0, 3) != $resp)
1751 {
patworkb0707982011-04-08 15:10:05 +02001752 $this->_set_error_message('lang:email_smtp_error', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001753 return FALSE;
1754 }
1755
1756 if ($cmd == 'quit')
1757 {
1758 fclose($this->_smtp_connect);
1759 }
1760
1761 return TRUE;
1762 }
Barry Mienydd671972010-10-04 16:33:58 +02001763
Derek Allard2067d1a2008-11-13 22:59:24 +00001764 // --------------------------------------------------------------------
1765
1766 /**
Derek Jones37f4b9c2011-07-01 17:56:50 -05001767 * SMTP Authenticate
Derek Allard2067d1a2008-11-13 22:59:24 +00001768 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001769 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001770 * @return bool
1771 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001772 protected function _smtp_authenticate()
Derek Allard2067d1a2008-11-13 22:59:24 +00001773 {
1774 if ( ! $this->_smtp_auth)
1775 {
1776 return TRUE;
1777 }
1778
Derek Jones37f4b9c2011-07-01 17:56:50 -05001779 if ($this->smtp_user == "" AND $this->smtp_pass == "")
Derek Allard2067d1a2008-11-13 22:59:24 +00001780 {
patworkb0707982011-04-08 15:10:05 +02001781 $this->_set_error_message('lang:email_no_smtp_unpw');
Derek Allard2067d1a2008-11-13 22:59:24 +00001782 return FALSE;
1783 }
1784
1785 $this->_send_data('AUTH LOGIN');
1786
1787 $reply = $this->_get_smtp_data();
1788
1789 if (strncmp($reply, '334', 3) != 0)
1790 {
patworkb0707982011-04-08 15:10:05 +02001791 $this->_set_error_message('lang:email_failed_smtp_login', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001792 return FALSE;
1793 }
1794
1795 $this->_send_data(base64_encode($this->smtp_user));
1796
1797 $reply = $this->_get_smtp_data();
1798
1799 if (strncmp($reply, '334', 3) != 0)
1800 {
patworkb0707982011-04-08 15:10:05 +02001801 $this->_set_error_message('lang:email_smtp_auth_un', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001802 return FALSE;
1803 }
1804
1805 $this->_send_data(base64_encode($this->smtp_pass));
1806
1807 $reply = $this->_get_smtp_data();
1808
1809 if (strncmp($reply, '235', 3) != 0)
1810 {
patworkb0707982011-04-08 15:10:05 +02001811 $this->_set_error_message('lang:email_smtp_auth_pw', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001812 return FALSE;
1813 }
1814
1815 return TRUE;
1816 }
Barry Mienydd671972010-10-04 16:33:58 +02001817
Derek Allard2067d1a2008-11-13 22:59:24 +00001818 // --------------------------------------------------------------------
1819
1820 /**
1821 * Send SMTP data
1822 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001823 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001824 * @return bool
1825 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001826 protected function _send_data($data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001827 {
1828 if ( ! fwrite($this->_smtp_connect, $data . $this->newline))
1829 {
patworkb0707982011-04-08 15:10:05 +02001830 $this->_set_error_message('lang:email_smtp_data_failure', $data);
Derek Allard2067d1a2008-11-13 22:59:24 +00001831 return FALSE;
1832 }
1833 else
1834 {
1835 return TRUE;
1836 }
1837 }
Barry Mienydd671972010-10-04 16:33:58 +02001838
Derek Allard2067d1a2008-11-13 22:59:24 +00001839 // --------------------------------------------------------------------
1840
1841 /**
1842 * Get SMTP data
1843 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001844 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001845 * @return string
1846 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001847 protected function _get_smtp_data()
Derek Allard2067d1a2008-11-13 22:59:24 +00001848 {
1849 $data = "";
1850
1851 while ($str = fgets($this->_smtp_connect, 512))
1852 {
1853 $data .= $str;
1854
1855 if (substr($str, 3, 1) == " ")
1856 {
1857 break;
1858 }
1859 }
1860
1861 return $data;
1862 }
Barry Mienydd671972010-10-04 16:33:58 +02001863
Derek Allard2067d1a2008-11-13 22:59:24 +00001864 // --------------------------------------------------------------------
1865
1866 /**
1867 * Get Hostname
1868 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001869 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001870 * @return string
1871 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001872 protected function _get_hostname()
Derek Allard2067d1a2008-11-13 22:59:24 +00001873 {
1874 return (isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain';
1875 }
Barry Mienydd671972010-10-04 16:33:58 +02001876
Derek Allard2067d1a2008-11-13 22:59:24 +00001877 // --------------------------------------------------------------------
1878
1879 /**
1880 * Get IP
1881 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001882 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001883 * @return string
1884 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001885 protected function _get_ip()
Derek Allard2067d1a2008-11-13 22:59:24 +00001886 {
1887 if ($this->_IP !== FALSE)
1888 {
1889 return $this->_IP;
1890 }
1891
1892 $cip = (isset($_SERVER['HTTP_CLIENT_IP']) AND $_SERVER['HTTP_CLIENT_IP'] != "") ? $_SERVER['HTTP_CLIENT_IP'] : FALSE;
1893 $rip = (isset($_SERVER['REMOTE_ADDR']) AND $_SERVER['REMOTE_ADDR'] != "") ? $_SERVER['REMOTE_ADDR'] : FALSE;
1894 $fip = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND $_SERVER['HTTP_X_FORWARDED_FOR'] != "") ? $_SERVER['HTTP_X_FORWARDED_FOR'] : FALSE;
1895
Barry Mienydd671972010-10-04 16:33:58 +02001896 if ($cip && $rip) $this->_IP = $cip;
Derek Allard2067d1a2008-11-13 22:59:24 +00001897 elseif ($rip) $this->_IP = $rip;
1898 elseif ($cip) $this->_IP = $cip;
1899 elseif ($fip) $this->_IP = $fip;
1900
Robin Sowell76b369e2010-03-19 11:15:28 -04001901 if (strpos($this->_IP, ',') !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001902 {
1903 $x = explode(',', $this->_IP);
1904 $this->_IP = end($x);
1905 }
1906
1907 if ( ! preg_match( "/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $this->_IP))
1908 {
1909 $this->_IP = '0.0.0.0';
1910 }
1911
1912 unset($cip);
1913 unset($rip);
1914 unset($fip);
1915
1916 return $this->_IP;
1917 }
Barry Mienydd671972010-10-04 16:33:58 +02001918
Derek Allard2067d1a2008-11-13 22:59:24 +00001919 // --------------------------------------------------------------------
1920
1921 /**
1922 * Get Debug Message
1923 *
1924 * @access public
1925 * @return string
1926 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +00001927 public function print_debugger()
Derek Allard2067d1a2008-11-13 22:59:24 +00001928 {
1929 $msg = '';
1930
1931 if (count($this->_debug_msg) > 0)
1932 {
1933 foreach ($this->_debug_msg as $val)
1934 {
1935 $msg .= $val;
1936 }
1937 }
1938
1939 $msg .= "<pre>".$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".htmlspecialchars($this->_finalbody).'</pre>';
1940 return $msg;
1941 }
Barry Mienydd671972010-10-04 16:33:58 +02001942
Derek Allard2067d1a2008-11-13 22:59:24 +00001943 // --------------------------------------------------------------------
1944
1945 /**
1946 * Set Message
1947 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001948 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001949 * @param string
1950 * @return string
1951 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001952 protected function _set_error_message($msg, $val = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001953 {
1954 $CI =& get_instance();
1955 $CI->lang->load('email');
1956
patworkb0707982011-04-08 15:10:05 +02001957 if (substr($msg, 0, 5) != 'lang:' || FALSE === ($line = $CI->lang->line(substr($msg, 5))))
Derek Allard2067d1a2008-11-13 22:59:24 +00001958 {
1959 $this->_debug_msg[] = str_replace('%s', $val, $msg)."<br />";
1960 }
1961 else
1962 {
1963 $this->_debug_msg[] = str_replace('%s', $val, $line)."<br />";
1964 }
1965 }
Barry Mienydd671972010-10-04 16:33:58 +02001966
Derek Allard2067d1a2008-11-13 22:59:24 +00001967 // --------------------------------------------------------------------
1968
1969 /**
1970 * Mime Types
1971 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001972 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001973 * @param string
1974 * @return string
1975 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001976 protected function _mime_types($ext = "")
Derek Allard2067d1a2008-11-13 22:59:24 +00001977 {
1978 $mimes = array( 'hqx' => 'application/mac-binhex40',
1979 'cpt' => 'application/mac-compactpro',
1980 'doc' => 'application/msword',
1981 'bin' => 'application/macbinary',
1982 'dms' => 'application/octet-stream',
1983 'lha' => 'application/octet-stream',
1984 'lzh' => 'application/octet-stream',
1985 'exe' => 'application/octet-stream',
1986 'class' => 'application/octet-stream',
1987 'psd' => 'application/octet-stream',
1988 'so' => 'application/octet-stream',
1989 'sea' => 'application/octet-stream',
1990 'dll' => 'application/octet-stream',
1991 'oda' => 'application/oda',
1992 'pdf' => 'application/pdf',
1993 'ai' => 'application/postscript',
1994 'eps' => 'application/postscript',
1995 'ps' => 'application/postscript',
1996 'smi' => 'application/smil',
1997 'smil' => 'application/smil',
1998 'mif' => 'application/vnd.mif',
1999 'xls' => 'application/vnd.ms-excel',
2000 'ppt' => 'application/vnd.ms-powerpoint',
2001 'wbxml' => 'application/vnd.wap.wbxml',
2002 'wmlc' => 'application/vnd.wap.wmlc',
2003 'dcr' => 'application/x-director',
2004 'dir' => 'application/x-director',
2005 'dxr' => 'application/x-director',
2006 'dvi' => 'application/x-dvi',
2007 'gtar' => 'application/x-gtar',
2008 'php' => 'application/x-httpd-php',
2009 'php4' => 'application/x-httpd-php',
2010 'php3' => 'application/x-httpd-php',
2011 'phtml' => 'application/x-httpd-php',
2012 'phps' => 'application/x-httpd-php-source',
2013 'js' => 'application/x-javascript',
2014 'swf' => 'application/x-shockwave-flash',
2015 'sit' => 'application/x-stuffit',
2016 'tar' => 'application/x-tar',
2017 'tgz' => 'application/x-tar',
2018 'xhtml' => 'application/xhtml+xml',
2019 'xht' => 'application/xhtml+xml',
2020 'zip' => 'application/zip',
2021 'mid' => 'audio/midi',
2022 'midi' => 'audio/midi',
2023 'mpga' => 'audio/mpeg',
2024 'mp2' => 'audio/mpeg',
2025 'mp3' => 'audio/mpeg',
2026 'aif' => 'audio/x-aiff',
2027 'aiff' => 'audio/x-aiff',
2028 'aifc' => 'audio/x-aiff',
2029 'ram' => 'audio/x-pn-realaudio',
2030 'rm' => 'audio/x-pn-realaudio',
2031 'rpm' => 'audio/x-pn-realaudio-plugin',
2032 'ra' => 'audio/x-realaudio',
2033 'rv' => 'video/vnd.rn-realvideo',
2034 'wav' => 'audio/x-wav',
2035 'bmp' => 'image/bmp',
2036 'gif' => 'image/gif',
2037 'jpeg' => 'image/jpeg',
2038 'jpg' => 'image/jpeg',
2039 'jpe' => 'image/jpeg',
2040 'png' => 'image/png',
2041 'tiff' => 'image/tiff',
2042 'tif' => 'image/tiff',
2043 'css' => 'text/css',
2044 'html' => 'text/html',
2045 'htm' => 'text/html',
2046 'shtml' => 'text/html',
2047 'txt' => 'text/plain',
2048 'text' => 'text/plain',
2049 'log' => 'text/plain',
2050 'rtx' => 'text/richtext',
2051 'rtf' => 'text/rtf',
2052 'xml' => 'text/xml',
2053 'xsl' => 'text/xml',
2054 'mpeg' => 'video/mpeg',
2055 'mpg' => 'video/mpeg',
2056 'mpe' => 'video/mpeg',
2057 'qt' => 'video/quicktime',
2058 'mov' => 'video/quicktime',
2059 'avi' => 'video/x-msvideo',
2060 'movie' => 'video/x-sgi-movie',
2061 'doc' => 'application/msword',
2062 'word' => 'application/msword',
2063 'xl' => 'application/excel',
2064 'eml' => 'message/rfc822'
2065 );
2066
2067 return ( ! isset($mimes[strtolower($ext)])) ? "application/x-unknown-content-type" : $mimes[strtolower($ext)];
2068 }
2069
2070}
2071// END CI_Email class
2072
2073/* End of file Email.php */
patworkb0707982011-04-08 15:10:05 +02002074/* Location: ./system/libraries/Email.php */