dolibarr 22.0.5
smtps.class.php
Go to the documentation of this file.
1<?php
2/*
3 * Copyright (C) Walter Torres <walter@torres.ws> [with a *lot* of help!]
4 * Copyright (C) 2005-2015 Laurent Destailleur <eldy@users.sourceforge.net>
5 * Copyright (C) 2006-2011 Regis Houssin
6 * Copyright (C) 2016 Jonathan TISSEAU <jonathan.tisseau@86dev.fr>
7 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
8 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
48class SMTPs
49{
53 private $_smtpsHost = 'localhost';
54
61 private $_smtpsPort = 25;
62
67 private $_smtpsID = null;
68
73 private $_smtpsPW = null;
74
78 private $_smtpsToken = null;
79
83 private $_msgId = null;
84
89 private $_msgFrom = null;
90
95 private $_msgReplyTo = null;
96
100 private $_msgInReplyTo = null;
101
105 private $_msgReferences = null;
106
112 private $_msgRecipients = null;
113
117 private $_msgSubject = null;
118
124 private $_msgContent = array();
125
129 private $_msgXheader = array();
130
136 private $_smtpsCharSet = 'iso-8859-1';
137
143 private $_msgSensitivity = 0;
144
148 private $_arySensitivity = array(false,
149 'Personal',
150 'Private',
151 'Company Confidential');
152
157 private $_msgPriority = 3;
158
162 private $_aryPriority = array('Bulk',
163 'Highest',
164 'High',
165 'Normal',
166 'Low',
167 'Lowest');
168
173 private $_smtpsTransEncodeType = 0;
174
178 private $_smtpsTransEncodeTypes = array('7bit', // Simple 7-bit ASCII
179 '8bit', // 8-bit coding with line termination characters
180 'base64', // 3 octets encoded into 4 sextets with offset
181 'binary', // Arbitrary binary stream
182 'mac-binhex40', // Macintosh binary to hex encoding
183 'quoted-printable', // Mostly 7-bit, with 8-bit characters encoded as "=HH"
184 'uuencode'); // UUENCODE encoding
185
191 private $_smtpsTransEncode = '7bit';
192
196 private $_smtpsBoundary = null;
197
201 private $_smtpsRelatedBoundary = null;
202
206 private $_smtpsAlternativeBoundary = null;
207
216 private $_transportType = 0;
217
222 private $_mailPath = '/usr/lib/sendmail'; // @phpstan-ignore-line
223
227 private $_smtpTimeout = 10;
228
232 private $_smtpMD5 = false;
233
237 private $_smtpsErrors = array();
238
246 private $_log_level = 0; // @phpstan-ignore-line
247
251 private $_debug = false;
252
253
254 // @CHANGE LDR
258 public $log = '';
262 public $lastretval = '';
263
267 public $socket;
268
272 public $errno;
273
277 public $errstr;
278
282 private $_errorsTo = array();
286 private $_deliveryReceipt = 0;
290 private $_trackId = '';
294 private $_moreinheader = '';
295
299 private $_options = array();
300
301
308 public function setMessageID($_msgId = '')
309 {
310 $this->_msgId = $_msgId;
311 }
312
319 public function setOptions($_options = array())
320 {
321 $this->_options = $_options;
322 }
323
330 public function setDeliveryReceipt($_val = 0)
331 {
332 $this->_deliveryReceipt = $_val;
333 }
334
340 public function getDeliveryReceipt()
341 {
342 return $this->_deliveryReceipt;
343 }
344
351 public function setSMTPTimeout($timeout)
352 {
353 $this->_smtpTimeout = $timeout;
354 }
355
361 public function getSMTPTimeout()
362 {
363 return $this->_smtpTimeout;
364 }
365
372 public function setTrackId($_val = '')
373 {
374 $this->_trackId = $_val;
375 }
376
383 public function setMoreInHeader($_val = '')
384 {
385 $this->_moreinheader = $_val;
386 }
387
393 public function getTrackId()
394 {
395 return $this->_trackId;
396 }
397
403 public function getMoreInHeader()
404 {
405 return $this->_moreinheader;
406 }
407
414 public function setErrorsTo($_strErrorsTo)
415 {
416 if ($_strErrorsTo) {
417 $this->_errorsTo = $this->_strip_email($_strErrorsTo);
418 }
419 }
420
427 public function getErrorsTo($_part = true)
428 {
429 $_retValue = '';
430
431 if ($_part === true || !array_key_exists($_part, $this->_errorsTo)) {
432 $_retValue = $this->_errorsTo;
433 } else {
434 $_retValue = $this->_errorsTo[$_part];
435 }
436
437 return $_retValue;
438 }
439
446 public function setDebug($_vDebug = false)
447 {
448 $this->_debug = $_vDebug;
449 }
450
456 public function buildRCPTlist()
457 {
458 // Pull TO list
459 $_aryToList = $this->getTo();
460 }
461
462 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
468 private function _server_connect()
469 {
470 // phpcs:enable
471 // Default return value
472 $_retVal = true;
473
474 // We have to make sure the HOST given is valid
475 // This is done here because '@fsockopen' will not give me this
476 // information if it fails to connect because it can't find the HOST
477 $host = $this->getHost();
478 $usetls = preg_match('@tls://@i', $host);
479
480 $host = preg_replace('@tcp://@i', '', $host); // Remove prefix
481 $host = preg_replace('@ssl://@i', '', $host); // Remove prefix
482 $host = preg_replace('@tls://@i', '', $host); // Remove prefix
483
484 // @CHANGE LDR
485 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
486
487 if ((!is_ip($host)) && ((gethostbyname($host)) == $host)) {
488 $this->_setErr(99, $host.' is either offline or is an invalid host name.');
489 $_retVal = false;
490 } else {
491 if (function_exists('stream_socket_client') && !empty($this->_options)) {
492 $socket_context = stream_context_create($this->_options); // An array of options for stream_context_create()
493 $this->socket = @stream_socket_client(
494 preg_replace('@tls://@i', '', $this->getHost()).// Host to 'hit', IP or domain
495 ':'.$this->getPort(), // which Port number to use
496 $this->errno, // actual system level error
497 $this->errstr, // and any text that goes with the error
498 $this->_smtpTimeout, // timeout for reading/writing data over the socket
499 STREAM_CLIENT_CONNECT,
500 $socket_context // Options for connection
501 );
502 } else {
503 $this->socket = @fsockopen(
504 preg_replace('@tls://@i', '', $this->getHost()), // Host to 'hit', IP or domain
505 $this->getPort(), // which Port number to use
506 $this->errno, // actual system level error
507 $this->errstr, // and any text that goes with the error
508 $this->_smtpTimeout // timeout for reading/writing data over the socket
509 );
510 }
511
512 //See if we can connect to the SMTP server
513 if (is_resource($this->socket)) {
514 // Fix from PHP SMTP class by 'Chris Ryan'
515 // Sometimes the SMTP server takes a little longer to respond
516 // so we will give it a longer timeout for the first read
517 // Windows still does not have support for this timeout function
518 if (function_exists('stream_set_timeout')) {
519 stream_set_timeout($this->socket, $this->_smtpTimeout, 0);
520 }
521
522 // Check response from Server
523 if ($_retVal = $this->server_parse($this->socket, "220")) {
524 $_retVal = $this->socket;
525 }
526 } else {
527 // This connection attempt failed.
528 // @CHANGE LDR
529 if (empty($this->errstr)) {
530 $this->errstr = 'Failed to connect with stream_context_create or fsockopen host='.$this->getHost().' port='.$this->getPort();
531 }
532 $this->_setErr($this->errno, $this->errstr);
533 $_retVal = false;
534 }
535 }
536
537 return $_retVal;
538 }
539
540 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
546 private function _server_authenticate()
547 {
548 // phpcs:enable
549 global $conf;
550
551 require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
552 // Send the RFC2554 specified EHLO.
553 // This improvement as provided by 'SirSir' to
554 // accommodate both SMTP AND ESMTP capable servers
555 $host = $this->getHost();
556 $usetls = preg_match('@tls://@i', $host);
557
558 $host = preg_replace('@tcp://@i', '', $host); // Remove prefix
559 $host = preg_replace('@ssl://@i', '', $host); // Remove prefix
560 $host = preg_replace('@tls://@i', '', $host); // Remove prefix
561
562 if ($usetls && getDolGlobalString('MAIN_SMTPS_ADD_TLS_TO_HOST_FOR_HELO')) {
563 $host = 'tls://'.$host;
564 }
565
566 $hosth = $host; // so for example 'localhost' or 'smtp-relay.gmail.com'
567
568 if (getDolGlobalString('MAIL_SMTP_USE_FROM_FOR_HELO')) { // Note that default value is forced to MAIL_SMTP_USE_FROM_FOR_HELO=2 if not set
569 if (!is_numeric(getDolGlobalString('MAIL_SMTP_USE_FROM_FOR_HELO'))) {
570 // If value of MAIL_SMTP_USE_FROM_FOR_HELO is a string, we use it as domain name
571 $hosth = getDolGlobalString('MAIL_SMTP_USE_FROM_FOR_HELO');
572 } elseif (getDolGlobalInt('MAIL_SMTP_USE_FROM_FOR_HELO') == 1) {
573 // If value of MAIL_SMTP_USE_FROM_FOR_HELO is 1, we use the domain in the from.
574 // So if the from to is 'aaa <bbb@ccc.com>', we will keep 'ccc.com'
575 $hosth = (string) $this->getFrom('addr');
576 $hosth = preg_replace('/^.*</', '', $hosth);
577 $hosth = preg_replace('/>.*$/', '', $hosth);
578 $hosth = preg_replace('/.*@/', '', $hosth);
579 } elseif (getDolGlobalInt('MAIL_SMTP_USE_FROM_FOR_HELO') == 2) {
580 // If value of MAIL_SMTP_USE_FROM_FOR_HELO is 2, we use the domain in the $dolibarr_main_url_root.
583 }
584 }
585
586 if ($_retVal = $this->socket_send_str('EHLO '.$hosth, '250')) {
587 if ($usetls) {
588 /*
589 The following dialog illustrates how a client and server can start a TLS STARTTLS session:
590 S: <waits for connection on TCP port 25>
591 C: <opens connection>
592 S: 220 mail.imc.org SMTP service ready
593 C: EHLO mail.ietf.org
594 S: 250-mail.imc.org offers a warm hug of welcome
595 S: 250 STARTTLS
596 C: STARTTLS
597 S: 220 Go ahead
598 C: <starts TLS negotiation>
599 C & S: <negotiate a TLS session>
600 C & S: <check result of negotiation>
601 // Second pass EHLO
602 C: EHLO client-domain.com
603 S: 250-server-domain.com
604 S: 250 AUTH LOGIN
605 C: <continues by sending an SMTP command
606
607 Another example here:
608 S: 220 smtp.server.com Simple Mail Transfer Service Ready
609 C: EHLO client.example.com
610 S: 250-smtp.server.com Hello client.example.com
611 S: 250-SIZE 1000000
612 S: 250-AUTH LOGIN PLAIN CRAM-MD5
613 S: 250-STARTTLS
614 S: 250 HELP
615 C: STARTTLS
616 S: 220 TLS go ahead
617 C: EHLO client.example.com *
618 S: 250-smtp.server.com Hello client.example.com
619 S: 250-SIZE 1000000
620 S: 250-AUTH LOGIN PLAIN CRAM-MD5
621 S: 250 HELP
622 C: AUTH LOGIN
623 S: 334 VXNlcm5hbWU6
624 C: adlxdkej
625 S: 334 UGFzc3dvcmQ6
626 C: lkujsefxlj
627 S: 235 2.7.0 Authentication successful
628 C: MAIL FROM:<mail@samlogic.com>
629 S: 250 OK
630 C: RCPT TO:<john@mail.com>
631 S: 250 OK
632 C: DATA
633 S: 354 Send message, end with a "." on a line by itself
634 C: <The message data (body text, subject, e-mail header, attachments etc) is sent>
635 S .
636 S: 250 OK, message accepted for delivery: queued as 12345
637 C: QUIT
638 S: 221 Bye
639 */
640 if (!$_retVal = $this->socket_send_str('STARTTLS', '220')) {
641 $this->_setErr(131, 'STARTTLS connection is not supported.');
642 return $_retVal;
643 }
644
645 // Before 5.6.7:
646 // STREAM_CRYPTO_METHOD_SSLv23_CLIENT = STREAM_CRYPTO_METHOD_SSLv2_CLIENT|STREAM_CRYPTO_METHOD_SSLv3_CLIENT
647 // STREAM_CRYPTO_METHOD_TLS_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
648 // PHP >= 5.6.7:
649 // STREAM_CRYPTO_METHOD_SSLv23_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
650 // STREAM_CRYPTO_METHOD_TLS_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
651
652 $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
653 if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
654 $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
655 $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
656 }
657
658 if (!stream_socket_enable_crypto($this->socket, true, $crypto_method)) {
659 $this->_setErr(132, 'STARTTLS connection failed.');
660 return $_retVal;
661 }
662 // Most servers expect a 2nd pass of EHLO after TLS is established to get another time
663 // the answer with list of supported AUTH methods. They may differs between non STARTTLS and with STARTTLS.
664 if (! $_retVal = $this->socket_send_str('EHLO '.$hosth, '250')) {
665 $this->_setErr(126, '"'.$hosth.'" does not support authenticated connections or temporary error. Error after 2nd sending EHLO '.$hosth.' : '.$this->lastretval);
666 return $_retVal;
667 }
668 }
669
670 // Default authentication method is LOGIN
671 if (!getDolGlobalString('MAIN_MAIL_SMTPS_AUTH_TYPE')) {
672 $conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE = 'LOGIN';
673 }
674
675 // Send Authentication to Server
676 // Check for errors along the way
677 switch ($conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE) {
678 case 'NONE':
679 // Do not send the 'AUTH type' message. For test purpose, if you don't need authentication, it is better to not enter login/pass into setup.
680 $_retVal = true;
681 break;
682 case 'PLAIN':
683 $this->socket_send_str('AUTH PLAIN', '334');
684 // The error here just means the ID/password combo doesn't work.
685 $_retVal = $this->socket_send_str(base64_encode("\0".$this->_smtpsID."\0".$this->_smtpsPW), '235');
686 break;
687 case 'XOAUTH2':
688 // "user=$email\1auth=Bearer $token\1\1"
689 $user = $this->_smtpsID;
690 $token = $this->_smtpsToken;
691 $initRes = "user=".$user."\001auth=Bearer ".$token."\001\001";
692 $_retVal = $this->socket_send_str('AUTH XOAUTH2 '.base64_encode($initRes), '235');
693 if (!$_retVal) {
694 $this->_setErr(130, 'Error when asking for AUTH XOAUTH2');
695 }
696 break;
697 case 'LOGIN': // most common case
698 default:
699 $_retVal = $this->socket_send_str('AUTH LOGIN', '334');
700 if (!$_retVal) {
701 $this->_setErr(130, 'Error when asking for AUTH LOGIN');
702 } else {
703 // User name will not return any error, server will take anything we give it.
704 $this->socket_send_str(base64_encode((string) $this->_smtpsID), '334');
705 // The error here just means the ID/password combo doesn't work.
706 // There is no method to determine which is the problem, ID or password
707 $_retVal = $this->socket_send_str(base64_encode((string) $this->_smtpsPW), '235');
708 }
709 break;
710 }
711 if (!$_retVal) {
712 $this->_setErr(130, 'Invalid Authentication Credentials.');
713 }
714 } else {
715 $this->_setErr(126, '"'.$host.'" refused the EHLO command. Error after sending EHLO '.$hosth.' : '.$this->lastretval);
716 }
717
718 return $_retVal;
719 }
720
726 public function sendMsg()
727 {
728 require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
729
730 // Default return value
731 $_retVal = false;
732
733 // Connect to Server
734 if ($this->socket = $this->_server_connect()) {
735 // If a User ID *and* a password is given, assume Authentication is desired
736 if (!empty($this->_smtpsID) && (!empty($this->_smtpsPW) || !empty($this->_smtpsToken))) {
737 // Send the RFC2554 specified EHLO.
738 $_retVal = $this->_server_authenticate();
739 } else {
740 // This is a "normal" SMTP Server "handshack"
741 // Send the RFC821 specified HELO.
742 $host = $this->getHost();
743 $usetls = preg_match('@tls://@i', $host);
744
745 $host = preg_replace('@tcp://@i', '', $host); // Remove prefix
746 $host = preg_replace('@ssl://@i', '', $host); // Remove prefix
747 $host = preg_replace('@tls://@i', '', $host); // Remove prefix
748
749 if ($usetls && getDolGlobalString('MAIN_SMTPS_ADD_TLS_TO_HOST_FOR_HELO')) {
750 $host = 'tls://'.$host;
751 }
752
753 $hosth = $host;
754
755 if (getDolGlobalString('MAIL_SMTP_USE_FROM_FOR_HELO')) {
756 if (!is_numeric(getDolGlobalString('MAIL_SMTP_USE_FROM_FOR_HELO'))) {
757 // If value of MAIL_SMTP_USE_FROM_FOR_HELO is a string, we use it as domain name
758 $hosth = getDolGlobalString('MAIL_SMTP_USE_FROM_FOR_HELO');
759 } elseif (getDolGlobalInt('MAIL_SMTP_USE_FROM_FOR_HELO') == 1) {
760 // If value of MAIL_SMTP_USE_FROM_FOR_HELO is 1, we use the domain in the from.
761 // So if the from to is 'aaa <bbb@ccc.com>', we will keep 'ccc.com'
762 $hosth = (string) $this->getFrom('addr');
763 $hosth = preg_replace('/^.*</', '', $hosth);
764 $hosth = preg_replace('/>.*$/', '', $hosth);
765 $hosth = preg_replace('/.*@/', '', $hosth);
766 } elseif (getDolGlobalInt('MAIL_SMTP_USE_FROM_FOR_HELO') == 2) {
767 // If value of MAIL_SMTP_USE_FROM_FOR_HELO is 2, we use the domain in the $dolibarr_main_url_root.
770 }
771 }
772
773 // Send the HELO message to the SMTP server
774 $_retVal = $this->socket_send_str('HELO '.$hosth, '250');
775 }
776
777 // Well, did we get the server answer with correct code ?
778 if ($_retVal) {
779 // From this point onward most server response codes should be 250
780 // Specify who the mail is from....
781 // This has to be the raw email address, strip the "name" off
782 $resultmailfrom = $this->socket_send_str('MAIL FROM: '.$this->getFrom('addr'), '250');
783 if (!$resultmailfrom) {
784 fclose($this->socket);
785 return false;
786 }
787
788 // 'RCPT TO:' must be given a single address, so this has to loop
789 // through the list of addresses, regardless of TO, CC or BCC
790 // and send it out "single file"
791 foreach ($this->get_RCPT_list() as $_address) {
792 /* Note:
793 * BCC email addresses must be listed in the RCPT TO command list,
794 * but the BCC header should not be printed under the DATA command.
795 * http://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server
796 */
797
798 /*
799 * TODO
800 * After each 'RCPT TO:' is sent, we need to make sure it was kosher,
801 * if not, the whole message will fail
802 * If any email address fails, we will need to RESET the connection,
803 * mark the last address as "bad" and start the address loop over again.
804 * If any address fails, the entire message fails.
805 */
806 $this->socket_send_str('RCPT TO: <'.$_address.'>', '250');
807 }
808
809 // Tell the server we are ready to start sending data
810 // with any custom headers...
811 // This is the last response code we look for until the end of the message.
812 $this->socket_send_str('DATA', '354');
813
814 // Now we are ready for the message...
815 // Ok, all the ingredients are mixed in let's cook this puppy...
816 $this->socket_send_str($this->getHeader().$this->getBodyContent()."\r\n".'.', '250');
817
818 // Now tell the server we are done and close the socket...
819 fwrite($this->socket, 'QUIT');
820 } else {
821 // We got error code into $this->lastretval
822 }
823
824 fclose($this->socket);
825 }
826
827 return $_retVal;
828 }
829
830 // =============================================================
831 // ** Setter & Getter methods
832
833 // ** Basic System configuration
834
860 public function setConfig($_strConfigPath = null)
861 {
866 $_retVal = true;
867
868 // if we have a path...
869 if (!empty($_strConfigPath)) {
870 // If the path is not valid, this will NOT generate an error,
871 // it will simply return false.
872 if (!@include $_strConfigPath) {
873 $this->_setErr(110, '"'.$_strConfigPath.'" is not a valid path.');
874 $_retVal = false;
875 }
876 } else {
877 // Read the Systems php.ini file
878 // Set these properties ONLY if they are set in the php.ini file.
879 // Otherwise the default values will be used.
880 if ($_host = ini_get('SMTPs')) {
881 $this->setHost($_host);
882 }
883
884 if ($_port = ini_get('smtp_port')) {
885 $this->setPort($_port);
886 }
887
888 if ($_from = ini_get('sendmail_from')) {
889 $this->setFrom($_from);
890 }
891 }
892
893 // Send back what we have
894 return $_retVal;
895 }
896
906 public function setTransportType($_type = 0)
907 {
908 if ((is_numeric($_type)) && (($_type >= 0) && ($_type <= 3))) {
909 $this->_transportType = $_type;
910 }
911 }
912
921 public function getTransportType()
922 {
923 return $this->_transportType;
924 }
925
932 public function setMailPath($_path)
933 {
934 // This feature is not yet implemented
935 return true;
936
937 //if ( $_path ) $this->_mailPath = $_path;
938 }
939
948 public function setHost($_strHost)
949 {
950 if ($_strHost) {
951 $this->_smtpsHost = $_strHost;
952 }
953 }
954
961 public function getHost()
962 {
963 return $this->_smtpsHost;
964 }
965
974 public function setPort($_intPort)
975 {
976 if ((is_numeric($_intPort)) &&
977 (($_intPort >= 1) && ($_intPort <= 65536))) {
978 $this->_smtpsPort = (int) $_intPort;
979 }
980 }
981
988 public function getPort()
989 {
990 return (int) $this->_smtpsPort;
991 }
992
999 public function setID($_strID)
1000 {
1001 $this->_smtpsID = $_strID;
1002 }
1003
1009 public function getID()
1010 {
1011 return $this->_smtpsID;
1012 }
1013
1020 public function setPW($_strPW)
1021 {
1022 $this->_smtpsPW = $_strPW;
1023 }
1024
1030 public function getPW()
1031 {
1032 return $this->_smtpsPW;
1033 }
1034
1041 public function setToken($_strToken)
1042 {
1043 $this->_smtpsToken = $_strToken;
1044 }
1045
1051 public function getToken()
1052 {
1053 return $this->_smtpsToken;
1054 }
1055
1063 public function setCharSet($_strCharSet)
1064 {
1065 if ($_strCharSet) {
1066 $this->_smtpsCharSet = $_strCharSet;
1067 }
1068 }
1069
1075 public function getCharSet()
1076 {
1077 return $this->_smtpsCharSet;
1078 }
1079
1095 public function setTransEncode($_strTransEncode)
1096 {
1097 if (array_search($_strTransEncode, $this->_smtpsTransEncodeTypes)) {
1098 $this->_smtpsTransEncode = $_strTransEncode;
1099 }
1100 }
1101
1107 public function getTransEncode()
1108 {
1109 return $this->_smtpsTransEncode;
1110 }
1111
1127 public function setTransEncodeType($_strTransEncodeType)
1128 {
1129 if (array_search($_strTransEncodeType, $this->_smtpsTransEncodeTypes)) {
1130 $this->_smtpsTransEncodeType = $_strTransEncodeType;
1131 }
1132 }
1133
1139 public function getTransEncodeType()
1140 {
1141 return $this->_smtpsTransEncodeTypes[$this->_smtpsTransEncodeType];
1142 }
1143
1144
1145 // ** Message Construction
1146
1153 public function setFrom($_strFrom)
1154 {
1155 if ($_strFrom) {
1156 $this->_msgFrom = $this->_strip_email($_strFrom);
1157 }
1158 }
1159
1166 public function getFrom($_part = true)
1167 {
1168 $_retValue = '';
1169
1170 if ($_part === true || $this->_msgFrom === null) {
1171 $_retValue = $this->_msgFrom;
1172 } else {
1173 $_retValue = $this->_msgFrom[$_part];
1174 }
1175
1176 return $_retValue;
1177 }
1178
1185 public function setReplyTo($_strReplyTo)
1186 {
1187 if ($_strReplyTo) {
1188 $this->_msgReplyTo = $this->_strip_email($_strReplyTo);
1189 }
1190 }
1191
1198 public function getReplyTo($_part = true)
1199 {
1200 $_retValue = '';
1201
1202 if ($_part === true) {
1203 $_retValue = $this->_msgReplyTo;
1204 } else {
1205 $_retValue = $this->_msgReplyTo[$_part];
1206 }
1207
1208 return $_retValue;
1209 }
1210
1217 public function setInReplyTo($_strInReplyTo)
1218 {
1219 if ($_strInReplyTo) {
1220 $this->_msgInReplyTo = $_strInReplyTo;
1221 }
1222 }
1223
1229 public function getInReplyTo()
1230 {
1231 $_retValue = $this->_msgInReplyTo;
1232
1233 return $_retValue;
1234 }
1235
1242 public function setReferences($_strReferences)
1243 {
1244 if ($_strReferences) {
1245 $this->_msgReferences = $_strReferences;
1246 }
1247 }
1248
1254 public function getReferences()
1255 {
1256 $_retValue = $this->_msgReferences;
1257
1258 return $_retValue;
1259 }
1260
1270 private function _buildAddrList($_type, $_addrList)
1271 {
1272 // Pull existing list
1273 $aryHost = $this->_msgRecipients;
1274
1275 // Only run this if we have something
1276 if (!empty($_addrList)) {
1277 // $_addrList can be a STRING or an array
1278 if (is_string($_addrList)) {
1279 // This could be a COMMA delimited string
1280 if (strstr($_addrList, ',')) {
1281 // "explode "list" into an array
1282 $_addrList = explode(',', $_addrList);
1283 } else {
1284 // Stick it in an array
1285 $_addrList = array($_addrList);
1286 }
1287 }
1288
1289 // take the array of addresses and split them further
1290 foreach ($_addrList as $_strAddr) {
1291 // Strip off the end '>'
1292 $_strAddr = str_replace('>', '', $_strAddr);
1293
1294 // Separate "Real Name" from eMail address
1295 $_tmpaddr = null;
1296 $_tmpaddr = explode('<', $_strAddr);
1297
1298 // We have a "Real Name" and eMail address
1299 if (count($_tmpaddr) == 2) {
1300 $_tmpHost = explode('@', $_tmpaddr[1]);
1301 $_tmpaddr[0] = trim($_tmpaddr[0], ' ">');
1302 $aryHost[$_tmpHost[1]][$_type][$_tmpHost[0]] = $_tmpaddr[0];
1303 } else {
1304 // We only have an eMail address
1305 // Strip off the beginning '<'
1306 $_strAddr = str_replace('<', '', $_strAddr);
1307
1308 $_tmpHost = explode('@', $_strAddr);
1309 $_tmpHost[0] = trim($_tmpHost[0]);
1310 $_tmpHost[1] = trim($_tmpHost[1]);
1311
1312 $aryHost[$_tmpHost[1]][$_type][$_tmpHost[0]] = '';
1313 }
1314 }
1315 }
1316 // replace list
1317 $this->_msgRecipients = $aryHost;
1318 }
1319
1320 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1337 private function _strip_email($_strAddr)
1338 {
1339 // phpcs:enable
1340 $_aryEmail = array();
1341 // Keep the original
1342 $_aryEmail['org'] = $_strAddr;
1343
1344 // Set entire string to Lower Case
1345 $_strAddr = strtolower($_strAddr);
1346
1347 // Drop "stuff' off the end
1348 $_strAddr = trim($_strAddr, ' ">');
1349
1350 // Separate "Real Name" from eMail address, if we have one
1351 $_tmpAry = explode('<', $_strAddr);
1352
1353 // Do we have a "Real name"
1354 if (count($_tmpAry) == 2) {
1355 // We may not really have a "Real Name"
1356 if ($_tmpAry[0]) {
1357 $_aryEmail['real'] = trim($_tmpAry[0], ' ">');
1358 }
1359
1360 $_aryEmail['addr'] = $_tmpAry[1];
1361 } else {
1362 $_aryEmail['addr'] = $_tmpAry[0];
1363 }
1364
1365 // Pull User Name and Host.tld apart
1366 $_tmpHost = explode('@', $_aryEmail['addr']);
1367 $_aryEmail['user'] = $_tmpHost[0];
1368 $_aryEmail['host'] = $_tmpHost[1];
1369
1370 // Put the brackets back around the address
1371 $_aryEmail['addr'] = '<'.$_aryEmail['addr'].'>';
1372
1373 return $_aryEmail;
1374 }
1375
1376 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1384 public function get_RCPT_list()
1385 {
1386 // phpcs:enable
1390 $_RCPT_list = array();
1391
1392 // walk down Recipients array and pull just email addresses
1393 foreach ($this->_msgRecipients as $_host => $_list) {
1394 foreach ($_list as $_subList) {
1395 foreach ($_subList as $_name => $_addr) {
1396 // build RCPT list
1397 $_RCPT_list[] = $_name.'@'.$_host;
1398 }
1399 }
1400 }
1401
1402 return $_RCPT_list;
1403 }
1404
1405 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1412 public function get_email_list($_which = null)
1413 {
1414 // phpcs:enable
1415 // We need to know which address segment to pull
1416 if ($_which) {
1417 // Make sure we have addresses to process
1418 if ($this->_msgRecipients) {
1419 $_RCPT_list = array();
1420 // walk down Recipients array and pull just email addresses
1421 foreach ($this->_msgRecipients as $_host => $_list) {
1422 if (!empty($this->_msgRecipients[$_host][$_which])) {
1423 foreach ($this->_msgRecipients[$_host][$_which] as $_addr => $_realName) {
1424 if ($_realName) { // @CHANGE LDR
1425 $_realName = '"'.$_realName.'"';
1426 $_RCPT_list[] = $_realName.' <'.$_addr.'@'.$_host.'>';
1427 } else {
1428 $_RCPT_list[] = $_addr.'@'.$_host;
1429 }
1430 }
1431 }
1432 }
1433
1434 return implode(', ', $_RCPT_list);
1435 } else {
1436 $this->_setErr(101, 'No eMail Address for message to be sent to.');
1437 return false;
1438 }
1439 } else {
1440 $this->_setErr(102, 'eMail type not defined.');
1441 return false;
1442 }
1443 }
1444
1451 public function setTO($_addrTo)
1452 {
1453 if ($_addrTo) {
1454 $this->_buildAddrList('to', $_addrTo);
1455 }
1456 }
1457
1463 public function getTo()
1464 {
1465 return $this->get_email_list('to');
1466 }
1467
1474 public function setCC($_strCC)
1475 {
1476 if ($_strCC) {
1477 $this->_buildAddrList('cc', $_strCC);
1478 }
1479 }
1480
1486 public function getCC()
1487 {
1488 return $this->get_email_list('cc');
1489 }
1490
1497 public function setBCC($_strBCC)
1498 {
1499 if ($_strBCC) {
1500 $this->_buildAddrList('bcc', $_strBCC);
1501 }
1502 }
1503
1509 public function getBCC()
1510 {
1511 return $this->get_email_list('bcc');
1512 }
1513
1520 public function setSubject($_strSubject = '')
1521 {
1522 if ($_strSubject) {
1523 $this->_msgSubject = $_strSubject;
1524 }
1525 }
1526
1532 public function getSubject()
1533 {
1534 return $this->_msgSubject;
1535 }
1536
1542 public function getHeader()
1543 {
1544 global $conf;
1545
1546 $_header = 'From: '.$this->getFrom('org')."\r\n"
1547 . 'To: '.$this->getTo()."\r\n";
1548
1549 if ($this->getCC()) {
1550 $_header .= 'Cc: '.$this->getCC()."\r\n";
1551 }
1552
1553 /* Note:
1554 * BCC email addresses must be listed in the RCPT TO command list,
1555 * but the BCC header should not be printed under the DATA command.
1556 * So it is included into the function sendMsg() but not here.
1557 * http://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server
1558 */
1559 /*
1560 if ( $this->getBCC() )
1561 $_header .= 'Bcc: ' . $this->getBCC() . "\r\n";
1562 */
1563
1564 $host = dol_getprefix('email');
1565
1566 $_header .= 'Subject: '.$this->getSubject()."\r\n";
1567 $_header .= 'Date: '.date("r")."\r\n";
1568
1569 $trackid = $this->getTrackId();
1570 if ($trackid) {
1571 $_header .= 'Message-ID: <'.(empty($this->_msgId) ? uniqid().'.SMTPs-dolibarr-'.$trackid.'@'.$host : $this->_msgId).">\r\n";
1572 $_header .= 'X-Dolibarr-TRACKID: '.$trackid.'@'.$host."\r\n";
1573 } else {
1574 $_header .= 'Message-ID: <'.(empty($this->_msgId) ? uniqid().'.SMTPs@'.$host : $this->_msgId).">\r\n";
1575 }
1576 if (!empty($_SERVER['REMOTE_ADDR'])) {
1577 $_header .= "X-RemoteAddr: ".$_SERVER['REMOTE_ADDR']."\r\n";
1578 }
1579 if ($this->getMoreInHeader()) {
1580 $_header .= $this->getMoreInHeader(); // Value must include the "\r\n";
1581 }
1582
1583 if ($this->getSensitivity()) {
1584 $_header .= 'Sensitivity: '.$this->getSensitivity()."\r\n";
1585 }
1586
1587 if ($this->_msgPriority != 3) {
1588 $_header .= $this->getPriority();
1589 }
1590
1591
1592 // @CHANGE LDR
1593 if ($this->getDeliveryReceipt()) {
1594 $_header .= 'Disposition-Notification-To: '.$this->getFrom('addr')."\r\n";
1595 }
1596 if ($this->getErrorsTo()) {
1597 $_header .= 'Errors-To: '.$this->getErrorsTo('addr')."\r\n";
1598 }
1599 if ($this->getReplyTo()) {
1600 $_header .= "Reply-To: ".$this->getReplyTo('addr')."\r\n";
1601 }
1602
1603 $_header .= 'X-Mailer: Dolibarr version '.DOL_VERSION.' (using SMTPs Mailer)'."\r\n";
1604 $_header .= 'X-Dolibarr-Option: '.($conf->global->MAIN_MAIL_USE_MULTI_PART ? 'MAIN_MAIL_USE_MULTI_PART' : 'No MAIN_MAIL_USE_MULTI_PART')."\r\n";
1605 $_header .= 'Mime-Version: 1.0'."\r\n";
1606
1607 // Add also $this->references and In-Reply-To
1608 if ($this->getInReplyTo()) {
1609 $_header .= "In-Reply-To: ".$this->getInReplyTo()."\r\n";
1610 }
1611 $references = $this->getReferences();
1612 if ($references) {
1613 // List of message ids:
1614 // Example "References: <id1@domain2.com> <id2@domain.com>
1615 $_header .= "References: ".implode(' ', $references)."\r\n";
1616 }
1617
1618 return $_header;
1619 }
1620
1628 public function setBodyContent($strContent, $strType = 'plain')
1629 {
1630 //if ( $strContent )
1631 //{
1632 if ($strType == 'html') {
1633 $strMimeType = 'text/html';
1634 } else {
1635 $strMimeType = 'text/plain';
1636 }
1637
1638 // Make RFC821 Compliant, replace bare linefeeds
1639 $strContent = preg_replace("/(?<!\r)\n/si", "\r\n", $strContent);
1640
1641 $strContentAltText = '';
1642 if ($strType == 'html') {
1643 // Similar code to forge a text from html is also in CMailFile.class.php
1644 $strContentAltText = preg_replace('/<head><title>.*<\/style><\/head>/', '', $strContent);
1645 $strContentAltText = preg_replace("/<br\s*[^>]*>/", " ", $strContentAltText);
1646 $strContentAltText = html_entity_decode(strip_tags($strContentAltText));
1647 $strContentAltText = trim(wordwrap($strContentAltText, 75, "\r\n"));
1648 }
1649
1650 // Make RFC2045 Compliant
1651 //$strContent = rtrim(chunk_split($strContent)); // Function chunck_split seems ko if not used on a base64 content
1652 $strContent = rtrim(wordwrap($strContent, 75, "\r\n")); // TODO Using this method creates unexpected line break on text/plain content.
1653
1654 $this->_msgContent[$strType] = array();
1655
1656 $this->_msgContent[$strType]['mimeType'] = $strMimeType;
1657 $this->_msgContent[$strType]['data'] = $strContent;
1658 $this->_msgContent[$strType]['dataText'] = $strContentAltText;
1659
1660 if ($this->getMD5flag()) {
1661 $this->_msgContent[$strType]['md5'] = dol_hash($strContent, '3');
1662 }
1663 //}
1664 }
1665
1671 public function getBodyContent()
1672 {
1673 global $conf;
1674
1675 // Generate a new Boundary string
1676 $this->_setBoundary();
1677
1678 // What type[s] of content do we have
1679 $_types = array_keys($this->_msgContent);
1680
1681 // How many content types do we have
1682 $keyCount = count($_types);
1683
1684 // If we have ZERO, we have a problem
1685 if ($keyCount === 0) {
1686 die("Sorry, no content");
1687 } elseif ($keyCount === 1 && !getDolGlobalString('MAIN_MAIL_USE_MULTI_PART')) {
1688 // If we have ONE, we can use the simple format
1689 $_msgData = $this->_msgContent;
1690 $_msgData = $_msgData[$_types[0]];
1691
1692 $content = 'Content-Type: '.$_msgData['mimeType'].'; charset="'.$this->getCharSet().'"'."\r\n"
1693 . 'Content-Transfer-Encoding: '.$this->getTransEncodeType()."\r\n"
1694 . 'Content-Disposition: inline'."\r\n"
1695 . 'Content-Description: Message'."\r\n";
1696
1697 if ($this->getMD5flag()) {
1698 $content .= 'Content-MD5: '.$_msgData['md5']."\r\n";
1699 }
1700
1701 $content .= "\r\n"
1702 . $_msgData['data']."\r\n";
1703 } elseif ($keyCount >= 1 || getDolGlobalString('MAIN_MAIL_USE_MULTI_PART')) {
1704 // If we have more than ONE, we use the multi-part format
1705 // Since this is an actual multi-part message
1706 // We need to define a content message Boundary
1707 // NOTE: This was 'multipart/alternative', but Windows based mail servers have issues with this.
1708
1709 //$content = 'Content-Type: multipart/related; boundary="' . $this->_getBoundary() . '"' . "\r\n";
1710 $content = 'Content-Type: multipart/mixed; boundary="'.$this->_getBoundary('mixed').'"'."\r\n";
1711
1712 // . "\r\n"
1713 // . 'This is a multi-part message in MIME format.' . "\r\n";
1714 $content .= "Content-Transfer-Encoding: 8bit\r\n";
1715 $content .= "\r\n";
1716
1717 $content .= "--".$this->_getBoundary('mixed')."\r\n";
1718
1719 if (array_key_exists('image', $this->_msgContent)) { // If inline image found
1720 $content .= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"'."\r\n";
1721 $content .= "\r\n";
1722 $content .= "--".$this->_getBoundary('alternative')."\r\n";
1723 }
1724
1725
1726 // $this->_msgContent must be sorted with key 'text' or 'html' first then 'image' then 'attachment'
1727
1728
1729 // Loop through message content array
1730 foreach ($this->_msgContent as $type => $_content) {
1731 if ($type == 'attachment') {
1732 // loop through all attachments
1733 foreach ($_content as $_file => $_data) {
1734 $content .= "--".$this->_getBoundary('mixed')."\r\n"
1735 . 'Content-Disposition: attachment; filename="'.$_data['fileName'].'"'."\r\n"
1736 . 'Content-Type: '.$_data['mimeType'].'; name="'.$_data['fileName'].'"'."\r\n"
1737 . 'Content-Transfer-Encoding: base64'."\r\n"
1738 . 'Content-Description: '.$_data['fileName']."\r\n";
1739 if (!empty($_data['cid'])) {
1740 $content .= "X-Attachment-Id: ".$_data['cid']."\r\n";
1741 $content .= "Content-ID: <".$_data['cid'].">\r\n";
1742 }
1743 if ($this->getMD5flag()) {
1744 $content .= 'Content-MD5: '.$_data['md5']."\r\n";
1745 }
1746
1747 $content .= "\r\n".$_data['data']."\r\n\r\n";
1748 }
1749 } elseif ($type == 'image') {
1750 // @CHANGE LDR
1751 // loop through all images
1752 foreach ($_content as $_image => $_data) {
1753 $content .= "--".$this->_getBoundary('related')."\r\n"; // always related for an inline image
1754
1755 $content .= 'Content-Type: '.$_data['mimeType'].'; name="'.$_data['imageName'].'"'."\r\n"
1756 . 'Content-Transfer-Encoding: base64'."\r\n"
1757 . 'Content-Disposition: inline; filename="'.$_data['imageName'].'"'."\r\n"
1758 . 'Content-ID: <'.$_data['cid'].'> '."\r\n";
1759
1760 if ($this->getMD5flag()) {
1761 $content .= 'Content-MD5: '.$_data['md5']."\r\n";
1762 }
1763
1764 $content .= "\r\n"
1765 . $_data['data']."\r\n";
1766 }
1767
1768 // always end related and end alternative after inline images
1769 $content .= "--".$this->_getBoundary('related')."--\r\n";
1770 $content .= "\r\n--".$this->_getBoundary('alternative')."--\r\n";
1771 $content .= "\r\n";
1772 } else {
1773 if (array_key_exists('image', $this->_msgContent)) {
1774 $content .= "Content-Type: text/plain; charset=".$this->getCharSet()."\r\n";
1775 $content .= "\r\n".($_content['dataText'] ? $_content['dataText'] : strip_tags($_content['data']))."\r\n"; // Add plain text message
1776 $content .= "--".$this->_getBoundary('alternative')."\r\n";
1777 $content .= 'Content-Type: multipart/related; boundary="'.$this->_getBoundary('related').'"'."\r\n";
1778 $content .= "\r\n";
1779 $content .= "--".$this->_getBoundary('related')."\r\n";
1780 }
1781
1782 if (!array_key_exists('image', $this->_msgContent) && $_content['dataText'] && getDolGlobalString('MAIN_MAIL_USE_MULTI_PART')) {
1783 // Add plain text message part before html part
1784 $content .= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"'."\r\n";
1785 $content .= "\r\n";
1786 $content .= "--".$this->_getBoundary('alternative')."\r\n";
1787
1788 $content .= "Content-Type: text/plain; charset=".$this->getCharSet()."\r\n";
1789 $content .= "\r\n".$_content['dataText']."\r\n";
1790 $content .= "--".$this->_getBoundary('alternative')."\r\n";
1791 }
1792
1793 $content .= 'Content-Type: '.$_content['mimeType'].'; charset='.$this->getCharSet();
1794
1795 $content .= "\r\n";
1796
1797 if ($this->getMD5flag()) {
1798 $content .= 'Content-MD5: '.$_content['md5']."\r\n";
1799 }
1800
1801 $content .= "\r\n".$_content['data']."\r\n";
1802
1803 if (!array_key_exists('image', $this->_msgContent) && $_content['dataText'] && getDolGlobalString('MAIN_MAIL_USE_MULTI_PART')) {
1804 // Add plain text message part after html part
1805 $content .= "--".$this->_getBoundary('alternative')."--\r\n";
1806 }
1807
1808 $content .= "\r\n";
1809 }
1810 }
1811
1812 $content .= "--".$this->_getBoundary('mixed').'--'."\r\n";
1813 } else {
1814 die("Sorry, no content");
1815 }
1816
1817 return $content;
1818 }
1819
1830 public function setAttachment($strContent, $strFileName = 'unknown', $strMimeType = 'unknown', $strCid = '')
1831 {
1832 if ($strContent) {
1833 $strContent = rtrim(chunk_split(base64_encode($strContent), 76, "\r\n")); // 76 max is defined into http://tools.ietf.org/html/rfc2047
1834
1835 $this->_msgContent['attachment'][$strFileName]['mimeType'] = $strMimeType;
1836 $this->_msgContent['attachment'][$strFileName]['fileName'] = $strFileName;
1837 $this->_msgContent['attachment'][$strFileName]['data'] = $strContent;
1838 $this->_msgContent['attachment'][$strFileName]['cid'] = $strCid; // If defined, it means this attachment must be shown inline
1839
1840 if ($this->getMD5flag()) {
1841 $this->_msgContent['attachment'][$strFileName]['md5'] = dol_hash($strContent, '3');
1842 }
1843 }
1844 }
1845
1846
1847 // @CHANGE LDR
1848
1859 public function setImageInline($strContent, $strImageName = 'unknown', $strMimeType = 'unknown', $strImageCid = 'unknown')
1860 {
1861 if ($strContent) {
1862 $this->_msgContent['image'][$strImageName]['mimeType'] = $strMimeType;
1863 $this->_msgContent['image'][$strImageName]['imageName'] = $strImageName;
1864 $this->_msgContent['image'][$strImageName]['cid'] = $strImageCid;
1865 $this->_msgContent['image'][$strImageName]['data'] = $strContent;
1866
1867 if ($this->getMD5flag()) {
1868 $this->_msgContent['image'][$strImageName]['md5'] = dol_hash($strContent, '3');
1869 }
1870 }
1871 }
1872 // END @CHANGE LDR
1873
1874
1886 public function setSensitivity($_value = 0)
1887 {
1888 if ((is_numeric($_value)) &&
1889 (($_value >= 0) && ($_value <= 3))) {
1890 $this->_msgSensitivity = $_value;
1891 }
1892 }
1893
1904 public function getSensitivity()
1905 {
1906 return $this->_arySensitivity[$this->_msgSensitivity];
1907 }
1908
1922 public function setPriority($_value = 3)
1923 {
1924 if ((is_numeric($_value)) &&
1925 (($_value >= 0) && ($_value <= 5))) {
1926 $this->_msgPriority = $_value;
1927 }
1928 }
1929
1942 public function getPriority()
1943 {
1944 return 'Importance: '.$this->_aryPriority[$this->_msgPriority]."\r\n"
1945 . 'Priority: '.$this->_aryPriority[$this->_msgPriority]."\r\n"
1946 . 'X-Priority: '.$this->_msgPriority.' ('.$this->_aryPriority[$this->_msgPriority].')'."\r\n";
1947 }
1948
1955 public function setMD5flag($_flag = false)
1956 {
1957 $this->_smtpMD5 = $_flag;
1958 }
1959
1965 public function getMD5flag()
1966 {
1967 return $this->_smtpMD5;
1968 }
1969
1978 public function setXheader($strXdata)
1979 {
1980 if ($strXdata) {
1981 $this->_msgXheader[] = $strXdata;
1982 }
1983 }
1984
1990 public function getXheader()
1991 {
1992 return $this->_msgXheader;
1993 }
1994
2000 private function _setBoundary()
2001 {
2002 $this->_smtpsBoundary = "multipart_x.".time().".x_boundary";
2003 $this->_smtpsRelatedBoundary = 'mul_'.dol_hash(uniqid("dolibarr2"), '3');
2004 $this->_smtpsAlternativeBoundary = 'mul_'.dol_hash(uniqid("dolibarr3"), '3');
2005 }
2006
2013 private function _getBoundary($type = 'mixed')
2014 {
2015 if ($type == 'mixed') {
2016 return $this->_smtpsBoundary;
2017 } elseif ($type == 'related') {
2018 return $this->_smtpsRelatedBoundary;
2019 } elseif ($type == 'alternative') {
2020 return $this->_smtpsAlternativeBoundary;
2021 }
2022 return '';
2023 }
2024
2025 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2036 public function server_parse($socket, $response)
2037 {
2038 // phpcs:enable
2043 $_retVal = true;
2044
2045 $server_response = '';
2046
2047 // avoid infinite loop
2048 $limit = 0;
2049
2050 while (substr($server_response, 3, 1) != ' ' && $limit < 100) {
2051 if (!($server_response = fgets($socket, 256))) {
2052 $this->_setErr(121, "Couldn't get mail server response codes");
2053 $_retVal = false;
2054 break;
2055 }
2056 $this->log .= $server_response;
2057 $limit++;
2058 }
2059
2060 $this->lastretval = substr($server_response, 0, 3);
2061
2062 if (!(substr($server_response, 0, 3) == $response)) {
2063 $this->_setErr(120, "Ran into problems sending Mail.\r\nResponse: ".$server_response);
2064 $_retVal = false;
2065 }
2066
2067 return $_retVal;
2068 }
2069
2070 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2079 public function socket_send_str($_strSend, $_returnCode = null, $CRLF = "\r\n")
2080 {
2081 // phpcs:enable
2082 if ($this->_debug) {
2083 $this->log .= $_strSend; // @CHANGE LDR for log
2084 }
2085 fwrite($this->socket, $_strSend.$CRLF);
2086 if ($this->_debug) {
2087 $this->log .= ' ('.$_returnCode.')'.$CRLF;
2088 }
2089
2090 if ($_returnCode) {
2091 return $this->server_parse($this->socket, $_returnCode);
2092 }
2093
2094 return null;
2095 }
2096
2097 // =============================================================
2098 // ** Error handling methods
2099
2107 private function _setErr($_errNum, $_errMsg)
2108 {
2109 $this->_smtpsErrors[] = array(
2110 'num' => $_errNum,
2111 'msg' => $_errMsg,
2112 );
2113 }
2114
2120 public function getErrors()
2121 {
2122 $_errMsg = array();
2123
2124 if (is_array($this->_smtpsErrors)) {
2125 foreach ($this->_smtpsErrors as $_err => $_info) {
2126 $_errMsg[] = 'Error ['.$_info['num'].']: '.$_info['msg'];
2127 }
2128 }
2129
2130 return implode("\n", $_errMsg);
2131 }
2132}
2133
2134
2135// =============================================================
2136// ** CSV Version Control Info
2137
global $dolibarr_main_url_root
Class to construct and send SMTP compliant email, even to a secure SMTP server, regardless of platfor...
_getBoundary($type='mixed')
Retrieves the MIME message Boundary.
setConfig($_strConfigPath=null)
setConfig() is used to populate select class properties from either a user defined INI file or the sy...
sendMsg()
Now send the message.
getErrors()
Returns applicative errors codes and messages for Class (not the SMTP error code)
setCharSet($_strCharSet)
Character set used for current message Character set is defaulted to 'iso-8859-1';.
setSubject($_strSubject='')
Message Subject.
getPriority()
Message Content Priority Message Priority values:
setReferences($_strReferences)
Set References in the list of Msg-Id.
getMD5flag()
Gets flag which determines whether to calculate message MD5 checksum.
socket_send_str($_strSend, $_returnCode=null, $CRLF="\r\n")
Send str.
_strip_email($_strAddr)
Returns an array of the various parts of an email address This assumes a well formed address:
getTransEncodeType()
Retrieves the Content-Transfer-Encoding.
setTrackId($_val='')
Set trackid.
setToken($_strToken)
User token for OAUTH2.
setInReplyTo($_strInReplyTo)
Set References in the list of Msg-Id.
buildRCPTlist()
build RECIPIENT List, all addresses who will receive this message
getBodyContent()
Retrieves the Message Content.
_buildAddrList($_type, $_addrList)
Inserts given addresses into structured format.
getInReplyTo()
Retrieves the InReplyTo from which mail we reply to.
setOptions($_options=array())
Set options.
_server_connect()
Attempt a connection to mail server.
setBodyContent($strContent, $strType='plain')
Message Content.
server_parse($socket, $response)
This function has been modified as provided by SirSir to allow multiline responses when using SMTP Ex...
setTransportType($_type=0)
Determines the method inwhich the messages are to be sent.
getBCC()
Retrieves the BCC Address[es] inwhich to send mail to.
setAttachment($strContent, $strFileName='unknown', $strMimeType='unknown', $strCid='')
File attachments are added to the content array as sub-arrays, allowing for multiple attachments for ...
_setBoundary()
Generates Random string for MIME message Boundary.
getTo()
Retrieves the TO Address[es] inwhich to send mail to.
setPort($_intPort)
Defines the Port Number of the Mail Server to use The default is 25 This is used only with 'socket' b...
getID()
Retrieves the User Name for authentication on Mail Server.
setBCC($_strBCC)
BCC Address[es] inwhich to send mail to.
setReplyTo($_strReplyTo)
Reply-To Address from which mail will be the reply-to.
getToken()
Retrieves the User token for OAUTH2.
setSensitivity($_value=0)
Message Content Sensitivity Message Sensitivity values:
setCC($_strCC)
CC Address[es] inwhich to send mail to.
getSMTPTimeout()
Get socket timeout.
setTO($_addrTo)
TO Address[es] inwhich to send mail to.
setTransEncodeType($_strTransEncodeType)
Content-Transfer-Encoding, Defaulted to '0' [ZERO] This can be changed for 2byte characters sets Know...
get_email_list($_which=null)
Returns an array of addresses for a specific type; TO, CC or BCC.
setMD5flag($_flag=false)
Set flag which determines whether to calculate message MD5 checksum.
getCharSet()
Retrieves the Character set used for current message.
getCC()
Retrieves the CC Address[es] inwhich to send mail to.
getDeliveryReceipt()
get delivery receipt
getTrackId()
get trackid
setFrom($_strFrom)
FROM Address from which mail will be sent.
get_RCPT_list()
Returns an array of bare addresses for use with 'RCPT TO:' This is a "build as you go" method.
_server_authenticate()
Attempt mail server authentication for a secure connection.
setID($_strID)
User Name for authentication on Mail Server.
getMoreInHeader()
get moreInHeader
getPW()
Retrieves the User Password for authentication on Mail Server.
getSubject()
Retrieves the Message Subject.
getXheader()
Retrieves the Message X-Header Content.
setErrorsTo($_strErrorsTo)
Set errors to.
setImageInline($strContent, $strImageName='unknown', $strMimeType='unknown', $strImageCid='unknown')
Image attachments are added to the content array as sub-arrays, allowing for multiple images for each...
setMessageID($_msgId='')
Set Message-ID.
setHost($_strHost)
Defines the Host Name or IP of the Mail Server to use.
getFrom($_part=true)
Retrieves the Address from which mail will be sent.
getHost()
Retrieves the Host Name or IP of the Mail Server to use This is used only with 'socket' based mail tr...
setPW($_strPW)
User Password for authentication on Mail Server.
getReplyTo($_part=true)
Retrieves the Address from which mail will be the reply-to.
setPriority($_value=3)
Message Content Priority Message Priority values:
setMoreInHeader($_val='')
Set moreInHeader.
getErrorsTo($_part=true)
Get errors to.
getSensitivity()
Returns Message Content Sensitivity string Message Sensitivity values:
setSMTPTimeout($timeout)
Set socket timeout.
getPort()
Retrieves the Port Number of the Mail Server to use This is used only with 'socket' based mail transm...
getTransportType()
Return the method inwhich the message is to be sent.
setMailPath($_path)
Path to the sendmail executable.
getTransEncode()
Retrieves the Content-Transfer-Encoding.
getReferences()
Retrieves the References from which mail will be the reply-to.
setTransEncode($_strTransEncode)
Content-Transfer-Encoding, Defaulted to '7bit' This can be changed for 2byte characters sets Known En...
setDebug($_vDebug=false)
Set debug.
setDeliveryReceipt($_val=0)
Set delivery receipt.
_setErr($_errNum, $_errMsg)
Defines errors codes and messages for Class.
getHeader()
Constructs and returns message header.
setXheader($strXdata)
Message X-Header Content This is a simple "insert".
is_ip($ip)
This function evaluates a string that should be a valid IPv4 Note: For ip 169.254....
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
getDomainFromURL($url, $mode=0)
Function get second level domain name.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
dol_hash($chain, $type='0', $nosalt=0, $mode=0)
Returns a hash (non reversible encryption) of a string.