PageRenderTime 73ms CodeModel.GetById 20ms app.highlight 44ms RepoModel.GetById 2ms app.codeStats 0ms

/chronique/includes/htmlMimeMail.php

http://chronique.googlecode.com/
PHP | 775 lines | 449 code | 94 blank | 232 comment | 68 complexity | 6b3dfb78d5b7979f0711d2c8acbc08ad MD5 | raw file
  1<?php
  2/* $Id: htmlMimeMail.php 4622 2011-07-03 04:33:19Z daintree $*/
  3/**
  4* Filename.......: class.html.mime.mail.inc
  5* Project........: HTML Mime mail class
  6* Last Modified..: $Date: 2007/11/02 21:39:47 $
  7* CVS Revision...: $Revision: 1.6 $
  8* Copyright......: 2001, 2002 Richard Heyes
  9*/
 10
 11require_once('includes/mimePart.php');
 12
 13class htmlMimeMail
 14{
 15	/**
 16	* The html part of the message
 17    * @var string
 18    */
 19	var $html;
 20
 21	/**
 22	* The text part of the message(only used in TEXT only messages)
 23	* @var string
 24	*/
 25	var $text;
 26
 27	/**
 28	* The main body of the message after building
 29	* @var string
 30	*/
 31	var $output;
 32
 33	/**
 34	* The alternative text to the HTML part (only used in HTML messages)
 35	* @var string
 36	*/
 37	var $html_text;
 38
 39	/**
 40	* An array of embedded images/objects
 41	* @var array
 42	*/
 43	var $html_images;
 44
 45	/**
 46	* An array of recognised image types for the findHtmlImages() method
 47	* @var array
 48	*/
 49	var $image_types;
 50
 51	/**
 52	* Parameters that affect the build process
 53	* @var array
 54	*/
 55	var $build_params;
 56
 57	/**
 58	* Array of attachments
 59	* @var array
 60	*/
 61	var $attachments;
 62
 63	/**
 64	* The main message headers
 65	* @var array
 66	*/
 67	var $headers;
 68
 69	/**
 70	* Whether the message has been built or not
 71	* @var boolean
 72	*/
 73	var $is_built;
 74
 75	/**
 76    * The return path address. If not set the From:
 77	* address is used instead
 78	* @var string
 79    */
 80	var $return_path;
 81
 82	/**
 83    * Array of information needed for smtp sending
 84	* @var array
 85    */
 86	var $smtp_params;
 87
 88/**
 89* Constructor function. Sets the headers
 90* if supplied.
 91*/
 92
 93	function htmlMimeMail()
 94	{
 95		/**
 96        * Initialise some variables.
 97        */
 98		$this->html_images = array();
 99		$this->headers     = array();
100		$this->is_built    = false;
101
102		/**
103        * If you want the auto load functionality
104		* to find other image/file types, add the
105		* extension and content type here.
106        */
107		$this->image_types = array(
108									'gif'	=> 'image/gif',
109									'jpg'	=> 'image/jpeg',
110									'jpeg'	=> 'image/jpeg',
111									'jpe'	=> 'image/jpeg',
112									'bmp'	=> 'image/bmp',
113									'png'	=> 'image/png',
114									'tif'	=> 'image/tiff',
115									'tiff'	=> 'image/tiff',
116									'swf'	=> 'application/x-shockwave-flash'
117								  );
118
119		/**
120        * Set these up
121        */
122		$this->build_params['html_encoding'] = 'quoted-printable';
123		$this->build_params['text_encoding'] = '7bit';
124		$this->build_params['html_charset']  = 'ISO-8859-1';
125		$this->build_params['text_charset']  = 'ISO-8859-1';
126		$this->build_params['head_charset']  = 'ISO-8859-1';
127		$this->build_params['text_wrap']     = 998;
128
129		/**
130        * Defaults for smtp sending
131        */
132		if (!empty($GLOBALS['HTTP_SERVER_VARS']['HTTP_HOST'])) {
133			$helo = $GLOBALS['HTTP_SERVER_VARS']['HTTP_HOST'];
134		} elseif (!empty($GLOBALS['HTTP_SERVER_VARS']['SERVER_NAME'])) {
135			$helo = $GLOBALS['HTTP_SERVER_VARS']['SERVER_NAME'];
136		} else {
137			$helo = 'localhost';
138		}
139
140		$this->smtp_params['host'] = $_SESSION['SMTPSettings']['host'];
141		$this->smtp_params['port'] = $_SESSION['SMTPSettings']['port'];
142		$this->smtp_params['helo'] = $_SESSION['SMTPSettings']['heloaddress'];
143		$this->smtp_params['auth'] = $_SESSION['SMTPSettings']['auth'];
144		$this->smtp_params['user'] = html_entity_decode($_SESSION['SMTPSettings']['username']);
145		$this->smtp_params['pass'] = html_entity_decode($_SESSION['SMTPSettings']['password']);
146
147		/**
148        * Make sure the MIME version header is first.
149        */
150		$this->headers['MIME-Version'] = '1.0';
151	}
152
153/**
154* This function will read a file in
155* from a supplied filename and return
156* it. This can then be given as the first
157* argument of the the functions
158* add_html_image() or add_attachment().
159*/
160	function getFile($filename)
161	{
162		$return = '';
163		if ($fp = fopen($filename, 'rb')) {
164			while (!feof($fp)) {
165				$return .= fread($fp, 1024);
166			}
167			fclose($fp);
168			return $return;
169
170		} else {
171			return false;
172		}
173	}
174
175/**
176* Accessor to set the CRLF style
177*/
178	function setCrlf($crlf = "\n")
179	{
180		if (!defined('CRLF')) {
181			define('CRLF', $crlf, true);
182		}
183
184		if (!defined('MAIL_MIMEPART_CRLF')) {
185			define('MAIL_MIMEPART_CRLF', $crlf, true);
186		}
187	}
188
189/**
190* Accessor to set the SMTP parameters
191*/
192	function setSMTPParams($host = null, $port = null, $helo = null, $auth = null, $user = null, $pass = null)
193	{
194		if (!is_null($host)) $this->smtp_params['host'] = $host;
195		if (!is_null($port)) $this->smtp_params['port'] = $port;
196		if (!is_null($helo)) $this->smtp_params['helo'] = $helo;
197		if (!is_null($auth)) $this->smtp_params['auth'] = $auth;
198		if (!is_null($user)) $this->smtp_params['user'] = $user;
199		if (!is_null($pass)) $this->smtp_params['pass'] = $pass;
200	}
201
202/**
203* Accessor function to set the text encoding
204*/
205	function setTextEncoding($encoding = '7bit')
206	{
207		$this->build_params['text_encoding'] = $encoding;
208	}
209
210/**
211* Accessor function to set the HTML encoding
212*/
213	function setHtmlEncoding($encoding = 'quoted-printable')
214	{
215		$this->build_params['html_encoding'] = $encoding;
216	}
217
218/**
219* Accessor function to set the text charset
220*/
221	function setTextCharset($charset = 'ISO-8859-1')
222	{
223		$this->build_params['text_charset'] = $charset;
224	}
225
226/**
227* Accessor function to set the HTML charset
228*/
229	function setHtmlCharset($charset = 'ISO-8859-1')
230	{
231		$this->build_params['html_charset'] = $charset;
232	}
233
234/**
235* Accessor function to set the header encoding charset
236*/
237	function setHeadCharset($charset = 'ISO-8859-1')
238	{
239		$this->build_params['head_charset'] = $charset;
240	}
241
242/**
243* Accessor function to set the text wrap count
244*/
245	function setTextWrap($count = 998)
246	{
247		$this->build_params['text_wrap'] = $count;
248	}
249
250/**
251* Accessor to set a header
252*/
253	function setHeader($name, $value)
254	{
255		$this->headers[$name] = $value;
256	}
257
258/**
259* Accessor to add a Subject: header
260*/
261	function setSubject($subject)
262	{
263		$this->headers['Subject'] = $subject;
264	}
265
266/**
267* Accessor to add a From: header
268*/
269	function setFrom($from)
270	{
271		$this->headers['From'] = $from;
272	}
273
274/**
275* Accessor to set the return path
276*/
277	function setReturnPath($return_path)
278	{
279		$this->return_path = $return_path;
280	}
281
282/**
283* Accessor to add a Cc: header
284*/
285	function setCc($cc)
286	{
287		$this->headers['Cc'] = $cc;
288	}
289
290/**
291* Accessor to add a Bcc: header
292*/
293	function setBcc($bcc)
294	{
295		$this->headers['Bcc'] = $bcc;
296	}
297
298/**
299* Adds plain text. Use this function
300* when NOT sending html email
301*/
302	function setText($text = '')
303	{
304		$this->text = $text;
305	}
306
307/**
308* Adds a html part to the mail.
309* Also replaces image names with
310* content-id's.
311*/
312	function setHtml($html, $text = null, $images_dir = null)
313	{
314		$this->html      = $html;
315		$this->html_text = $text;
316
317		if (isset($images_dir)) {
318			$this->_findHtmlImages($images_dir);
319		}
320	}
321
322/**
323* Function for extracting images from
324* html source. This function will look
325* through the html code supplied by add_html()
326* and find any file that ends in one of the
327* extensions defined in $obj->image_types.
328* If the file exists it will read it in and
329* embed it, (not an attachment).
330*
331* @author Dan Allen
332*/
333	function _findHtmlImages($images_dir)
334	{
335		// Build the list of image extensions
336		while (list($key,) = each($this->image_types)) {
337			$extensions[] = $key;
338		}
339
340		preg_match_all('/(?:"|\')([^"\']+\.('.implode('|', $extensions).'))(?:"|\')/Ui', $this->html, $images);
341
342		for ($i=0; $i<count($images[1]); $i++) {
343			if (file_exists($images_dir . $images[1][$i])) {
344				$html_images[] = $images[1][$i];
345				$this->html = str_replace($images[1][$i], basename($images[1][$i]), $this->html);
346			}
347		}
348
349		if (!empty($html_images)) {
350
351			// If duplicate images are embedded, they may show up as attachments, so remove them.
352			$html_images = array_unique($html_images);
353			sort($html_images);
354
355			for ($i=0; $i<count($html_images); $i++) {
356				if ($image = $this->getFile($images_dir.$html_images[$i])) {
357					$ext = mb_substr($html_images[$i], strrpos($html_images[$i], '.') + 1);
358					$content_type = $this->image_types[strtolower($ext)];
359					$this->addHtmlImage($image, basename($html_images[$i]), $content_type);
360				}
361			}
362		}
363	}
364
365/**
366* Adds an image to the list of embedded
367* images.
368*/
369	function addHtmlImage($file, $name = '', $c_type='application/octet-stream')
370	{
371		$this->html_images[] = array(
372										'body'   => $file,
373										'name'   => $name,
374										'c_type' => $c_type,
375										'cid'    => md5(uniqid(time()))
376									);
377	}
378
379
380/**
381* Adds a file to the list of attachments.
382*/
383	function addAttachment($file, $name = '', $c_type='application/octet-stream', $encoding = 'base64')
384	{
385		$this->attachments[] = array(
386									'body'		=> $file,
387									'name'		=> $name,
388									'c_type'	=> $c_type,
389									'encoding'	=> $encoding
390								  );
391	}
392
393/**
394* Adds a text subpart to a mime_part object
395*/
396	function _addTextPart(&$obj, $text) // // FIXED PHP & PEAR LIBRARY ERROR - ONLY VARIABLE REFERENCES SHOULD BE RETURNED BY REFERENCE
397	{
398		$params['content_type'] = 'text/plain';
399		$params['encoding']     = $this->build_params['text_encoding'];
400		$params['charset']      = $this->build_params['text_charset'];
401		if (is_object($obj)) {
402			return $obj->addSubpart($text, $params);
403		} else {
404			return new Mail_mimePart($text, $params);
405		}
406	}
407
408/**
409* Adds a html subpart to a mime_part object
410*/
411	function _addHtmlPart(&$obj) // // FIXED PHP & PEAR LIBRARY ERROR - ONLY VARIABLE REFERENCES SHOULD BE RETURNED BY REFERENCE
412	{
413		$params['content_type'] = 'text/html';
414		$params['encoding']     = $this->build_params['html_encoding'];
415		$params['charset']      = $this->build_params['html_charset'];
416		if (is_object($obj)) {
417			return $obj->addSubpart($this->html, $params);
418		} else {
419			return new Mail_mimePart($this->html, $params);
420		}
421	}
422
423/**
424* Starts a message with a mixed part
425*/
426	function _addMixedPart() // // FIXED PHP & PEAR LIBRARY ERROR - ONLY VARIABLE REFERENCES SHOULD BE RETURNED BY REFERENCE
427	{
428		$params['content_type'] = 'multipart/mixed';
429		return new Mail_mimePart('', $params);
430	}
431
432/**
433* Adds an alternative part to a mime_part object
434*/
435	function _addAlternativePart(&$obj) // // FIXED PHP & PEAR LIBRARY ERROR - ONLY VARIABLE REFERENCES SHOULD BE RETURNED BY REFERENCE
436	{
437		$params['content_type'] = 'multipart/alternative';
438		if (is_object($obj)) {
439			return $obj->addSubpart('', $params);
440		} else {
441			return new Mail_mimePart('', $params);
442		}
443	}
444
445/**
446* Adds a html subpart to a mime_part object
447*/
448	function _addRelatedPart(&$obj) // // FIXED PHP & PEAR LIBRARY ERROR - ONLY VARIABLE REFERENCES SHOULD BE RETURNED BY REFERENCE
449	{
450		$params['content_type'] = 'multipart/related';
451		if (is_object($obj)) {
452			return $obj->addSubpart('', $params);
453		} else {
454			return new Mail_mimePart('', $params);
455		}
456	}
457
458/**
459* Adds an html image subpart to a mime_part object
460*/
461	function _addHtmlImagePart(&$obj, $value) // // FIXED PHP & PEAR LIBRARY ERROR - ONLY VARIABLE REFERENCES SHOULD BE RETURNED BY REFERENCE
462	{
463		$params['content_type'] = $value['c_type'];
464		$params['encoding']     = 'base64';
465		$params['disposition']  = 'inline';
466		$params['dfilename']    = $value['name'];
467		$params['cid']          = $value['cid'];
468		$obj->addSubpart($value['body'], $params);
469	}
470
471/**
472* Adds an attachment subpart to a mime_part object
473*/
474	function _addAttachmentPart(&$obj, $value) // // FIXED PHP & PEAR LIBRARY ERROR - ONLY VARIABLE REFERENCES SHOULD BE RETURNED BY REFERENCE
475	{
476		$params['content_type'] = $value['c_type'];
477		$params['encoding']     = $value['encoding'];
478		$params['disposition']  = 'attachment';
479		$params['dfilename']    = $value['name'];
480		$obj->addSubpart($value['body'], $params);
481	}
482
483/**
484* Builds the multipart message from the
485* list ($this->_parts). $params is an
486* array of parameters that shape the building
487* of the message. Currently supported are:
488*
489* $params['html_encoding'] - The type of encoding to use on html. Valid options are
490*                            "7bit", "quoted-printable" or "base64" (all without quotes).
491*                            7bit is EXPRESSLY NOT RECOMMENDED. Default is quoted-printable
492* $params['text_encoding'] - The type of encoding to use on plain text Valid options are
493*                            "7bit", "quoted-printable" or "base64" (all without quotes).
494*                            Default is 7bit
495* $params['text_wrap']     - The character count at which to wrap 7bit encoded data.
496*                            Default this is 998.
497* $params['html_charset']  - The character set to use for a html section.
498*                            Default is ISO-8859-1
499* $params['text_charset']  - The character set to use for a text section.
500*                          - Default is ISO-8859-1
501* $params['head_charset']  - The character set to use for header encoding should it be needed.
502*                          - Default is ISO-8859-1
503*/
504	function buildMessage($params = array())
505	{
506		if (!empty($params)) {
507			while (list($key, $value) = each($params)) {
508				$this->build_params[$key] = $value;
509			}
510		}
511
512		if (!empty($this->html_images)) {
513			foreach ($this->html_images as $value) {
514				$this->html = str_replace($value['name'], 'cid:'.$value['cid'], $this->html);
515			}
516		}
517
518		$null        = null;
519		$attachments = !empty($this->attachments) ? true : false;
520		$html_images = !empty($this->html_images) ? true : false;
521		$html        = !empty($this->html)        ? true : false;
522		$text        = isset($this->text)         ? true : false;
523
524		switch (true) {
525			case $text AND !$attachments:
526				$message = &$this->_addTextPart($null, $this->text);
527				break;
528
529			case !$text AND $attachments AND !$html:
530				$message = &$this->_addMixedPart();
531
532				for ($i=0; $i<count($this->attachments); $i++) {
533					$this->_addAttachmentPart($message, $this->attachments[$i]);
534				}
535				break;
536
537			case $text AND $attachments:
538				$message = &$this->_addMixedPart();
539				$this->_addTextPart($message, $this->text);
540
541				for ($i=0; $i<count($this->attachments); $i++) {
542					$this->_addAttachmentPart($message, $this->attachments[$i]);
543				}
544				break;
545
546			case $html AND !$attachments AND !$html_images:
547				if (!is_null($this->html_text)) {
548					$message = &$this->_addAlternativePart($null);
549					$this->_addTextPart($message, $this->html_text);
550					$this->_addHtmlPart($message);
551				} else {
552					$message = &$this->_addHtmlPart($null);
553				}
554				break;
555
556			case $html AND !$attachments AND $html_images:
557				if (!is_null($this->html_text)) {
558					$message = &$this->_addAlternativePart($null);
559					$this->_addTextPart($message, $this->html_text);
560					$related = &$this->_addRelatedPart($message);
561				} else {
562					$message = &$this->_addRelatedPart($null);
563					$related = &$message;
564				}
565				$this->_addHtmlPart($related);
566				for ($i=0; $i<count($this->html_images); $i++) {
567					$this->_addHtmlImagePart($related, $this->html_images[$i]);
568				}
569				break;
570
571			case $html AND $attachments AND !$html_images:
572				$message = &$this->_addMixedPart();
573				if (!is_null($this->html_text)) {
574					$alt = &$this->_addAlternativePart($message);
575					$this->_addTextPart($alt, $this->html_text);
576					$this->_addHtmlPart($alt);
577				} else {
578					$this->_addHtmlPart($message);
579				}
580				for ($i=0; $i<count($this->attachments); $i++) {
581					$this->_addAttachmentPart($message, $this->attachments[$i]);
582				}
583				break;
584
585			case $html AND $attachments AND $html_images:
586				$message = &$this->_addMixedPart();
587				if (!is_null($this->html_text)) {
588					$alt = &$this->_addAlternativePart($message);
589					$this->_addTextPart($alt, $this->html_text);
590					$rel = &$this->_addRelatedPart($alt);
591				} else {
592					$rel = &$this->_addRelatedPart($message);
593				}
594				$this->_addHtmlPart($rel);
595				for ($i=0; $i<count($this->html_images); $i++) {
596					$this->_addHtmlImagePart($rel, $this->html_images[$i]);
597				}
598				for ($i=0; $i<count($this->attachments); $i++) {
599					$this->_addAttachmentPart($message, $this->attachments[$i]);
600				}
601				break;
602
603		}
604
605		if (isset($message)) {
606			$output = $message->encode();
607			$this->output   = $output['body'];
608			$this->headers  = array_merge($this->headers, $output['headers']);
609
610			// Add message ID header
611			srand((double)microtime()*10000000);
612//			$message_id = sprintf('<%s.%s@%s>', base_convert(time(), 10, 36), base_convert(rand(), 10, 36), !empty($GLOBALS['HTTP_SERVER_VARS']['HTTP_HOST']) ? $GLOBALS['HTTP_SERVER_VARS']['HTTP_HOST'] : $GLOBALS['HTTP_SERVER_VARS']['SERVER_NAME']);
613//			$this->headers['Message-ID'] = $message_id;
614
615			$this->is_built = true;
616			return true;
617		} else {
618			return false;
619		}
620	}
621
622/**
623* Function to encode a header if necessary
624* according to RFC2047
625*/
626	function _encodeHeader($input, $charset = 'ISO-8859-1')
627	{
628		preg_match_all('/(\w*[\x80-\xFF]+\w*)/', $input, $matches);
629		foreach ($matches[1] as $value) {
630			$replacement = preg_replace('/([\x80-\xFF])/e', '"=" . mb_strtoupper(dechex(ord("\1")))', $value);
631			$input = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $input);
632		}
633
634		return $input;
635	}
636
637/**
638* Sends the mail.
639*
640* @param  array  $recipients
641* @param  string $type OPTIONAL
642* @return mixed
643*/
644	function send($recipients, $type = 'mail')
645	{
646		if (!defined('CRLF')) {
647			$this->setCrlf($type == 'mail' ? "\n" : "\r\n");
648		}
649
650		if (!$this->is_built) {
651			$this->buildMessage();
652		}
653
654		switch ($type) {
655			case 'mail':
656				$subject = '';
657				if (!empty($this->headers['Subject'])) {
658					$subject = $this->_encodeHeader($this->headers['Subject'], $this->build_params['head_charset']);
659					unset($this->headers['Subject']);
660				}
661
662				// Get flat representation of headers
663				foreach ($this->headers as $name => $value) {
664					$headers[] = $name . ': ' . $this->_encodeHeader($value, $this->build_params['head_charset']);
665				}
666
667				$to = $this->_encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
668
669				if (!empty($this->return_path)) {
670					$result = mail($to, $subject, $this->output, implode(CRLF, $headers), '-f' . $this->return_path);
671				} else {
672					$result = mail($to, $subject, $this->output, implode(CRLF, $headers));
673				}
674
675				// Reset the subject in case mail is resent
676				if ($subject !== '') {
677					$this->headers['Subject'] = $subject;
678				}
679
680				// Return
681				return $result;
682				break;
683
684			case 'smtp':
685				require_once(dirname(__FILE__) . '/smtp.php');
686				require_once(dirname(__FILE__) . '/RFC822.php');
687				$smtp = &smtp::connect($this->smtp_params);
688
689				// Parse recipients argument for internet addresses
690				foreach ($recipients as $recipient) {
691					$addresses = Mail_RFC822::parseAddressList($recipient, $this->smtp_params['helo'], null, false);
692					foreach ($addresses as $address) {
693						$smtp_recipients[] = sprintf('%s@%s', $address->mailbox, $address->host);
694					}
695				}
696				unset($addresses); // These are reused
697				unset($address);   // These are reused
698
699				// Get flat representation of headers, parsing
700				// Cc and Bcc as we go
701				foreach ($this->headers as $name => $value) {
702					if ($name == 'Cc' OR $name == 'Bcc') {
703						$addresses = Mail_RFC822::parseAddressList($value, $this->smtp_params['helo'], null, false);
704						foreach ($addresses as $address) {
705							$smtp_recipients[] = sprintf('%s@%s', $address->mailbox, $address->host);
706						}
707					}
708					if ($name == 'Bcc') {
709						continue;
710					}
711					$headers[] = $name . ': ' . $this->_encodeHeader($value, $this->build_params['head_charset']);
712				}
713				// Add To header based on $recipients argument
714				$headers[] = 'To: ' . $this->_encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
715
716				// Add headers to send_params
717				$send_params['headers']    = $headers;
718				$send_params['recipients'] = array_values(array_unique($smtp_recipients));
719				$send_params['body']       = $this->output;
720
721				// Setup return path
722				if (isset($this->return_path)) {
723					$send_params['from'] = $this->return_path;
724				} elseif (!empty($this->headers['From'])) {
725					$from = Mail_RFC822::parseAddressList($this->headers['From']);
726					$send_params['from'] = sprintf('%s@%s', $from[0]->mailbox, $from[0]->host);
727				} else {
728					$send_params['from'] = 'postmaster@' . $this->smtp_params['helo'];
729				}
730
731				// Send it
732				if (!$smtp->send($send_params)) {
733					$this->errors = $smtp->errors;
734					return false;
735				}
736				return true;
737				break;
738		}
739	}
740
741/**
742* Use this method to return the email
743* in message/rfc822 format. Useful for
744* adding an email to another email as
745* an attachment. there's a commented
746* out example in example.php.
747*/
748	function getRFC822($recipients)
749	{
750		// Make up the date header as according to RFC822
751		$this->setHeader('Date', date('D, d M y H:i:s O'));
752
753		if (!defined('CRLF')) {
754			$this->setCrlf($type == 'mail' ? "\n" : "\r\n");
755		}
756
757		if (!$this->is_built) {
758			$this->buildMessage();
759		}
760
761		// Return path ?
762		if (isset($this->return_path)) {
763			$headers[] = 'Return-Path: ' . $this->return_path;
764		}
765
766		// Get flat representation of headers
767		foreach ($this->headers as $name => $value) {
768			$headers[] = $name . ': ' . $value;
769		}
770		$headers[] = 'To: ' . implode(', ', $recipients);
771
772		return implode(CRLF, $headers) . CRLF . CRLF . $this->output;
773	}
774} // End of class.
775?>