dolibarr  17.0.4
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 
103  private $_msgContent = null;
104 
108  private $_msgXheader = null;
109 
114  private $_smtpsCharSet = 'iso-8859-1';
115 
120  private $_msgSensitivity = 0;
121 
125  private $_arySensitivity = array(false,
126  'Personal',
127  'Private',
128  'Company Confidential');
129 
134  private $_msgPriority = 3;
135 
139  private $_aryPriority = array('Bulk',
140  'Highest',
141  'High',
142  'Normal',
143  'Low',
144  'Lowest');
145 
151 
155  private $_smtpsTransEncodeTypes = array('7bit', // Simple 7-bit ASCII
156  '8bit', // 8-bit coding with line termination characters
157  'base64', // 3 octets encoded into 4 sextets with offset
158  'binary', // Arbitrary binary stream
159  'mac-binhex40', // Macintosh binary to hex encoding
160  'quoted-printable', // Mostly 7-bit, with 8-bit characters encoded as "=HH"
161  'uuencode'); // UUENCODE encoding
162 
167  private $_smtpsTransEncode = '7bit';
168 
172  private $_smtpsBoundary = null;
173 
177  private $_smtpsRelatedBoundary = null;
178 
183 
191  private $_transportType = 0;
192 
197  private $_mailPath = '/usr/lib/sendmail';
198 
202  private $_smtpTimeout = 10;
203 
207  private $_smtpMD5 = false;
208 
212  private $_smtpsErrors = null;
213 
221  private $_log_level = 0;
222 
226  private $_debug = false;
227 
228 
229  // @CHANGE LDR
230  public $log = '';
231  public $lastretval = '';
232  private $_errorsTo = '';
233  private $_deliveryReceipt = 0;
234  private $_trackId = '';
235  private $_moreinheader = '';
236 
240  private $_options = array();
241 
248  public function setOptions($_options = array())
249  {
250  $this->_options = $_options;
251  }
252 
259  public function setDeliveryReceipt($_val = 0)
260  {
261  $this->_deliveryReceipt = $_val;
262  }
263 
269  public function getDeliveryReceipt()
270  {
271  return $this->_deliveryReceipt;
272  }
273 
280  public function setTrackId($_val = '')
281  {
282  $this->_trackId = $_val;
283  }
284 
291  public function setMoreInHeader($_val = '')
292  {
293  $this->_moreinheader = $_val;
294  }
295 
301  public function getTrackId()
302  {
303  return $this->_trackId;
304  }
305 
311  public function getMoreInHeader()
312  {
313  return $this->_moreinheader;
314  }
315 
322  public function setErrorsTo($_strErrorsTo)
323  {
324  if ($_strErrorsTo) {
325  $this->_errorsTo = $this->_strip_email($_strErrorsTo);
326  }
327  }
328 
335  public function getErrorsTo($_part = true)
336  {
337  $_retValue = '';
338 
339  if ($_part === true) {
340  $_retValue = $this->_errorsTo;
341  } else {
342  $_retValue = $this->_errorsTo[$_part];
343  }
344 
345  return $_retValue;
346  }
347 
354  public function setDebug($_vDebug = false)
355  {
356  $this->_debug = $_vDebug;
357  }
358 
364  public function buildRCPTlist()
365  {
366  // Pull TO list
367  $_aryToList = $this->getTO();
368  }
369 
370  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
376  private function _server_connect()
377  {
378  // phpcs:enable
379  // Default return value
380  $_retVal = true;
381 
382  // We have to make sure the HOST given is valid
383  // This is done here because '@fsockopen' will not give me this
384  // information if it failes to connect because it can't find the HOST
385  $host = $this->getHost();
386  $usetls = preg_match('@tls://@i', $host);
387 
388  $host = preg_replace('@tcp://@i', '', $host); // Remove prefix
389  $host = preg_replace('@ssl://@i', '', $host); // Remove prefix
390  $host = preg_replace('@tls://@i', '', $host); // Remove prefix
391 
392  // @CHANGE LDR
393  include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
394 
395  if ((!is_ip($host)) && ((gethostbyname($host)) == $host)) {
396  $this->_setErr(99, $host.' is either offline or is an invalid host name.');
397  $_retVal = false;
398  } else {
399  if (function_exists('stream_socket_client') && !empty($this->_options)) {
400  $socket_context = stream_context_create($this->_options); // An array of options for stream_context_create()
401  $this->socket = @stream_socket_client(
402  preg_replace('@tls://@i', '', $this->getHost()).// Host to 'hit', IP or domain
403  ':'.$this->getPort(), // which Port number to use
404  $this->errno, // actual system level error
405  $this->errstr, // and any text that goes with the error
406  $this->_smtpTimeout, // timeout for reading/writing data over the socket
407  STREAM_CLIENT_CONNECT,
408  $socket_context // Options for connection
409  );
410  } else {
411  $this->socket = @fsockopen(
412  preg_replace('@tls://@i', '', $this->getHost()), // Host to 'hit', IP or domain
413  $this->getPort(), // which Port number to use
414  $this->errno, // actual system level error
415  $this->errstr, // and any text that goes with the error
416  $this->_smtpTimeout // timeout for reading/writing data over the socket
417  );
418  }
419 
420  //See if we can connect to the SMTP server
421  if (is_resource($this->socket)) {
422  // Fix from PHP SMTP class by 'Chris Ryan'
423  // Sometimes the SMTP server takes a little longer to respond
424  // so we will give it a longer timeout for the first read
425  // Windows still does not have support for this timeout function
426  if (function_exists('stream_set_timeout')) {
427  stream_set_timeout($this->socket, $this->_smtpTimeout, 0);
428  }
429 
430  // Check response from Server
431  if ($_retVal = $this->server_parse($this->socket, "220")) {
432  $_retVal = $this->socket;
433  }
434  } else {
435  // This connection attempt failed.
436  // @CHANGE LDR
437  if (empty($this->errstr)) {
438  $this->errstr = 'Failed to connect with fsockopen host='.$this->getHost().' port='.$this->getPort();
439  }
440  $this->_setErr($this->errno, $this->errstr);
441  $_retVal = false;
442  }
443  }
444 
445  return $_retVal;
446  }
447 
448  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
454  private function _server_authenticate()
455  {
456  // phpcs:enable
457  global $conf;
458 
459  // Send the RFC2554 specified EHLO.
460  // This improvment as provided by 'SirSir' to
461  // accomodate both SMTP AND ESMTP capable servers
462  $host = $this->getHost();
463  $usetls = preg_match('@tls://@i', $host);
464 
465  $host = preg_replace('@tcp://@i', '', $host); // Remove prefix
466  $host = preg_replace('@ssl://@i', '', $host); // Remove prefix
467  $host = preg_replace('@tls://@i', '', $host); // Remove prefix
468 
469  if ($usetls && !empty($conf->global->MAIN_SMTPS_ADD_TLS_TO_HOST_FOR_HELO)) {
470  $host = 'tls://'.$host;
471  }
472 
473  $hosth = $host; // so for example 'localhost' or 'smtp-relay.gmail.com'
474 
475  if (!empty($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO)) {
476  if (!is_numeric($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO)) {
477  // If value of MAIL_SMTP_USE_FROM_FOR_HELO is a string, we use it as domain name
478  $hosth = $conf->global->MAIL_SMTP_USE_FROM_FOR_HELO;
479  } else {
480  // If value of MAIL_SMTP_USE_FROM_FOR_HELO is 1, we use the domain in the from.
481  // So if the from to is 'aaa <bbb@ccc.com>', we will keep 'ccc.com'
482  $hosth = $this->getFrom('addr');
483  $hosth = preg_replace('/^.*</', '', $hosth);
484  $hosth = preg_replace('/>.*$/', '', $hosth);
485  $hosth = preg_replace('/.*@/', '', $hosth);
486  }
487  }
488 
489  if ($_retVal = $this->socket_send_str('EHLO '.$hosth, '250')) {
490  if ($usetls) {
491  /*
492  The following dialog illustrates how a client and server can start a TLS STARTTLS session:
493  S: <waits for connection on TCP port 25>
494  C: <opens connection>
495  S: 220 mail.imc.org SMTP service ready
496  C: EHLO mail.ietf.org
497  S: 250-mail.imc.org offers a warm hug of welcome
498  S: 250 STARTTLS
499  C: STARTTLS
500  S: 220 Go ahead
501  C: <starts TLS negotiation>
502  C & S: <negotiate a TLS session>
503  C & S: <check result of negotiation>
504  // Second pass EHLO
505  C: EHLO client-domain.com
506  S: 250-server-domain.com
507  S: 250 AUTH LOGIN
508  C: <continues by sending an SMTP command
509 
510  Another example here:
511  S: 220 smtp.server.com Simple Mail Transfer Service Ready
512  C: EHLO client.example.com
513  S: 250-smtp.server.com Hello client.example.com
514  S: 250-SIZE 1000000
515  S: 250-AUTH LOGIN PLAIN CRAM-MD5
516  S: 250-STARTTLS
517  S: 250 HELP
518  C: STARTTLS
519  S: 220 TLS go ahead
520  C: EHLO client.example.com *
521  S: 250-smtp.server.com Hello client.example.com
522  S: 250-SIZE 1000000
523  S: 250-AUTH LOGIN PLAIN CRAM-MD5
524  S: 250 HELP
525  C: AUTH LOGIN
526  S: 334 VXNlcm5hbWU6
527  C: adlxdkej
528  S: 334 UGFzc3dvcmQ6
529  C: lkujsefxlj
530  S: 235 2.7.0 Authentication successful
531  C: MAIL FROM:<mail@samlogic.com>
532  S: 250 OK
533  C: RCPT TO:<john@mail.com>
534  S: 250 OK
535  C: DATA
536  S: 354 Send message, end with a "." on a line by itself
537  C: <The message data (body text, subject, e-mail header, attachments etc) is sent>
538  S .
539  S: 250 OK, message accepted for delivery: queued as 12345
540  C: QUIT
541  S: 221 Bye
542  */
543  if (!$_retVal = $this->socket_send_str('STARTTLS', 220)) {
544  $this->_setErr(131, 'STARTTLS connection is not supported.');
545  return $_retVal;
546  }
547 
548  // Before 5.6.7:
549  // STREAM_CRYPTO_METHOD_SSLv23_CLIENT = STREAM_CRYPTO_METHOD_SSLv2_CLIENT|STREAM_CRYPTO_METHOD_SSLv3_CLIENT
550  // STREAM_CRYPTO_METHOD_TLS_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
551  // PHP >= 5.6.7:
552  // STREAM_CRYPTO_METHOD_SSLv23_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
553  // STREAM_CRYPTO_METHOD_TLS_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
554 
555  $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
556  if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
557  $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
558  $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
559  }
560 
561  if (!stream_socket_enable_crypto($this->socket, true, $crypto_method)) {
562  $this->_setErr(132, 'STARTTLS connection failed.');
563  return $_retVal;
564  }
565  // Most servers expect a 2nd pass of EHLO after TLS is established to get another time
566  // the answer with list of supported AUTH methods. They may differs between non STARTTLS and with STARTTLS.
567  if (! $_retVal = $this->socket_send_str('EHLO '.$hosth, '250')) {
568  $this->_setErr(126, '"'.$hosth.'" does not support authenticated connections or temporary error. Error after 2nd sending EHLO '.$hosth.' : '.$this->lastretval);
569  return $_retVal;
570  }
571  }
572 
573  // Default authentication method is LOGIN
574  if (empty($conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE)) {
575  $conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE = 'LOGIN';
576  }
577 
578  // Send Authentication to Server
579  // Check for errors along the way
580  switch ($conf->global->MAIN_MAIL_SMTPS_AUTH_TYPE) {
581  case 'NONE':
582  // 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.
583  $_retVal = true;
584  break;
585  case 'PLAIN':
586  $this->socket_send_str('AUTH PLAIN', '334');
587  // The error here just means the ID/password combo doesn't work.
588  $_retVal = $this->socket_send_str(base64_encode("\0".$this->_smtpsID."\0".$this->_smtpsPW), '235');
589  break;
590  case 'XOAUTH2':
591  // "user=$email\1auth=Bearer $token\1\1"
592  $user = $this->_smtpsID;
593  $token = $this->_smtpsToken;
594  $initRes = "user=".$user."\001auth=Bearer ".$token."\001\001";
595  $_retVal = $this->socket_send_str('AUTH XOAUTH2 '.base64_encode($initRes), '235');
596  if (!$_retVal) {
597  $this->_setErr(130, 'Error when asking for AUTH XOAUTH2');
598  }
599  break;
600  case 'LOGIN': // most common case
601  default:
602  $_retVal = $this->socket_send_str('AUTH LOGIN', '334');
603  if (!$_retVal) {
604  $this->_setErr(130, 'Error when asking for AUTH LOGIN');
605  } else {
606  // User name will not return any error, server will take anything we give it.
607  $this->socket_send_str(base64_encode($this->_smtpsID), '334');
608  // The error here just means the ID/password combo doesn't work.
609  // There is no method to determine which is the problem, ID or password
610  $_retVal = $this->socket_send_str(base64_encode($this->_smtpsPW), '235');
611  }
612  break;
613  }
614  if (!$_retVal) {
615  $this->_setErr(130, 'Invalid Authentication Credentials.');
616  }
617  } else {
618  $this->_setErr(126, '"'.$host.'" does not support authenticated connections or temporary error. Error after sending EHLO '.$hosth.' : '.$this->lastretval);
619  }
620 
621  return $_retVal;
622  }
623 
629  public function sendMsg()
630  {
631  global $conf;
632 
636  $_retVal = false;
637 
638  // Connect to Server
639  if ($this->socket = $this->_server_connect()) {
640  // If a User ID *and* a password is given, assume Authentication is desired
641  if (!empty($this->_smtpsID) && (!empty($this->_smtpsPW) || !empty($this->_smtpsToken))) {
642  // Send the RFC2554 specified EHLO.
643  $_retVal = $this->_server_authenticate();
644  } else {
645  // This is a "normal" SMTP Server "handshack"
646  // Send the RFC821 specified HELO.
647  $host = $this->getHost();
648  $usetls = preg_match('@tls://@i', $host);
649 
650  $host = preg_replace('@tcp://@i', '', $host); // Remove prefix
651  $host = preg_replace('@ssl://@i', '', $host); // Remove prefix
652  $host = preg_replace('@tls://@i', '', $host); // Remove prefix
653 
654  if ($usetls && !empty($conf->global->MAIN_SMTPS_ADD_TLS_TO_HOST_FOR_HELO)) {
655  $host = 'tls://'.$host;
656  }
657 
658  $hosth = $host;
659 
660  if (!empty($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO)) {
661  if (!is_numeric($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO)) {
662  // If value of MAIL_SMTP_USE_FROM_FOR_HELO is a string, we use it as domain name
663  $hosth = $conf->global->MAIL_SMTP_USE_FROM_FOR_HELO;
664  } else {
665  // If value of MAIL_SMTP_USE_FROM_FOR_HELO is 1, we use the domain in the from.
666  // If the from to is 'aaa <bbb@ccc.com>', we will keep 'ccc.com'
667  $hosth = $this->getFrom('addr');
668  $hosth = preg_replace('/^.*</', '', $hosth);
669  $hosth = preg_replace('/>.*$/', '', $hosth);
670  $hosth = preg_replace('/.*@/', '', $hosth);
671  }
672  }
673 
674  // Send the HELO message to the SMTP server
675  $_retVal = $this->socket_send_str('HELO '.$hosth, '250');
676  }
677 
678  // Well, did we get the server answer with correct code ?
679  if ($_retVal) {
680  // From this point onward most server response codes should be 250
681  // Specify who the mail is from....
682  // This has to be the raw email address, strip the "name" off
683  $resultmailfrom = $this->socket_send_str('MAIL FROM: '.$this->getFrom('addr'), '250');
684  if (!$resultmailfrom) {
685  fclose($this->socket);
686  return false;
687  }
688 
689  // 'RCPT TO:' must be given a single address, so this has to loop
690  // through the list of addresses, regardless of TO, CC or BCC
691  // and send it out "single file"
692  foreach ($this->get_RCPT_list() as $_address) {
693  /* Note:
694  * BCC email addresses must be listed in the RCPT TO command list,
695  * but the BCC header should not be printed under the DATA command.
696  * http://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server
697  */
698 
699  /*
700  * TODO
701  * After each 'RCPT TO:' is sent, we need to make sure it was kosher,
702  * if not, the whole message will fail
703  * If any email address fails, we will need to RESET the connection,
704  * mark the last address as "bad" and start the address loop over again.
705  * If any address fails, the entire message fails.
706  */
707  $this->socket_send_str('RCPT TO: <'.$_address.'>', '250');
708  }
709 
710  // Tell the server we are ready to start sending data
711  // with any custom headers...
712  // This is the last response code we look for until the end of the message.
713  $this->socket_send_str('DATA', '354');
714 
715  // Now we are ready for the message...
716  // Ok, all the ingredients are mixed in let's cook this puppy...
717  $this->socket_send_str($this->getHeader().$this->getBodyContent()."\r\n".'.', '250');
718 
719  // Now tell the server we are done and close the socket...
720  fputs($this->socket, 'QUIT');
721  } else {
722  // We got error code into $this->lastretval
723  }
724 
725  fclose($this->socket);
726  }
727 
728  return $_retVal;
729  }
730 
731  // =============================================================
732  // ** Setter & Getter methods
733 
734  // ** Basic System configuration
735 
761  public function setConfig($_strConfigPath = null)
762  {
767  $_retVal = true;
768 
769  // if we have a path...
770  if (!empty($_strConfigPath)) {
771  // If the path is not valid, this will NOT generate an error,
772  // it will simply return false.
773  if (!@include $_strConfigPath) {
774  $this->_setErr(110, '"'.$_strConfigPath.'" is not a valid path.');
775  $_retVal = false;
776  }
777  } else {
778  // Read the Systems php.ini file
779  // Set these properties ONLY if they are set in the php.ini file.
780  // Otherwise the default values will be used.
781  if ($_host = ini_get('SMTPs')) {
782  $this->setHost($_host);
783  }
784 
785  if ($_port = ini_get('smtp_port')) {
786  $this->setPort($_port);
787  }
788 
789  if ($_from = ini_get('sendmail_from')) {
790  $this->setFrom($_from);
791  }
792  }
793 
794  // Send back what we have
795  return $_retVal;
796  }
797 
807  public function setTransportType($_type = 0)
808  {
809  if ((is_numeric($_type)) && (($_type >= 0) && ($_type <= 3))) {
810  $this->_transportType = $_type;
811  }
812  }
813 
822  public function getTransportType()
823  {
824  return $this->_transportType;
825  }
826 
834  public function setMailPath($_path)
835  {
836  // This feature is not yet implemented
837  return true;
838 
839  //if ( $_path ) $this->_mailPath = $_path;
840  }
841 
850  public function setHost($_strHost)
851  {
852  if ($_strHost) {
853  $this->_smtpsHost = $_strHost;
854  }
855  }
856 
863  public function getHost()
864  {
865  return $this->_smtpsHost;
866  }
867 
876  public function setPort($_intPort)
877  {
878  if ((is_numeric($_intPort)) &&
879  (($_intPort >= 1) && ($_intPort <= 65536))) {
880  $this->_smtpsPort = $_intPort;
881  }
882  }
883 
890  public function getPort()
891  {
892  return $this->_smtpsPort;
893  }
894 
901  public function setID($_strID)
902  {
903  $this->_smtpsID = $_strID;
904  }
905 
911  public function getID()
912  {
913  return $this->_smtpsID;
914  }
915 
922  public function setPW($_strPW)
923  {
924  $this->_smtpsPW = $_strPW;
925  }
926 
932  public function getPW()
933  {
934  return $this->_smtpsPW;
935  }
936 
943  public function setToken($_strToken)
944  {
945  $this->_smtpsToken = $_strToken;
946  }
947 
953  public function getToken()
954  {
955  return $this->_smtpsToken;
956  }
957 
965  public function setCharSet($_strCharSet)
966  {
967  if ($_strCharSet) {
968  $this->_smtpsCharSet = $_strCharSet;
969  }
970  }
971 
977  public function getCharSet()
978  {
979  return $this->_smtpsCharSet;
980  }
981 
997  public function setTransEncode($_strTransEncode)
998  {
999  if (array_search($_strTransEncode, $this->_smtpsTransEncodeTypes)) {
1000  $this->_smtpsTransEncode = $_strTransEncode;
1001  }
1002  }
1003 
1009  public function getTransEncode()
1010  {
1011  return $this->_smtpsTransEncode;
1012  }
1013 
1030  public function setTransEncodeType($_strTransEncodeType)
1031  {
1032  if (array_search($_strTransEncodeType, $this->_smtpsTransEncodeTypes)) {
1033  $this->_smtpsTransEncodeType = $_strTransEncodeType;
1034  }
1035  }
1036 
1042  public function getTransEncodeType()
1043  {
1044  return $this->_smtpsTransEncodeTypes[$this->_smtpsTransEncodeType];
1045  }
1046 
1047 
1048  // ** Message Construction
1049 
1056  public function setFrom($_strFrom)
1057  {
1058  if ($_strFrom) {
1059  $this->_msgFrom = $this->_strip_email($_strFrom);
1060  }
1061  }
1062 
1069  public function getFrom($_part = true)
1070  {
1071  $_retValue = '';
1072 
1073  if ($_part === true) {
1074  $_retValue = $this->_msgFrom;
1075  } else {
1076  $_retValue = $this->_msgFrom[$_part];
1077  }
1078 
1079  return $_retValue;
1080  }
1081 
1088  public function setReplyTo($_strReplyTo)
1089  {
1090  if ($_strReplyTo) {
1091  $this->_msgReplyTo = $this->_strip_email($_strReplyTo);
1092  }
1093  }
1094 
1101  public function getReplyTo($_part = true)
1102  {
1103  $_retValue = '';
1104 
1105  if ($_part === true) {
1106  $_retValue = $this->_msgReplyTo;
1107  } else {
1108  $_retValue = $this->_msgReplyTo[$_part];
1109  }
1110 
1111  return $_retValue;
1112  }
1113 
1126  private function _buildAddrList($_type, $_addrList)
1127  {
1128  // Pull existing list
1129  $aryHost = $this->_msgRecipients;
1130 
1131  // Only run this if we have something
1132  if (!empty($_addrList)) {
1133  // $_addrList can be a STRING or an array
1134  if (is_string($_addrList)) {
1135  // This could be a COMMA delimited string
1136  if (strstr($_addrList, ',')) {
1137  // "explode "list" into an array
1138  $_addrList = explode(',', $_addrList);
1139  } else {
1140  // Stick it in an array
1141  $_addrList = array($_addrList);
1142  }
1143  }
1144 
1145  // take the array of addresses and split them further
1146  foreach ($_addrList as $_strAddr) {
1147  // Strip off the end '>'
1148  $_strAddr = str_replace('>', '', $_strAddr);
1149 
1150  // Seperate "Real Name" from eMail address
1151  $_tmpaddr = null;
1152  $_tmpaddr = explode('<', $_strAddr);
1153 
1154  // We have a "Real Name" and eMail address
1155  if (count($_tmpaddr) == 2) {
1156  $_tmpHost = explode('@', $_tmpaddr[1]);
1157  $_tmpaddr[0] = trim($_tmpaddr[0], ' ">');
1158  $aryHost[$_tmpHost[1]][$_type][$_tmpHost[0]] = $_tmpaddr[0];
1159  } else {
1160  // We only have an eMail address
1161  // Strip off the beggining '<'
1162  $_strAddr = str_replace('<', '', $_strAddr);
1163 
1164  $_tmpHost = explode('@', $_strAddr);
1165  $_tmpHost[0] = trim($_tmpHost[0]);
1166  $_tmpHost[1] = trim($_tmpHost[1]);
1167 
1168  $aryHost[$_tmpHost[1]][$_type][$_tmpHost[0]] = '';
1169  }
1170  }
1171  }
1172  // replace list
1173  $this->_msgRecipients = $aryHost;
1174  }
1175 
1176  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1193  private function _strip_email($_strAddr)
1194  {
1195  // phpcs:enable
1196  // Keep the orginal
1197  $_aryEmail['org'] = $_strAddr;
1198 
1199  // Set entire string to Lower Case
1200  $_strAddr = strtolower($_strAddr);
1201 
1202  // Drop "stuff' off the end
1203  $_strAddr = trim($_strAddr, ' ">');
1204 
1205  // Seperate "Real Name" from eMail address, if we have one
1206  $_tmpAry = explode('<', $_strAddr);
1207 
1208  // Do we have a "Real name"
1209  if (count($_tmpAry) == 2) {
1210  // We may not really have a "Real Name"
1211  if ($_tmpAry[0]) {
1212  $_aryEmail['real'] = trim($_tmpAry[0], ' ">');
1213  }
1214 
1215  $_aryEmail['addr'] = $_tmpAry[1];
1216  } else {
1217  $_aryEmail['addr'] = $_tmpAry[0];
1218  }
1219 
1220  // Pull User Name and Host.tld apart
1221  list($_aryEmail['user'], $_aryEmail['host']) = explode('@', $_aryEmail['addr']);
1222 
1223  // Put the brackets back around the address
1224  $_aryEmail['addr'] = '<'.$_aryEmail['addr'].'>';
1225 
1226  return $_aryEmail;
1227  }
1228 
1229  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1237  public function get_RCPT_list()
1238  {
1239  // phpcs:enable
1243  $_RCPT_list = array();
1244 
1245  // walk down Recipients array and pull just email addresses
1246  foreach ($this->_msgRecipients as $_host => $_list) {
1247  foreach ($_list as $_subList) {
1248  foreach ($_subList as $_name => $_addr) {
1249  // build RCPT list
1250  $_RCPT_list[] = $_name.'@'.$_host;
1251  }
1252  }
1253  }
1254 
1255  return $_RCPT_list;
1256  }
1257 
1258  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1265  public function get_email_list($_which = null)
1266  {
1267  // phpcs:enable
1268  // We need to know which address segment to pull
1269  if ($_which) {
1270  // Make sure we have addresses to process
1271  if ($this->_msgRecipients) {
1272  $_RCPT_list = array();
1273  // walk down Recipients array and pull just email addresses
1274  foreach ($this->_msgRecipients as $_host => $_list) {
1275  if (!empty($this->_msgRecipients[$_host][$_which])) {
1276  foreach ($this->_msgRecipients[$_host][$_which] as $_addr => $_realName) {
1277  if ($_realName) { // @CHANGE LDR
1278  $_realName = '"'.$_realName.'"';
1279  $_RCPT_list[] = $_realName.' <'.$_addr.'@'.$_host.'>';
1280  } else {
1281  $_RCPT_list[] = $_addr.'@'.$_host;
1282  }
1283  }
1284  }
1285  }
1286 
1287  return implode(', ', $_RCPT_list);
1288  } else {
1289  $this->_setErr(101, 'No eMail Address for message to be sent to.');
1290  return false;
1291  }
1292  } else {
1293  $this->_setErr(102, 'eMail type not defined.');
1294  return false;
1295  }
1296  }
1297 
1304  public function setTO($_addrTo)
1305  {
1306  if ($_addrTo) {
1307  $this->_buildAddrList('to', $_addrTo);
1308  }
1309  }
1310 
1316  public function getTo()
1317  {
1318  return $this->get_email_list('to');
1319  }
1320 
1327  public function setCC($_strCC)
1328  {
1329  if ($_strCC) {
1330  $this->_buildAddrList('cc', $_strCC);
1331  }
1332  }
1333 
1339  public function getCC()
1340  {
1341  return $this->get_email_list('cc');
1342  }
1343 
1350  public function setBCC($_strBCC)
1351  {
1352  if ($_strBCC) {
1353  $this->_buildAddrList('bcc', $_strBCC);
1354  }
1355  }
1356 
1362  public function getBCC()
1363  {
1364  return $this->get_email_list('bcc');
1365  }
1366 
1373  public function setSubject($_strSubject = '')
1374  {
1375  if ($_strSubject) {
1376  $this->_msgSubject = $_strSubject;
1377  }
1378  }
1379 
1385  public function getSubject()
1386  {
1387  return $this->_msgSubject;
1388  }
1389 
1395  public function getHeader()
1396  {
1397  global $conf;
1398 
1399  $_header = 'From: '.$this->getFrom('org')."\r\n"
1400  . 'To: '.$this->getTO()."\r\n";
1401 
1402  if ($this->getCC()) {
1403  $_header .= 'Cc: '.$this->getCC()."\r\n";
1404  }
1405 
1406  /* Note:
1407  * BCC email addresses must be listed in the RCPT TO command list,
1408  * but the BCC header should not be printed under the DATA command.
1409  * So it is included into the function sendMsg() but not here.
1410  * http://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server
1411  */
1412  /*
1413  if ( $this->getBCC() )
1414  $_header .= 'Bcc: ' . $this->getBCC() . "\r\n";
1415  */
1416 
1417  $host = dol_getprefix('email');
1418 
1419  //NOTE: Message-ID should probably contain the username of the user who sent the msg
1420  $_header .= 'Subject: '.$this->getSubject()."\r\n";
1421  $_header .= 'Date: '.date("r")."\r\n";
1422 
1423  $trackid = $this->getTrackId();
1424  if ($trackid) {
1425  // References is kept in response and Message-ID is returned into In-Reply-To:
1426  $_header .= 'Message-ID: <'.time().'.SMTPs-dolibarr-'.$trackid.'@'.$host.">\r\n";
1427  $_header .= 'References: <'.time().'.SMTPs-dolibarr-'.$trackid.'@'.$host.">\r\n";
1428  $_header .= 'X-Dolibarr-TRACKID: '.$trackid.'@'.$host."\r\n";
1429  } else {
1430  $_header .= 'Message-ID: <'.time().'.SMTPs@'.$host.">\r\n";
1431  }
1432  if (!empty($_SERVER['REMOTE_ADDR'])) {
1433  $_header .= "X-RemoteAddr: ".$_SERVER['REMOTE_ADDR']."\r\n";
1434  }
1435  if ($this->getMoreInHeader()) {
1436  $_header .= $this->getMoreInHeader(); // Value must include the "\r\n";
1437  }
1438 
1439  //$_header .=
1440  // 'Read-Receipt-To: ' . $this->getFrom( 'org' ) . "\r\n"
1441  // 'Return-Receipt-To: ' . $this->getFrom( 'org' ) . "\r\n";
1442 
1443  if ($this->getSensitivity()) {
1444  $_header .= 'Sensitivity: '.$this->getSensitivity()."\r\n";
1445  }
1446 
1447  if ($this->_msgPriority != 3) {
1448  $_header .= $this->getPriority();
1449  }
1450 
1451 
1452  // @CHANGE LDR
1453  if ($this->getDeliveryReceipt()) {
1454  $_header .= 'Disposition-Notification-To: '.$this->getFrom('addr')."\r\n";
1455  }
1456  if ($this->getErrorsTo()) {
1457  $_header .= 'Errors-To: '.$this->getErrorsTo('addr')."\r\n";
1458  }
1459  if ($this->getReplyTo()) {
1460  $_header .= "Reply-To: ".$this->getReplyTo('addr')."\r\n";
1461  }
1462 
1463  $_header .= 'X-Mailer: Dolibarr version '.DOL_VERSION.' (using SMTPs Mailer)'."\r\n";
1464  $_header .= 'X-Dolibarr-Option: '.($conf->global->MAIN_MAIL_USE_MULTI_PART ? 'MAIN_MAIL_USE_MULTI_PART' : 'No MAIN_MAIL_USE_MULTI_PART')."\r\n";
1465  $_header .= 'Mime-Version: 1.0'."\r\n";
1466 
1467 
1468  return $_header;
1469  }
1470 
1478  public function setBodyContent($strContent, $strType = 'plain')
1479  {
1480  //if ( $strContent )
1481  //{
1482  if ($strType == 'html') {
1483  $strMimeType = 'text/html';
1484  } else {
1485  $strMimeType = 'text/plain';
1486  }
1487 
1488  // Make RFC821 Compliant, replace bare linefeeds
1489  $strContent = preg_replace("/(?<!\r)\n/si", "\r\n", $strContent);
1490 
1491  $strContentAltText = '';
1492  if ($strType == 'html') {
1493  // Similar code to forge a text from html is also in CMailFile.class.php
1494  $strContentAltText = preg_replace('/<head><title>.*<\/style><\/head>/', '', $strContent);
1495  $strContentAltText = preg_replace("/<br\s*[^>]*>/", " ", $strContentAltText);
1496  $strContentAltText = html_entity_decode(strip_tags($strContentAltText));
1497  $strContentAltText = trim(wordwrap($strContentAltText, 75, "\r\n"));
1498  }
1499 
1500  // Make RFC2045 Compliant
1501  //$strContent = rtrim(chunk_split($strContent)); // Function chunck_split seems ko if not used on a base64 content
1502  $strContent = rtrim(wordwrap($strContent, 75, "\r\n")); // TODO Using this method creates unexpected line break on text/plain content.
1503 
1504  $this->_msgContent[$strType] = array();
1505 
1506  $this->_msgContent[$strType]['mimeType'] = $strMimeType;
1507  $this->_msgContent[$strType]['data'] = $strContent;
1508  $this->_msgContent[$strType]['dataText'] = $strContentAltText;
1509 
1510  if ($this->getMD5flag()) {
1511  $this->_msgContent[$strType]['md5'] = dol_hash($strContent, 3);
1512  }
1513  //}
1514  }
1515 
1521  public function getBodyContent()
1522  {
1523  global $conf;
1524 
1525  // Generate a new Boundary string
1526  $this->_setBoundary();
1527 
1528  // What type[s] of content do we have
1529  $_types = array_keys($this->_msgContent);
1530 
1531  // How many content types do we have
1532  $keyCount = count($_types);
1533 
1534  // If we have ZERO, we have a problem
1535  if ($keyCount === 0) {
1536  die("Sorry, no content");
1537  } elseif ($keyCount === 1 && empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) {
1538  // If we have ONE, we can use the simple format
1539  $_msgData = $this->_msgContent;
1540  $_msgData = $_msgData[$_types[0]];
1541 
1542  $content = 'Content-Type: '.$_msgData['mimeType'].'; charset="'.$this->getCharSet().'"'."\r\n"
1543  . 'Content-Transfer-Encoding: '.$this->getTransEncodeType()."\r\n"
1544  . 'Content-Disposition: inline'."\r\n"
1545  . 'Content-Description: Message'."\r\n";
1546 
1547  if ($this->getMD5flag()) {
1548  $content .= 'Content-MD5: '.$_msgData['md5']."\r\n";
1549  }
1550 
1551  $content .= "\r\n"
1552  . $_msgData['data']."\r\n";
1553  } elseif ($keyCount >= 1 || !empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) {
1554  // If we have more than ONE, we use the multi-part format
1555  // Since this is an actual multi-part message
1556  // We need to define a content message Boundary
1557  // NOTE: This was 'multipart/alternative', but Windows based mail servers have issues with this.
1558 
1559  //$content = 'Content-Type: multipart/related; boundary="' . $this->_getBoundary() . '"' . "\r\n";
1560  $content = 'Content-Type: multipart/mixed; boundary="'.$this->_getBoundary('mixed').'"'."\r\n";
1561 
1562  // . "\r\n"
1563  // . 'This is a multi-part message in MIME format.' . "\r\n";
1564  $content .= "Content-Transfer-Encoding: 8bit\r\n";
1565  $content .= "\r\n";
1566 
1567  $content .= "--".$this->_getBoundary('mixed')."\r\n";
1568 
1569  if (key_exists('image', $this->_msgContent)) { // If inline image found
1570  $content .= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"'."\r\n";
1571  $content .= "\r\n";
1572  $content .= "--".$this->_getBoundary('alternative')."\r\n";
1573  }
1574 
1575 
1576  // $this->_msgContent must be sorted with key 'text' or 'html' first then 'image' then 'attachment'
1577 
1578 
1579  // Loop through message content array
1580  foreach ($this->_msgContent as $type => $_content) {
1581  if ($type == 'attachment') {
1582  // loop through all attachments
1583  foreach ($_content as $_file => $_data) {
1584  $content .= "--".$this->_getBoundary('mixed')."\r\n"
1585  . 'Content-Disposition: attachment; filename="'.$_data['fileName'].'"'."\r\n"
1586  . 'Content-Type: '.$_data['mimeType'].'; name="'.$_data['fileName'].'"'."\r\n"
1587  . 'Content-Transfer-Encoding: base64'."\r\n"
1588  . 'Content-Description: '.$_data['fileName']."\r\n";
1589  if (!empty($_data['cid'])) {
1590  $content .= "X-Attachment-Id: ".$_data['cid']."\r\n";
1591  $content .= "Content-ID: <".$_data['cid'].">\r\n";
1592  }
1593  if ($this->getMD5flag()) {
1594  $content .= 'Content-MD5: '.$_data['md5']."\r\n";
1595  }
1596 
1597  $content .= "\r\n".$_data['data']."\r\n\r\n";
1598  }
1599  } elseif ($type == 'image') {
1600  // @CHANGE LDR
1601  // loop through all images
1602  foreach ($_content as $_image => $_data) {
1603  $content .= "--".$this->_getBoundary('related')."\r\n"; // always related for an inline image
1604 
1605  $content .= 'Content-Type: '.$_data['mimeType'].'; name="'.$_data['imageName'].'"'."\r\n"
1606  . 'Content-Transfer-Encoding: base64'."\r\n"
1607  . 'Content-Disposition: inline; filename="'.$_data['imageName'].'"'."\r\n"
1608  . 'Content-ID: <'.$_data['cid'].'> '."\r\n";
1609 
1610  if ($this->getMD5flag()) {
1611  $content .= 'Content-MD5: '.$_data['md5']."\r\n";
1612  }
1613 
1614  $content .= "\r\n"
1615  . $_data['data']."\r\n";
1616  }
1617 
1618  // always end related and end alternative after inline images
1619  $content .= "--".$this->_getBoundary('related')."--\r\n";
1620  $content .= "\r\n--".$this->_getBoundary('alternative')."--\r\n";
1621  $content .= "\r\n";
1622  } else {
1623  if (key_exists('image', $this->_msgContent)) {
1624  $content .= "Content-Type: text/plain; charset=".$this->getCharSet()."\r\n";
1625  $content .= "\r\n".($_content['dataText'] ? $_content['dataText'] : strip_tags($_content['data']))."\r\n"; // Add plain text message
1626  $content .= "--".$this->_getBoundary('alternative')."\r\n";
1627  $content .= 'Content-Type: multipart/related; boundary="'.$this->_getBoundary('related').'"'."\r\n";
1628  $content .= "\r\n";
1629  $content .= "--".$this->_getBoundary('related')."\r\n";
1630  }
1631 
1632  if (!key_exists('image', $this->_msgContent) && $_content['dataText'] && !empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) {
1633  // Add plain text message part before html part
1634  $content .= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"'."\r\n";
1635  $content .= "\r\n";
1636  $content .= "--".$this->_getBoundary('alternative')."\r\n";
1637 
1638  $content .= "Content-Type: text/plain; charset=".$this->getCharSet()."\r\n";
1639  $content .= "\r\n".$_content['dataText']."\r\n";
1640  $content .= "--".$this->_getBoundary('alternative')."\r\n";
1641  }
1642 
1643  $content .= 'Content-Type: '.$_content['mimeType'].'; charset='.$this->getCharSet();
1644 
1645  $content .= "\r\n";
1646 
1647  if ($this->getMD5flag()) {
1648  $content .= 'Content-MD5: '.$_content['md5']."\r\n";
1649  }
1650 
1651  $content .= "\r\n".$_content['data']."\r\n";
1652 
1653  if (!key_exists('image', $this->_msgContent) && $_content['dataText'] && !empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) {
1654  // Add plain text message part after html part
1655  $content .= "--".$this->_getBoundary('alternative')."--\r\n";
1656  }
1657 
1658  $content .= "\r\n";
1659  }
1660  }
1661 
1662  $content .= "--".$this->_getBoundary('mixed').'--'."\r\n";
1663  }
1664 
1665  return $content;
1666  }
1667 
1678  public function setAttachment($strContent, $strFileName = 'unknown', $strMimeType = 'unknown', $strCid = '')
1679  {
1680  if ($strContent) {
1681  $strContent = rtrim(chunk_split(base64_encode($strContent), 76, "\r\n")); // 76 max is defined into http://tools.ietf.org/html/rfc2047
1682 
1683  $this->_msgContent['attachment'][$strFileName]['mimeType'] = $strMimeType;
1684  $this->_msgContent['attachment'][$strFileName]['fileName'] = $strFileName;
1685  $this->_msgContent['attachment'][$strFileName]['data'] = $strContent;
1686  $this->_msgContent['attachment'][$strFileName]['cid'] = $strCid; // If defined, it means this attachment must be shown inline
1687 
1688  if ($this->getMD5flag()) {
1689  $this->_msgContent['attachment'][$strFileName]['md5'] = dol_hash($strContent, 3);
1690  }
1691  }
1692  }
1693 
1694 
1695  // @CHANGE LDR
1696 
1707  public function setImageInline($strContent, $strImageName = 'unknown', $strMimeType = 'unknown', $strImageCid = 'unknown')
1708  {
1709  if ($strContent) {
1710  $this->_msgContent['image'][$strImageName]['mimeType'] = $strMimeType;
1711  $this->_msgContent['image'][$strImageName]['imageName'] = $strImageName;
1712  $this->_msgContent['image'][$strImageName]['cid'] = $strImageCid;
1713  $this->_msgContent['image'][$strImageName]['data'] = $strContent;
1714 
1715  if ($this->getMD5flag()) {
1716  $this->_msgContent['image'][$strImageName]['md5'] = dol_hash($strContent, 3);
1717  }
1718  }
1719  }
1720  // END @CHANGE LDR
1721 
1722 
1734  public function setSensitivity($_value = 0)
1735  {
1736  if ((is_numeric($_value)) &&
1737  (($_value >= 0) && ($_value <= 3))) {
1738  $this->_msgSensitivity = $_value;
1739  }
1740  }
1741 
1752  public function getSensitivity()
1753  {
1754  return $this->_arySensitivity[$this->_msgSensitivity];
1755  }
1756 
1770  public function setPriority($_value = 3)
1771  {
1772  if ((is_numeric($_value)) &&
1773  (($_value >= 0) && ($_value <= 5))) {
1774  $this->_msgPriority = $_value;
1775  }
1776  }
1777 
1790  public function getPriority()
1791  {
1792  return 'Importance: '.$this->_aryPriority[$this->_msgPriority]."\r\n"
1793  . 'Priority: '.$this->_aryPriority[$this->_msgPriority]."\r\n"
1794  . 'X-Priority: '.$this->_msgPriority.' ('.$this->_aryPriority[$this->_msgPriority].')'."\r\n";
1795  }
1796 
1803  public function setMD5flag($_flag = false)
1804  {
1805  $this->_smtpMD5 = $_flag;
1806  }
1807 
1813  public function getMD5flag()
1814  {
1815  return $this->_smtpMD5;
1816  }
1817 
1826  public function setXheader($strXdata)
1827  {
1828  if ($strXdata) {
1829  $this->_msgXheader[] = $strXdata;
1830  }
1831  }
1832 
1838  public function getXheader()
1839  {
1840  return $this->_msgXheader;
1841  }
1842 
1848  private function _setBoundary()
1849  {
1850  $this->_smtpsBoundary = "multipart_x.".time().".x_boundary";
1851  $this->_smtpsRelatedBoundary = 'mul_'.dol_hash(uniqid("dolibarr2"), 3);
1852  $this->_smtpsAlternativeBoundary = 'mul_'.dol_hash(uniqid("dolibarr3"), 3);
1853  }
1854 
1861  private function _getBoundary($type = 'mixed')
1862  {
1863  if ($type == 'mixed') {
1864  return $this->_smtpsBoundary;
1865  } elseif ($type == 'related') {
1867  } elseif ($type == 'alternative') {
1869  }
1870  }
1871 
1872  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1883  public function server_parse($socket, $response)
1884  {
1885  // phpcs:enable
1890  $_retVal = true;
1891 
1892  $server_response = '';
1893 
1894  // avoid infinite loop
1895  $limit = 0;
1896 
1897  while (substr($server_response, 3, 1) != ' ' && $limit < 100) {
1898  if (!($server_response = fgets($socket, 256))) {
1899  $this->_setErr(121, "Couldn't get mail server response codes");
1900  $_retVal = false;
1901  break;
1902  }
1903  $this->log .= $server_response;
1904  $limit++;
1905  }
1906 
1907  $this->lastretval = substr($server_response, 0, 3);
1908 
1909  if (!(substr($server_response, 0, 3) == $response)) {
1910  $this->_setErr(120, "Ran into problems sending Mail.\r\nResponse: ".$server_response);
1911  $_retVal = false;
1912  }
1913 
1914  return $_retVal;
1915  }
1916 
1917  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1926  public function socket_send_str($_strSend, $_returnCode = null, $CRLF = "\r\n")
1927  {
1928  // phpcs:enable
1929  if ($this->_debug) {
1930  $this->log .= $_strSend; // @CHANGE LDR for log
1931  }
1932  fputs($this->socket, $_strSend.$CRLF);
1933  if ($this->_debug) {
1934  $this->log .= ' ('.$_returnCode.')'.$CRLF;
1935  }
1936 
1937  if ($_returnCode) {
1938  return $this->server_parse($this->socket, $_returnCode);
1939  }
1940 
1941  return null;
1942  }
1943 
1944  // =============================================================
1945  // ** Error handling methods
1946 
1954  private function _setErr($_errNum, $_errMsg)
1955  {
1956  $this->_smtpsErrors[] = array(
1957  'num' => $_errNum,
1958  'msg' => $_errMsg,
1959  );
1960  }
1961 
1967  public function getErrors()
1968  {
1969  $_errMsg = array();
1970 
1971  if (is_array($this->_smtpsErrors)) {
1972  foreach ($this->_smtpsErrors as $_err => $_info) {
1973  $_errMsg[] = 'Error ['.$_info['num'].']: '.$_info['msg'];
1974  }
1975  }
1976 
1977  return implode("\n", $_errMsg);
1978  }
1979 }
1980 
1981 
1982 // =============================================================
1983 // ** CSV Version Control Info
1984 
Class to construct and send SMTP compliant email, even to a secure SMTP server, regardless of platfor...
Definition: smtps.class.php:47
$_smtpsToken
Token in case we use OAUTH2.
Definition: smtps.class.php:74
_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.
$_arySensitivity
Message Sensitivity.
$_smtpsCharSet
Character set Defaulted to 'iso-8859-1'.
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:
$_smtpsHost
Host Name or IP of SMTP Server to use.
Definition: smtps.class.php:51
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.
buildRCPTlist()
build RECIPIENT List, all addresses who will recieve this message
getBodyContent()
Retrieves the Message Content.
_buildAddrList($_type, $_addrList)
Inserts given addresses into structured format.
setOptions($_options=array())
Set delivery receipt.
_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.
$_smtpsTransEncodeTypes
Content-Transfer-Encoding.
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 This is defaulted to '25' This is used only with 's...
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.
$_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
$_smtpsID
Secure SMTP Server access ID This can be defined via a INI file or via a setter method.
Definition: smtps.class.php:63
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 characers sets Known...
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 bares 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
$_log_level
Defines log level 0 - no logging 1 - connectivity logging 2 - message generation logging 3 - detail l...
getPW()
Retrieves the User Password for authentication on Mail Server.
getSubject()
Retrieves the Message Subject.
getXheader()
Retrieves the Message X-Header Content.
$_msgFrom
Who sent the Message This can be defined via a INI file or via a setter method.
Definition: smtps.class.php:80
setErrorsTo($_strErrorsTo)
Set errors to.
$_smtpsTransEncodeType
Content-Transfer-Encoding Defaulted to 0 - 7bit.
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...
$_smtpsTransEncode
Content-Transfer-Encoding Defaulted to '7bit'.
$_smtpTimeout
Sets the SMTP server timeout in seconds.
$_smtpsRelatedBoundary
Related Boundary.
setHost($_strHost)
Defines the Host Name or IP of the Mail Server to use.
$_msgPriority
Message Sensitivity Defaults to 3 - Normal.
$_smtpsPort
SMTP Server Port definition.
Definition: smtps.class.php:57
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...
$_msgSensitivity
Message Sensitivity Defaults to ZERO - None.
setPW($_strPW)
User Password for authentication on Mail Server.
$_smtpsErrors
Class error codes and messages.
$_msgSubject
Message Subject.
Definition: smtps.class.php:98
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.
$_smtpMD5
Determines whether to calculate message MD5 checksum.
$_smtpsAlternativeBoundary
Alternative Boundary.
$_aryPriority
Message Priority.
$_smtpsBoundary
Boundary String for MIME seperation.
getErrorsTo($_part=true)
Get errors to.
getSensitivity()
Returns Message Content Sensitivity string Message Sensitivity values:
getPort()
Retrieves the Port Number of the Mail Server to use This is used only with 'socket' based mail transm...
$_msgXheader
Custom X-Headers.
$_options
An array of options for stream_context_create()
$_smtpsPW
Secure SMTP Server access Password This can be defined via a INI file or via a setter method.
Definition: smtps.class.php:69
getTransportType()
Return the method inwhich the message is to be sent.
setMailPath($_path)
Path to the sendmail execuable.
$_msgContent
Message Content.
getTransEncode()
Retrieves the Content-Transfer-Encoding.
setTransEncode($_strTransEncode)
Content-Transfer-Encoding, Defaulted to '7bit' This can be changed for 2byte characers sets Known Enc...
$_mailPath
If '$_transportType' is set to '1', then this variable is used to define the UNIX file system path to...
setDebug($_vDebug=false)
Set debug.
$_msgRecipients
Who will the Message be sent to; TO, CC, BCC Multi-diminsional array containg addresses the message w...
Definition: smtps.class.php:93
setDeliveryReceipt($_val=0)
Set delivery receipt.
_setErr($_errNum, $_errMsg)
Defines errors codes and messages for Class.
getHeader()
Constructes and returns message header.
$_debug
Place Class in" debug" mode.
setXheader($strXdata)
Message X-Header Content This is a simple "insert".
$_transportType
Determines the method inwhich the message are to be sent.
is_ip($ip)
This function evaluates a string that should be a valid IPv4 Note: For ip 169.254....
dol_hash($chain, $type='0')
Returns a hash (non reversible encryption) of a string.