CWIS Developer Documentation

- Home
- Main Page
- Classes
- Files

- File List
- File Members

Email.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: Email.php
4 #
5 # Part of the ScoutLib application support library
6 # Copyright 2012-2013 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu
8 #
9
14 class Email {
15
16 # ---- PUBLIC INTERFACE --------------------------------------------------
17 /*@(*/
19
25 function Send()
26 {
27 switch (self::$DeliveryMethod)
28 {
29 case self::METHOD_PHPMAIL:
30 # use PHPMailer to send multipart alternative messages because
31 # they can be tricky to construct properly
32 if ($this->HasAlternateBody())
33 {
34 $Result = $this->SendViaPhpMailerLib();
35 }
36
37 # otherwise, just use the built-in mail() function
38 else
39 {
40 $Result = $this->SendViaPhpMailFunc();
41 }
42 break;
43
44 case self::METHOD_SMTP:
45 $Result = $this->SendViaSmtp();
46 break;
47 }
48 return $Result;
49 }
50
51 /*@(*/
53
59 function Body($NewValue = NULL)
60 {
61 if ($NewValue !== NULL) { $this->Body = $NewValue; }
62 return $this->Body;
63 }
64
70 public function AlternateBody($NewValue = NULL)
71 {
72 # set the plain-text alternative if a parameter is given
73 if (func_num_args() > 0)
74 {
75 $this->AlternateBody = $NewValue;
76 }
77
78 return $this->AlternateBody;
79 }
80
86 function Subject($NewValue = NULL)
87 {
88 if ($NewValue !== NULL) { $this->Subject = $NewValue; }
89 return $this->Subject;
90 }
91
100 function From($NewAddress = NULL, $NewName = NULL)
101 {
102 if ($NewAddress !== NULL)
103 {
104 $NewAddress = trim($NewAddress);
105 if ($NewName !== NULL)
106 {
107 $NewName = trim($NewName);
108 $this->From = $NewName." <".$NewAddress.">";
109 }
110 else
111 {
112 $this->From = $NewAddress;
113 }
114 }
115 return $this->From;
116 }
117
124 static function DefaultFrom($NewValue = NULL)
125 {
126 if ($NewValue !== NULL) { self::$DefaultFrom = $NewValue; }
127 return self::$DefaultFrom;
128 }
129
138 function ReplyTo($NewAddress = NULL, $NewName = NULL)
139 {
140 if ($NewAddress !== NULL)
141 {
142 $NewAddress = trim($NewAddress);
143 if ($NewName !== NULL)
144 {
145 $NewName = trim($NewName);
146 $this->ReplyTo = $NewName." <".$NewAddress.">";
147 }
148 else
149 {
150 $this->ReplyTo = $NewAddress;
151 }
152 }
153 return $this->ReplyTo;
154 }
155
163 function To($NewValue = NULL)
164 {
165 if ($NewValue !== NULL)
166 {
167 if (!is_array($NewValue))
168 {
169 $this->To = array($NewValue);
170 }
171 else
172 {
173 $this->To = $NewValue;
174 }
175 }
176 return $this->To;
177 }
178
186 function CC($NewValue = NULL)
187 {
188 if ($NewValue !== NULL)
189 {
190 if (!is_array($NewValue))
191 {
192 $this->CC = array($NewValue);
193 }
194 else
195 {
196 $this->CC = $NewValue;
197 }
198 }
199 return $this->CC;
200 }
201
209 function BCC($NewValue = NULL)
210 {
211 if ($NewValue !== NULL)
212 {
213 if (!is_array($NewValue))
214 {
215 $this->BCC = array($NewValue);
216 }
217 else
218 {
219 $this->BCC = $NewValue;
220 }
221 }
222 return $this->BCC;
223 }
224
229 function AddHeaders($NewHeaders)
230 {
231 # add new headers to list
232 $this->Headers = array_merge($this->Headers, $NewHeaders);
233 }
234
241 public function CharSet($NewValue = NULL)
242 {
243 # set the plain-text alternative if a parameter is given
244 if (func_num_args() > 0)
245 {
246 $this->CharSet = $NewValue;
247 }
248
249 return $this->CharSet;
250 }
251
257 public static function LineEnding($NewValue = NULL)
258 {
259 if (!is_null($NewValue))
260 {
261 self::$LineEnding = $NewValue;
262 }
263
264 return self::$LineEnding;
265 }
266
279 public static function WrapHtmlAsNecessary($Html, $MaxLineLength=998, $LineEnding="\r\n")
280 {
281 # the regular expression used to find long lines
282 $LongLineRegExp = '/[^\r\n]{'.($MaxLineLength+1).',}/';
283
284 # find all lines that are too long
285 preg_match_all($LongLineRegExp, $Html, $Matches, PREG_PATTERN_ORDER|PREG_OFFSET_CAPTURE);
286
287 # no changes are necessary
288 if (!count($Matches))
289 {
290 return $Html;
291 }
292
293 # go backwards so that the HTML can be edited in place without messing
294 # with the offsets
295 for ($i = count($Matches[0]) - 1; $i >= 0; $i--)
296 {
297 # extract the line text and its offset within the string
298 list($Line, $Offset) = $Matches[0][$i];
299
300 # first try to get the line under the limit without being too
301 # aggressive
302 $BetterLine = self::ConvertHtmlWhiteSpace($Line, FALSE, $LineEnding);
303 $WasAggressive = "No";
304
305 # if the line is still too long, be more aggressive with replacing
306 # horizontal whitespace
307 if (preg_match($LongLineRegExp, $BetterLine))
308 {
309 $BetterLine = self::ConvertHtmlWhiteSpace($Line, TRUE, $LineEnding);
310 $WasAggressive = "Yes";
311 }
312
313 # tack on an HTML comment stating that the line was wrapped and give
314 # some additional info
315 $BetterLine = $LineEnding."<!-- Line was wrapped. Aggressive: "
316 .$WasAggressive.", Max: ".$MaxLineLength.", Actual: "
317 .strlen($Line)." -->".$LineEnding.$BetterLine;
318
319 # replace the line within the HTML
320 $Html = substr_replace($Html, $BetterLine, $Offset, strlen($Line));
321 }
322
323 return $Html;
324 }
325
333 public static function TestLineEndings($Value, $LineEnding)
334 {
335 # the number of \r in the string
336 $NumCR = substr_count($Value, "\r");
337
338 # LF
339 if ($LineEnding == "\n")
340 {
341 return $NumCR === 0;
342 }
343
344 # the number of \n in the string
345 $NumLF = substr_count($Value, "\n");
346
347 # CR
348 if ($LineEnding == "\r")
349 {
350 return $NumLF === 0;
351 }
352
353 # the number of \r\n in the string
354 $NumCRLF = substr_count($Value, "\r\n");
355
356 # CRLF. also check CRLF to make sure CR and LF appear together and in
357 # the correct order
358 return $NumCR === $NumLF && $NumLF === $NumCRLF;
359 }
360
366 public static function ConvertHtmlToPlainText($Html)
367 {
368 # remove newlines
369 $Text = str_replace(array("\r", "\n"), "", $Html);
370
371 # convert HTML breaks to newlines
372 $Text = preg_replace('/<br\s*\/?>/', "\n", $Text);
373
374 # strip remaining tags
375 $Text = strip_tags($Text);
376
377 # convert HTML entities to their plain-text equivalents
378 $Text = html_entity_decode($Text);
379
380 # single quotes aren't always handled
381 $Text = str_replace('&#39;', "'", $Text);
382
383 # remove HTML entities that have no equivalents
384 $Text = preg_replace('/&(#[0-9]{1,6}|[a-zA-Z0-9]{1,6});/', "", $Text);
385
386 # return the plain text version
387 return $Text;
388 }
389 /*@(*/
391
398 static function DeliveryMethod($NewValue = NULL)
399 {
400 if ($NewValue !== NULL)
401 {
402 self::$DeliveryMethod = $NewValue;
403 }
404 return self::$DeliveryMethod;
405 }
407 const METHOD_PHPMAIL = 1;
409 const METHOD_SMTP = 2;
410
416 static function Server($NewValue = NULL)
417 {
418 if ($NewValue !== NULL) { self::$Server = $NewValue; }
419 return self::$Server;
420 }
421
427 static function Port($NewValue = NULL)
428 {
429 if ($NewValue !== NULL) { self::$Port = $NewValue; }
430 return self::$Port;
431 }
432
438 static function UserName($NewValue = NULL)
439 {
440 if ($NewValue !== NULL) { self::$UserName = $NewValue; }
441 return self::$UserName;
442 }
443
449 static function Password($NewValue = NULL)
450 {
451 if ($NewValue !== NULL) { self::$Password = $NewValue; }
452 return self::$Password;
453 }
454
460 static function UseAuthentication($NewValue = NULL)
461 {
462 if ($NewValue !== NULL) { self::$UseAuthentication = $NewValue; }
463 return self::$UseAuthentication;
464 }
465
473 static function DeliverySettings($NewSettings = NULL)
474 {
475 if ($NewSettings !== NULL)
476 {
477 $Settings = unserialize($NewSettings);
478 self::$DeliveryMethod = $Settings["DeliveryMethod"];
479 self::$Server = $Settings["Server"];
480 self::$Port = $Settings["Port"];
481 self::$UserName = $Settings["UserName"];
482 self::$Password = $Settings["Password"];
483 self::$UseAuthentication = $Settings["UseAuthentication"];
484 }
485 else
486 {
487 $Settings["DeliveryMethod"] = self::$DeliveryMethod;
488 $Settings["Server"] = self::$Server;
489 $Settings["Port"] = self::$Port;
490 $Settings["UserName"] = self::$UserName;
491 $Settings["Password"] = self::$Password;
492 $Settings["UseAuthentication"] = self::$UseAuthentication;
493 }
494 return serialize($Settings);
495 }
496
505 static function DeliverySettingsOkay()
506 {
507 # start out with error list clear
508 self::$DeliverySettingErrorList = array();
509
510 # test based on delivery method
511 switch (self::$DeliveryMethod)
512 {
513 case self::METHOD_PHPMAIL:
514 # always report success
515 $SettingsOkay = TRUE;
516 break;
517
518 case self::METHOD_SMTP:
519 # set up PHPMailer for test
520 $PMail = new PHPMailer(TRUE);
521 $PMail->IsSMTP();
522 $PMail->SMTPAuth = self::$UseAuthentication;
523 $PMail->Host = self::$Server;
524 $PMail->Port = self::$Port;
525 $PMail->Username = self::$UserName;
526 $PMail->Password = self::$Password;
527
528 # test settings
529 try
530 {
531 $SettingsOkay = $PMail->SmtpConnect();
532 }
533 # if test failed
534 catch (phpmailerException $Except)
535 {
536 # translate PHPMailer error message to possibly bad settings
537 switch ($Except->getMessage())
538 {
539 case 'SMTP Error: Could not authenticate.':
540 self::$DeliverySettingErrorList = array(
541 "UseAuthentication",
542 "UserName",
543 "Password",
544 );
545 break;
546
547 case 'SMTP Error: Could not connect to SMTP host.':
548 self::$DeliverySettingErrorList = array(
549 "Server",
550 "Port",
551 );
552 break;
553
554 case 'Language string failed to load: tls':
555 self::$DeliverySettingErrorList = array("TLS");
556 break;
557
558 default:
559 self::$DeliverySettingErrorList = array("UNKNOWN");
560 break;
561 }
562
563 # make sure failure is reported
564 $SettingsOkay = FALSE;
565 }
566 break;
567 }
568
569 # report result to caller
570 return $SettingsOkay;
571 }
572
577 static function DeliverySettingErrors()
578 {
579 return self::$DeliverySettingErrorList;
580 }
581
582
583 # ---- PRIVATE INTERFACE -------------------------------------------------
584
585 private $From = "";
586 private $ReplyTo = "";
587 private $To = array();
588 private $CC = array();
589 private $BCC = array();
590 private $Body = "";
591 private $AlternateBody = "";
592 private $Subject = "";
593 private $Headers = array();
594 private $CharSet;
595 private static $LineEnding = "\r\n";
596 private static $DefaultFrom = "";
597
598 private static $DeliveryMethod = self::METHOD_PHPMAIL;
599 private static $DeliverySettingErrorList = array();
600 private static $Server;
601 private static $Port = 25;
602 private static $UserName = "";
603 private static $Password = "";
604 private static $UseAuthentication = FALSE;
605
610 private function SendViaPhpMailFunc()
611 {
612 # make lines using the line ending variable a bit shorter
613 $LE = self::$LineEnding;
614
615 # build basic headers list
616 $From = strlen($this->From) ? $this->From : self::$DefaultFrom;
617 $Headers = "From: ".self::CleanHeaderValue($From).$LE;
618 $Headers .= $this->BuildAddresseeLine("Cc", $this->CC);
619 $Headers .= $this->BuildAddresseeLine("Bcc", $this->BCC);
620 $Headers .= "Reply-To: ".self::CleanHeaderValue(
621 strlen($this->ReplyTo) ? $this->ReplyTo : $this->From).$LE;
622
623 # add additional headers
624 foreach ($this->Headers as $ExtraHeader)
625 {
626 $Headers .= $ExtraHeader.$LE;
627 }
628
629 # build recipient list
630 $To = "";
631 $Separator = "";
632 foreach ($this->To as $Recipient)
633 {
634 $To .= $Separator.$Recipient;
635 $Separator = ", ";
636 }
637
638 # normalize message body line endings
639 $Body = $this->NormalizeLineEndings($this->Body, $LE);
640
641 # send message
642 $Result = mail($To, $this->Subject, $Body, $Headers);
643
644 # report to caller whether attempt to send succeeded
645 return $Result;
646 }
647
653 private function SendViaPhpMailerLib()
654 {
655 # create and initialize PHPMailer
656 $PMail = new PHPMailer();
657 $PMail->LE = self::$LineEnding;
658 $PMail->Subject = $this->Subject;
659 $PMail->Body = $this->Body;
660 $PMail->IsHTML(FALSE);
661
662 # default values for the sender's name and address
663 $Name = "";
664 $Address = $this->From;
665
666 # if the address contains a name and address, they need to extracted
667 # because PHPMailer requires that they are set as two different
668 # parameters
669 if (preg_match("/ </", $this->From))
670 {
671 $Pieces = explode(" ", $this->From);
672 $Address = array_pop($Pieces);
673 $Address = preg_replace("/[<>]+/", "", $Address);
674 $Name = trim(implode($Pieces, " "));
675 }
676
677 # add the sender
678 $PMail->SetFrom($Address, $Name);
679
680 # add each recipient
681 foreach ($this->To as $Recipient)
682 {
683 $PMail->AddAddress($Recipient);
684 }
685
686 # add any extra header lines
687 foreach ($this->Headers as $ExtraHeader)
688 {
689 $PMail->AddCustomHeader($ExtraHeader);
690 }
691
692 # add the charset if it's set
693 if (isset($this->CharSet))
694 {
695 $PMail->CharSet = strtolower($this->CharSet);
696 }
697
698 # add the alternate plain-text body if it's set
699 if ($this->HasAlternateBody())
700 {
701 $PMail->AltBody = $this->AlternateBody;
702 }
703
704 # set up SMTP if necessary
705 if (self::$DeliveryMethod == self::METHOD_SMTP)
706 {
707 $PMail->IsSMTP();
708 $PMail->SMTPAuth = self::$UseAuthentication;
709 $PMail->Host = self::$Server;
710 $PMail->Port = self::$Port;
711 $PMail->Username = self::$UserName;
712 $PMail->Password = self::$Password;
713 }
714
715 # send message
716 $Result = $PMail->Send();
717
718 # report to caller whether attempt to send succeeded
719 return $Result;
720 }
721
726 private function SendViaSmtp()
727 {
728 # send via PHPMailer because it's capable of handling SMTP
729 return $this->SendViaPhpMailerLib();
730 }
731
738 private function BuildAddresseeLine($Label, $Recipients)
739 {
740 $Line = "";
741 if (count($Recipients))
742 {
743 $Line .= $Label.": ";
744 $Separator = "";
745 foreach ($Recipients as $Recipient)
746 {
747 $Line .= $Separator.self::CleanHeaderValue($Recipient);
748 $Separator = ", ";
749 }
750 $Line .= self::$LineEnding;
751 }
752 return $Line;
753 }
754
759 private function HasAlternateBody()
760 {
761 return isset($this->AlternateBody) && strlen(trim($this->AlternateBody)) > 0;
762 }
763
769 private static function CleanHeaderValue($Value)
770 {
771 # (regular expression taken from sanitizeHeaders() function in
772 # Mail PEAR package)
773 return preg_replace('=((<CR>|<LF>|0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i',
774 "", $Value);
775 }
776
783 private static function NormalizeLineEndings($Value, $LineEnding)
784 {
785 return preg_replace('/\r\n|\r|\n/', $LineEnding, $Value);
786 }
787
802 protected static function ConvertHtmlWhiteSpace($Html, $Aggressive=FALSE, $LineEnding="\r\n")
803 {
804 $HtmlLength = strlen($Html);
805
806 # tags that should have their inner HTML left alone
807 $IgnoredTags = array('script', 'style', 'textarea', 'title');
808
809 # values for determining context
810 $InTag = FALSE;
811 $InClosingTag = FALSE;
812 $InIgnoredTag = FALSE;
813 $InAttribute = FALSE;
814 $TagName = NULL;
815 $IgnoredTagName = NULL;
816 $AttributeDelimiter = NULL;
817
818 # loop through each character of the string
819 for ($i = 0; $i < $HtmlLength; $i++)
820 {
821 $Char = $Html{$i};
822
823 # beginning of a tag
824 if ($Char == "<" && !$InTag)
825 {
826 $InTag = TRUE;
827 $InAttribute = FALSE;
828 $AttributeDelimiter = NULL;
829
830 # do some lookaheads to get the tag name and to see if the tag
831 # is a closing tag
832 list($InClosingTag, $TagName) = self::GetTagInfo($Html, $i);
833
834 # moving into an ignored tag
835 if (!$InClosingTag && in_array($TagName, $IgnoredTags))
836 {
837 $InIgnoredTag = TRUE;
838 $IgnoredTagName = $TagName;
839 }
840
841 continue;
842 }
843
844 # end of a tag
845 if ($Char == ">" && $InTag && !$InAttribute)
846 {
847 # moving out of an ignored tag
848 if ($InClosingTag && $InIgnoredTag && $TagName == $IgnoredTagName)
849 {
850 $InIgnoredTag = FALSE;
851 $IgnoredTagName = NULL;
852 }
853
854 $InTag = FALSE;
855 $InClosingTag = FALSE;
856 $InAttribute = FALSE;
857 $TagName = NULL;
858 $AttributeDelimiter = NULL;
859
860 continue;
861 }
862
863 # attribute delimiter characters
864 if ($Char == "'" || $Char == '"')
865 {
866 # beginning of an attribute
867 if (!$InAttribute)
868 {
869 $InAttribute = TRUE;
870 $AttributeDelimiter = $Char;
871 continue;
872 }
873
874 # end of the attribute
875 if ($InAttribute && $Char == $AttributeDelimiter)
876 {
877 $InAttribute = FALSE;
878 $AttributeDelimiter = NULL;
879 continue;
880 }
881 }
882
883 # whitespace inside of a tag but outside of an attribute can be
884 # safely converted to a newline
885 if ($InTag && !$InAttribute && preg_match('/\s/', $Char))
886 {
887 $Html{$i} = $LineEnding;
888 continue;
889 }
890
891 # whitespace outside of a tag can be safely converted to a newline
892 # when not in one of the ignored tags, but only do so if horizontal
893 # space is at a premium because it can make the resulting HTML
894 # difficult to read
895 if ($Aggressive && !$InTag && !$InIgnoredTag && preg_match('/\s/', $Char))
896 {
897 $Html{$i} = $LineEnding;
898 continue;
899 }
900 }
901
902 return $Html;
903 }
904
913 protected static function GetTagInfo($Html, $TagBegin)
914 {
915 $HtmlLength = strlen($Html);
916
917 # default return values
918 $InClosingTag = FALSE;
919 $TagName = NULL;
920
921 # if at the end of the string and lookaheads aren't possible
922 if ($TagBegin + 1 >= $HtmlLength)
923 {
924 return array($InClosingTag, $TagName);
925 }
926
927 # do a lookahead for whether it's a closing tag
928 if ($Html{$TagBegin+1} == "/")
929 {
930 $InClosingTag = TRUE;
931 }
932
933 # determine whether to offset by one or two to get the tag name
934 $TagStart = $InClosingTag ? $TagBegin + 2 : $TagBegin + 1;
935
936 # do a lookahead for the tag name
937 for ($i = $TagStart; $i < $HtmlLength; $i++)
938 {
939 $Char = $Html{$i};
940
941 # stop getting the tag name if whitespace is found and something is
942 # available for the tag name
943 if (strlen($TagName) && preg_match('/[\r\n\s]/', $Char))
944 {
945 break;
946 }
947
948 # stop getting the tag name if the character is >
949 if ($Char == ">")
950 {
951 break;
952 }
953
954 $TagName .= $Char;
955 }
956
957 # comment "tag"
958 if (substr($TagName, 0, 3) == "!--")
959 {
960 return array($InClosingTag, "!--");
961 }
962
963 # remove characters that aren't part of a valid tag name
964 $TagName = preg_replace('/[^a-zA-Z0-9]/', '', $TagName);
965
966 return array($InClosingTag, $TagName);
967 }
968
969 }
Email\From
From($NewAddress=NULL, $NewName=NULL)
Get/set message sender.
Definition: Email.php:100
Email\Server
static Server($NewValue=NULL)
Get/set server for mail delivery.
Definition: Email.php:416
Email\DeliveryMethod
static DeliveryMethod($NewValue=NULL)
Get/set mail delivery method.
Definition: Email.php:398
Email\WrapHtmlAsNecessary
static WrapHtmlAsNecessary($Html, $MaxLineLength=998, $LineEnding="\r\n")
Wrap HTML in an e-mail as necessary to get its lines less than some max length.
Definition: Email.php:279
Email\To
To($NewValue=NULL)
Get/set message recipient(s).
Definition: Email.php:163
Email\DeliverySettings
static DeliverySettings($NewSettings=NULL)
Get/set serialized (opaque text) version of delivery settings.
Definition: Email.php:473
Email\ReplyTo
ReplyTo($NewAddress=NULL, $NewName=NULL)
Get/set message &quot;Reply-To&quot; address.
Definition: Email.php:138
Email\DeliverySettingsOkay
static DeliverySettingsOkay()
Test delivery settings and report their validity.
Definition: Email.php:505
Email\LineEnding
static LineEnding($NewValue=NULL)
Specify the character sequence that should be used to end lines.
Definition: Email.php:257
Email\DeliverySettingErrors
static DeliverySettingErrors()
Return array with list of delivery setting errors (if any).
Definition: Email.php:577
Email\CharSet
CharSet($NewValue=NULL)
Specify a character encoding for the message.
Definition: Email.php:241
Email
Electronic mail message.
Definition: Email.php:14
Email\DefaultFrom
static DefaultFrom($NewValue=NULL)
Get/set default &quot;From&quot; address.
Definition: Email.php:124
Email\GetTagInfo
static GetTagInfo($Html, $TagBegin)
Get the tag name and whether it&#39;s a closing tag from a tag that begins at a specific offset within so...
Definition: Email.php:913
Email\Send
Send()
Mail the message.
Definition: Email.php:25
PHP
PHP
Definition: OAIClient.php:39
Email\AddHeaders
AddHeaders($NewHeaders)
Specify additional message headers to be included.
Definition: Email.php:229
Email\METHOD_PHPMAIL
const METHOD_PHPMAIL
Deliver using PHP&#39;s internal mail() mechanism.
Definition: Email.php:407
Email\BCC
BCC($NewValue=NULL)
Get/set message BCC list.
Definition: Email.php:209
Email\Body
Body($NewValue=NULL)
Get/set message body.
Definition: Email.php:59
Email\Port
static Port($NewValue=NULL)
Get/set port number for mail delivery.
Definition: Email.php:427
Email\UserName
static UserName($NewValue=NULL)
Get/set user name for mail delivery.
Definition: Email.php:438
Email\AlternateBody
AlternateBody($NewValue=NULL)
Get/set the plain-text alternative to the body.
Definition: Email.php:70
Email\Subject
Subject($NewValue=NULL)
Get/set message subject.
Definition: Email.php:86
Email\METHOD_SMTP
const METHOD_SMTP
Deliver using SMTP.
Definition: Email.php:409
Email\Password
static Password($NewValue=NULL)
Get/set password for mail delivery.
Definition: Email.php:449
Email\ConvertHtmlToPlainText
static ConvertHtmlToPlainText($Html)
Try as best as possible to convert HTML to plain text.
Definition: Email.php:366
Email\UseAuthentication
static UseAuthentication($NewValue=NULL)
Get/set whether to use authentication for mail delivery.
Definition: Email.php:460
Email\TestLineEndings
static TestLineEndings($Value, $LineEnding)
Test the line endings in a value to see if they all match the given line ending.
Definition: Email.php:333
Email\CC
CC($NewValue=NULL)
Get/set message CC list.
Definition: Email.php:186
Email\ConvertHtmlWhiteSpace
static ConvertHtmlWhiteSpace($Html, $Aggressive=FALSE, $LineEnding="\r\n")
Convert horizontal white space with no semantic value to vertical white space when possible...
Definition: Email.php:802