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 # Contrary to the PHP documentation, line endings for PHP's
613 # mail function should be the system native line endings.
614 #
615 # see https://bugs.php.net/bug.php?id=15841 for details
616
617 # Use the system line endings
618 $LE = PHP_EOL;
619
620 # build basic headers list
621 $From = strlen($this->From) ? $this->From : self::$DefaultFrom;
622 $Headers = "From: ".self::CleanHeaderValue($From).$LE;
623 $Headers .= $this->BuildAddresseeLine("Cc", $this->CC);
624 $Headers .= $this->BuildAddresseeLine("Bcc", $this->BCC);
625 $Headers .= "Reply-To: ".self::CleanHeaderValue(
626 strlen($this->ReplyTo) ? $this->ReplyTo : $this->From).$LE;
627
628 # add additional headers
629 foreach ($this->Headers as $ExtraHeader)
630 {
631 $Headers .= $ExtraHeader.$LE;
632 }
633
634 # build recipient list
635 $To = "";
636 $Separator = "";
637 foreach ($this->To as $Recipient)
638 {
639 $To .= $Separator.$Recipient;
640 $Separator = ", ";
641 }
642
643 # normalize message body line endings
644 $Body = $this->NormalizeLineEndings($this->Body, $LE);
645
646 # send message
647 $Result = mail($To, $this->Subject, $Body, $Headers);
648
649 # report to caller whether attempt to send succeeded
650 return $Result;
651 }
652
658 private function SendViaPhpMailerLib()
659 {
660 # create and initialize PHPMailer
661 $PMail = new PHPMailer();
662 $PMail->LE = self::$LineEnding;
663 $PMail->Subject = $this->Subject;
664 $PMail->Body = $this->Body;
665 $PMail->IsHTML(FALSE);
666
667 # default values for the sender's name and address
668 $Name = "";
669 $Address = $this->From;
670
671 # if the address contains a name and address, they need to extracted
672 # because PHPMailer requires that they are set as two different
673 # parameters
674 if (preg_match("/ </", $this->From))
675 {
676 $Pieces = explode(" ", $this->From);
677 $Address = array_pop($Pieces);
678 $Address = preg_replace("/[<>]+/", "", $Address);
679 $Name = trim(implode($Pieces, " "));
680 }
681
682 # add the sender
683 $PMail->SetFrom($Address, $Name);
684
685 # add each recipient
686 foreach ($this->To as $Recipient)
687 {
688 $PMail->AddAddress($Recipient);
689 }
690
691 # add any extra header lines
692 foreach ($this->Headers as $ExtraHeader)
693 {
694 $PMail->AddCustomHeader($ExtraHeader);
695 }
696
697 # add the charset if it's set
698 if (isset($this->CharSet))
699 {
700 $PMail->CharSet = strtolower($this->CharSet);
701 }
702
703 # add the alternate plain-text body if it's set
704 if ($this->HasAlternateBody())
705 {
706 $PMail->AltBody = $this->AlternateBody;
707 }
708
709 # set up SMTP if necessary
710 if (self::$DeliveryMethod == self::METHOD_SMTP)
711 {
712 $PMail->IsSMTP();
713 $PMail->SMTPAuth = self::$UseAuthentication;
714 $PMail->Host = self::$Server;
715 $PMail->Port = self::$Port;
716 $PMail->Username = self::$UserName;
717 $PMail->Password = self::$Password;
718 }
719
720 # send message
721 $Result = $PMail->Send();
722
723 # report to caller whether attempt to send succeeded
724 return $Result;
725 }
726
731 private function SendViaSmtp()
732 {
733 # send via PHPMailer because it's capable of handling SMTP
734 return $this->SendViaPhpMailerLib();
735 }
736
743 private function BuildAddresseeLine($Label, $Recipients)
744 {
745 $Line = "";
746 if (count($Recipients))
747 {
748 $Line .= $Label.": ";
749 $Separator = "";
750 foreach ($Recipients as $Recipient)
751 {
752 $Line .= $Separator.self::CleanHeaderValue($Recipient);
753 $Separator = ", ";
754 }
755 $Line .= self::$LineEnding;
756 }
757 return $Line;
758 }
759
764 private function HasAlternateBody()
765 {
766 return isset($this->AlternateBody) && strlen(trim($this->AlternateBody)) > 0;
767 }
768
774 private static function CleanHeaderValue($Value)
775 {
776 # (regular expression taken from sanitizeHeaders() function in
777 # Mail PEAR package)
778 return preg_replace('=((<CR>|<LF>|0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i',
779 "", $Value);
780 }
781
788 private static function NormalizeLineEndings($Value, $LineEnding)
789 {
790 return preg_replace('/\r\n|\r|\n/', $LineEnding, $Value);
791 }
792
807 protected static function ConvertHtmlWhiteSpace($Html, $Aggressive=FALSE, $LineEnding="\r\n")
808 {
809 $HtmlLength = strlen($Html);
810
811 # tags that should have their inner HTML left alone
812 $IgnoredTags = array('script', 'style', 'textarea', 'title');
813
814 # values for determining context
815 $InTag = FALSE;
816 $InClosingTag = FALSE;
817 $InIgnoredTag = FALSE;
818 $InAttribute = FALSE;
819 $TagName = NULL;
820 $IgnoredTagName = NULL;
821 $AttributeDelimiter = NULL;
822
823 # loop through each character of the string
824 for ($i = 0; $i < $HtmlLength; $i++)
825 {
826 $Char = $Html{$i};
827
828 # beginning of a tag
829 if ($Char == "<" && !$InTag)
830 {
831 $InTag = TRUE;
832 $InAttribute = FALSE;
833 $AttributeDelimiter = NULL;
834
835 # do some lookaheads to get the tag name and to see if the tag
836 # is a closing tag
837 list($InClosingTag, $TagName) = self::GetTagInfo($Html, $i);
838
839 # moving into an ignored tag
840 if (!$InClosingTag && in_array($TagName, $IgnoredTags))
841 {
842 $InIgnoredTag = TRUE;
843 $IgnoredTagName = $TagName;
844 }
845
846 continue;
847 }
848
849 # end of a tag
850 if ($Char == ">" && $InTag && !$InAttribute)
851 {
852 # moving out of an ignored tag
853 if ($InClosingTag && $InIgnoredTag && $TagName == $IgnoredTagName)
854 {
855 $InIgnoredTag = FALSE;
856 $IgnoredTagName = NULL;
857 }
858
859 $InTag = FALSE;
860 $InClosingTag = FALSE;
861 $InAttribute = FALSE;
862 $TagName = NULL;
863 $AttributeDelimiter = NULL;
864
865 continue;
866 }
867
868 # attribute delimiter characters
869 if ($Char == "'" || $Char == '"')
870 {
871 # beginning of an attribute
872 if (!$InAttribute)
873 {
874 $InAttribute = TRUE;
875 $AttributeDelimiter = $Char;
876 continue;
877 }
878
879 # end of the attribute
880 if ($InAttribute && $Char == $AttributeDelimiter)
881 {
882 $InAttribute = FALSE;
883 $AttributeDelimiter = NULL;
884 continue;
885 }
886 }
887
888 # whitespace inside of a tag but outside of an attribute can be
889 # safely converted to a newline
890 if ($InTag && !$InAttribute && preg_match('/\s/', $Char))
891 {
892 $Html{$i} = $LineEnding;
893 continue;
894 }
895
896 # whitespace outside of a tag can be safely converted to a newline
897 # when not in one of the ignored tags, but only do so if horizontal
898 # space is at a premium because it can make the resulting HTML
899 # difficult to read
900 if ($Aggressive && !$InTag && !$InIgnoredTag && preg_match('/\s/', $Char))
901 {
902 $Html{$i} = $LineEnding;
903 continue;
904 }
905 }
906
907 return $Html;
908 }
909
918 protected static function GetTagInfo($Html, $TagBegin)
919 {
920 $HtmlLength = strlen($Html);
921
922 # default return values
923 $InClosingTag = FALSE;
924 $TagName = NULL;
925
926 # if at the end of the string and lookaheads aren't possible
927 if ($TagBegin + 1 >= $HtmlLength)
928 {
929 return array($InClosingTag, $TagName);
930 }
931
932 # do a lookahead for whether it's a closing tag
933 if ($Html{$TagBegin+1} == "/")
934 {
935 $InClosingTag = TRUE;
936 }
937
938 # determine whether to offset by one or two to get the tag name
939 $TagStart = $InClosingTag ? $TagBegin + 2 : $TagBegin + 1;
940
941 # do a lookahead for the tag name
942 for ($i = $TagStart; $i < $HtmlLength; $i++)
943 {
944 $Char = $Html{$i};
945
946 # stop getting the tag name if whitespace is found and something is
947 # available for the tag name
948 if (strlen($TagName) && preg_match('/[\r\n\s]/', $Char))
949 {
950 break;
951 }
952
953 # stop getting the tag name if the character is >
954 if ($Char == ">")
955 {
956 break;
957 }
958
959 $TagName .= $Char;
960 }
961
962 # comment "tag"
963 if (substr($TagName, 0, 3) == "!--")
964 {
965 return array($InClosingTag, "!--");
966 }
967
968 # remove characters that aren't part of a valid tag name
969 $TagName = preg_replace('/[^a-zA-Z0-9]/', '', $TagName);
970
971 return array($InClosingTag, $TagName);
972 }
973
974 }
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 "Reply-To" 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 "From" address.
Definition: Email.php:124
Email\GetTagInfo
static GetTagInfo($Html, $TagBegin)
Get the tag name and whether it's a closing tag from a tag that begins at a specific offset within so...
Definition: Email.php:918
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'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:807