blob: db6ea8f902bd72d955a9ee472d358d555dbae802 [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 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
8 *
9 * Licensed under the Open Software License version 3.0
10 *
11 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
Derek Allard2067d1a2008-11-13 22:59:24 +000019 * @package CodeIgniter
Derek Jonesf4a4bd82011-10-20 12:18:42 -050020 * @author EllisLab Dev Team
21 * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. (http://ellislab.com/)
22 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Derek Allard2067d1a2008-11-13 22:59:24 +000023 * @link http://codeigniter.com
24 * @since Version 1.0
25 * @filesource
26 */
27
28// ------------------------------------------------------------------------
29
30/**
31 * CodeIgniter Email Class
32 *
33 * Permits email to be sent using Mail, Sendmail, or SMTP.
34 *
35 * @package CodeIgniter
36 * @subpackage Libraries
37 * @category Libraries
Derek Jonesf4a4bd82011-10-20 12:18:42 -050038 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000039 * @link http://codeigniter.com/user_guide/libraries/email.html
40 */
41class CI_Email {
42
43 var $useragent = "CodeIgniter";
44 var $mailpath = "/usr/sbin/sendmail"; // Sendmail path
45 var $protocol = "mail"; // mail/sendmail/smtp
Derek Jones37f4b9c2011-07-01 17:56:50 -050046 var $smtp_host = ""; // SMTP Server. Example: mail.earthlink.net
Derek Allard2067d1a2008-11-13 22:59:24 +000047 var $smtp_user = ""; // SMTP Username
48 var $smtp_pass = ""; // SMTP Password
49 var $smtp_port = "25"; // SMTP Port
50 var $smtp_timeout = 5; // SMTP Timeout in seconds
Radu Potopbbf04b02011-09-28 13:57:51 +030051 var $smtp_crypto = ""; // SMTP Encryption. Can be null, tls or ssl.
Derek Jones37f4b9c2011-07-01 17:56:50 -050052 var $wordwrap = TRUE; // TRUE/FALSE Turns word-wrap on/off
Derek Allard2067d1a2008-11-13 22:59:24 +000053 var $wrapchars = "76"; // Number of characters to wrap at.
Derek Jones37f4b9c2011-07-01 17:56:50 -050054 var $mailtype = "text"; // text/html Defines email formatting
Derek Allard2067d1a2008-11-13 22:59:24 +000055 var $charset = "utf-8"; // Default char set: iso-8859-1 or us-ascii
56 var $multipart = "mixed"; // "mixed" (in the body) or "related" (separate)
57 var $alt_message = ''; // Alternative message for HTML emails
Derek Jones37f4b9c2011-07-01 17:56:50 -050058 var $validate = FALSE; // TRUE/FALSE. Enables email validation
Derek Allard2067d1a2008-11-13 22:59:24 +000059 var $priority = "3"; // Default priority (1 - 5)
60 var $newline = "\n"; // Default newline. "\r\n" or "\n" (Use "\r\n" to comply with RFC 822)
Derek Jones37f4b9c2011-07-01 17:56:50 -050061 var $crlf = "\n"; // The RFC 2045 compliant CRLF for quoted-printable is "\r\n". Apparently some servers,
Derek Allard2067d1a2008-11-13 22:59:24 +000062 // even on the receiving end think they need to muck with CRLFs, so using "\n", while
63 // distasteful, is the only thing that seems to work for all environments.
Derek Jones37f4b9c2011-07-01 17:56:50 -050064 var $send_multipart = TRUE; // TRUE/FALSE - Yahoo does not like multipart alternative, so this is an override. Set to FALSE for Yahoo.
65 var $bcc_batch_mode = FALSE; // TRUE/FALSE Turns on/off Bcc batch feature
Derek Allard2067d1a2008-11-13 22:59:24 +000066 var $bcc_batch_size = 200; // If bcc_batch_mode = TRUE, sets max number of Bccs in each batch
67 var $_safe_mode = FALSE;
68 var $_subject = "";
69 var $_body = "";
70 var $_finalbody = "";
71 var $_alt_boundary = "";
72 var $_atc_boundary = "";
73 var $_header_str = "";
74 var $_smtp_connect = "";
75 var $_encoding = "8bit";
76 var $_IP = FALSE;
77 var $_smtp_auth = FALSE;
78 var $_replyto_flag = FALSE;
79 var $_debug_msg = array();
80 var $_recipients = array();
81 var $_cc_array = array();
82 var $_bcc_array = array();
83 var $_headers = array();
84 var $_attach_name = array();
85 var $_attach_type = array();
86 var $_attach_disp = array();
87 var $_protocols = array('mail', 'sendmail', 'smtp');
88 var $_base_charsets = array('us-ascii', 'iso-2022-'); // 7-bit charsets (excluding language suffix)
89 var $_bit_depths = array('7bit', '8bit');
90 var $_priorities = array('1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)');
91
92
93 /**
94 * Constructor - Sets Email Preferences
95 *
96 * The constructor can be passed an array of config values
97 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +000098 public function __construct($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000099 {
100 if (count($config) > 0)
101 {
102 $this->initialize($config);
103 }
104 else
105 {
106 $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE;
107 $this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE;
108 }
109
110 log_message('debug', "Email Class Initialized");
111 }
112
113 // --------------------------------------------------------------------
114
115 /**
116 * Initialize preferences
117 *
118 * @access public
119 * @param array
120 * @return void
121 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000122 public function initialize($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000123 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000124 foreach ($config as $key => $val)
125 {
126 if (isset($this->$key))
127 {
128 $method = 'set_'.$key;
129
130 if (method_exists($this, $method))
131 {
132 $this->$method($val);
133 }
134 else
135 {
136 $this->$key = $val;
137 }
138 }
139 }
Eric Barnes6113f542010-12-29 13:36:12 -0500140 $this->clear();
Derek Allard2067d1a2008-11-13 22:59:24 +0000141
142 $this->_smtp_auth = ($this->smtp_user == '' AND $this->smtp_pass == '') ? FALSE : TRUE;
143 $this->_safe_mode = ((boolean)@ini_get("safe_mode") === FALSE) ? FALSE : TRUE;
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000144
145 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000146 }
Barry Mienydd671972010-10-04 16:33:58 +0200147
Derek Allard2067d1a2008-11-13 22:59:24 +0000148 // --------------------------------------------------------------------
149
150 /**
151 * Initialize the Email Data
152 *
153 * @access public
Bo-Yi Wu83320eb2011-09-15 13:28:02 +0800154 * @param bool
Derek Allard2067d1a2008-11-13 22:59:24 +0000155 * @return void
156 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000157 public function clear($clear_attachments = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000158 {
159 $this->_subject = "";
160 $this->_body = "";
161 $this->_finalbody = "";
162 $this->_header_str = "";
163 $this->_replyto_flag = FALSE;
164 $this->_recipients = array();
Derek Jonesd1606352010-09-01 11:16:07 -0500165 $this->_cc_array = array();
166 $this->_bcc_array = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000167 $this->_headers = array();
168 $this->_debug_msg = array();
169
170 $this->_set_header('User-Agent', $this->useragent);
171 $this->_set_header('Date', $this->_set_date());
172
173 if ($clear_attachments !== FALSE)
174 {
175 $this->_attach_name = array();
176 $this->_attach_type = array();
177 $this->_attach_disp = array();
178 }
Eric Barnes6113f542010-12-29 13:36:12 -0500179
Greg Akera769deb2010-11-10 15:47:29 -0600180 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000181 }
Barry Mienydd671972010-10-04 16:33:58 +0200182
Derek Allard2067d1a2008-11-13 22:59:24 +0000183 // --------------------------------------------------------------------
184
185 /**
186 * Set FROM
187 *
188 * @access public
189 * @param string
190 * @param string
191 * @return void
192 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000193 public function from($from, $name = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000194 {
195 if (preg_match( '/\<(.*)\>/', $from, $match))
196 {
197 $from = $match['1'];
198 }
199
200 if ($this->validate)
201 {
202 $this->validate_email($this->_str_to_array($from));
203 }
204
205 // prepare the display name
206 if ($name != '')
207 {
208 // only use Q encoding if there are characters that would require it
209 if ( ! preg_match('/[\200-\377]/', $name))
210 {
211 // add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes
Derek Jonesc630bcf2008-11-17 21:09:45 +0000212 $name = '"'.addcslashes($name, "\0..\37\177'\"\\").'"';
Derek Allard2067d1a2008-11-13 22:59:24 +0000213 }
214 else
215 {
216 $name = $this->_prep_q_encoding($name, TRUE);
217 }
218 }
219
220 $this->_set_header('From', $name.' <'.$from.'>');
221 $this->_set_header('Return-Path', '<'.$from.'>');
Eric Barnes6113f542010-12-29 13:36:12 -0500222
Greg Akera769deb2010-11-10 15:47:29 -0600223 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000224 }
Barry Mienydd671972010-10-04 16:33:58 +0200225
Derek Allard2067d1a2008-11-13 22:59:24 +0000226 // --------------------------------------------------------------------
227
228 /**
229 * Set Reply-to
230 *
231 * @access public
232 * @param string
233 * @param string
234 * @return void
235 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000236 public function reply_to($replyto, $name = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000237 {
238 if (preg_match( '/\<(.*)\>/', $replyto, $match))
239 {
240 $replyto = $match['1'];
241 }
242
243 if ($this->validate)
244 {
245 $this->validate_email($this->_str_to_array($replyto));
246 }
247
248 if ($name == '')
249 {
250 $name = $replyto;
251 }
252
253 if (strncmp($name, '"', 1) != 0)
254 {
255 $name = '"'.$name.'"';
256 }
257
258 $this->_set_header('Reply-To', $name.' <'.$replyto.'>');
259 $this->_replyto_flag = TRUE;
Greg Akera769deb2010-11-10 15:47:29 -0600260
261 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000262 }
Barry Mienydd671972010-10-04 16:33:58 +0200263
Derek Allard2067d1a2008-11-13 22:59:24 +0000264 // --------------------------------------------------------------------
265
266 /**
267 * Set Recipients
268 *
269 * @access public
270 * @param string
271 * @return void
272 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000273 public function to($to)
Derek Allard2067d1a2008-11-13 22:59:24 +0000274 {
275 $to = $this->_str_to_array($to);
276 $to = $this->clean_email($to);
277
278 if ($this->validate)
279 {
280 $this->validate_email($to);
281 }
282
283 if ($this->_get_protocol() != 'mail')
284 {
285 $this->_set_header('To', implode(", ", $to));
286 }
287
288 switch ($this->_get_protocol())
289 {
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000290 case 'smtp' :
291 $this->_recipients = $to;
Derek Allard2067d1a2008-11-13 22:59:24 +0000292 break;
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000293 case 'sendmail' :
294 case 'mail' :
295 $this->_recipients = implode(", ", $to);
Derek Allard2067d1a2008-11-13 22:59:24 +0000296 break;
297 }
Eric Barnes6113f542010-12-29 13:36:12 -0500298
Greg Akera769deb2010-11-10 15:47:29 -0600299 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000300 }
Barry Mienydd671972010-10-04 16:33:58 +0200301
Derek Allard2067d1a2008-11-13 22:59:24 +0000302 // --------------------------------------------------------------------
303
304 /**
305 * Set CC
306 *
307 * @access public
308 * @param string
309 * @return void
310 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000311 public function cc($cc)
Derek Allard2067d1a2008-11-13 22:59:24 +0000312 {
313 $cc = $this->_str_to_array($cc);
314 $cc = $this->clean_email($cc);
315
316 if ($this->validate)
317 {
318 $this->validate_email($cc);
319 }
320
321 $this->_set_header('Cc', implode(", ", $cc));
322
323 if ($this->_get_protocol() == "smtp")
324 {
325 $this->_cc_array = $cc;
326 }
Eric Barnes6113f542010-12-29 13:36:12 -0500327
Greg Akera769deb2010-11-10 15:47:29 -0600328 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000329 }
Barry Mienydd671972010-10-04 16:33:58 +0200330
Derek Allard2067d1a2008-11-13 22:59:24 +0000331 // --------------------------------------------------------------------
332
333 /**
334 * Set BCC
335 *
336 * @access public
337 * @param string
338 * @param string
339 * @return void
340 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000341 public function bcc($bcc, $limit = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000342 {
343 if ($limit != '' && is_numeric($limit))
344 {
345 $this->bcc_batch_mode = TRUE;
346 $this->bcc_batch_size = $limit;
347 }
348
349 $bcc = $this->_str_to_array($bcc);
350 $bcc = $this->clean_email($bcc);
351
352 if ($this->validate)
353 {
354 $this->validate_email($bcc);
355 }
356
357 if (($this->_get_protocol() == "smtp") OR ($this->bcc_batch_mode && count($bcc) > $this->bcc_batch_size))
358 {
359 $this->_bcc_array = $bcc;
360 }
361 else
362 {
363 $this->_set_header('Bcc', implode(", ", $bcc));
364 }
Eric Barnes6113f542010-12-29 13:36:12 -0500365
Greg Akera769deb2010-11-10 15:47:29 -0600366 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000367 }
Barry Mienydd671972010-10-04 16:33:58 +0200368
Derek Allard2067d1a2008-11-13 22:59:24 +0000369 // --------------------------------------------------------------------
370
371 /**
372 * Set Email Subject
373 *
374 * @access public
375 * @param string
376 * @return void
377 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000378 public function subject($subject)
Derek Allard2067d1a2008-11-13 22:59:24 +0000379 {
380 $subject = $this->_prep_q_encoding($subject);
381 $this->_set_header('Subject', $subject);
Greg Akera769deb2010-11-10 15:47:29 -0600382 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000383 }
Barry Mienydd671972010-10-04 16:33:58 +0200384
Derek Allard2067d1a2008-11-13 22:59:24 +0000385 // --------------------------------------------------------------------
386
387 /**
388 * Set Body
389 *
390 * @access public
391 * @param string
392 * @return void
393 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000394 public function message($body)
Derek Allard2067d1a2008-11-13 22:59:24 +0000395 {
diegorivera33c32802011-10-19 02:56:15 -0200396 $this->_body = rtrim(str_replace("\r", "", $body));
397
Andrey Andreevaf728622011-10-20 10:11:59 +0300398 /* strip slashes only if magic quotes is ON
399 if we do it with magic quotes OFF, it strips real, user-inputted chars.
400
401 NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and
402 it will probably not exist in future versions at all.
403 */
404 if ( ! is_php('5.4') && get_magic_quotes_gpc())
diegorivera9fca6152011-10-19 11:18:45 -0200405 {
diegorivera33c32802011-10-19 02:56:15 -0200406 $this->_body = stripslashes($this->_body);
diegorivera9fca6152011-10-19 11:18:45 -0200407 }
diegorivera33c32802011-10-19 02:56:15 -0200408
Greg Akera769deb2010-11-10 15:47:29 -0600409 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000410 }
Barry Mienydd671972010-10-04 16:33:58 +0200411
Derek Allard2067d1a2008-11-13 22:59:24 +0000412 // --------------------------------------------------------------------
413
414 /**
415 * Assign file attachments
416 *
417 * @access public
418 * @param string
419 * @return void
420 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000421 public function attach($filename, $disposition = 'attachment')
Derek Allard2067d1a2008-11-13 22:59:24 +0000422 {
423 $this->_attach_name[] = $filename;
Phil Sturgeon0aaf42b2011-08-10 08:06:37 -0600424 $this->_attach_type[] = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION));
Derek Jones37f4b9c2011-07-01 17:56:50 -0500425 $this->_attach_disp[] = $disposition; // Can also be 'inline' Not sure if it matters
Greg Akera769deb2010-11-10 15:47:29 -0600426 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000427 }
428
429 // --------------------------------------------------------------------
430
431 /**
432 * Add a Header Item
433 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600434 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000435 * @param string
436 * @param string
437 * @return void
438 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600439 protected function _set_header($header, $value)
Derek Allard2067d1a2008-11-13 22:59:24 +0000440 {
441 $this->_headers[$header] = $value;
442 }
Barry Mienydd671972010-10-04 16:33:58 +0200443
Derek Allard2067d1a2008-11-13 22:59:24 +0000444 // --------------------------------------------------------------------
445
446 /**
447 * Convert a String to an Array
448 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600449 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000450 * @param string
451 * @return array
452 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600453 protected function _str_to_array($email)
Derek Allard2067d1a2008-11-13 22:59:24 +0000454 {
455 if ( ! is_array($email))
456 {
457 if (strpos($email, ',') !== FALSE)
458 {
459 $email = preg_split('/[\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY);
460 }
461 else
462 {
463 $email = trim($email);
464 settype($email, "array");
465 }
466 }
467 return $email;
468 }
Barry Mienydd671972010-10-04 16:33:58 +0200469
Derek Allard2067d1a2008-11-13 22:59:24 +0000470 // --------------------------------------------------------------------
471
472 /**
473 * Set Multipart Value
474 *
475 * @access public
476 * @param string
477 * @return void
478 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000479 public function set_alt_message($str = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000480 {
Dan Horrigand0ddeaf2011-08-21 09:07:27 -0400481 $this->alt_message = (string) $str;
Greg Akera769deb2010-11-10 15:47:29 -0600482 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000483 }
Barry Mienydd671972010-10-04 16:33:58 +0200484
Derek Allard2067d1a2008-11-13 22:59:24 +0000485 // --------------------------------------------------------------------
486
487 /**
488 * Set Mailtype
489 *
490 * @access public
491 * @param string
492 * @return void
493 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000494 public function set_mailtype($type = 'text')
Derek Allard2067d1a2008-11-13 22:59:24 +0000495 {
496 $this->mailtype = ($type == 'html') ? 'html' : 'text';
Greg Akera769deb2010-11-10 15:47:29 -0600497 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000498 }
Barry Mienydd671972010-10-04 16:33:58 +0200499
Derek Allard2067d1a2008-11-13 22:59:24 +0000500 // --------------------------------------------------------------------
501
502 /**
503 * Set Wordwrap
504 *
505 * @access public
Dan Horrigan628e6602011-08-21 09:08:31 -0400506 * @param bool
Derek Allard2067d1a2008-11-13 22:59:24 +0000507 * @return void
508 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000509 public function set_wordwrap($wordwrap = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000510 {
Dan Horrigan628e6602011-08-21 09:08:31 -0400511 $this->wordwrap = (bool) $wordwrap;
Greg Akera769deb2010-11-10 15:47:29 -0600512 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000513 }
Barry Mienydd671972010-10-04 16:33:58 +0200514
Derek Allard2067d1a2008-11-13 22:59:24 +0000515 // --------------------------------------------------------------------
516
517 /**
518 * Set Protocol
519 *
520 * @access public
521 * @param string
522 * @return void
523 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000524 public function set_protocol($protocol = 'mail')
Derek Allard2067d1a2008-11-13 22:59:24 +0000525 {
526 $this->protocol = ( ! in_array($protocol, $this->_protocols, TRUE)) ? 'mail' : strtolower($protocol);
Greg Akera769deb2010-11-10 15:47:29 -0600527 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000528 }
Barry Mienydd671972010-10-04 16:33:58 +0200529
Derek Allard2067d1a2008-11-13 22:59:24 +0000530 // --------------------------------------------------------------------
531
532 /**
533 * Set Priority
534 *
535 * @access public
536 * @param integer
537 * @return void
538 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000539 public function set_priority($n = 3)
Derek Allard2067d1a2008-11-13 22:59:24 +0000540 {
541 if ( ! is_numeric($n))
542 {
543 $this->priority = 3;
544 return;
545 }
546
547 if ($n < 1 OR $n > 5)
548 {
549 $this->priority = 3;
550 return;
551 }
552
553 $this->priority = $n;
Greg Akera769deb2010-11-10 15:47:29 -0600554 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000555 }
Barry Mienydd671972010-10-04 16:33:58 +0200556
Derek Allard2067d1a2008-11-13 22:59:24 +0000557 // --------------------------------------------------------------------
558
559 /**
560 * Set Newline Character
561 *
562 * @access public
563 * @param string
564 * @return void
565 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000566 public function set_newline($newline = "\n")
Derek Allard2067d1a2008-11-13 22:59:24 +0000567 {
568 if ($newline != "\n" AND $newline != "\r\n" AND $newline != "\r")
569 {
570 $this->newline = "\n";
571 return;
572 }
573
574 $this->newline = $newline;
Eric Barnes6113f542010-12-29 13:36:12 -0500575
Greg Akera769deb2010-11-10 15:47:29 -0600576 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000577 }
Barry Mienydd671972010-10-04 16:33:58 +0200578
Derek Allard2067d1a2008-11-13 22:59:24 +0000579 // --------------------------------------------------------------------
580
581 /**
582 * Set CRLF
583 *
584 * @access public
585 * @param string
586 * @return void
587 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000588 public function set_crlf($crlf = "\n")
Derek Allard2067d1a2008-11-13 22:59:24 +0000589 {
590 if ($crlf != "\n" AND $crlf != "\r\n" AND $crlf != "\r")
591 {
592 $this->crlf = "\n";
593 return;
594 }
595
596 $this->crlf = $crlf;
Eric Barnes6113f542010-12-29 13:36:12 -0500597
Greg Akera769deb2010-11-10 15:47:29 -0600598 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000599 }
Barry Mienydd671972010-10-04 16:33:58 +0200600
Derek Allard2067d1a2008-11-13 22:59:24 +0000601 // --------------------------------------------------------------------
602
603 /**
604 * Set Message Boundary
605 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600606 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000607 * @return void
608 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600609 protected function _set_boundaries()
Derek Allard2067d1a2008-11-13 22:59:24 +0000610 {
611 $this->_alt_boundary = "B_ALT_".uniqid(''); // multipart/alternative
612 $this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary
613 }
Barry Mienydd671972010-10-04 16:33:58 +0200614
Derek Allard2067d1a2008-11-13 22:59:24 +0000615 // --------------------------------------------------------------------
616
617 /**
618 * Get the Message ID
619 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600620 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000621 * @return string
622 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600623 protected function _get_message_id()
Derek Allard2067d1a2008-11-13 22:59:24 +0000624 {
625 $from = $this->_headers['Return-Path'];
626 $from = str_replace(">", "", $from);
627 $from = str_replace("<", "", $from);
628
Derek Jones37f4b9c2011-07-01 17:56:50 -0500629 return "<".uniqid('').strstr($from, '@').">";
Derek Allard2067d1a2008-11-13 22:59:24 +0000630 }
Barry Mienydd671972010-10-04 16:33:58 +0200631
Derek Allard2067d1a2008-11-13 22:59:24 +0000632 // --------------------------------------------------------------------
633
634 /**
635 * Get Mail Protocol
636 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600637 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000638 * @param bool
639 * @return string
640 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600641 protected function _get_protocol($return = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000642 {
643 $this->protocol = strtolower($this->protocol);
644 $this->protocol = ( ! in_array($this->protocol, $this->_protocols, TRUE)) ? 'mail' : $this->protocol;
645
646 if ($return == TRUE)
647 {
648 return $this->protocol;
649 }
650 }
Barry Mienydd671972010-10-04 16:33:58 +0200651
Derek Allard2067d1a2008-11-13 22:59:24 +0000652 // --------------------------------------------------------------------
653
654 /**
655 * Get Mail Encoding
656 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600657 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000658 * @param bool
659 * @return string
660 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600661 protected function _get_encoding($return = TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000662 {
663 $this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '8bit' : $this->_encoding;
664
665 foreach ($this->_base_charsets as $charset)
666 {
667 if (strncmp($charset, $this->charset, strlen($charset)) == 0)
668 {
669 $this->_encoding = '7bit';
670 }
671 }
672
673 if ($return == TRUE)
674 {
675 return $this->_encoding;
676 }
677 }
678
679 // --------------------------------------------------------------------
680
681 /**
682 * Get content type (text/html/attachment)
683 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600684 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000685 * @return string
686 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600687 protected function _get_content_type()
Derek Allard2067d1a2008-11-13 22:59:24 +0000688 {
Derek Jones37f4b9c2011-07-01 17:56:50 -0500689 if ($this->mailtype == 'html' && count($this->_attach_name) == 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000690 {
691 return 'html';
692 }
Derek Jones37f4b9c2011-07-01 17:56:50 -0500693 elseif ($this->mailtype == 'html' && count($this->_attach_name) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000694 {
695 return 'html-attach';
696 }
Derek Jones37f4b9c2011-07-01 17:56:50 -0500697 elseif ($this->mailtype == 'text' && count($this->_attach_name) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000698 {
699 return 'plain-attach';
700 }
701 else
702 {
703 return 'plain';
704 }
705 }
Barry Mienydd671972010-10-04 16:33:58 +0200706
Derek Allard2067d1a2008-11-13 22:59:24 +0000707 // --------------------------------------------------------------------
708
709 /**
710 * Set RFC 822 Date
711 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600712 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000713 * @return string
714 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600715 protected function _set_date()
Derek Allard2067d1a2008-11-13 22:59:24 +0000716 {
717 $timezone = date("Z");
718 $operator = (strncmp($timezone, '-', 1) == 0) ? '-' : '+';
719 $timezone = abs($timezone);
720 $timezone = floor($timezone/3600) * 100 + ($timezone % 3600 ) / 60;
721
722 return sprintf("%s %s%04d", date("D, j M Y H:i:s"), $operator, $timezone);
723 }
Barry Mienydd671972010-10-04 16:33:58 +0200724
Derek Allard2067d1a2008-11-13 22:59:24 +0000725 // --------------------------------------------------------------------
726
727 /**
728 * Mime message
729 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600730 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000731 * @return string
732 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600733 protected function _get_mime_message()
Derek Allard2067d1a2008-11-13 22:59:24 +0000734 {
735 return "This is a multi-part message in MIME format.".$this->newline."Your email application may not support this format.";
736 }
Barry Mienydd671972010-10-04 16:33:58 +0200737
Derek Allard2067d1a2008-11-13 22:59:24 +0000738 // --------------------------------------------------------------------
739
740 /**
741 * Validate Email Address
742 *
743 * @access public
744 * @param string
745 * @return bool
746 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000747 public function validate_email($email)
Derek Allard2067d1a2008-11-13 22:59:24 +0000748 {
749 if ( ! is_array($email))
750 {
patworkb0707982011-04-08 15:10:05 +0200751 $this->_set_error_message('lang:email_must_be_array');
Derek Allard2067d1a2008-11-13 22:59:24 +0000752 return FALSE;
753 }
754
755 foreach ($email as $val)
756 {
757 if ( ! $this->valid_email($val))
758 {
patworkb0707982011-04-08 15:10:05 +0200759 $this->_set_error_message('lang:email_invalid_address', $val);
Derek Allard2067d1a2008-11-13 22:59:24 +0000760 return FALSE;
761 }
762 }
763
764 return TRUE;
765 }
Barry Mienydd671972010-10-04 16:33:58 +0200766
Derek Allard2067d1a2008-11-13 22:59:24 +0000767 // --------------------------------------------------------------------
768
769 /**
770 * Email Validation
771 *
772 * @access public
773 * @param string
774 * @return bool
775 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000776 public function valid_email($address)
Derek Allard2067d1a2008-11-13 22:59:24 +0000777 {
778 return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $address)) ? FALSE : TRUE;
779 }
Barry Mienydd671972010-10-04 16:33:58 +0200780
Derek Allard2067d1a2008-11-13 22:59:24 +0000781 // --------------------------------------------------------------------
782
783 /**
784 * Clean Extended Email Address: Joe Smith <joe@smith.com>
785 *
786 * @access public
787 * @param string
788 * @return string
789 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000790 public function clean_email($email)
Derek Allard2067d1a2008-11-13 22:59:24 +0000791 {
792 if ( ! is_array($email))
793 {
794 if (preg_match('/\<(.*)\>/', $email, $match))
795 {
Barry Mienydd671972010-10-04 16:33:58 +0200796 return $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 return $email;
Derek Allard2067d1a2008-11-13 22:59:24 +0000801 }
802 }
803
804 $clean_email = array();
805
806 foreach ($email as $addy)
807 {
808 if (preg_match( '/\<(.*)\>/', $addy, $match))
809 {
Barry Mienydd671972010-10-04 16:33:58 +0200810 $clean_email[] = $match['1'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000811 }
Barry Mienydd671972010-10-04 16:33:58 +0200812 else
Derek Allard2067d1a2008-11-13 22:59:24 +0000813 {
Barry Mienydd671972010-10-04 16:33:58 +0200814 $clean_email[] = $addy;
Derek Allard2067d1a2008-11-13 22:59:24 +0000815 }
816 }
817
818 return $clean_email;
819 }
Barry Mienydd671972010-10-04 16:33:58 +0200820
Derek Allard2067d1a2008-11-13 22:59:24 +0000821 // --------------------------------------------------------------------
822
823 /**
824 * Build alternative plain text message
825 *
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000826 * This public function provides the raw message for use
Derek Allard2067d1a2008-11-13 22:59:24 +0000827 * in plain-text headers of HTML-formatted emails.
828 * If the user hasn't specified his own alternative message
829 * it creates one by stripping the HTML
830 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600831 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000832 * @return string
833 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600834 protected function _get_alt_message()
Derek Allard2067d1a2008-11-13 22:59:24 +0000835 {
836 if ($this->alt_message != "")
837 {
838 return $this->word_wrap($this->alt_message, '76');
839 }
840
841 if (preg_match('/\<body.*?\>(.*)\<\/body\>/si', $this->_body, $match))
842 {
843 $body = $match['1'];
844 }
845 else
846 {
847 $body = $this->_body;
848 }
849
850 $body = trim(strip_tags($body));
851 $body = preg_replace( '#<!--(.*)--\>#', "", $body);
852 $body = str_replace("\t", "", $body);
853
854 for ($i = 20; $i >= 3; $i--)
855 {
856 $n = "";
857
858 for ($x = 1; $x <= $i; $x ++)
859 {
Barry Mienydd671972010-10-04 16:33:58 +0200860 $n .= "\n";
Derek Allard2067d1a2008-11-13 22:59:24 +0000861 }
862
863 $body = str_replace($n, "\n\n", $body);
864 }
865
866 return $this->word_wrap($body, '76');
867 }
Barry Mienydd671972010-10-04 16:33:58 +0200868
Derek Allard2067d1a2008-11-13 22:59:24 +0000869 // --------------------------------------------------------------------
870
871 /**
872 * Word Wrap
873 *
874 * @access public
875 * @param string
876 * @param integer
877 * @return string
878 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000879 public function word_wrap($str, $charlim = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000880 {
881 // Se the character limit
882 if ($charlim == '')
883 {
884 $charlim = ($this->wrapchars == "") ? "76" : $this->wrapchars;
885 }
886
887 // Reduce multiple spaces
888 $str = preg_replace("| +|", " ", $str);
889
890 // Standardize newlines
891 if (strpos($str, "\r") !== FALSE)
892 {
893 $str = str_replace(array("\r\n", "\r"), "\n", $str);
894 }
895
896 // If the current word is surrounded by {unwrap} tags we'll
897 // strip the entire chunk and replace it with a marker.
898 $unwrap = array();
899 if (preg_match_all("|(\{unwrap\}.+?\{/unwrap\})|s", $str, $matches))
900 {
901 for ($i = 0; $i < count($matches['0']); $i++)
902 {
903 $unwrap[] = $matches['1'][$i];
904 $str = str_replace($matches['1'][$i], "{{unwrapped".$i."}}", $str);
905 }
906 }
907
Phil Sturgeona0f980e2011-01-13 10:59:12 +0000908 // Use PHP's native public function to do the initial wordwrap.
Derek Allard2067d1a2008-11-13 22:59:24 +0000909 // We set the cut flag to FALSE so that any individual words that are
Derek Jones37f4b9c2011-07-01 17:56:50 -0500910 // too long get left alone. In the next step we'll deal with them.
Derek Allard2067d1a2008-11-13 22:59:24 +0000911 $str = wordwrap($str, $charlim, "\n", FALSE);
912
913 // Split the string into individual lines of text and cycle through them
914 $output = "";
915 foreach (explode("\n", $str) as $line)
916 {
917 // Is the line within the allowed character count?
918 // If so we'll join it to the output and continue
919 if (strlen($line) <= $charlim)
920 {
921 $output .= $line.$this->newline;
922 continue;
923 }
924
925 $temp = '';
Pascal Kriete14287f32011-02-14 13:39:34 -0500926 while ((strlen($line)) > $charlim)
Derek Allard2067d1a2008-11-13 22:59:24 +0000927 {
928 // If the over-length word is a URL we won't wrap it
929 if (preg_match("!\[url.+\]|://|wwww.!", $line))
930 {
931 break;
932 }
933
934 // Trim the word down
935 $temp .= substr($line, 0, $charlim-1);
936 $line = substr($line, $charlim-1);
937 }
938
939 // If $temp contains data it means we had to split up an over-length
940 // word into smaller chunks so we'll add it back to our current line
941 if ($temp != '')
942 {
943 $output .= $temp.$this->newline.$line;
944 }
945 else
946 {
947 $output .= $line;
948 }
949
950 $output .= $this->newline;
951 }
952
953 // Put our markers back
954 if (count($unwrap) > 0)
955 {
956 foreach ($unwrap as $key => $val)
957 {
958 $output = str_replace("{{unwrapped".$key."}}", $val, $output);
959 }
960 }
961
962 return $output;
963 }
Barry Mienydd671972010-10-04 16:33:58 +0200964
Derek Allard2067d1a2008-11-13 22:59:24 +0000965 // --------------------------------------------------------------------
966
967 /**
968 * Build final headers
969 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600970 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000971 * @param string
972 * @return string
973 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600974 protected function _build_headers()
Derek Allard2067d1a2008-11-13 22:59:24 +0000975 {
976 $this->_set_header('X-Sender', $this->clean_email($this->_headers['From']));
977 $this->_set_header('X-Mailer', $this->useragent);
978 $this->_set_header('X-Priority', $this->_priorities[$this->priority - 1]);
979 $this->_set_header('Message-ID', $this->_get_message_id());
980 $this->_set_header('Mime-Version', '1.0');
981 }
Barry Mienydd671972010-10-04 16:33:58 +0200982
Derek Allard2067d1a2008-11-13 22:59:24 +0000983 // --------------------------------------------------------------------
984
985 /**
986 * Write Headers as a string
987 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600988 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +0000989 * @return void
990 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -0600991 protected function _write_headers()
Derek Allard2067d1a2008-11-13 22:59:24 +0000992 {
993 if ($this->protocol == 'mail')
994 {
995 $this->_subject = $this->_headers['Subject'];
996 unset($this->_headers['Subject']);
997 }
998
999 reset($this->_headers);
1000 $this->_header_str = "";
1001
Pascal Kriete14287f32011-02-14 13:39:34 -05001002 foreach ($this->_headers as $key => $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001003 {
1004 $val = trim($val);
1005
1006 if ($val != "")
1007 {
1008 $this->_header_str .= $key.": ".$val.$this->newline;
1009 }
1010 }
1011
1012 if ($this->_get_protocol() == 'mail')
1013 {
Derek Jones1d890882009-02-10 20:32:14 +00001014 $this->_header_str = rtrim($this->_header_str);
Derek Allard2067d1a2008-11-13 22:59:24 +00001015 }
1016 }
Barry Mienydd671972010-10-04 16:33:58 +02001017
Derek Allard2067d1a2008-11-13 22:59:24 +00001018 // --------------------------------------------------------------------
1019
1020 /**
1021 * Build Final Body and attachments
1022 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001023 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001024 * @return void
1025 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001026 protected function _build_message()
Derek Allard2067d1a2008-11-13 22:59:24 +00001027 {
Derek Jones37f4b9c2011-07-01 17:56:50 -05001028 if ($this->wordwrap === TRUE AND $this->mailtype != 'html')
Derek Allard2067d1a2008-11-13 22:59:24 +00001029 {
1030 $this->_body = $this->word_wrap($this->_body);
1031 }
1032
1033 $this->_set_boundaries();
1034 $this->_write_headers();
1035
1036 $hdr = ($this->_get_protocol() == 'mail') ? $this->newline : '';
Brandon Jones485d7412010-11-09 16:38:17 -05001037 $body = '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001038
1039 switch ($this->_get_content_type())
1040 {
1041 case 'plain' :
1042
1043 $hdr .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1044 $hdr .= "Content-Transfer-Encoding: " . $this->_get_encoding();
1045
1046 if ($this->_get_protocol() == 'mail')
1047 {
1048 $this->_header_str .= $hdr;
1049 $this->_finalbody = $this->_body;
Derek Allard2067d1a2008-11-13 22:59:24 +00001050 }
Brandon Jones485d7412010-11-09 16:38:17 -05001051 else
1052 {
1053 $this->_finalbody = $hdr . $this->newline . $this->newline . $this->_body;
1054 }
Eric Barnes6113f542010-12-29 13:36:12 -05001055
Derek Allard2067d1a2008-11-13 22:59:24 +00001056 return;
1057
1058 break;
1059 case 'html' :
1060
1061 if ($this->send_multipart === FALSE)
1062 {
1063 $hdr .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
1064 $hdr .= "Content-Transfer-Encoding: quoted-printable";
1065 }
1066 else
1067 {
Derek Jonesa45e7612009-02-10 18:33:01 +00001068 $hdr .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001069
Brandon Jones485d7412010-11-09 16:38:17 -05001070 $body .= $this->_get_mime_message() . $this->newline . $this->newline;
1071 $body .= "--" . $this->_alt_boundary . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001072
Brandon Jones485d7412010-11-09 16:38:17 -05001073 $body .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1074 $body .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
1075 $body .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
1076
1077 $body .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
1078 $body .= "Content-Transfer-Encoding: quoted-printable" . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001079 }
Eric Barnes6113f542010-12-29 13:36:12 -05001080
Brandon Jones485d7412010-11-09 16:38:17 -05001081 $this->_finalbody = $body . $this->_prep_quoted_printable($this->_body) . $this->newline . $this->newline;
Eric Barnes6113f542010-12-29 13:36:12 -05001082
1083
Derek Allard2067d1a2008-11-13 22:59:24 +00001084 if ($this->_get_protocol() == 'mail')
1085 {
1086 $this->_header_str .= $hdr;
Brandon Jones485d7412010-11-09 16:38:17 -05001087 }
1088 else
1089 {
1090 $this->_finalbody = $hdr . $this->_finalbody;
Derek Allard2067d1a2008-11-13 22:59:24 +00001091 }
1092
Derek Allard2067d1a2008-11-13 22:59:24 +00001093
1094 if ($this->send_multipart !== FALSE)
1095 {
Brandon Jones485d7412010-11-09 16:38:17 -05001096 $this->_finalbody .= "--" . $this->_alt_boundary . "--";
Derek Allard2067d1a2008-11-13 22:59:24 +00001097 }
1098
Derek Allard2067d1a2008-11-13 22:59:24 +00001099 return;
1100
1101 break;
1102 case 'plain-attach' :
1103
Derek Jonesa45e7612009-02-10 18:33:01 +00001104 $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001105
1106 if ($this->_get_protocol() == 'mail')
1107 {
1108 $this->_header_str .= $hdr;
Eric Barnes6113f542010-12-29 13:36:12 -05001109 }
1110
Brandon Jones485d7412010-11-09 16:38:17 -05001111 $body .= $this->_get_mime_message() . $this->newline . $this->newline;
1112 $body .= "--" . $this->_atc_boundary . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001113
Brandon Jones485d7412010-11-09 16:38:17 -05001114 $body .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1115 $body .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001116
Brandon Jones485d7412010-11-09 16:38:17 -05001117 $body .= $this->_body . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001118
1119 break;
1120 case 'html-attach' :
1121
Derek Jonesa45e7612009-02-10 18:33:01 +00001122 $hdr .= "Content-Type: multipart/".$this->multipart."; boundary=\"" . $this->_atc_boundary."\"" . $this->newline . $this->newline;
Eric Barnes6113f542010-12-29 13:36:12 -05001123
Derek Allard2067d1a2008-11-13 22:59:24 +00001124 if ($this->_get_protocol() == 'mail')
1125 {
1126 $this->_header_str .= $hdr;
Derek Allard2067d1a2008-11-13 22:59:24 +00001127 }
1128
Brandon Jones485d7412010-11-09 16:38:17 -05001129 $body .= $this->_get_mime_message() . $this->newline . $this->newline;
1130 $body .= "--" . $this->_atc_boundary . $this->newline;
1131
1132 $body .= "Content-Type: multipart/alternative; boundary=\"" . $this->_alt_boundary . "\"" . $this->newline .$this->newline;
1133 $body .= "--" . $this->_alt_boundary . $this->newline;
1134
1135 $body .= "Content-Type: text/plain; charset=" . $this->charset . $this->newline;
1136 $body .= "Content-Transfer-Encoding: " . $this->_get_encoding() . $this->newline . $this->newline;
1137 $body .= $this->_get_alt_message() . $this->newline . $this->newline . "--" . $this->_alt_boundary . $this->newline;
1138
1139 $body .= "Content-Type: text/html; charset=" . $this->charset . $this->newline;
1140 $body .= "Content-Transfer-Encoding: quoted-printable" . $this->newline . $this->newline;
1141
1142 $body .= $this->_prep_quoted_printable($this->_body) . $this->newline . $this->newline;
1143 $body .= "--" . $this->_alt_boundary . "--" . $this->newline . $this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001144
1145 break;
1146 }
1147
1148 $attachment = array();
1149
1150 $z = 0;
1151
1152 for ($i=0; $i < count($this->_attach_name); $i++)
1153 {
1154 $filename = $this->_attach_name[$i];
1155 $basename = basename($filename);
1156 $ctype = $this->_attach_type[$i];
1157
1158 if ( ! file_exists($filename))
1159 {
patworkb0707982011-04-08 15:10:05 +02001160 $this->_set_error_message('lang:email_attachment_missing', $filename);
Derek Allard2067d1a2008-11-13 22:59:24 +00001161 return FALSE;
1162 }
1163
Derek Jones37f4b9c2011-07-01 17:56:50 -05001164 $h = "--".$this->_atc_boundary.$this->newline;
Derek Allard2067d1a2008-11-13 22:59:24 +00001165 $h .= "Content-type: ".$ctype."; ";
1166 $h .= "name=\"".$basename."\"".$this->newline;
1167 $h .= "Content-Disposition: ".$this->_attach_disp[$i].";".$this->newline;
1168 $h .= "Content-Transfer-Encoding: base64".$this->newline;
1169
1170 $attachment[$z++] = $h;
1171 $file = filesize($filename) +1;
1172
1173 if ( ! $fp = fopen($filename, FOPEN_READ))
1174 {
patworkb0707982011-04-08 15:10:05 +02001175 $this->_set_error_message('lang:email_attachment_unreadable', $filename);
Derek Allard2067d1a2008-11-13 22:59:24 +00001176 return FALSE;
1177 }
1178
1179 $attachment[$z++] = chunk_split(base64_encode(fread($fp, $file)));
1180 fclose($fp);
1181 }
1182
Brandon Jones485d7412010-11-09 16:38:17 -05001183 $body .= implode($this->newline, $attachment).$this->newline."--".$this->_atc_boundary."--";
Eric Barnes6113f542010-12-29 13:36:12 -05001184
Brandon Jones485d7412010-11-09 16:38:17 -05001185
Derek Allard2067d1a2008-11-13 22:59:24 +00001186 if ($this->_get_protocol() == 'mail')
1187 {
Brandon Jones485d7412010-11-09 16:38:17 -05001188 $this->_finalbody = $body;
Derek Allard2067d1a2008-11-13 22:59:24 +00001189 }
Brandon Jones485d7412010-11-09 16:38:17 -05001190 else
1191 {
1192 $this->_finalbody = $hdr . $body;
1193 }
Eric Barnes6113f542010-12-29 13:36:12 -05001194
Derek Allard2067d1a2008-11-13 22:59:24 +00001195 return;
1196 }
Barry Mienydd671972010-10-04 16:33:58 +02001197
Derek Allard2067d1a2008-11-13 22:59:24 +00001198 // --------------------------------------------------------------------
1199
1200 /**
1201 * Prep Quoted Printable
1202 *
1203 * Prepares string for Quoted-Printable Content-Transfer-Encoding
1204 * Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt
1205 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001206 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001207 * @param string
1208 * @param integer
1209 * @return string
1210 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001211 protected function _prep_quoted_printable($str, $charlim = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001212 {
1213 // Set the character limit
1214 // Don't allow over 76, as that will make servers and MUAs barf
1215 // all over quoted-printable data
1216 if ($charlim == '' OR $charlim > '76')
1217 {
1218 $charlim = '76';
1219 }
1220
1221 // Reduce multiple spaces
1222 $str = preg_replace("| +|", " ", $str);
1223
1224 // kill nulls
1225 $str = preg_replace('/\x00+/', '', $str);
1226
1227 // Standardize newlines
1228 if (strpos($str, "\r") !== FALSE)
1229 {
1230 $str = str_replace(array("\r\n", "\r"), "\n", $str);
1231 }
1232
1233 // We are intentionally wrapping so mail servers will encode characters
1234 // properly and MUAs will behave, so {unwrap} must go!
1235 $str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str);
1236
1237 // Break into an array of lines
1238 $lines = explode("\n", $str);
1239
1240 $escape = '=';
1241 $output = '';
1242
1243 foreach ($lines as $line)
1244 {
1245 $length = strlen($line);
1246 $temp = '';
1247
1248 // Loop through each character in the line to add soft-wrap
1249 // characters at the end of a line " =\r\n" and add the newly
1250 // processed line(s) to the output (see comment on $crlf class property)
1251 for ($i = 0; $i < $length; $i++)
1252 {
1253 // Grab the next character
1254 $char = substr($line, $i, 1);
1255 $ascii = ord($char);
1256
1257 // Convert spaces and tabs but only if it's the end of the line
1258 if ($i == ($length - 1))
1259 {
1260 $char = ($ascii == '32' OR $ascii == '9') ? $escape.sprintf('%02s', dechex($ascii)) : $char;
1261 }
1262
1263 // encode = signs
1264 if ($ascii == '61')
1265 {
Derek Jones37f4b9c2011-07-01 17:56:50 -05001266 $char = $escape.strtoupper(sprintf('%02s', dechex($ascii))); // =3D
Derek Allard2067d1a2008-11-13 22:59:24 +00001267 }
1268
1269 // If we're at the character limit, add the line to the output,
1270 // reset our temp variable, and keep on chuggin'
1271 if ((strlen($temp) + strlen($char)) >= $charlim)
1272 {
1273 $output .= $temp.$escape.$this->crlf;
1274 $temp = '';
1275 }
1276
1277 // Add the character to our temporary line
1278 $temp .= $char;
1279 }
1280
1281 // Add our completed line to the output
1282 $output .= $temp.$this->crlf;
1283 }
1284
1285 // get rid of extra CRLF tacked onto the end
1286 $output = substr($output, 0, strlen($this->crlf) * -1);
1287
1288 return $output;
1289 }
1290
1291 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001292
Derek Allard2067d1a2008-11-13 22:59:24 +00001293 /**
1294 * Prep Q Encoding
1295 *
Derek Jones37f4b9c2011-07-01 17:56:50 -05001296 * Performs "Q Encoding" on a string for use in email headers. It's related
Derek Allard2067d1a2008-11-13 22:59:24 +00001297 * but not identical to quoted-printable, so it has its own method
1298 *
1299 * @access public
1300 * @param str
1301 * @param bool // set to TRUE for processing From: headers
1302 * @return str
1303 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001304 protected function _prep_q_encoding($str, $from = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001305 {
1306 $str = str_replace(array("\r", "\n"), array('', ''), $str);
1307
1308 // Line length must not exceed 76 characters, so we adjust for
1309 // a space, 7 extra characters =??Q??=, and the charset that we will add to each line
1310 $limit = 75 - 7 - strlen($this->charset);
1311
1312 // these special characters must be converted too
1313 $convert = array('_', '=', '?');
1314
1315 if ($from === TRUE)
1316 {
1317 $convert[] = ',';
1318 $convert[] = ';';
1319 }
1320
1321 $output = '';
1322 $temp = '';
1323
1324 for ($i = 0, $length = strlen($str); $i < $length; $i++)
1325 {
1326 // Grab the next character
1327 $char = substr($str, $i, 1);
1328 $ascii = ord($char);
1329
1330 // convert ALL non-printable ASCII characters and our specials
1331 if ($ascii < 32 OR $ascii > 126 OR in_array($char, $convert))
1332 {
1333 $char = '='.dechex($ascii);
1334 }
1335
1336 // handle regular spaces a bit more compactly than =20
1337 if ($ascii == 32)
1338 {
1339 $char = '_';
1340 }
1341
1342 // If we're at the character limit, add the line to the output,
1343 // reset our temp variable, and keep on chuggin'
1344 if ((strlen($temp) + strlen($char)) >= $limit)
1345 {
1346 $output .= $temp.$this->crlf;
1347 $temp = '';
1348 }
1349
1350 // Add the character to our temporary line
1351 $temp .= $char;
1352 }
1353
1354 $str = $output.$temp;
1355
1356 // wrap each line with the shebang, charset, and transfer encoding
1357 // the preceding space on successive lines is required for header "folding"
1358 $str = trim(preg_replace('/^(.*)$/m', ' =?'.$this->charset.'?Q?$1?=', $str));
1359
1360 return $str;
1361 }
1362
1363 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001364
Derek Allard2067d1a2008-11-13 22:59:24 +00001365 /**
1366 * Send Email
1367 *
1368 * @access public
1369 * @return bool
1370 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +00001371 public function send()
Derek Allard2067d1a2008-11-13 22:59:24 +00001372 {
1373 if ($this->_replyto_flag == FALSE)
1374 {
1375 $this->reply_to($this->_headers['From']);
1376 }
1377
Derek Jones37f4b9c2011-07-01 17:56:50 -05001378 if (( ! isset($this->_recipients) AND ! isset($this->_headers['To'])) AND
Derek Allard2067d1a2008-11-13 22:59:24 +00001379 ( ! isset($this->_bcc_array) AND ! isset($this->_headers['Bcc'])) AND
1380 ( ! isset($this->_headers['Cc'])))
1381 {
patworkb0707982011-04-08 15:10:05 +02001382 $this->_set_error_message('lang:email_no_recipients');
Derek Allard2067d1a2008-11-13 22:59:24 +00001383 return FALSE;
1384 }
1385
1386 $this->_build_headers();
1387
Derek Jones37f4b9c2011-07-01 17:56:50 -05001388 if ($this->bcc_batch_mode AND count($this->_bcc_array) > 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001389 {
1390 if (count($this->_bcc_array) > $this->bcc_batch_size)
1391 return $this->batch_bcc_send();
1392 }
1393
1394 $this->_build_message();
1395
1396 if ( ! $this->_spool_email())
1397 {
1398 return FALSE;
1399 }
1400 else
1401 {
1402 return TRUE;
1403 }
1404 }
Barry Mienydd671972010-10-04 16:33:58 +02001405
Derek Allard2067d1a2008-11-13 22:59:24 +00001406 // --------------------------------------------------------------------
1407
1408 /**
Derek Jones37f4b9c2011-07-01 17:56:50 -05001409 * Batch Bcc Send. Sends groups of BCCs in batches
Derek Allard2067d1a2008-11-13 22:59:24 +00001410 *
1411 * @access public
1412 * @return bool
1413 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +00001414 public function batch_bcc_send()
Derek Allard2067d1a2008-11-13 22:59:24 +00001415 {
1416 $float = $this->bcc_batch_size -1;
1417
1418 $set = "";
1419
1420 $chunk = array();
1421
1422 for ($i = 0; $i < count($this->_bcc_array); $i++)
1423 {
1424 if (isset($this->_bcc_array[$i]))
1425 {
1426 $set .= ", ".$this->_bcc_array[$i];
1427 }
1428
1429 if ($i == $float)
1430 {
1431 $chunk[] = substr($set, 1);
1432 $float = $float + $this->bcc_batch_size;
1433 $set = "";
1434 }
1435
1436 if ($i == count($this->_bcc_array)-1)
1437 {
1438 $chunk[] = substr($set, 1);
1439 }
1440 }
1441
1442 for ($i = 0; $i < count($chunk); $i++)
1443 {
1444 unset($this->_headers['Bcc']);
1445 unset($bcc);
1446
1447 $bcc = $this->_str_to_array($chunk[$i]);
1448 $bcc = $this->clean_email($bcc);
1449
1450 if ($this->protocol != 'smtp')
1451 {
1452 $this->_set_header('Bcc', implode(", ", $bcc));
1453 }
1454 else
1455 {
1456 $this->_bcc_array = $bcc;
1457 }
1458
1459 $this->_build_message();
1460 $this->_spool_email();
1461 }
1462 }
Barry Mienydd671972010-10-04 16:33:58 +02001463
Derek Allard2067d1a2008-11-13 22:59:24 +00001464 // --------------------------------------------------------------------
1465
1466 /**
1467 * Unwrap special elements
1468 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001469 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001470 * @return void
1471 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001472 protected function _unwrap_specials()
Derek Allard2067d1a2008-11-13 22:59:24 +00001473 {
1474 $this->_finalbody = preg_replace_callback("/\{unwrap\}(.*?)\{\/unwrap\}/si", array($this, '_remove_nl_callback'), $this->_finalbody);
1475 }
Barry Mienydd671972010-10-04 16:33:58 +02001476
Derek Allard2067d1a2008-11-13 22:59:24 +00001477 // --------------------------------------------------------------------
1478
1479 /**
1480 * Strip line-breaks via callback
1481 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001482 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001483 * @return string
1484 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001485 protected function _remove_nl_callback($matches)
Derek Allard2067d1a2008-11-13 22:59:24 +00001486 {
1487 if (strpos($matches[1], "\r") !== FALSE OR strpos($matches[1], "\n") !== FALSE)
1488 {
1489 $matches[1] = str_replace(array("\r\n", "\r", "\n"), '', $matches[1]);
1490 }
1491
1492 return $matches[1];
1493 }
Barry Mienydd671972010-10-04 16:33:58 +02001494
Derek Allard2067d1a2008-11-13 22:59:24 +00001495 // --------------------------------------------------------------------
1496
1497 /**
1498 * Spool mail to the mail server
1499 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001500 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001501 * @return bool
1502 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001503 protected function _spool_email()
Derek Allard2067d1a2008-11-13 22:59:24 +00001504 {
1505 $this->_unwrap_specials();
1506
1507 switch ($this->_get_protocol())
1508 {
1509 case 'mail' :
1510
1511 if ( ! $this->_send_with_mail())
1512 {
patworkb0707982011-04-08 15:10:05 +02001513 $this->_set_error_message('lang:email_send_failure_phpmail');
Derek Allard2067d1a2008-11-13 22:59:24 +00001514 return FALSE;
1515 }
1516 break;
1517 case 'sendmail' :
1518
1519 if ( ! $this->_send_with_sendmail())
1520 {
patworkb0707982011-04-08 15:10:05 +02001521 $this->_set_error_message('lang:email_send_failure_sendmail');
Derek Allard2067d1a2008-11-13 22:59:24 +00001522 return FALSE;
1523 }
1524 break;
1525 case 'smtp' :
1526
1527 if ( ! $this->_send_with_smtp())
1528 {
patworkb0707982011-04-08 15:10:05 +02001529 $this->_set_error_message('lang:email_send_failure_smtp');
Derek Allard2067d1a2008-11-13 22:59:24 +00001530 return FALSE;
1531 }
1532 break;
1533
1534 }
1535
patworkb0707982011-04-08 15:10:05 +02001536 $this->_set_error_message('lang:email_sent', $this->_get_protocol());
Derek Allard2067d1a2008-11-13 22:59:24 +00001537 return TRUE;
1538 }
Barry Mienydd671972010-10-04 16:33:58 +02001539
Derek Allard2067d1a2008-11-13 22:59:24 +00001540 // --------------------------------------------------------------------
1541
1542 /**
1543 * Send using mail()
1544 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001545 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001546 * @return bool
1547 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001548 protected function _send_with_mail()
Derek Allard2067d1a2008-11-13 22:59:24 +00001549 {
1550 if ($this->_safe_mode == TRUE)
1551 {
1552 if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str))
1553 {
1554 return FALSE;
1555 }
1556 else
1557 {
1558 return TRUE;
1559 }
1560 }
1561 else
1562 {
1563 // most documentation of sendmail using the "-f" flag lacks a space after it, however
1564 // we've encountered servers that seem to require it to be in place.
Eric Barnes6113f542010-12-29 13:36:12 -05001565
Derek Allard2067d1a2008-11-13 22:59:24 +00001566 if ( ! mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, "-f ".$this->clean_email($this->_headers['From'])))
1567 {
1568 return FALSE;
1569 }
1570 else
1571 {
1572 return TRUE;
1573 }
1574 }
1575 }
Barry Mienydd671972010-10-04 16:33:58 +02001576
Derek Allard2067d1a2008-11-13 22:59:24 +00001577 // --------------------------------------------------------------------
1578
1579 /**
1580 * Send using Sendmail
1581 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001582 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001583 * @return bool
1584 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001585 protected function _send_with_sendmail()
Derek Allard2067d1a2008-11-13 22:59:24 +00001586 {
1587 $fp = @popen($this->mailpath . " -oi -f ".$this->clean_email($this->_headers['From'])." -t", 'w');
1588
Derek Jones4cefaa42009-04-29 19:13:56 +00001589 if ($fp === FALSE OR $fp === NULL)
1590 {
1591 // server probably has popen disabled, so nothing we can do to get a verbose error.
1592 return FALSE;
1593 }
Derek Jones71141ce2010-03-02 16:41:20 -06001594
Derek Jonesc630bcf2008-11-17 21:09:45 +00001595 fputs($fp, $this->_header_str);
1596 fputs($fp, $this->_finalbody);
1597
Barry Mienydd671972010-10-04 16:33:58 +02001598 $status = pclose($fp);
Eric Barnes6113f542010-12-29 13:36:12 -05001599
Derek Jonesc630bcf2008-11-17 21:09:45 +00001600 if (version_compare(PHP_VERSION, '4.2.3') == -1)
1601 {
1602 $status = $status >> 8 & 0xFF;
Barry Mienydd671972010-10-04 16:33:58 +02001603 }
Derek Jones71141ce2010-03-02 16:41:20 -06001604
Derek Jones604873f2008-11-18 15:57:24 +00001605 if ($status != 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001606 {
patworkb0707982011-04-08 15:10:05 +02001607 $this->_set_error_message('lang:email_exit_status', $status);
1608 $this->_set_error_message('lang:email_no_socket');
Derek Allard2067d1a2008-11-13 22:59:24 +00001609 return FALSE;
1610 }
1611
Derek Allard2067d1a2008-11-13 22:59:24 +00001612 return TRUE;
1613 }
Barry Mienydd671972010-10-04 16:33:58 +02001614
Derek Allard2067d1a2008-11-13 22:59:24 +00001615 // --------------------------------------------------------------------
1616
1617 /**
1618 * Send using SMTP
1619 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001620 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001621 * @return bool
1622 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001623 protected function _send_with_smtp()
Derek Allard2067d1a2008-11-13 22:59:24 +00001624 {
1625 if ($this->smtp_host == '')
1626 {
patworkb0707982011-04-08 15:10:05 +02001627 $this->_set_error_message('lang:email_no_hostname');
Derek Allard2067d1a2008-11-13 22:59:24 +00001628 return FALSE;
1629 }
1630
1631 $this->_smtp_connect();
1632 $this->_smtp_authenticate();
1633
1634 $this->_send_command('from', $this->clean_email($this->_headers['From']));
1635
Pascal Kriete14287f32011-02-14 13:39:34 -05001636 foreach ($this->_recipients as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001637 {
1638 $this->_send_command('to', $val);
1639 }
1640
1641 if (count($this->_cc_array) > 0)
1642 {
Pascal Kriete14287f32011-02-14 13:39:34 -05001643 foreach ($this->_cc_array as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001644 {
1645 if ($val != "")
1646 {
1647 $this->_send_command('to', $val);
1648 }
1649 }
1650 }
1651
1652 if (count($this->_bcc_array) > 0)
1653 {
Pascal Kriete14287f32011-02-14 13:39:34 -05001654 foreach ($this->_bcc_array as $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001655 {
1656 if ($val != "")
1657 {
1658 $this->_send_command('to', $val);
1659 }
1660 }
1661 }
1662
1663 $this->_send_command('data');
1664
1665 // perform dot transformation on any lines that begin with a dot
1666 $this->_send_data($this->_header_str . preg_replace('/^\./m', '..$1', $this->_finalbody));
1667
1668 $this->_send_data('.');
1669
1670 $reply = $this->_get_smtp_data();
1671
1672 $this->_set_error_message($reply);
1673
1674 if (strncmp($reply, '250', 3) != 0)
1675 {
patworkb0707982011-04-08 15:10:05 +02001676 $this->_set_error_message('lang:email_smtp_error', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001677 return FALSE;
1678 }
1679
1680 $this->_send_command('quit');
1681 return TRUE;
1682 }
Barry Mienydd671972010-10-04 16:33:58 +02001683
Derek Allard2067d1a2008-11-13 22:59:24 +00001684 // --------------------------------------------------------------------
1685
1686 /**
1687 * SMTP Connect
1688 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001689 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001690 * @param string
1691 * @return string
1692 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001693 protected function _smtp_connect()
Derek Allard2067d1a2008-11-13 22:59:24 +00001694 {
Radu Potopbbf04b02011-09-28 13:57:51 +03001695 $ssl = NULL;
Radu Potop4c589ae2011-09-29 10:19:55 +03001696
Radu Potopbbf04b02011-09-28 13:57:51 +03001697 if ($this->smtp_crypto == 'ssl')
Radu Potop4c589ae2011-09-29 10:19:55 +03001698 {
Radu Potopbbf04b02011-09-28 13:57:51 +03001699 $ssl = 'ssl://';
Radu Potop4c589ae2011-09-29 10:19:55 +03001700 }
1701
Radu Potopbbf04b02011-09-28 13:57:51 +03001702 $this->_smtp_connect = fsockopen($ssl.$this->smtp_host,
Derek Allard2067d1a2008-11-13 22:59:24 +00001703 $this->smtp_port,
1704 $errno,
1705 $errstr,
1706 $this->smtp_timeout);
1707
Pascal Kriete14287f32011-02-14 13:39:34 -05001708 if ( ! is_resource($this->_smtp_connect))
Derek Allard2067d1a2008-11-13 22:59:24 +00001709 {
patworkb0707982011-04-08 15:10:05 +02001710 $this->_set_error_message('lang:email_smtp_error', $errno." ".$errstr);
Derek Allard2067d1a2008-11-13 22:59:24 +00001711 return FALSE;
1712 }
1713
1714 $this->_set_error_message($this->_get_smtp_data());
Radu Potopbbf04b02011-09-28 13:57:51 +03001715
1716 if ($this->smtp_crypto == 'tls')
1717 {
1718 $this->_send_command('hello');
1719 $this->_send_command('starttls');
Radu Potop4c589ae2011-09-29 10:19:55 +03001720 $crypto = stream_socket_enable_crypto($this->_smtp_connect, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT);
1721 }
1722
1723 if ($crypto !== TRUE)
1724 {
1725 $this->_set_error_message('lang:email_smtp_error', $this->_get_smtp_data());
1726 return FALSE;
Radu Potopbbf04b02011-09-28 13:57:51 +03001727 }
1728
Derek Allard2067d1a2008-11-13 22:59:24 +00001729 return $this->_send_command('hello');
1730 }
Barry Mienydd671972010-10-04 16:33:58 +02001731
Derek Allard2067d1a2008-11-13 22:59:24 +00001732 // --------------------------------------------------------------------
1733
1734 /**
1735 * Send SMTP command
1736 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001737 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001738 * @param string
1739 * @param string
1740 * @return string
1741 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001742 protected function _send_command($cmd, $data = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001743 {
1744 switch ($cmd)
1745 {
1746 case 'hello' :
1747
1748 if ($this->_smtp_auth OR $this->_get_encoding() == '8bit')
1749 $this->_send_data('EHLO '.$this->_get_hostname());
1750 else
1751 $this->_send_data('HELO '.$this->_get_hostname());
1752
1753 $resp = 250;
1754 break;
Radu Potopbbf04b02011-09-28 13:57:51 +03001755 case 'starttls' :
1756
1757 $this->_send_data('STARTTLS');
1758
1759 $resp = 220;
1760 break;
Derek Allard2067d1a2008-11-13 22:59:24 +00001761 case 'from' :
1762
1763 $this->_send_data('MAIL FROM:<'.$data.'>');
1764
1765 $resp = 250;
1766 break;
1767 case 'to' :
1768
1769 $this->_send_data('RCPT TO:<'.$data.'>');
1770
1771 $resp = 250;
1772 break;
1773 case 'data' :
1774
1775 $this->_send_data('DATA');
1776
1777 $resp = 354;
1778 break;
1779 case 'quit' :
1780
1781 $this->_send_data('QUIT');
1782
1783 $resp = 221;
1784 break;
1785 }
1786
1787 $reply = $this->_get_smtp_data();
1788
1789 $this->_debug_msg[] = "<pre>".$cmd.": ".$reply."</pre>";
1790
1791 if (substr($reply, 0, 3) != $resp)
1792 {
patworkb0707982011-04-08 15:10:05 +02001793 $this->_set_error_message('lang:email_smtp_error', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001794 return FALSE;
1795 }
1796
1797 if ($cmd == 'quit')
1798 {
1799 fclose($this->_smtp_connect);
1800 }
1801
1802 return TRUE;
1803 }
Barry Mienydd671972010-10-04 16:33:58 +02001804
Derek Allard2067d1a2008-11-13 22:59:24 +00001805 // --------------------------------------------------------------------
1806
1807 /**
Derek Jones37f4b9c2011-07-01 17:56:50 -05001808 * SMTP Authenticate
Derek Allard2067d1a2008-11-13 22:59:24 +00001809 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001810 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001811 * @return bool
1812 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001813 protected function _smtp_authenticate()
Derek Allard2067d1a2008-11-13 22:59:24 +00001814 {
1815 if ( ! $this->_smtp_auth)
1816 {
1817 return TRUE;
1818 }
1819
Derek Jones37f4b9c2011-07-01 17:56:50 -05001820 if ($this->smtp_user == "" AND $this->smtp_pass == "")
Derek Allard2067d1a2008-11-13 22:59:24 +00001821 {
patworkb0707982011-04-08 15:10:05 +02001822 $this->_set_error_message('lang:email_no_smtp_unpw');
Derek Allard2067d1a2008-11-13 22:59:24 +00001823 return FALSE;
1824 }
1825
1826 $this->_send_data('AUTH LOGIN');
1827
1828 $reply = $this->_get_smtp_data();
1829
1830 if (strncmp($reply, '334', 3) != 0)
1831 {
patworkb0707982011-04-08 15:10:05 +02001832 $this->_set_error_message('lang:email_failed_smtp_login', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001833 return FALSE;
1834 }
1835
1836 $this->_send_data(base64_encode($this->smtp_user));
1837
1838 $reply = $this->_get_smtp_data();
1839
1840 if (strncmp($reply, '334', 3) != 0)
1841 {
patworkb0707982011-04-08 15:10:05 +02001842 $this->_set_error_message('lang:email_smtp_auth_un', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001843 return FALSE;
1844 }
1845
1846 $this->_send_data(base64_encode($this->smtp_pass));
1847
1848 $reply = $this->_get_smtp_data();
1849
1850 if (strncmp($reply, '235', 3) != 0)
1851 {
patworkb0707982011-04-08 15:10:05 +02001852 $this->_set_error_message('lang:email_smtp_auth_pw', $reply);
Derek Allard2067d1a2008-11-13 22:59:24 +00001853 return FALSE;
1854 }
1855
1856 return TRUE;
1857 }
Barry Mienydd671972010-10-04 16:33:58 +02001858
Derek Allard2067d1a2008-11-13 22:59:24 +00001859 // --------------------------------------------------------------------
1860
1861 /**
1862 * Send SMTP data
1863 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001864 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001865 * @return bool
1866 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001867 protected function _send_data($data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001868 {
1869 if ( ! fwrite($this->_smtp_connect, $data . $this->newline))
1870 {
patworkb0707982011-04-08 15:10:05 +02001871 $this->_set_error_message('lang:email_smtp_data_failure', $data);
Derek Allard2067d1a2008-11-13 22:59:24 +00001872 return FALSE;
1873 }
1874 else
1875 {
1876 return TRUE;
1877 }
1878 }
Barry Mienydd671972010-10-04 16:33:58 +02001879
Derek Allard2067d1a2008-11-13 22:59:24 +00001880 // --------------------------------------------------------------------
1881
1882 /**
1883 * Get SMTP data
1884 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001885 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001886 * @return string
1887 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001888 protected function _get_smtp_data()
Derek Allard2067d1a2008-11-13 22:59:24 +00001889 {
1890 $data = "";
1891
1892 while ($str = fgets($this->_smtp_connect, 512))
1893 {
1894 $data .= $str;
1895
1896 if (substr($str, 3, 1) == " ")
1897 {
1898 break;
1899 }
1900 }
1901
1902 return $data;
1903 }
Barry Mienydd671972010-10-04 16:33:58 +02001904
Derek Allard2067d1a2008-11-13 22:59:24 +00001905 // --------------------------------------------------------------------
1906
1907 /**
1908 * Get Hostname
1909 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001910 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001911 * @return string
1912 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001913 protected function _get_hostname()
Derek Allard2067d1a2008-11-13 22:59:24 +00001914 {
1915 return (isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain';
1916 }
Barry Mienydd671972010-10-04 16:33:58 +02001917
Derek Allard2067d1a2008-11-13 22:59:24 +00001918 // --------------------------------------------------------------------
1919
1920 /**
1921 * Get IP
1922 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001923 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001924 * @return string
1925 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001926 protected function _get_ip()
Derek Allard2067d1a2008-11-13 22:59:24 +00001927 {
1928 if ($this->_IP !== FALSE)
1929 {
1930 return $this->_IP;
1931 }
1932
1933 $cip = (isset($_SERVER['HTTP_CLIENT_IP']) AND $_SERVER['HTTP_CLIENT_IP'] != "") ? $_SERVER['HTTP_CLIENT_IP'] : FALSE;
1934 $rip = (isset($_SERVER['REMOTE_ADDR']) AND $_SERVER['REMOTE_ADDR'] != "") ? $_SERVER['REMOTE_ADDR'] : FALSE;
1935 $fip = (isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND $_SERVER['HTTP_X_FORWARDED_FOR'] != "") ? $_SERVER['HTTP_X_FORWARDED_FOR'] : FALSE;
1936
Barry Mienydd671972010-10-04 16:33:58 +02001937 if ($cip && $rip) $this->_IP = $cip;
Derek Allard2067d1a2008-11-13 22:59:24 +00001938 elseif ($rip) $this->_IP = $rip;
1939 elseif ($cip) $this->_IP = $cip;
1940 elseif ($fip) $this->_IP = $fip;
1941
Robin Sowell76b369e2010-03-19 11:15:28 -04001942 if (strpos($this->_IP, ',') !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001943 {
1944 $x = explode(',', $this->_IP);
1945 $this->_IP = end($x);
1946 }
1947
1948 if ( ! preg_match( "/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $this->_IP))
1949 {
1950 $this->_IP = '0.0.0.0';
1951 }
1952
1953 unset($cip);
1954 unset($rip);
1955 unset($fip);
1956
1957 return $this->_IP;
1958 }
Barry Mienydd671972010-10-04 16:33:58 +02001959
Derek Allard2067d1a2008-11-13 22:59:24 +00001960 // --------------------------------------------------------------------
1961
1962 /**
1963 * Get Debug Message
1964 *
1965 * @access public
1966 * @return string
1967 */
Phil Sturgeona0f980e2011-01-13 10:59:12 +00001968 public function print_debugger()
Derek Allard2067d1a2008-11-13 22:59:24 +00001969 {
1970 $msg = '';
1971
1972 if (count($this->_debug_msg) > 0)
1973 {
1974 foreach ($this->_debug_msg as $val)
1975 {
1976 $msg .= $val;
1977 }
1978 }
1979
1980 $msg .= "<pre>".$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".htmlspecialchars($this->_finalbody).'</pre>';
1981 return $msg;
1982 }
Barry Mienydd671972010-10-04 16:33:58 +02001983
Derek Allard2067d1a2008-11-13 22:59:24 +00001984 // --------------------------------------------------------------------
1985
1986 /**
1987 * Set Message
1988 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001989 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00001990 * @param string
1991 * @return string
1992 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06001993 protected function _set_error_message($msg, $val = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001994 {
1995 $CI =& get_instance();
1996 $CI->lang->load('email');
1997
patworkb0707982011-04-08 15:10:05 +02001998 if (substr($msg, 0, 5) != 'lang:' || FALSE === ($line = $CI->lang->line(substr($msg, 5))))
Derek Allard2067d1a2008-11-13 22:59:24 +00001999 {
2000 $this->_debug_msg[] = str_replace('%s', $val, $msg)."<br />";
2001 }
2002 else
2003 {
2004 $this->_debug_msg[] = str_replace('%s', $val, $line)."<br />";
2005 }
2006 }
Barry Mienydd671972010-10-04 16:33:58 +02002007
Derek Allard2067d1a2008-11-13 22:59:24 +00002008 // --------------------------------------------------------------------
2009
2010 /**
2011 * Mime Types
2012 *
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06002013 * @access protected
Derek Allard2067d1a2008-11-13 22:59:24 +00002014 * @param string
2015 * @return string
2016 */
Phil Sturgeon6d2f13a2011-07-20 10:04:52 -06002017 protected function _mime_types($ext = "")
Derek Allard2067d1a2008-11-13 22:59:24 +00002018 {
2019 $mimes = array( 'hqx' => 'application/mac-binhex40',
2020 'cpt' => 'application/mac-compactpro',
2021 'doc' => 'application/msword',
2022 'bin' => 'application/macbinary',
2023 'dms' => 'application/octet-stream',
2024 'lha' => 'application/octet-stream',
2025 'lzh' => 'application/octet-stream',
2026 'exe' => 'application/octet-stream',
2027 'class' => 'application/octet-stream',
2028 'psd' => 'application/octet-stream',
2029 'so' => 'application/octet-stream',
2030 'sea' => 'application/octet-stream',
2031 'dll' => 'application/octet-stream',
2032 'oda' => 'application/oda',
2033 'pdf' => 'application/pdf',
2034 'ai' => 'application/postscript',
2035 'eps' => 'application/postscript',
2036 'ps' => 'application/postscript',
2037 'smi' => 'application/smil',
2038 'smil' => 'application/smil',
2039 'mif' => 'application/vnd.mif',
2040 'xls' => 'application/vnd.ms-excel',
2041 'ppt' => 'application/vnd.ms-powerpoint',
2042 'wbxml' => 'application/vnd.wap.wbxml',
2043 'wmlc' => 'application/vnd.wap.wmlc',
2044 'dcr' => 'application/x-director',
2045 'dir' => 'application/x-director',
2046 'dxr' => 'application/x-director',
2047 'dvi' => 'application/x-dvi',
2048 'gtar' => 'application/x-gtar',
2049 'php' => 'application/x-httpd-php',
2050 'php4' => 'application/x-httpd-php',
2051 'php3' => 'application/x-httpd-php',
2052 'phtml' => 'application/x-httpd-php',
2053 'phps' => 'application/x-httpd-php-source',
2054 'js' => 'application/x-javascript',
2055 'swf' => 'application/x-shockwave-flash',
2056 'sit' => 'application/x-stuffit',
2057 'tar' => 'application/x-tar',
2058 'tgz' => 'application/x-tar',
2059 'xhtml' => 'application/xhtml+xml',
2060 'xht' => 'application/xhtml+xml',
2061 'zip' => 'application/zip',
2062 'mid' => 'audio/midi',
2063 'midi' => 'audio/midi',
2064 'mpga' => 'audio/mpeg',
2065 'mp2' => 'audio/mpeg',
2066 'mp3' => 'audio/mpeg',
2067 'aif' => 'audio/x-aiff',
2068 'aiff' => 'audio/x-aiff',
2069 'aifc' => 'audio/x-aiff',
2070 'ram' => 'audio/x-pn-realaudio',
2071 'rm' => 'audio/x-pn-realaudio',
2072 'rpm' => 'audio/x-pn-realaudio-plugin',
2073 'ra' => 'audio/x-realaudio',
2074 'rv' => 'video/vnd.rn-realvideo',
2075 'wav' => 'audio/x-wav',
2076 'bmp' => 'image/bmp',
2077 'gif' => 'image/gif',
2078 'jpeg' => 'image/jpeg',
2079 'jpg' => 'image/jpeg',
2080 'jpe' => 'image/jpeg',
2081 'png' => 'image/png',
2082 'tiff' => 'image/tiff',
2083 'tif' => 'image/tiff',
2084 'css' => 'text/css',
2085 'html' => 'text/html',
2086 'htm' => 'text/html',
2087 'shtml' => 'text/html',
2088 'txt' => 'text/plain',
2089 'text' => 'text/plain',
2090 'log' => 'text/plain',
2091 'rtx' => 'text/richtext',
2092 'rtf' => 'text/rtf',
2093 'xml' => 'text/xml',
2094 'xsl' => 'text/xml',
2095 'mpeg' => 'video/mpeg',
2096 'mpg' => 'video/mpeg',
2097 'mpe' => 'video/mpeg',
2098 'qt' => 'video/quicktime',
2099 'mov' => 'video/quicktime',
2100 'avi' => 'video/x-msvideo',
2101 'movie' => 'video/x-sgi-movie',
2102 'doc' => 'application/msword',
2103 'word' => 'application/msword',
2104 'xl' => 'application/excel',
2105 'eml' => 'message/rfc822'
2106 );
2107
2108 return ( ! isset($mimes[strtolower($ext)])) ? "application/x-unknown-content-type" : $mimes[strtolower($ext)];
2109 }
2110
2111}
2112// END CI_Email class
2113
2114/* End of file Email.php */
patworkb0707982011-04-08 15:10:05 +02002115/* Location: ./system/libraries/Email.php */