dolibarr  19.0.0-dev
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  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
46 class SMTPs
47 {
51  private $_smtpsHost = 'localhost';
52 
57  private $_smtpsPort = '25';
58 
63  private $_smtpsID = null;
64 
69  private $_smtpsPW = null;
70 
74  private $_smtpsToken = null;
75 
80  private $_msgFrom = null;
81 
86  private $_msgReplyTo = null;
87 
93  private $_msgRecipients = null;
94 
98  private $_msgSubject = null;
99 
105  private $_msgContent = array();
106 
110  private $_msgXheader = null;
111 
116  private $_smtpsCharSet = 'iso-8859-1';
117 
122  private $_msgSensitivity = 0;
123 
127  private $_arySensitivity = array(false,
128  'Personal',
129  'Private',
130  'Company Confidential');
131 
136  private $_msgPriority = 3;
137 
141  private $_aryPriority = array('Bulk',
142  'Highest',
143  'High',
144  'Normal',
145  'Low',
146  'Lowest');
147 
153 
157  private $_smtpsTransEncodeTypes = array('7bit', // Simple 7-bit ASCII
158  '8bit', // 8-bit coding with line termination characters
159  'base64', // 3 octets encoded into 4 sextets with offset
160  'binary', // Arbitrary binary stream
161  'mac-binhex40', // Macintosh binary to hex encoding
162  'quoted-printable', // Mostly 7-bit, with 8-bit characters encoded as "=HH"
163  'uuencode'); // UUENCODE encoding
164 
169  private $_smtpsTransEncode = '7bit';
170 
174  private $_smtpsBoundary = null;
175 
179  private $_smtpsRelatedBoundary = null;
180 
185 
193  private $_transportType = 0;
194 
199  private $_mailPath = '/usr/lib/sendmail';
200 
204  private $_smtpTimeout = 10;
205 
209  private $_smtpMD5 = false;
210 
214  private $_smtpsErrors = null;
215 
223  private $_log_level = 0;
224 
228  private $_debug = false;
229 
230 
231  // @CHANGE LDR
232  public $log = '';
233  public $lastretval = '';
234 
238  public $socket;
239 
243  public $errno;
244 
248  public $errstr;
249 
250  private $_errorsTo = '';
251  private $_deliveryReceipt = 0;
252  private $_trackId = '';
253  private $_moreinheader = '';
254 
258  private $_options = array();
259 
266  public function setOptions($_options = array())
267  {
268  $this->_options = $_options;
269  }
270 
277  public function setDeliveryReceipt($_val = 0)
278  {
279  $this->_deliveryReceipt = $_val;
280  }
281 
287  public function getDeliveryReceipt()
288  {
289  return $this->_deliveryReceipt;
290  }
291 
298  public function setTrackId($_val = '')
299  {
300  $this->_trackId = $_val;
301  }
302 
309  public function setMoreInHeader($_val = '')
310  {
311  $this->_moreinheader = $_val;
312  }
313 
319  public function getTrackId()
320  {
321  return $this->_trackId;
322  }
323 
329  public function getMoreInHeader()
330  {
331  return $this->_moreinheader;
332  }
333 
340  public function setErrorsTo($_strErrorsTo)
341  {
342  if ($_strErrorsTo) {
343  $this->_errorsTo = $this->_strip_email($_strErrorsTo);
344  }
345  }
346 
353  public function getErrorsTo($_part = true)
354  {
355  $_retValue = '';
356 
357  if ($_part === true) {
358  $_retValue = $this->_errorsTo;
359  } else {
360  $_retValue = $this->_errorsTo[$_part];
361  }
362 
363  return $_retValue;
364  }
365 
372  public function setDebug($_vDebug = false)
373  {
374  $this->_debug = $_vDebug;
375  }
376 
382  public function buildRCPTlist()
383  {
384  // Pull TO list
385  $_aryToList = $this->getTO();
386  }
387 
388  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
394  private function _server_connect()
395  {
396  // phpcs:enable
397  // Default return value
398  $_retVal = true;
399 
400  // We have to make sure the HOST given is valid
401  // This is done here because '@fsockopen' will not give me this
402  // information if it failes to connect because it can't find the HOST
403  $host = $this->getHost();
404  $usetls = preg_match('@tls://@i', $host);
405 
406  $host = preg_replace('@tcp://@i', '', $host); // Remove prefix
407  $host = preg_replace('@ssl://@i', '', $host); // Remove prefix
408  $host = preg_replace('@tls://@i', '', $host); // Remove prefix
409 
410  // @CHANGE LDR
411  include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
412 
413  if ((!is_ip($host)) && ((gethostbyname($host)) == $host)) {
414  $this->_setErr(99, $host.' is either offline or is an invalid host name.');
415  $_retVal = false;
416  } else {
417  if (function_exists('stream_socket_client') && !empty($this->_options)) {
418  $socket_context = stream_context_create($this->_options); // An array of options for stream_context_create()
419  $this->socket = @stream_socket_client(
420  preg_replace('@tls://@i', '', $this->getHost()).// Host to 'hit', IP or domain
421  ':'.$this->getPort(), // which Port number to use
422  $this->errno, // actual system level error
423  $this->errstr, // and any text that goes with the error
424  $this->_smtpTimeout, // timeout for reading/writing data over the socket
425  STREAM_CLIENT_CONNECT,
426  $socket_context // Options for connection
427  );
428  } else {
429  $this->socket = @fsockopen(
430  preg_replace('@tls://@i', '', $this->getHost()), // Host to 'hit', IP or domain
431  $this->getPort(), // which Port number to use
432  $this->errno, // actual system level error
433  $this->errstr, // and any text that goes with the error
434  $this->_smtpTimeout // timeout for reading/writing data over the socket
435  );
436  }
437 
438  //See if we can connect to the SMTP server
439  if (is_resource($this->socket)) {
440  // Fix from PHP SMTP class by 'Chris Ryan'
441  // Sometimes the SMTP server takes a little longer to respond
442  // so we will give it a longer timeout for the first read
443  // Windows still does not have support for this timeout function
444  if (function_exists('stream_set_timeout')) {
445  stream_set_timeout($this->socket, $this->_smtpTimeout, 0);
446  }
447 
448  // Check response from Server
449  if ($_retVal = $this->server_parse($this->socket, "220")) {
450  $_retVal = $this->socket;
451  }
452  } else {
453  // This connection attempt failed.
454  // @CHANGE LDR
455  if (empty($this->errstr)) {
456  $this->errstr = 'Failed to connect with fsockopen host='.$this->getHost().' port='.$this->getPort();
457  }
458  $this->_setErr($this->errno, $this->errstr);
459  $_retVal = false;
460  }
461  }
462 
463  return $_retVal;
464  }
465 
466  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
472  private function _server_authenticate()
473  {
474  // phpcs:enable
475  global $conf;
476 
477  require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
478  // Send the RFC2554 specified EHLO.
479  // This improvment as provided by 'SirSir' to
480  // accomodate both SMTP AND ESMTP capable servers
481  $host = $this->getHost();
482  $usetls = preg_match('@tls://@i', $host);
483 
484  $host = preg_replace('@tcp://@i', '', $host); // Remove prefix
485  $host = preg_replace('@ssl://@i', '', $host); // Remove prefix
486  $host = preg_replace('@tls://@i', '', $host); // Remove prefix
487 
488  if ($usetls && !empty($conf->global->MAIN_SMTPS_ADD_TLS_TO_HOST_FOR_HELO)) {
489  $host = 'tls://'.$host;
490  }
491 
492  $hosth = $host; // so for example 'localhost' or 'smtp-relay.gmail.com'
493 
494  if (!empty($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO)) {
495  if (!is_numeric($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO)) {
496  // If value of MAIL_SMTP_USE_FROM_FOR_HELO is a string, we use it as domain name
497  $hosth = $conf->global->MAIL_SMTP_USE_FROM_FOR_HELO;
498  } elseif ($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO == 1) {
499  // If value of MAIL_SMTP_USE_FROM_FOR_HELO is 1, we use the domain in the from.
500  // So if the from to is 'aaa <bbb@ccc.com>', we will keep 'ccc.com'
501  $hosth = $this->getFrom('addr');
502  $hosth = preg_replace('/^.*</', '', $hosth);
503  $hosth = preg_replace('/>.*$/', '', $hosth);
504  $hosth = preg_replace('/.*@/', '', $hosth);
505  } elseif ($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO == 2) {
506  // If value of MAIL_SMTP_USE_FROM_FOR_HELO is 2, we use the domain in the $dolibarr_main_url_root.
507  global $dolibarr_main_url_root;
508  $hosth = getDomainFromURL($dolibarr_main_url_root, 1);
509  }
510  }
511 
512  if ($_retVal = $this->socket_send_str('EHLO '.$hosth, '250')) {
513  if ($usetls) {
514  /*
515  The following dialog illustrates how a client and server can start a TLS STARTTLS session:
516  S: <waits for connection on TCP port 25>
517  C: <opens connection>
518  S: 220 mail.imc.org SMTP service ready
519  C: EHLO mail.ietf.org
520  S: 250-mail.imc.org offers a warm hug of welcome
521  S: 250 STARTTLS
522  C: STARTTLS
523  S: 220 Go ahead
524  C: <starts TLS negotiation>
525  C & S: <negotiate a TLS session>
526  C & S: <check result of negotiation>
527  // Second pass EHLO
528  C: EHLO client-domain.com
529  S: 250-server-domain.com
530  S: 250 AUTH LOGIN
531  C: <continues by sending an SMTP command
532 
533  Another example here:
534  S: 220 smtp.server.com Simple Mail Transfer Service Ready
535  C: EHLO client.example.com
536  S: 250-smtp.server.com Hello client.example.com
537  S: 250-SIZE 1000000
538  S: 250-AUTH LOGIN PLAIN CRAM-MD5
539  S: 250-STARTTLS
540  S: 250 HELP
541  C: STARTTLS
542  S: 220 TLS go ahead
543  C: EHLO client.example.com *
544  S: 250-smtp.server.com Hello client.example.com
545  S: 250-SIZE 1000000
546  S: 250-AUTH LOGIN PLAIN CRAM-MD5
547  S: 250 HELP
548  C: AUTH LOGIN
549  S: 334 VXNlcm5hbWU6
550  C: adlxdkej
551  S: 334 UGFzc3dvcmQ6
552  C: lkujsefxlj
553  S: 235 2.7.0 Authentication successful
554  C: MAIL FROM:<mail@samlogic.com>
555  S: 250 OK
556  C: RCPT TO:<john@mail.com>
557  S: 250 OK
558  C: DATA
559  S: 354 Send message, end with a "." on a line by itself
560  C: <The message data (body text, subject, e-mail header, attachments etc) is sent>
561  S .
562  S: 250 OK, message accepted for delivery: queued as 12345
563  C: QUIT
564  S: 221 Bye
565  */
566  if (!$_retVal = $this->socket_send_str('STARTTLS', 220)) {
567  $this->_setErr(131, 'STARTTLS connection is not supported.');
568  return $_retVal;
569  }
570 
571  // Before 5.6.7:
572  // STREAM_CRYPTO_METHOD_SSLv23_CLIENT = STREAM_CRYPTO_METHOD_SSLv2_CLIENT|STREAM_CRYPTO_METHOD_SSLv3_CLIENT
573  // STREAM_CRYPTO_METHOD_TLS_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
574  // PHP >= 5.6.7:
575  // STREAM_CRYPTO_METHOD_SSLv23_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
576  // STREAM_CRYPTO_METHOD_TLS_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
577 
578  $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
579  if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
580  $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
581  $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
582  }
583 
584  if (!stream_socket_enable_crypto($this->socket, true, $crypto_method)) {
585  $this->_setErr(132, 'STARTTLS connection failed.');
586  return $_retVal;
587  }
588  // Most servers expect a 2nd pass of EHLO after TLS is established to get another time
589  // the answer with list of supported AUTH methods. They may differs between non STARTTLS and with STARTTLS.
590  if (! $_retVal = $this->socket_send_str('EHLO '.$hosth, '250')) {
591  $this->_setErr(126, '"'.$hosth.'" does not support authenticated connections or temporary error. Error after 2nd sending EHLO '.$hosth.' : '.$this->lastretval);
592  return $_retVal;
593  }
594  }
595 
596  // Default authentication method is LOGIN
597  if (empty($conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE)) {
598  $conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE = 'LOGIN';
599  }
600 
601  // Send Authentication to Server
602  // Check for errors along the way
603  switch ($conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE) {
604  case 'NONE':
605  // 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.
606  $_retVal = true;
607  break;
608  case 'PLAIN':
609  $this->socket_send_str('AUTH PLAIN', '334');
610  // The error here just means the ID/password combo doesn't work.
611  $_retVal = $this->socket_send_str(base64_encode("\0".$this->_smtpsID."\0".$this->_smtpsPW), '235');
612  break;
613  case 'XOAUTH2':
614  // "user=$email\1auth=Bearer $token\1\1"
615  $user = $this->_smtpsID;
616  $token = $this->_smtpsToken;
617  $initRes = "user=".$user."\001auth=Bearer ".$token."\001\001";
618  $_retVal = $this->socket_send_str('AUTH XOAUTH2 '.base64_encode($initRes), '235');
619  if (!$_retVal) {
620  $this->_setErr(130, 'Error when asking for AUTH XOAUTH2');
621  }
622  break;
623  case 'LOGIN': // most common case
624  default:
625  $_retVal = $this->socket_send_str('AUTH LOGIN', '334');
626  if (!$_retVal) {
627  $this->_setErr(130, 'Error when asking for AUTH LOGIN');
628  } else {
629  // User name will not return any error, server will take anything we give it.
630  $this->socket_send_str(base64_encode($this->_smtpsID), '334');
631  // The error here just means the ID/password combo doesn't work.
632  // There is no method to determine which is the problem, ID or password
633  $_retVal = $this->socket_send_str(base64_encode($this->_smtpsPW), '235');
634  }
635  break;
636  }
637  if (!$_retVal) {
638  $this->_setErr(130, 'Invalid Authentication Credentials.');
639  }
640  } else {
641  $this->_setErr(126, '"'.$host.'" does not support authenticated connections or temporary error. Error after sending EHLO '.$hosth.' : '.$this->lastretval);
642  }
643 
644  return $_retVal;
645  }
646 
652  public function sendMsg()
653  {
654  global $conf;
655 
659  $_retVal = false;
660 
661  // Connect to Server
662  if ($this->socket = $this->_server_connect()) {
663  // If a User ID *and* a password is given, assume Authentication is desired
664  if (!empty($this->_smtpsID) && (!empty($this->_smtpsPW) || !empty($this->_smtpsToken))) {
665  // Send the RFC2554 specified EHLO.
666  $_retVal = $this->_server_authenticate();
667  } else {
668  // This is a "normal" SMTP Server "handshack"
669  // Send the RFC821 specified HELO.
670  $host = $this->getHost();
671  $usetls = preg_match('@tls://@i', $host);
672 
673  $host = preg_replace('@tcp://@i', '', $host); // Remove prefix
674  $host = preg_replace('@ssl://@i', '', $host); // Remove prefix
675  $host = preg_replace('@tls://@i', '', $host); // Remove prefix
676 
677  if ($usetls && !empty($conf->global->MAIN_SMTPS_ADD_TLS_TO_HOST_FOR_HELO)) {
678  $host = 'tls://'.$host;
679  }
680 
681  $hosth = $host;
682 
683  if (!empty($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO)) {
684  if (!is_numeric($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO)) {
685  // If value of MAIL_SMTP_USE_FROM_FOR_HELO is a string, we use it as domain name
686  $hosth = $conf->global->MAIL_SMTP_USE_FROM_FOR_HELO;
687  } elseif ($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO == 1) {
688  // If value of MAIL_SMTP_USE_FROM_FOR_HELO is 1, we use the domain in the from.
689  // So if the from to is 'aaa <bbb@ccc.com>', we will keep 'ccc.com'
690  $hosth = $this->getFrom('addr');
691  $hosth = preg_replace('/^.*</', '', $hosth);
692  $hosth = preg_replace('/>.*$/', '', $hosth);
693  $hosth = preg_replace('/.*@/', '', $hosth);
694  } elseif ($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO == 2) {
695  // If value of MAIL_SMTP_USE_FROM_FOR_HELO is 2, we use the domain in the $dolibarr_main_url_root.
696  global $dolibarr_main_url_root;
697  $hosth = getDomainFromURL($dolibarr_main_url_root, 1);
698  }
699  }
700 
701  // Send the HELO message to the SMTP server
702  $_retVal = $this->socket_send_str('HELO '.$hosth, '250');
703  }
704 
705  // Well, did we get the server answer with correct code ?
706  if ($_retVal) {
707  // From this point onward most server response codes should be 250
708  // Specify who the mail is from....
709  // This has to be the raw email address, strip the "name" off
710  $resultmailfrom = $this->socket_send_str('MAIL FROM: '.$this->getFrom('addr'), '250');
711  if (!$resultmailfrom) {
712  fclose($this->socket);
713  return false;
714  }
715 
716  // 'RCPT TO:' must be given a single address, so this has to loop
717  // through the list of addresses, regardless of TO, CC or BCC
718  // and send it out "single file"
719  foreach ($this->get_RCPT_list() as $_address) {
720  /* Note:
721  * BCC email addresses must be listed in the RCPT TO command list,
722  * but the BCC header should not be printed under the DATA command.
723  * http://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server
724  */
725 
726  /*
727  * TODO
728  * After each 'RCPT TO:' is sent, we need to make sure it was kosher,
729  * if not, the whole message will fail
730  * If any email address fails, we will need to RESET the connection,
731  * mark the last address as "bad" and start the address loop over again.
732  * If any address fails, the entire message fails.
733  */
734  $this->socket_send_str('RCPT TO: <'.$_address.'>', '250');
735  }
736 
737  // Tell the server we are ready to start sending data
738  // with any custom headers...
739  // This is the last response code we look for until the end of the message.
740  $this->socket_send_str('DATA', '354');
741 
742  // Now we are ready for the message...
743  // Ok, all the ingredients are mixed in let's cook this puppy...
744  $this->socket_send_str($this->getHeader().$this->getBodyContent()."\r\n".'.', '250');
745 
746  // Now tell the server we are done and close the socket...
747  fputs($this->socket, 'QUIT');
748  } else {
749  // We got error code into $this->lastretval
750  }
751 
752  fclose($this->socket);
753  }
754 
755  return $_retVal;
756  }
757 
758  // =============================================================
759  // ** Setter & Getter methods
760 
761  // ** Basic System configuration
762 
788  public function setConfig($_strConfigPath = null)
789  {
794  $_retVal = true;
795 
796  // if we have a path...
797  if (!empty($_strConfigPath)) {
798  // If the path is not valid, this will NOT generate an error,
799  // it will simply return false.
800  if (!@include $_strConfigPath) {
801  $this->_setErr(110, '"'.$_strConfigPath.'" is not a valid path.');
802  $_retVal = false;
803  }
804  } else {
805  // Read the Systems php.ini file
806  // Set these properties ONLY if they are set in the php.ini file.
807  // Otherwise the default values will be used.
808  if ($_host = ini_get('SMTPs')) {
809  $this->setHost($_host);
810  }
811 
812  if ($_port = ini_get('smtp_port')) {
813  $this->setPort($_port);
814  }
815 
816  if ($_from = ini_get('sendmail_from')) {
817  $this->setFrom($_from);
818  }
819  }
820 
821  // Send back what we have
822  return $_retVal;
823  }
824 
834  public function setTransportType($_type = 0)
835  {
836  if ((is_numeric($_type)) && (($_type >= 0) && ($_type <= 3))) {
837  $this->_transportType = $_type;
838  }
839  }
840 
849  public function getTransportType()
850  {
851  return $this->_transportType;
852  }
853 
861  public function setMailPath($_path)
862  {
863  // This feature is not yet implemented
864  return true;
865 
866  //if ( $_path ) $this->_mailPath = $_path;
867  }
868 
877  public function setHost($_strHost)
878  {
879  if ($_strHost) {
880  $this->_smtpsHost = $_strHost;
881  }
882  }
883 
890  public function getHost()
891  {
892  return $this->_smtpsHost;
893  }
894 
903  public function setPort($_intPort)
904  {
905  if ((is_numeric($_intPort)) &&
906  (($_intPort >= 1) && ($_intPort <= 65536))) {
907  $this->_smtpsPort = $_intPort;
908  }
909  }
910 
917  public function getPort()
918  {
919  return $this->_smtpsPort;
920  }
921 
928  public function setID($_strID)
929  {
930  $this->_smtpsID = $_strID;
931  }
932 
938  public function getID()
939  {
940  return $this->_smtpsID;
941  }
942 
949  public function setPW($_strPW)
950  {
951  $this->_smtpsPW = $_strPW;
952  }
953 
959  public function getPW()
960  {
961  return $this->_smtpsPW;
962  }
963 
970  public function setToken($_strToken)
971  {
972  $this->_smtpsToken = $_strToken;
973  }
974 
980  public function getToken()
981  {
982  return $this->_smtpsToken;
983  }
984 
992  public function setCharSet($_strCharSet)
993  {
994  if ($_strCharSet) {
995  $this->_smtpsCharSet = $_strCharSet;
996  }
997  }
998 
1004  public function getCharSet()
1005  {
1006  return $this->_smtpsCharSet;
1007  }
1008 
1024  public function setTransEncode($_strTransEncode)
1025  {
1026  if (array_search($_strTransEncode, $this->_smtpsTransEncodeTypes)) {
1027  $this->_smtpsTransEncode = $_strTransEncode;
1028  }
1029  }
1030 
1036  public function getTransEncode()
1037  {
1038  return $this->_smtpsTransEncode;
1039  }
1040 
1057  public function setTransEncodeType($_strTransEncodeType)
1058  {
1059  if (array_search($_strTransEncodeType, $this->_smtpsTransEncodeTypes)) {
1060  $this->_smtpsTransEncodeType = $_strTransEncodeType;
1061  }
1062  }
1063 
1069  public function getTransEncodeType()
1070  {
1071  return $this->_smtpsTransEncodeTypes[$this->_smtpsTransEncodeType];
1072  }
1073 
1074 
1075  // ** Message Construction
1076 
1083  public function setFrom($_strFrom)
1084  {
1085  if ($_strFrom) {
1086  $this->_msgFrom = $this->_strip_email($_strFrom);
1087  }
1088  }
1089 
1096  public function getFrom($_part = true)
1097  {
1098  $_retValue = '';
1099 
1100  if ($_part === true) {
1101  $_retValue = $this->_msgFrom;
1102  } else {
1103  $_retValue = $this->_msgFrom[$_part];
1104  }
1105 
1106  return $_retValue;
1107  }
1108 
1115  public function setReplyTo($_strReplyTo)
1116  {
1117  if ($_strReplyTo) {
1118  $this->_msgReplyTo = $this->_strip_email($_strReplyTo);
1119  }
1120  }
1121 
1128  public function getReplyTo($_part = true)
1129  {
1130  $_retValue = '';
1131 
1132  if ($_part === true) {
1133  $_retValue = $this->_msgReplyTo;
1134  } else {
1135  $_retValue = $this->_msgReplyTo[$_part];
1136  }
1137 
1138  return $_retValue;
1139  }
1140 
1151  private function _buildAddrList($_type, $_addrList)
1152  {
1153  // Pull existing list
1154  $aryHost = $this->_msgRecipients;
1155 
1156  // Only run this if we have something
1157  if (!empty($_addrList)) {
1158  // $_addrList can be a STRING or an array
1159  if (is_string($_addrList)) {
1160  // This could be a COMMA delimited string
1161  if (strstr($_addrList, ',')) {
1162  // "explode "list" into an array
1163  $_addrList = explode(',', $_addrList);
1164  } else {
1165  // Stick it in an array
1166  $_addrList = array($_addrList);
1167  }
1168  }
1169 
1170  // take the array of addresses and split them further
1171  foreach ($_addrList as $_strAddr) {
1172  // Strip off the end '>'
1173  $_strAddr = str_replace('>', '', $_strAddr);
1174 
1175  // Seperate "Real Name" from eMail address
1176  $_tmpaddr = null;
1177  $_tmpaddr = explode('<', $_strAddr);
1178 
1179  // We have a "Real Name" and eMail address
1180  if (count($_tmpaddr) == 2) {
1181  $_tmpHost = explode('@', $_tmpaddr[1]);
1182  $_tmpaddr[0] = trim($_tmpaddr[0], ' ">');
1183  $aryHost[$_tmpHost[1]][$_type][$_tmpHost[0]] = $_tmpaddr[0];
1184  } else {
1185  // We only have an eMail address
1186  // Strip off the beggining '<'
1187  $_strAddr = str_replace('<', '', $_strAddr);
1188 
1189  $_tmpHost = explode('@', $_strAddr);
1190  $_tmpHost[0] = trim($_tmpHost[0]);
1191  $_tmpHost[1] = trim($_tmpHost[1]);
1192 
1193  $aryHost[$_tmpHost[1]][$_type][$_tmpHost[0]] = '';
1194  }
1195  }
1196  }
1197  // replace list
1198  $this->_msgRecipients = $aryHost;
1199  }
1200 
1201  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1218  private function _strip_email($_strAddr)
1219  {
1220  // phpcs:enable
1221  // Keep the orginal
1222  $_aryEmail['org'] = $_strAddr;
1223 
1224  // Set entire string to Lower Case
1225  $_strAddr = strtolower($_strAddr);
1226 
1227  // Drop "stuff' off the end
1228  $_strAddr = trim($_strAddr, ' ">');
1229 
1230  // Seperate "Real Name" from eMail address, if we have one
1231  $_tmpAry = explode('<', $_strAddr);
1232 
1233  // Do we have a "Real name"
1234  if (count($_tmpAry) == 2) {
1235  // We may not really have a "Real Name"
1236  if ($_tmpAry[0]) {
1237  $_aryEmail['real'] = trim($_tmpAry[0], ' ">');
1238  }
1239 
1240  $_aryEmail['addr'] = $_tmpAry[1];
1241  } else {
1242  $_aryEmail['addr'] = $_tmpAry[0];
1243  }
1244 
1245  // Pull User Name and Host.tld apart
1246  $_tmpHost = explode('@', $_aryEmail['addr']);
1247  $_aryEmail['user'] = $_tmpHost[0];
1248  $_aryEmail['host'] = $_tmpHost[1];
1249 
1250  // Put the brackets back around the address
1251  $_aryEmail['addr'] = '<'.$_aryEmail['addr'].'>';
1252 
1253  return $_aryEmail;
1254  }
1255 
1256  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1264  public function get_RCPT_list()
1265  {
1266  // phpcs:enable
1270  $_RCPT_list = array();
1271 
1272  // walk down Recipients array and pull just email addresses
1273  foreach ($this->_msgRecipients as $_host => $_list) {
1274  foreach ($_list as $_subList) {
1275  foreach ($_subList as $_name => $_addr) {
1276  // build RCPT list
1277  $_RCPT_list[] = $_name.'@'.$_host;
1278  }
1279  }
1280  }
1281 
1282  return $_RCPT_list;
1283  }
1284 
1285  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1292  public function get_email_list($_which = null)
1293  {
1294  // phpcs:enable
1295  // We need to know which address segment to pull
1296  if ($_which) {
1297  // Make sure we have addresses to process
1298  if ($this->_msgRecipients) {
1299  $_RCPT_list = array();
1300  // walk down Recipients array and pull just email addresses
1301  foreach ($this->_msgRecipients as $_host => $_list) {
1302  if (!empty($this->_msgRecipients[$_host][$_which])) {
1303  foreach ($this->_msgRecipients[$_host][$_which] as $_addr => $_realName) {
1304  if ($_realName) { // @CHANGE LDR
1305  $_realName = '"'.$_realName.'"';
1306  $_RCPT_list[] = $_realName.' <'.$_addr.'@'.$_host.'>';
1307  } else {
1308  $_RCPT_list[] = $_addr.'@'.$_host;
1309  }
1310  }
1311  }
1312  }
1313 
1314  return implode(', ', $_RCPT_list);
1315  } else {
1316  $this->_setErr(101, 'No eMail Address for message to be sent to.');
1317  return false;
1318  }
1319  } else {
1320  $this->_setErr(102, 'eMail type not defined.');
1321  return false;
1322  }
1323  }
1324 
1331  public function setTO($_addrTo)
1332  {
1333  if ($_addrTo) {
1334  $this->_buildAddrList('to', $_addrTo);
1335  }
1336  }
1337 
1343  public function getTo()
1344  {
1345  return $this->get_email_list('to');
1346  }
1347 
1354  public function setCC($_strCC)
1355  {
1356  if ($_strCC) {
1357  $this->_buildAddrList('cc', $_strCC);
1358  }
1359  }
1360 
1366  public function getCC()
1367  {
1368  return $this->get_email_list('cc');
1369  }
1370 
1377  public function setBCC($_strBCC)
1378  {
1379  if ($_strBCC) {
1380  $this->_buildAddrList('bcc', $_strBCC);
1381  }
1382  }
1383 
1389  public function getBCC()
1390  {
1391  return $this->get_email_list('bcc');
1392  }
1393 
1400  public function setSubject($_strSubject = '')
1401  {
1402  if ($_strSubject) {
1403  $this->_msgSubject = $_strSubject;
1404  }
1405  }
1406 
1412  public function getSubject()
1413  {
1414  return $this->_msgSubject;
1415  }
1416 
1422  public function getHeader()
1423  {
1424  global $conf;
1425 
1426  $_header = 'From: '.$this->getFrom('org')."\r\n"
1427  . 'To: '.$this->getTO()."\r\n";
1428 
1429  if ($this->getCC()) {
1430  $_header .= 'Cc: '.$this->getCC()."\r\n";
1431  }
1432 
1433  /* Note:
1434  * BCC email addresses must be listed in the RCPT TO command list,
1435  * but the BCC header should not be printed under the DATA command.
1436  * So it is included into the function sendMsg() but not here.
1437  * http://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server
1438  */
1439  /*
1440  if ( $this->getBCC() )
1441  $_header .= 'Bcc: ' . $this->getBCC() . "\r\n";
1442  */
1443 
1444  $host = dol_getprefix('email');
1445 
1446  //NOTE: Message-ID should probably contain the username of the user who sent the msg
1447  $_header .= 'Subject: '.$this->getSubject()."\r\n";
1448  $_header .= 'Date: '.date("r")."\r\n";
1449 
1450  $trackid = $this->getTrackId();
1451  if ($trackid) {
1452  // References is kept in response and Message-ID is returned into In-Reply-To:
1453  $_header .= 'Message-ID: <'.time().'.SMTPs-dolibarr-'.$trackid.'@'.$host.">\r\n";
1454  $_header .= 'References: <'.time().'.SMTPs-dolibarr-'.$trackid.'@'.$host.">\r\n";
1455  $_header .= 'X-Dolibarr-TRACKID: '.$trackid.'@'.$host."\r\n";
1456  } else {
1457  $_header .= 'Message-ID: <'.time().'.SMTPs@'.$host.">\r\n";
1458  }
1459  if (!empty($_SERVER['REMOTE_ADDR'])) {
1460  $_header .= "X-RemoteAddr: ".$_SERVER['REMOTE_ADDR']."\r\n";
1461  }
1462  if ($this->getMoreInHeader()) {
1463  $_header .= $this->getMoreInHeader(); // Value must include the "\r\n";
1464  }
1465 
1466  //$_header .=
1467  // 'Read-Receipt-To: ' . $this->getFrom( 'org' ) . "\r\n"
1468  // 'Return-Receipt-To: ' . $this->getFrom( 'org' ) . "\r\n";
1469 
1470  if ($this->getSensitivity()) {
1471  $_header .= 'Sensitivity: '.$this->getSensitivity()."\r\n";
1472  }
1473 
1474  if ($this->_msgPriority != 3) {
1475  $_header .= $this->getPriority();
1476  }
1477 
1478 
1479  // @CHANGE LDR
1480  if ($this->getDeliveryReceipt()) {
1481  $_header .= 'Disposition-Notification-To: '.$this->getFrom('addr')."\r\n";
1482  }
1483  if ($this->getErrorsTo()) {
1484  $_header .= 'Errors-To: '.$this->getErrorsTo('addr')."\r\n";
1485  }
1486  if ($this->getReplyTo()) {
1487  $_header .= "Reply-To: ".$this->getReplyTo('addr')."\r\n";
1488  }
1489 
1490  $_header .= 'X-Mailer: Dolibarr version '.DOL_VERSION.' (using SMTPs Mailer)'."\r\n";
1491  $_header .= 'X-Dolibarr-Option: '.($conf->global->MAIN_MAIL_USE_MULTI_PART ? 'MAIN_MAIL_USE_MULTI_PART' : 'No MAIN_MAIL_USE_MULTI_PART')."\r\n";
1492  $_header .= 'Mime-Version: 1.0'."\r\n";
1493 
1494 
1495  return $_header;
1496  }
1497 
1505  public function setBodyContent($strContent, $strType = 'plain')
1506  {
1507  //if ( $strContent )
1508  //{
1509  if ($strType == 'html') {
1510  $strMimeType = 'text/html';
1511  } else {
1512  $strMimeType = 'text/plain';
1513  }
1514 
1515  // Make RFC821 Compliant, replace bare linefeeds
1516  $strContent = preg_replace("/(?<!\r)\n/si", "\r\n", $strContent);
1517 
1518  $strContentAltText = '';
1519  if ($strType == 'html') {
1520  // Similar code to forge a text from html is also in CMailFile.class.php
1521  $strContentAltText = preg_replace('/<head><title>.*<\/style><\/head>/', '', $strContent);
1522  $strContentAltText = preg_replace("/<br\s*[^>]*>/", " ", $strContentAltText);
1523  $strContentAltText = html_entity_decode(strip_tags($strContentAltText));
1524  $strContentAltText = trim(wordwrap($strContentAltText, 75, "\r\n"));
1525  }
1526 
1527  // Make RFC2045 Compliant
1528  //$strContent = rtrim(chunk_split($strContent)); // Function chunck_split seems ko if not used on a base64 content
1529  $strContent = rtrim(wordwrap($strContent, 75, "\r\n")); // TODO Using this method creates unexpected line break on text/plain content.
1530 
1531  $this->_msgContent[$strType] = array();
1532 
1533  $this->_msgContent[$strType]['mimeType'] = $strMimeType;
1534  $this->_msgContent[$strType]['data'] = $strContent;
1535  $this->_msgContent[$strType]['dataText'] = $strContentAltText;
1536 
1537  if ($this->getMD5flag()) {
1538  $this->_msgContent[$strType]['md5'] = dol_hash($strContent, 3);
1539  }
1540  //}
1541  }
1542 
1548  public function getBodyContent()
1549  {
1550  global $conf;
1551 
1552  // Generate a new Boundary string
1553  $this->_setBoundary();
1554 
1555  // What type[s] of content do we have
1556  $_types = array_keys($this->_msgContent);
1557 
1558  // How many content types do we have
1559  $keyCount = count($_types);
1560 
1561  // If we have ZERO, we have a problem
1562  if ($keyCount === 0) {
1563  die("Sorry, no content");
1564  } elseif ($keyCount === 1 && empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) {
1565  // If we have ONE, we can use the simple format
1566  $_msgData = $this->_msgContent;
1567  $_msgData = $_msgData[$_types[0]];
1568 
1569  $content = 'Content-Type: '.$_msgData['mimeType'].'; charset="'.$this->getCharSet().'"'."\r\n"
1570  . 'Content-Transfer-Encoding: '.$this->getTransEncodeType()."\r\n"
1571  . 'Content-Disposition: inline'."\r\n"
1572  . 'Content-Description: Message'."\r\n";
1573 
1574  if ($this->getMD5flag()) {
1575  $content .= 'Content-MD5: '.$_msgData['md5']."\r\n";
1576  }
1577 
1578  $content .= "\r\n"
1579  . $_msgData['data']."\r\n";
1580  } elseif ($keyCount >= 1 || !empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) {
1581  // If we have more than ONE, we use the multi-part format
1582  // Since this is an actual multi-part message
1583  // We need to define a content message Boundary
1584  // NOTE: This was 'multipart/alternative', but Windows based mail servers have issues with this.
1585 
1586  //$content = 'Content-Type: multipart/related; boundary="' . $this->_getBoundary() . '"' . "\r\n";
1587  $content = 'Content-Type: multipart/mixed; boundary="'.$this->_getBoundary('mixed').'"'."\r\n";
1588 
1589  // . "\r\n"
1590  // . 'This is a multi-part message in MIME format.' . "\r\n";
1591  $content .= "Content-Transfer-Encoding: 8bit\r\n";
1592  $content .= "\r\n";
1593 
1594  $content .= "--".$this->_getBoundary('mixed')."\r\n";
1595 
1596  if (key_exists('image', $this->_msgContent)) { // If inline image found
1597  $content .= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"'."\r\n";
1598  $content .= "\r\n";
1599  $content .= "--".$this->_getBoundary('alternative')."\r\n";
1600  }
1601 
1602 
1603  // $this->_msgContent must be sorted with key 'text' or 'html' first then 'image' then 'attachment'
1604 
1605 
1606  // Loop through message content array
1607  foreach ($this->_msgContent as $type => $_content) {
1608  if ($type == 'attachment') {
1609  // loop through all attachments
1610  foreach ($_content as $_file => $_data) {
1611  $content .= "--".$this->_getBoundary('mixed')."\r\n"
1612  . 'Content-Disposition: attachment; filename="'.$_data['fileName'].'"'."\r\n"
1613  . 'Content-Type: '.$_data['mimeType'].'; name="'.$_data['fileName'].'"'."\r\n"
1614  . 'Content-Transfer-Encoding: base64'."\r\n"
1615  . 'Content-Description: '.$_data['fileName']."\r\n";
1616  if (!empty($_data['cid'])) {
1617  $content .= "X-Attachment-Id: ".$_data['cid']."\r\n";
1618  $content .= "Content-ID: <".$_data['cid'].">\r\n";
1619  }
1620  if ($this->getMD5flag()) {
1621  $content .= 'Content-MD5: '.$_data['md5']."\r\n";
1622  }
1623 
1624  $content .= "\r\n".$_data['data']."\r\n\r\n";
1625  }
1626  } elseif ($type == 'image') {
1627  // @CHANGE LDR
1628  // loop through all images
1629  foreach ($_content as $_image => $_data) {
1630  $content .= "--".$this->_getBoundary('related')."\r\n"; // always related for an inline image
1631 
1632  $content .= 'Content-Type: '.$_data['mimeType'].'; name="'.$_data['imageName'].'"'."\r\n"
1633  . 'Content-Transfer-Encoding: base64'."\r\n"
1634  . 'Content-Disposition: inline; filename="'.$_data['imageName'].'"'."\r\n"
1635  . 'Content-ID: <'.$_data['cid'].'> '."\r\n";
1636 
1637  if ($this->getMD5flag()) {
1638  $content .= 'Content-MD5: '.$_data['md5']."\r\n";
1639  }
1640 
1641  $content .= "\r\n"
1642  . $_data['data']."\r\n";
1643  }
1644 
1645  // always end related and end alternative after inline images
1646  $content .= "--".$this->_getBoundary('related')."--\r\n";
1647  $content .= "\r\n--".$this->_getBoundary('alternative')."--\r\n";
1648  $content .= "\r\n";
1649  } else {
1650  if (key_exists('image', $this->_msgContent)) {
1651  $content .= "Content-Type: text/plain; charset=".$this->getCharSet()."\r\n";
1652  $content .= "\r\n".($_content['dataText'] ? $_content['dataText'] : strip_tags($_content['data']))."\r\n"; // Add plain text message
1653  $content .= "--".$this->_getBoundary('alternative')."\r\n";
1654  $content .= 'Content-Type: multipart/related; boundary="'.$this->_getBoundary('related').'"'."\r\n";
1655  $content .= "\r\n";
1656  $content .= "--".$this->_getBoundary('related')."\r\n";
1657  }
1658 
1659  if (!key_exists('image', $this->_msgContent) && $_content['dataText'] && !empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) {
1660  // Add plain text message part before html part
1661  $content .= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"'."\r\n";
1662  $content .= "\r\n";
1663  $content .= "--".$this->_getBoundary('alternative')."\r\n";
1664 
1665  $content .= "Content-Type: text/plain; charset=".$this->getCharSet()."\r\n";
1666  $content .= "\r\n".$_content['dataText']."\r\n";
1667  $content .= "--".$this->_getBoundary('alternative')."\r\n";
1668  }
1669 
1670  $content .= 'Content-Type: '.$_content['mimeType'].'; charset='.$this->getCharSet();
1671 
1672  $content .= "\r\n";
1673 
1674  if ($this->getMD5flag()) {
1675  $content .= 'Content-MD5: '.$_content['md5']."\r\n";
1676  }
1677 
1678  $content .= "\r\n".$_content['data']."\r\n";
1679 
1680  if (!key_exists('image', $this->_msgContent) && $_content['dataText'] && !empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) {
1681  // Add plain text message part after html part
1682  $content .= "--".$this->_getBoundary('alternative')."--\r\n";
1683  }
1684 
1685  $content .= "\r\n";
1686  }
1687  }
1688 
1689  $content .= "--".$this->_getBoundary('mixed').'--'."\r\n";
1690  }
1691 
1692  return $content;
1693  }
1694 
1705  public function setAttachment($strContent, $strFileName = 'unknown', $strMimeType = 'unknown', $strCid = '')
1706  {
1707  if ($strContent) {
1708  $strContent = rtrim(chunk_split(base64_encode($strContent), 76, "\r\n")); // 76 max is defined into http://tools.ietf.org/html/rfc2047
1709 
1710  $this->_msgContent['attachment'][$strFileName]['mimeType'] = $strMimeType;
1711  $this->_msgContent['attachment'][$strFileName]['fileName'] = $strFileName;
1712  $this->_msgContent['attachment'][$strFileName]['data'] = $strContent;
1713  $this->_msgContent['attachment'][$strFileName]['cid'] = $strCid; // If defined, it means this attachment must be shown inline
1714 
1715  if ($this->getMD5flag()) {
1716  $this->_msgContent['attachment'][$strFileName]['md5'] = dol_hash($strContent, 3);
1717  }
1718  }
1719  }
1720 
1721 
1722  // @CHANGE LDR
1723 
1734  public function setImageInline($strContent, $strImageName = 'unknown', $strMimeType = 'unknown', $strImageCid = 'unknown')
1735  {
1736  if ($strContent) {
1737  $this->_msgContent['image'][$strImageName]['mimeType'] = $strMimeType;
1738  $this->_msgContent['image'][$strImageName]['imageName'] = $strImageName;
1739  $this->_msgContent['image'][$strImageName]['cid'] = $strImageCid;
1740  $this->_msgContent['image'][$strImageName]['data'] = $strContent;
1741 
1742  if ($this->getMD5flag()) {
1743  $this->_msgContent['image'][$strImageName]['md5'] = dol_hash($strContent, 3);
1744  }
1745  }
1746  }
1747  // END @CHANGE LDR
1748 
1749 
1761  public function setSensitivity($_value = 0)
1762  {
1763  if ((is_numeric($_value)) &&
1764  (($_value >= 0) && ($_value <= 3))) {
1765  $this->_msgSensitivity = $_value;
1766  }
1767  }
1768 
1779  public function getSensitivity()
1780  {
1781  return $this->_arySensitivity[$this->_msgSensitivity];
1782  }
1783 
1797  public function setPriority($_value = 3)
1798  {
1799  if ((is_numeric($_value)) &&
1800  (($_value >= 0) && ($_value <= 5))) {
1801  $this->_msgPriority = $_value;
1802  }
1803  }
1804 
1817  public function getPriority()
1818  {
1819  return 'Importance: '.$this->_aryPriority[$this->_msgPriority]."\r\n"
1820  . 'Priority: '.$this->_aryPriority[$this->_msgPriority]."\r\n"
1821  . 'X-Priority: '.$this->_msgPriority.' ('.$this->_aryPriority[$this->_msgPriority].')'."\r\n";
1822  }
1823 
1830  public function setMD5flag($_flag = false)
1831  {
1832  $this->_smtpMD5 = $_flag;
1833  }
1834 
1840  public function getMD5flag()
1841  {
1842  return $this->_smtpMD5;
1843  }
1844 
1853  public function setXheader($strXdata)
1854  {
1855  if ($strXdata) {
1856  $this->_msgXheader[] = $strXdata;
1857  }
1858  }
1859 
1865  public function getXheader()
1866  {
1867  return $this->_msgXheader;
1868  }
1869 
1875  private function _setBoundary()
1876  {
1877  $this->_smtpsBoundary = "multipart_x.".time().".x_boundary";
1878  $this->_smtpsRelatedBoundary = 'mul_'.dol_hash(uniqid("dolibarr2"), 3);
1879  $this->_smtpsAlternativeBoundary = 'mul_'.dol_hash(uniqid("dolibarr3"), 3);
1880  }
1881 
1888  private function _getBoundary($type = 'mixed')
1889  {
1890  if ($type == 'mixed') {
1891  return $this->_smtpsBoundary;
1892  } elseif ($type == 'related') {
1894  } elseif ($type == 'alternative') {
1896  }
1897  return '';
1898  }
1899 
1900  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1911  public function server_parse($socket, $response)
1912  {
1913  // phpcs:enable
1918  $_retVal = true;
1919 
1920  $server_response = '';
1921 
1922  // avoid infinite loop
1923  $limit = 0;
1924 
1925  while (substr($server_response, 3, 1) != ' ' && $limit < 100) {
1926  if (!($server_response = fgets($socket, 256))) {
1927  $this->_setErr(121, "Couldn't get mail server response codes");
1928  $_retVal = false;
1929  break;
1930  }
1931  $this->log .= $server_response;
1932  $limit++;
1933  }
1934 
1935  $this->lastretval = substr($server_response, 0, 3);
1936 
1937  if (!(substr($server_response, 0, 3) == $response)) {
1938  $this->_setErr(120, "Ran into problems sending Mail.\r\nResponse: ".$server_response);
1939  $_retVal = false;
1940  }
1941 
1942  return $_retVal;
1943  }
1944 
1945  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1954  public function socket_send_str($_strSend, $_returnCode = null, $CRLF = "\r\n")
1955  {
1956  // phpcs:enable
1957  if ($this->_debug) {
1958  $this->log .= $_strSend; // @CHANGE LDR for log
1959  }
1960  fputs($this->socket, $_strSend.$CRLF);
1961  if ($this->_debug) {
1962  $this->log .= ' ('.$_returnCode.')'.$CRLF;
1963  }
1964 
1965  if ($_returnCode) {
1966  return $this->server_parse($this->socket, $_returnCode);
1967  }
1968 
1969  return null;
1970  }
1971 
1972  // =============================================================
1973  // ** Error handling methods
1974 
1982  private function _setErr($_errNum, $_errMsg)
1983  {
1984  $this->_smtpsErrors[] = array(
1985  'num' => $_errNum,
1986  'msg' => $_errMsg,
1987  );
1988  }
1989 
1995  public function getErrors()
1996  {
1997  $_errMsg = array();
1998 
1999  if (is_array($this->_smtpsErrors)) {
2000  foreach ($this->_smtpsErrors as $_err => $_info) {
2001  $_errMsg[] = 'Error ['.$_info['num'].']: '.$_info['msg'];
2002  }
2003  }
2004 
2005  return implode("\n", $_errMsg);
2006  }
2007 }
2008 
2009 
2010 // =============================================================
2011 // ** CSV Version Control Info
2012 
SMTPs\$_msgXheader
$_msgXheader
Custom X-Headers.
Definition: smtps.class.php:110
SMTPs\setTransEncode
setTransEncode($_strTransEncode)
Content-Transfer-Encoding, Defaulted to '7bit' This can be changed for 2byte characers sets Known Enc...
Definition: smtps.class.php:1024
SMTPs\setReplyTo
setReplyTo($_strReplyTo)
Reply-To Address from which mail will be the reply-to.
Definition: smtps.class.php:1115
SMTPs\$_msgReplyTo
$_msgReplyTo
Where are replies and errors to be sent to This can be defined via a INI file or via a setter method.
Definition: smtps.class.php:86
SMTPs\getBodyContent
getBodyContent()
Retrieves the Message Content.
Definition: smtps.class.php:1548
SMTPs\getPort
getPort()
Retrieves the Port Number of the Mail Server to use This is used only with 'socket' based mail transm...
Definition: smtps.class.php:917
SMTPs\getSensitivity
getSensitivity()
Returns Message Content Sensitivity string Message Sensitivity values:
Definition: smtps.class.php:1779
SMTPs\setTrackId
setTrackId($_val='')
Set trackid.
Definition: smtps.class.php:298
SMTPs\_strip_email
_strip_email($_strAddr)
Returns an array of the various parts of an email address This assumes a well formed address:
Definition: smtps.class.php:1218
SMTPs\$_smtpsCharSet
$_smtpsCharSet
Character set Defaulted to 'iso-8859-1'.
Definition: smtps.class.php:116
SMTPs\getTo
getTo()
Retrieves the TO Address[es] inwhich to send mail to.
Definition: smtps.class.php:1343
SMTPs\setTransportType
setTransportType($_type=0)
Determines the method inwhich the messages are to be sent.
Definition: smtps.class.php:834
SMTPs\setToken
setToken($_strToken)
User token for OAUTH2.
Definition: smtps.class.php:970
SMTPs\getID
getID()
Retrieves the User Name for authentication on Mail Server.
Definition: smtps.class.php:938
SMTPs\get_RCPT_list
get_RCPT_list()
Returns an array of bares addresses for use with 'RCPT TO:' This is a "build as you go" method.
Definition: smtps.class.php:1264
SMTPs\setTO
setTO($_addrTo)
TO Address[es] inwhich to send mail to.
Definition: smtps.class.php:1331
SMTPs\$_msgSubject
$_msgSubject
Message Subject.
Definition: smtps.class.php:98
SMTPs\get_email_list
get_email_list($_which=null)
Returns an array of addresses for a specific type; TO, CC or BCC.
Definition: smtps.class.php:1292
SMTPs\$_smtpsPort
$_smtpsPort
SMTP Server Port definition.
Definition: smtps.class.php:57
SMTPs\getPW
getPW()
Retrieves the User Password for authentication on Mail Server.
Definition: smtps.class.php:959
SMTPs\_setErr
_setErr($_errNum, $_errMsg)
Defines errors codes and messages for Class.
Definition: smtps.class.php:1982
SMTPs\setMailPath
setMailPath($_path)
Path to the sendmail execuable.
Definition: smtps.class.php:861
SMTPs\getBCC
getBCC()
Retrieves the BCC Address[es] inwhich to send mail to.
Definition: smtps.class.php:1389
SMTPs
Class to construct and send SMTP compliant email, even to a secure SMTP server, regardless of platfor...
Definition: smtps.class.php:46
SMTPs\$_msgRecipients
$_msgRecipients
Who will the Message be sent to; TO, CC, BCC Multi-diminsional array containg addresses the message w...
Definition: smtps.class.php:93
SMTPs\setPW
setPW($_strPW)
User Password for authentication on Mail Server.
Definition: smtps.class.php:949
SMTPs\setHost
setHost($_strHost)
Defines the Host Name or IP of the Mail Server to use.
Definition: smtps.class.php:877
SMTPs\getCC
getCC()
Retrieves the CC Address[es] inwhich to send mail to.
Definition: smtps.class.php:1366
SMTPs\setPriority
setPriority($_value=3)
Message Content Priority Message Priority values:
Definition: smtps.class.php:1797
SMTPs\getErrors
getErrors()
Returns applicative errors codes and messages for Class (not the SMTP error code)
Definition: smtps.class.php:1995
SMTPs\setDebug
setDebug($_vDebug=false)
Set debug.
Definition: smtps.class.php:372
SMTPs\getTransEncodeType
getTransEncodeType()
Retrieves the Content-Transfer-Encoding.
Definition: smtps.class.php:1069
SMTPs\$_smtpsRelatedBoundary
$_smtpsRelatedBoundary
Related Boundary.
Definition: smtps.class.php:179
SMTPs\_setBoundary
_setBoundary()
Generates Random string for MIME message Boundary.
Definition: smtps.class.php:1875
SMTPs\getFrom
getFrom($_part=true)
Retrieves the Address from which mail will be sent.
Definition: smtps.class.php:1096
SMTPs\setImageInline
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...
Definition: smtps.class.php:1734
SMTPs\$_options
$_options
An array of options for stream_context_create()
Definition: smtps.class.php:258
SMTPs\_server_connect
_server_connect()
Attempt a connection to mail server.
Definition: smtps.class.php:394
SMTPs\setPort
setPort($_intPort)
Defines the Port Number of the Mail Server to use This is defaulted to '25' This is used only with 's...
Definition: smtps.class.php:903
SMTPs\$_aryPriority
$_aryPriority
Message Priority.
Definition: smtps.class.php:141
SMTPs\setBCC
setBCC($_strBCC)
BCC Address[es] inwhich to send mail to.
Definition: smtps.class.php:1377
SMTPs\setTransEncodeType
setTransEncodeType($_strTransEncodeType)
Content-Transfer-Encoding, Defaulted to '0' [ZERO] This can be changed for 2byte characers sets Known...
Definition: smtps.class.php:1057
SMTPs\socket_send_str
socket_send_str($_strSend, $_returnCode=null, $CRLF="\r\n")
Send str.
Definition: smtps.class.php:1954
dol_hash
dol_hash($chain, $type='0')
Returns a hash (non reversible encryption) of a string.
Definition: security.lib.php:221
SMTPs\$_debug
$_debug
Place Class in" debug" mode.
Definition: smtps.class.php:228
SMTPs\setSubject
setSubject($_strSubject='')
Message Subject.
Definition: smtps.class.php:1400
SMTPs\getSubject
getSubject()
Retrieves the Message Subject.
Definition: smtps.class.php:1412
SMTPs\setXheader
setXheader($strXdata)
Message X-Header Content This is a simple "insert".
Definition: smtps.class.php:1853
SMTPs\getDeliveryReceipt
getDeliveryReceipt()
get delivery receipt
Definition: smtps.class.php:287
SMTPs\getErrorsTo
getErrorsTo($_part=true)
Get errors to.
Definition: smtps.class.php:353
SMTPs\getReplyTo
getReplyTo($_part=true)
Retrieves the Address from which mail will be the reply-to.
Definition: smtps.class.php:1128
SMTPs\$_mailPath
$_mailPath
If '$_transportType' is set to '1', then this variable is used to define the UNIX file system path to...
Definition: smtps.class.php:199
SMTPs\getCharSet
getCharSet()
Retrieves the Character set used for current message.
Definition: smtps.class.php:1004
SMTPs\sendMsg
sendMsg()
Now send the message.
Definition: smtps.class.php:652
SMTPs\setAttachment
setAttachment($strContent, $strFileName='unknown', $strMimeType='unknown', $strCid='')
File attachments are added to the content array as sub-arrays, allowing for multiple attachments for ...
Definition: smtps.class.php:1705
SMTPs\setMD5flag
setMD5flag($_flag=false)
Set flag which determines whether to calculate message MD5 checksum.
Definition: smtps.class.php:1830
SMTPs\getMoreInHeader
getMoreInHeader()
get moreInHeader
Definition: smtps.class.php:329
SMTPs\setDeliveryReceipt
setDeliveryReceipt($_val=0)
Set delivery receipt.
Definition: smtps.class.php:277
SMTPs\setCharSet
setCharSet($_strCharSet)
Character set used for current message Character set is defaulted to 'iso-8859-1';.
Definition: smtps.class.php:992
SMTPs\getXheader
getXheader()
Retrieves the Message X-Header Content.
Definition: smtps.class.php:1865
SMTPs\setConfig
setConfig($_strConfigPath=null)
setConfig() is used to populate select class properties from either a user defined INI file or the sy...
Definition: smtps.class.php:788
SMTPs\$_msgPriority
$_msgPriority
Message Sensitivity Defaults to 3 - Normal.
Definition: smtps.class.php:136
getDomainFromURL
getDomainFromURL($url, $mode=0)
Function get second level domain name.
Definition: geturl.lib.php:345
SMTPs\$_smtpsAlternativeBoundary
$_smtpsAlternativeBoundary
Alternative Boundary.
Definition: smtps.class.php:184
SMTPs\$_msgFrom
$_msgFrom
Who sent the Message This can be defined via a INI file or via a setter method.
Definition: smtps.class.php:80
SMTPs\setID
setID($_strID)
User Name for authentication on Mail Server.
Definition: smtps.class.php:928
SMTPs\$_arySensitivity
$_arySensitivity
Message Sensitivity.
Definition: smtps.class.php:127
SMTPs\setErrorsTo
setErrorsTo($_strErrorsTo)
Set errors to.
Definition: smtps.class.php:340
SMTPs\setMoreInHeader
setMoreInHeader($_val='')
Set moreInHeader.
Definition: smtps.class.php:309
SMTPs\$_smtpsToken
$_smtpsToken
Token in case we use OAUTH2.
Definition: smtps.class.php:74
SMTPs\_buildAddrList
_buildAddrList($_type, $_addrList)
Inserts given addresses into structured format.
Definition: smtps.class.php:1151
SMTPs\buildRCPTlist
buildRCPTlist()
build RECIPIENT List, all addresses who will recieve this message
Definition: smtps.class.php:382
SMTPs\setBodyContent
setBodyContent($strContent, $strType='plain')
Message Content.
Definition: smtps.class.php:1505
SMTPs\$_smtpsHost
$_smtpsHost
Host Name or IP of SMTP Server to use.
Definition: smtps.class.php:51
SMTPs\getMD5flag
getMD5flag()
Gets flag which determines whether to calculate message MD5 checksum.
Definition: smtps.class.php:1840
SMTPs\$_smtpsPW
$_smtpsPW
Secure SMTP Server access Password This can be defined via a INI file or via a setter method.
Definition: smtps.class.php:69
SMTPs\setOptions
setOptions($_options=array())
Set delivery receipt.
Definition: smtps.class.php:266
SMTPs\_server_authenticate
_server_authenticate()
Attempt mail server authentication for a secure connection.
Definition: smtps.class.php:472
SMTPs\getTransEncode
getTransEncode()
Retrieves the Content-Transfer-Encoding.
Definition: smtps.class.php:1036
SMTPs\$_smtpTimeout
$_smtpTimeout
Sets the SMTP server timeout in seconds.
Definition: smtps.class.php:204
SMTPs\$_smtpsTransEncodeTypes
$_smtpsTransEncodeTypes
Content-Transfer-Encoding.
Definition: smtps.class.php:157
SMTPs\getPriority
getPriority()
Message Content Priority Message Priority values:
Definition: smtps.class.php:1817
SMTPs\server_parse
server_parse($socket, $response)
This function has been modified as provided by SirSir to allow multiline responses when using SMTP Ex...
Definition: smtps.class.php:1911
SMTPs\$_smtpsTransEncodeType
$_smtpsTransEncodeType
Content-Transfer-Encoding Defaulted to 0 - 7bit.
Definition: smtps.class.php:152
SMTPs\$_msgSensitivity
$_msgSensitivity
Message Sensitivity Defaults to ZERO - None.
Definition: smtps.class.php:122
SMTPs\getToken
getToken()
Retrieves the User token for OAUTH2.
Definition: smtps.class.php:980
SMTPs\setFrom
setFrom($_strFrom)
FROM Address from which mail will be sent.
Definition: smtps.class.php:1083
SMTPs\getTrackId
getTrackId()
get trackid
Definition: smtps.class.php:319
SMTPs\$_smtpsErrors
$_smtpsErrors
Class error codes and messages.
Definition: smtps.class.php:214
SMTPs\$_log_level
$_log_level
Defines log level 0 - no logging 1 - connectivity logging 2 - message generation logging 3 - detail l...
Definition: smtps.class.php:223
SMTPs\$_smtpsID
$_smtpsID
Secure SMTP Server access ID This can be defined via a INI file or via a setter method.
Definition: smtps.class.php:63
SMTPs\$_transportType
$_transportType
Determines the method inwhich the message are to be sent.
Definition: smtps.class.php:193
SMTPs\setCC
setCC($_strCC)
CC Address[es] inwhich to send mail to.
Definition: smtps.class.php:1354
is_ip
is_ip($ip)
This function evaluates a string that should be a valid IPv4 Note: For ip 169.254....
Definition: functions2.lib.php:2018
SMTPs\getHeader
getHeader()
Constructes and returns message header.
Definition: smtps.class.php:1422
SMTPs\getTransportType
getTransportType()
Return the method inwhich the message is to be sent.
Definition: smtps.class.php:849
SMTPs\setSensitivity
setSensitivity($_value=0)
Message Content Sensitivity Message Sensitivity values:
Definition: smtps.class.php:1761
SMTPs\$_smtpMD5
$_smtpMD5
Determines whether to calculate message MD5 checksum.
Definition: smtps.class.php:209
SMTPs\$_smtpsTransEncode
$_smtpsTransEncode
Content-Transfer-Encoding Defaulted to '7bit'.
Definition: smtps.class.php:169
SMTPs\getHost
getHost()
Retrieves the Host Name or IP of the Mail Server to use This is used only with 'socket' based mail tr...
Definition: smtps.class.php:890
SMTPs\_getBoundary
_getBoundary($type='mixed')
Retrieves the MIME message Boundary.
Definition: smtps.class.php:1888
SMTPs\$_smtpsBoundary
$_smtpsBoundary
Boundary String for MIME seperation.
Definition: smtps.class.php:174