smtps.class.php 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064
  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 <http://www.gnu.org/licenses/>.
  20. */
  21. /**
  22. * \file htdocs/core/class/smtps.class.php
  23. * \brief Class to construct and send SMTP compliant email, even to a secure
  24. * SMTP server, regardless of platform.
  25. * Goals:
  26. * - mime compliant
  27. * - multiple Reciptiants
  28. * - TO
  29. * - CC
  30. * - BCC
  31. * - multi-part message
  32. * - plain text
  33. * - HTML
  34. * - inline attachments
  35. * - attachments
  36. * - GPG access
  37. * This Class is based off of 'SMTP PHP MAIL' by Dirk Paehl, http://www.paehl.de
  38. */
  39. /**
  40. * Class to construct and send SMTP compliant email, even
  41. * to a secure SMTP server, regardless of platform.
  42. */
  43. class SMTPs
  44. {
  45. /**
  46. * Host Name or IP of SMTP Server to use
  47. */
  48. var $_smtpsHost = 'localhost';
  49. /**
  50. * SMTP Server Port definition. 25 is default value
  51. * This can be defined via a INI file or via a setter method
  52. */
  53. var $_smtpsPort = '25';
  54. /**
  55. * Secure SMTP Server access ID
  56. * This can be defined via a INI file or via a setter method
  57. */
  58. var $_smtpsID = null;
  59. /**
  60. * Secure SMTP Server access Password
  61. * This can be defined via a INI file or via a setter method
  62. */
  63. var $_smtpsPW = null;
  64. /**
  65. * Who sent the Message
  66. * This can be defined via a INI file or via a setter method
  67. */
  68. var $_msgFrom = null;
  69. /**
  70. * Where are replies and errors to be sent to
  71. * This can be defined via a INI file or via a setter method
  72. */
  73. var $_msgReplyTo = null;
  74. /**
  75. * Who will the Message be sent to; TO, CC, BCC
  76. * Multi-diminsional array containg addresses the message will
  77. * be sent TO, CC or BCC
  78. */
  79. var $_msgRecipients = null;
  80. /**
  81. * Message Subject
  82. */
  83. var $_msgSubject = null;
  84. /**
  85. * Message Content
  86. */
  87. var $_msgContent = null;
  88. /**
  89. * Custom X-Headers
  90. */
  91. var $_msgXheader = null;
  92. /**
  93. * Character set
  94. * Defaulted to 'iso-8859-1'
  95. */
  96. var $_smtpsCharSet = 'iso-8859-1';
  97. /**
  98. * Message Sensitivity
  99. * Defaults to ZERO - None
  100. */
  101. var $_msgSensitivity = 0;
  102. /**
  103. * Message Sensitivity
  104. */
  105. var $_arySensitivity = array ( false,
  106. 'Personal',
  107. 'Private',
  108. 'Company Confidential' );
  109. /**
  110. * Message Sensitivity
  111. * Defaults to 3 - Normal
  112. */
  113. var $_msgPriority = 3;
  114. /**
  115. * Message Priority
  116. */
  117. var $_aryPriority = array ( 'Bulk',
  118. 'Highest',
  119. 'High',
  120. 'Normal',
  121. 'Low',
  122. 'Lowest' );
  123. /**
  124. * Content-Transfer-Encoding
  125. * Defaulted to 0 - 7bit
  126. */
  127. var $_smtpsTransEncodeType = 0;
  128. /**
  129. * Content-Transfer-Encoding
  130. */
  131. var $_smtpsTransEncodeTypes = array( '7bit', // Simple 7-bit ASCII
  132. '8bit', // 8-bit coding with line termination characters
  133. 'base64', // 3 octets encoded into 4 sextets with offset
  134. 'binary', // Arbitrary binary stream
  135. 'mac-binhex40', // Macintosh binary to hex encoding
  136. 'quoted-printable', // Mostly 7-bit, with 8-bit characters encoded as "=HH"
  137. 'uuencode' ); // UUENCODE encoding
  138. /**
  139. * Content-Transfer-Encoding
  140. * Defaulted to '7bit'
  141. */
  142. var $_smtpsTransEncode = '7bit';
  143. /**
  144. * Boundary String for MIME seperation
  145. */
  146. var $_smtpsBoundary = null;
  147. /**
  148. * Related Boundary
  149. */
  150. var $_smtpsRelatedBoundary = null;
  151. /**
  152. * Alternative Boundary
  153. */
  154. var $_smtpsAlternativeBoundary = null;
  155. /**
  156. * Determines the method inwhich the message are to be sent.
  157. * - 'sockets' [0] - conect via network to SMTP server - default
  158. * - 'pipe [1] - use UNIX path to EXE
  159. * - 'phpmail [2] - use the PHP built-in mail function
  160. * NOTE: Only 'sockets' is implemented
  161. */
  162. var $_transportType = 0;
  163. /**
  164. * If '$_transportType' is set to '1', then this variable is used
  165. * to define the UNIX file system path to the sendmail execuable
  166. */
  167. var $_mailPath = '/usr/lib/sendmail';
  168. /**
  169. * Sets the SMTP server timeout in seconds.
  170. */
  171. var $_smtpTimeout = 10;
  172. /**
  173. * Determines whether to calculate message MD5 checksum.
  174. */
  175. var $_smtpMD5 = false;
  176. /**
  177. * Class error codes and messages
  178. */
  179. var $_smtpsErrors = null;
  180. /**
  181. * Defines log level
  182. * 0 - no logging
  183. * 1 - connectivity logging
  184. * 2 - message generation logging
  185. * 3 - detail logging
  186. */
  187. var $_log_level = 0;
  188. /**
  189. * Place Class in" debug" mode
  190. */
  191. var $_debug = false;
  192. // @CHANGE LDR
  193. var $log = '';
  194. var $_errorsTo = '';
  195. var $_deliveryReceipt = 0;
  196. var $_trackId = '';
  197. var $_moreInHeader = '';
  198. /**
  199. * Set delivery receipt
  200. *
  201. * @param int $_val Value
  202. * @return void
  203. */
  204. function setDeliveryReceipt($_val = 0)
  205. {
  206. $this->_deliveryReceipt = $_val;
  207. }
  208. /**
  209. * get delivery receipt
  210. *
  211. * @return int Delivery receipt
  212. */
  213. function getDeliveryReceipt()
  214. {
  215. return $this->_deliveryReceipt;
  216. }
  217. /**
  218. * Set trackid
  219. *
  220. * @param string $_val Value
  221. * @return void
  222. */
  223. function setTrackId($_val = '')
  224. {
  225. $this->_trackId = $_val;
  226. }
  227. /**
  228. * Set moreInHeader
  229. *
  230. * @param string $_val Value
  231. * @return void
  232. */
  233. function setMoreInHeader($_val = '')
  234. {
  235. $this->_moreinheader = $_val;
  236. }
  237. /**
  238. * get trackid
  239. *
  240. * @return string Track id
  241. */
  242. function getTrackId()
  243. {
  244. return $this->_trackId;
  245. }
  246. /**
  247. * get moreInHeader
  248. *
  249. * @return string moreInHeader
  250. */
  251. function getMoreInHeader()
  252. {
  253. return $this->_moreinheader;
  254. }
  255. /**
  256. * Set errors to
  257. *
  258. * @param string $_strErrorsTo Errors to
  259. * @return void
  260. */
  261. function setErrorsTo($_strErrorsTo)
  262. {
  263. if ( $_strErrorsTo )
  264. $this->_errorsTo = $this->_strip_email($_strErrorsTo);
  265. }
  266. /**
  267. * Get errors to
  268. *
  269. * @param boolean $_part Variant
  270. * @return string Errors to
  271. */
  272. function getErrorsTo($_part = true )
  273. {
  274. $_retValue = '';
  275. if ( $_part === true )
  276. $_retValue = $this->_errorsTo;
  277. else
  278. $_retValue = $this->_errorsTo[$_part];
  279. return $_retValue;
  280. }
  281. /**
  282. * Set debug
  283. *
  284. * @param boolean $_vDebug Value for debug
  285. * @return void
  286. */
  287. function setDebug($_vDebug = false )
  288. {
  289. $this->_debug = $_vDebug;
  290. }
  291. /**
  292. * build RECIPIENT List, all addresses who will recieve this message
  293. *
  294. * @return void
  295. */
  296. function buildRCPTlist()
  297. {
  298. // Pull TO list
  299. $_aryToList = $this->getTO();
  300. }
  301. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  302. /**
  303. * Attempt a connection to mail server
  304. *
  305. * @return mixed $_retVal Boolean indicating success or failure on connection
  306. */
  307. function _server_connect()
  308. {
  309. // phpcs:enable
  310. // Default return value
  311. $_retVal = true;
  312. // We have to make sure the HOST given is valid
  313. // This is done here because '@fsockopen' will not give me this
  314. // information if it failes to connect because it can't find the HOST
  315. $host=$this->getHost();
  316. $usetls = preg_match('@tls://@i',$host);
  317. $host=preg_replace('@tcp://@i','',$host); // Remove prefix
  318. $host=preg_replace('@ssl://@i','',$host); // Remove prefix
  319. $host=preg_replace('@tls://@i','',$host); // Remove prefix
  320. // @CHANGE LDR
  321. include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
  322. if ( (! is_ip($host)) && ((gethostbyname($host)) == $host))
  323. {
  324. $this->_setErr(99, $host . ' is either offline or is an invalid host name.');
  325. $_retVal = false;
  326. }
  327. else
  328. {
  329. //See if we can connect to the SMTP server
  330. if ($this->socket = @fsockopen(
  331. preg_replace('@tls://@i','',$this->getHost()), // Host to 'hit', IP or domain
  332. $this->getPort(), // which Port number to use
  333. $this->errno, // actual system level error
  334. $this->errstr, // and any text that goes with the error
  335. $this->_smtpTimeout
  336. )) // timeout for reading/writing data over the socket
  337. {
  338. // Fix from PHP SMTP class by 'Chris Ryan'
  339. // Sometimes the SMTP server takes a little longer to respond
  340. // so we will give it a longer timeout for the first read
  341. // Windows still does not have support for this timeout function
  342. if (function_exists('stream_set_timeout')) stream_set_timeout($this->socket, $this->_smtpTimeout, 0);
  343. // Check response from Server
  344. if ( $_retVal = $this->server_parse($this->socket, "220") )
  345. $_retVal = $this->socket;
  346. }
  347. // This connection attempt failed.
  348. else
  349. {
  350. // @CHANGE LDR
  351. if (empty($this->errstr)) $this->errstr='Failed to connect with fsockopen host='.$this->getHost().' port='.$this->getPort();
  352. $this->_setErr($this->errno, $this->errstr);
  353. $_retVal = false;
  354. }
  355. }
  356. return $_retVal;
  357. }
  358. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  359. /**
  360. * Attempt mail server authentication for a secure connection
  361. *
  362. * @return boolean|null $_retVal Boolean indicating success or failure of authentication
  363. */
  364. function _server_authenticate()
  365. {
  366. // phpcs:enable
  367. global $conf;
  368. // Send the RFC2554 specified EHLO.
  369. // This improvment as provided by 'SirSir' to
  370. // accomodate both SMTP AND ESMTP capable servers
  371. $host=$this->getHost();
  372. $usetls = preg_match('@tls://@i',$host);
  373. $host=preg_replace('@tcp://@i','',$host); // Remove prefix
  374. $host=preg_replace('@ssl://@i','',$host); // Remove prefix
  375. $host=preg_replace('@tls://@i','',$host); // Remove prefix
  376. if ($usetls) $host='tls://'.$host;
  377. $hosth = $host;
  378. if (! empty($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO))
  379. {
  380. // If the from to is 'aaa <bbb@ccc.com>', we will keep 'ccc.com'
  381. $hosth = $this->getFrom('addr');
  382. $hosth = preg_replace('/^.*</', '', $hosth);
  383. $hosth = preg_replace('/>.*$/', '', $hosth);
  384. $hosth = preg_replace('/.*@/', '', $hosth);
  385. }
  386. if ( $_retVal = $this->socket_send_str('EHLO ' . $hosth, '250') )
  387. {
  388. if ($usetls)
  389. {
  390. /*
  391. The following dialog illustrates how a client and server can start a TLS STARTTLS session
  392. S: <waits for connection on TCP port 25>
  393. C: <opens connection>
  394. S: 220 mail.imc.org SMTP service ready
  395. C: EHLO mail.ietf.org
  396. S: 250-mail.imc.org offers a warm hug of welcome
  397. S: 250 STARTTLS
  398. C: STARTTLS
  399. S: 220 Go ahead
  400. C: <starts TLS negotiation>
  401. C & S: <negotiate a TLS session>
  402. C & S: <check result of negotiation>
  403. // Second pass EHLO
  404. C: EHLO client-domain.com
  405. S: 250-server-domain.com
  406. S: 250 AUTH LOGIN
  407. C: <continues by sending an SMTP command
  408. */
  409. if (!$_retVal = $this->socket_send_str('STARTTLS', 220))
  410. {
  411. $this->_setErr(131, 'STARTTLS connection is not supported.');
  412. return $_retVal;
  413. }
  414. // Before 5.6.7:
  415. // STREAM_CRYPTO_METHOD_SSLv23_CLIENT = STREAM_CRYPTO_METHOD_SSLv2_CLIENT|STREAM_CRYPTO_METHOD_SSLv3_CLIENT
  416. // STREAM_CRYPTO_METHOD_TLS_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
  417. // PHP >= 5.6.7:
  418. // STREAM_CRYPTO_METHOD_SSLv23_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
  419. // STREAM_CRYPTO_METHOD_TLS_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
  420. $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
  421. if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
  422. $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
  423. $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
  424. }
  425. if (!stream_socket_enable_crypto($this->socket, true, $crypto_method))
  426. {
  427. $this->_setErr(132, 'STARTTLS connection failed.');
  428. return $_retVal;
  429. }
  430. // Most server servers expect a 2nd pass of EHLO after TLS is established to get another time
  431. // the answer with list of supported AUTH methods. They may differs between non STARTTLS and with STARTTLS.
  432. if (!$_retVal = $this->socket_send_str('EHLO '.$host, '250'))
  433. {
  434. $this->_setErr(126, '"' . $host . '" does not support authenticated connections.');
  435. return $_retVal;
  436. }
  437. }
  438. // Send Authentication to Server
  439. // Check for errors along the way
  440. $this->socket_send_str('AUTH LOGIN', '334');
  441. // User name will not return any error, server will take anything we give it.
  442. $this->socket_send_str(base64_encode($this->_smtpsID), '334');
  443. // The error here just means the ID/password combo doesn't work.
  444. // There is not a method to determine which is the problem, ID or password
  445. if ( ! $_retVal = $this->socket_send_str(base64_encode($this->_smtpsPW), '235') )
  446. $this->_setErr(130, 'Invalid Authentication Credentials.');
  447. }
  448. else
  449. {
  450. $this->_setErr(126, '"' . $host . '" does not support authenticated connections.');
  451. }
  452. return $_retVal;
  453. }
  454. /**
  455. * Now send the message
  456. *
  457. * @param boolean $_bolTestMsg whether to run this method in 'Test' mode.
  458. * @param boolean $_bolDebug whether to log all communication between this Class and the Mail Server.
  459. * @return boolean|null void
  460. * $_strMsg If this is run in 'Test' mode, the actual message structure will be returned
  461. */
  462. function sendMsg($_bolTestMsg = false, $_bolDebug = false)
  463. {
  464. global $conf;
  465. /**
  466. * Default return value
  467. */
  468. $_retVal = false;
  469. // Connect to Server
  470. if ( $this->socket = $this->_server_connect() )
  471. {
  472. // If a User ID *and* a password is given, assume Authentication is desired
  473. if( !empty($this->_smtpsID) && !empty($this->_smtpsPW) )
  474. {
  475. // Send the RFC2554 specified EHLO.
  476. $_retVal = $this->_server_authenticate();
  477. }
  478. // This is a "normal" SMTP Server "handshack"
  479. else
  480. {
  481. // Send the RFC821 specified HELO.
  482. $host=$this->getHost();
  483. $usetls = preg_match('@tls://@i',$host);
  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. $hosth = $host;
  488. if (! empty($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO))
  489. {
  490. // If the from to is 'aaa <bbb@ccc.com>', we will keep 'ccc.com'
  491. $hosth = $this->getFrom('addr');
  492. $hosth = preg_replace('/^.*</', '', $hosth);
  493. $hosth = preg_replace('/>.*$/', '', $hosth);
  494. $hosth = preg_replace('/.*@/', '', $hosth);
  495. }
  496. $_retVal = $this->socket_send_str('HELO ' . $hosth, '250');
  497. }
  498. // Well, did we get to the server?
  499. if ( $_retVal )
  500. {
  501. // From this point onward most server response codes should be 250
  502. // Specify who the mail is from....
  503. // This has to be the raw email address, strip the "name" off
  504. $this->socket_send_str('MAIL FROM: ' . $this->getFrom('addr'), '250');
  505. // 'RCPT TO:' must be given a single address, so this has to loop
  506. // through the list of addresses, regardless of TO, CC or BCC
  507. // and send it out "single file"
  508. foreach ( $this->get_RCPT_list() as $_address )
  509. {
  510. /* Note:
  511. * BCC email addresses must be listed in the RCPT TO command list,
  512. * but the BCC header should not be printed under the DATA command.
  513. * http://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server
  514. */
  515. /*
  516. * TODO
  517. * After each 'RCPT TO:' is sent, we need to make sure it was kosher,
  518. * if not, the whole message will fail
  519. * If any email address fails, we will need to RESET the connection,
  520. * mark the last address as "bad" and start the address loop over again.
  521. * If any address fails, the entire message fails.
  522. */
  523. $this->socket_send_str('RCPT TO: <' . $_address . '>', '250');
  524. }
  525. // Tell the server we are ready to start sending data
  526. // with any custom headers...
  527. // This is the last response code we look for until the end of the message.
  528. $this->socket_send_str('DATA', '354');
  529. // Now we are ready for the message...
  530. // Ok, all the ingredients are mixed in let's cook this puppy...
  531. $this->socket_send_str($this->getHeader().$this->getBodyContent() . "\r\n" . '.', '250');
  532. // Now tell the server we are done and close the socket...
  533. fputs($this->socket, 'QUIT');
  534. fclose($this->socket);
  535. }
  536. }
  537. return $_retVal;
  538. }
  539. // =============================================================
  540. // ** Setter & Getter methods
  541. // ** Basic System configuration
  542. /**
  543. * setConfig() is used to populate select class properties from either
  544. * a user defined INI file or the systems 'php.ini' file
  545. *
  546. * If a user defined INI is to be used, the files complete path is passed
  547. * as the method single parameter. The INI can define any class and/or
  548. * user properties. Only properties defined within this file will be setter
  549. * and/or orverwritten
  550. *
  551. * If the systems 'php.ini' file is to be used, the method is called without
  552. * parameters. In this case, only HOST, PORT and FROM properties will be set
  553. * as they are the only properties that are defined within the 'php.ini'.
  554. *
  555. * If secure SMTP is to be used, the user ID and Password can be defined with
  556. * the user INI file, but the properties are not defined with the systems
  557. * 'php.ini'file, they must be defined via their setter methods
  558. *
  559. * This method can be called twice, if desired. Once without a parameter to
  560. * load the properties as defined within the systems 'php.ini' file, and a
  561. * second time, with a path to a user INI file for other properties to be
  562. * defined.
  563. *
  564. * @param mixed $_strConfigPath path to config file or VOID
  565. * @return boolean
  566. */
  567. function setConfig($_strConfigPath = null)
  568. {
  569. /**
  570. * Returns constructed SELECT Object string or boolean upon failure
  571. * Default value is set at true
  572. */
  573. $_retVal = true;
  574. // if we have a path...
  575. if ( ! empty ($_strConfigPath) )
  576. {
  577. // If the path is not valid, this will NOT generate an error,
  578. // it will simply return false.
  579. if ( ! @include $_strConfigPath)
  580. {
  581. $this->_setErr(110, '"' . $_strConfigPath . '" is not a valid path.');
  582. $_retVal = false;
  583. }
  584. }
  585. // Read the Systems php.ini file
  586. else
  587. {
  588. // Set these properties ONLY if they are set in the php.ini file.
  589. // Otherwise the default values will be used.
  590. if ( $_host = ini_get('SMTPs') )
  591. $this->setHost($_host);
  592. if ( $_port = ini_get('smtp_port') )
  593. $this->setPort($_port);
  594. if ( $_from = ini_get('sendmail_from') )
  595. $this->setFrom($_from);
  596. }
  597. // Send back what we have
  598. return $_retVal;
  599. }
  600. /**
  601. * Determines the method inwhich the messages are to be sent.
  602. * - 'sockets' [0] - conect via network to SMTP server
  603. * - 'pipe [1] - use UNIX path to EXE
  604. * - 'phpmail [2] - use the PHP built-in mail function
  605. *
  606. * @param int $_type Interger value representing Mail Transport Type
  607. * @return void
  608. */
  609. function setTransportType($_type = 0)
  610. {
  611. if ( ( is_numeric($_type) ) &&
  612. ( ( $_type >= 0 ) && ( $_type <= 3 ) ) )
  613. $this->_transportType = $_type;
  614. }
  615. /**
  616. * Return the method inwhich the message is to be sent.
  617. * - 'sockets' [0] - conect via network to SMTP server
  618. * - 'pipe [1] - use UNIX path to EXE
  619. * - 'phpmail [2] - use the PHP built-in mail function
  620. *
  621. * @return int $_strHost Host Name or IP of the Mail Server to use
  622. */
  623. function getTransportType()
  624. {
  625. return $this->_transportType;
  626. }
  627. /**
  628. * Path to the sendmail execuable
  629. *
  630. * @param string $_path Path to the sendmail execuable
  631. * @return boolean
  632. *
  633. */
  634. function setMailPath($_path)
  635. {
  636. // This feature is not yet implemented
  637. return true;
  638. //if ( $_path ) $this->_mailPath = $_path;
  639. }
  640. /**
  641. * Defines the Host Name or IP of the Mail Server to use.
  642. * This is defaulted to 'localhost'
  643. * This is used only with 'socket' based mail transmission
  644. *
  645. * @param string $_strHost Host Name or IP of the Mail Server to use
  646. * @return void
  647. */
  648. function setHost($_strHost)
  649. {
  650. if ( $_strHost )
  651. $this->_smtpsHost = $_strHost;
  652. }
  653. /**
  654. * Retrieves the Host Name or IP of the Mail Server to use
  655. * This is used only with 'socket' based mail transmission
  656. *
  657. * @return string $_strHost Host Name or IP of the Mail Server to use
  658. */
  659. function getHost()
  660. {
  661. return $this->_smtpsHost;
  662. }
  663. /**
  664. * Defines the Port Number of the Mail Server to use
  665. * This is defaulted to '25'
  666. * This is used only with 'socket' based mail transmission
  667. *
  668. * @param int $_intPort Port Number of the Mail Server to use
  669. * @return void
  670. */
  671. function setPort($_intPort)
  672. {
  673. if ( ( is_numeric($_intPort) ) &&
  674. ( ( $_intPort >= 1 ) && ( $_intPort <= 65536 ) ) )
  675. $this->_smtpsPort = $_intPort;
  676. }
  677. /**
  678. * Retrieves the Port Number of the Mail Server to use
  679. * This is used only with 'socket' based mail transmission
  680. *
  681. * @return string Port Number of the Mail Server to use
  682. */
  683. function getPort()
  684. {
  685. return $this->_smtpsPort;
  686. }
  687. /**
  688. * User Name for authentication on Mail Server
  689. *
  690. * @param string $_strID User Name for authentication on Mail Server
  691. * @return void
  692. */
  693. function setID($_strID)
  694. {
  695. $this->_smtpsID = $_strID;
  696. }
  697. /**
  698. * Retrieves the User Name for authentication on Mail Server
  699. *
  700. * @return string User Name for authentication on Mail Server
  701. */
  702. function getID()
  703. {
  704. return $this->_smtpsID;
  705. }
  706. /**
  707. * User Password for authentication on Mail Server
  708. *
  709. * @param string $_strPW User Password for authentication on Mail Server
  710. * @return void
  711. */
  712. function setPW($_strPW)
  713. {
  714. $this->_smtpsPW = $_strPW;
  715. }
  716. /**
  717. * Retrieves the User Password for authentication on Mail Server
  718. *
  719. * @return string User Password for authentication on Mail Server
  720. */
  721. function getPW()
  722. {
  723. return $this->_smtpsPW;
  724. }
  725. /**
  726. * Character set used for current message
  727. * Character set is defaulted to 'iso-8859-1';
  728. *
  729. * @param string $_strCharSet Character set used for current message
  730. * @return void
  731. */
  732. function setCharSet($_strCharSet)
  733. {
  734. if ( $_strCharSet )
  735. $this->_smtpsCharSet = $_strCharSet;
  736. }
  737. /**
  738. * Retrieves the Character set used for current message
  739. *
  740. * @return string $_smtpsCharSet Character set used for current message
  741. */
  742. function getCharSet()
  743. {
  744. return $this->_smtpsCharSet;
  745. }
  746. /**
  747. * Content-Transfer-Encoding, Defaulted to '7bit'
  748. * This can be changed for 2byte characers sets
  749. * Known Encode Types
  750. * - 7bit Simple 7-bit ASCII
  751. * - 8bit 8-bit coding with line termination characters
  752. * - base64 3 octets encoded into 4 sextets with offset
  753. * - binary Arbitrary binary stream
  754. * - mac-binhex40 Macintosh binary to hex encoding
  755. * - quoted-printable Mostly 7-bit, with 8-bit characters encoded as "=HH"
  756. * - uuencode UUENCODE encoding
  757. *
  758. * @param string $_strTransEncode Content-Transfer-Encoding
  759. * @return void
  760. */
  761. function setTransEncode($_strTransEncode)
  762. {
  763. if (array_search($_strTransEncode, $this->_smtpsTransEncodeTypes))
  764. $this->_smtpsTransEncode = $_strTransEncode;
  765. }
  766. /**
  767. * Retrieves the Content-Transfer-Encoding
  768. *
  769. * @return string $_smtpsTransEncode Content-Transfer-Encoding
  770. */
  771. function getTransEncode()
  772. {
  773. return $this->_smtpsTransEncode;
  774. }
  775. /**
  776. * Content-Transfer-Encoding, Defaulted to '0' [ZERO]
  777. * This can be changed for 2byte characers sets
  778. * Known Encode Types
  779. * - [0] 7bit Simple 7-bit ASCII
  780. * - [1] 8bit 8-bit coding with line termination characters
  781. * - [2] base64 3 octets encoded into 4 sextets with offset
  782. * - [3] binary Arbitrary binary stream
  783. * - [4] mac-binhex40 Macintosh binary to hex encoding
  784. * - [5] quoted-printable Mostly 7-bit, with 8-bit characters encoded as "=HH"
  785. * - [6] uuencode UUENCODE encoding
  786. *
  787. * @param string $_strTransEncodeType Content-Transfer-Encoding
  788. * @return void
  789. *
  790. */
  791. function setTransEncodeType($_strTransEncodeType)
  792. {
  793. if (array_search($_strTransEncodeType, $this->_smtpsTransEncodeTypes))
  794. $this->_smtpsTransEncodeType = $_strTransEncodeType;
  795. }
  796. /**
  797. * Retrieves the Content-Transfer-Encoding
  798. *
  799. * @return string Content-Transfer-Encoding
  800. */
  801. function getTransEncodeType()
  802. {
  803. return $this->_smtpsTransEncodeTypes[$this->_smtpsTransEncodeType];
  804. }
  805. // ** Message Construction
  806. /**
  807. * FROM Address from which mail will be sent
  808. *
  809. * @param string $_strFrom Address from which mail will be sent
  810. * @return void
  811. */
  812. function setFrom($_strFrom)
  813. {
  814. if ( $_strFrom )
  815. $this->_msgFrom = $this->_strip_email($_strFrom);
  816. }
  817. /**
  818. * Retrieves the Address from which mail will be sent
  819. *
  820. * @param boolean $_part To "strip" 'Real name' from address
  821. * @return string Address from which mail will be sent
  822. */
  823. function getFrom($_part = true)
  824. {
  825. $_retValue = '';
  826. if ( $_part === true )
  827. $_retValue = $this->_msgFrom;
  828. else
  829. $_retValue = $this->_msgFrom[$_part];
  830. return $_retValue;
  831. }
  832. /**
  833. * Reply-To Address from which mail will be the reply-to
  834. *
  835. * @param string $_strReplyTo Address from which mail will be the reply-to
  836. * @return void
  837. */
  838. function setReplyTo($_strReplyTo)
  839. {
  840. if ( $_strReplyTo )
  841. $this->_msgReplyTo = $this->_strip_email($_strReplyTo);
  842. }
  843. /**
  844. * Retrieves the Address from which mail will be the reply-to
  845. *
  846. * @param boolean $_part To "strip" 'Real name' from address
  847. * @return string Address from which mail will be the reply-to
  848. */
  849. function getReplyTo($_part = true)
  850. {
  851. $_retValue = '';
  852. if ( $_part === true )
  853. $_retValue = $this->_msgReplyTo;
  854. else
  855. $_retValue = $this->_msgReplyTo[$_part];
  856. return $_retValue;
  857. }
  858. /**
  859. * Inserts given addresses into structured format.
  860. * This method takes a list of given addresses, via an array
  861. * or a COMMA delimted string, and inserts them into a highly
  862. * structured array. This array is designed to remove duplicate
  863. * addresses and to sort them by Domain.
  864. *
  865. * @param string $_type TO, CC, or BCC lists to add addrresses into
  866. * @param mixed $_addrList Array or COMMA delimited string of addresses
  867. * @return void
  868. *
  869. */
  870. function _buildAddrList($_type, $_addrList)
  871. {
  872. // Pull existing list
  873. $aryHost = $this->_msgRecipients;
  874. // Only run this if we have something
  875. if ( !empty ($_addrList ))
  876. {
  877. // $_addrList can be a STRING or an array
  878. if ( is_string($_addrList) )
  879. {
  880. // This could be a COMMA delimited string
  881. if ( strstr($_addrList, ',') )
  882. // "explode "list" into an array
  883. $_addrList = explode(',', $_addrList);
  884. // Stick it in an array
  885. else
  886. $_addrList = array($_addrList);
  887. }
  888. // take the array of addresses and split them further
  889. foreach ( $_addrList as $_strAddr )
  890. {
  891. // Strip off the end '>'
  892. $_strAddr = str_replace('>', '', $_strAddr);
  893. // Seperate "Real Name" from eMail address
  894. $_tmpaddr = null;
  895. $_tmpaddr = explode('<', $_strAddr);
  896. // We have a "Real Name" and eMail address
  897. if ( count($_tmpaddr) == 2 )
  898. {
  899. $_tmpHost = explode('@', $_tmpaddr[1]);
  900. $_tmpaddr[0] = trim($_tmpaddr[0], ' ">');
  901. $aryHost[$_tmpHost[1]][$_type][$_tmpHost[0]] = $_tmpaddr[0];
  902. }
  903. // We only have an eMail address
  904. else
  905. {
  906. // Strip off the beggining '<'
  907. $_strAddr = str_replace('<', '', $_strAddr);
  908. $_tmpHost = explode('@', $_strAddr);
  909. $_tmpHost[0] = trim($_tmpHost[0]);
  910. $_tmpHost[1] = trim($_tmpHost[1]);
  911. $aryHost[$_tmpHost[1]][$_type][$_tmpHost[0]] = '';
  912. }
  913. }
  914. }
  915. // replace list
  916. $this->_msgRecipients = $aryHost;
  917. }
  918. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  919. /**
  920. * Returns an array of the various parts of an email address
  921. * This assumes a well formed address:
  922. * - "Real name" <username@domain.tld>
  923. * - "Real Name" is optional
  924. * - if "Real Name" does not exist, the angle brackets are optional
  925. * This will split an email address into 4 or 5 parts.
  926. * - $_aryEmail[org] = orignal string
  927. * - $_aryEmail[real] = "real name" - if there is one
  928. * - $_aryEmail[addr] = address part "username@domain.tld"
  929. * - $_aryEmail[host] = "domain.tld"
  930. * - $_aryEmail[user] = "userName"
  931. *
  932. * @param string $_strAddr Email address
  933. * @return array An array of the various parts of an email address
  934. */
  935. function _strip_email($_strAddr)
  936. {
  937. // phpcs:enable
  938. // Keep the orginal
  939. $_aryEmail['org'] = $_strAddr;
  940. // Set entire string to Lower Case
  941. $_strAddr = strtolower($_strAddr);
  942. // Drop "stuff' off the end
  943. $_strAddr = trim($_strAddr, ' ">');
  944. // Seperate "Real Name" from eMail address, if we have one
  945. $_tmpAry = explode('<', $_strAddr);
  946. // Do we have a "Real name"
  947. if ( count($_tmpAry) == 2 )
  948. {
  949. // We may not really have a "Real Name"
  950. if ( $_tmpAry[0])
  951. $_aryEmail['real'] = trim($_tmpAry[0], ' ">');
  952. $_aryEmail['addr'] = $_tmpAry[1];
  953. }
  954. else
  955. $_aryEmail['addr'] = $_tmpAry[0];
  956. // Pull User Name and Host.tld apart
  957. list($_aryEmail['user'], $_aryEmail['host'] ) = explode('@', $_aryEmail['addr']);
  958. // Put the brackets back around the address
  959. $_aryEmail['addr'] = '<' . $_aryEmail['addr'] . '>';
  960. return $_aryEmail;
  961. }
  962. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  963. /**
  964. * Returns an array of bares addresses for use with 'RCPT TO:'
  965. * This is a "build as you go" method. Each time this method is called
  966. * the underlaying array is destroyed and reconstructed.
  967. *
  968. * @return array Returns an array of bares addresses
  969. */
  970. function get_RCPT_list()
  971. {
  972. // phpcs:enable
  973. /**
  974. * An array of bares addresses for use with 'RCPT TO:'
  975. */
  976. $_RCPT_list=array();
  977. // walk down Recipients array and pull just email addresses
  978. foreach ( $this->_msgRecipients as $_host => $_list )
  979. {
  980. foreach ( $_list as $_subList )
  981. {
  982. foreach ( $_subList as $_name => $_addr )
  983. {
  984. // build RCPT list
  985. $_RCPT_list[] = $_name . '@' . $_host;
  986. }
  987. }
  988. }
  989. return $_RCPT_list;
  990. }
  991. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  992. /**
  993. * Returns an array of addresses for a specific type; TO, CC or BCC
  994. *
  995. * @param string $_which Which collection of addresses to return ('to', 'cc', 'bcc')
  996. * @return string|false Array of emaill address
  997. */
  998. function get_email_list($_which = null)
  999. {
  1000. // phpcs:enable
  1001. // We need to know which address segment to pull
  1002. if ( $_which )
  1003. {
  1004. // Make sure we have addresses to process
  1005. if ( $this->_msgRecipients )
  1006. {
  1007. $_RCPT_list=array();
  1008. // walk down Recipients array and pull just email addresses
  1009. foreach ( $this->_msgRecipients as $_host => $_list )
  1010. {
  1011. if ( $this->_msgRecipients[$_host][$_which] )
  1012. {
  1013. foreach ( $this->_msgRecipients[$_host][$_which] as $_addr => $_realName )
  1014. {
  1015. if ( $_realName ) // @CHANGE LDR
  1016. {
  1017. $_realName = '"' . $_realName . '"';
  1018. $_RCPT_list[] = $_realName . ' <' . $_addr . '@' . $_host . '>';
  1019. }
  1020. else
  1021. {
  1022. $_RCPT_list[] = $_addr . '@' . $_host;
  1023. }
  1024. }
  1025. }
  1026. }
  1027. return implode(', ', $_RCPT_list);
  1028. }
  1029. else
  1030. {
  1031. $this->_setErr(101, 'No eMail Address for message to be sent to.');
  1032. return false;
  1033. }
  1034. }
  1035. else
  1036. {
  1037. $this->_setErr(102, 'eMail type not defined.');
  1038. return false;
  1039. }
  1040. }
  1041. /**
  1042. * TO Address[es] inwhich to send mail to
  1043. *
  1044. * @param string $_addrTo TO Address[es] inwhich to send mail to
  1045. * @return void
  1046. */
  1047. function setTO($_addrTo)
  1048. {
  1049. if ( $_addrTo )
  1050. $this->_buildAddrList('to', $_addrTo);
  1051. }
  1052. /**
  1053. * Retrieves the TO Address[es] inwhich to send mail to
  1054. *
  1055. * @return string TO Address[es] inwhich to send mail to
  1056. */
  1057. function getTo()
  1058. {
  1059. return $this->get_email_list('to');
  1060. }
  1061. /**
  1062. * CC Address[es] inwhich to send mail to
  1063. *
  1064. * @param string $_strCC CC Address[es] inwhich to send mail to
  1065. * @return void
  1066. */
  1067. function setCC($_strCC)
  1068. {
  1069. if ( $_strCC )
  1070. $this->_buildAddrList('cc', $_strCC);
  1071. }
  1072. /**
  1073. * Retrieves the CC Address[es] inwhich to send mail to
  1074. *
  1075. * @return string CC Address[es] inwhich to send mail to
  1076. */
  1077. function getCC()
  1078. {
  1079. return $this->get_email_list('cc');
  1080. }
  1081. /**
  1082. * BCC Address[es] inwhich to send mail to
  1083. *
  1084. * @param string $_strBCC Recipients BCC Address[es] inwhich to send mail to
  1085. * @return void
  1086. */
  1087. function setBCC($_strBCC)
  1088. {
  1089. if ( $_strBCC )
  1090. $this->_buildAddrList('bcc', $_strBCC);
  1091. }
  1092. /**
  1093. * Retrieves the BCC Address[es] inwhich to send mail to
  1094. *
  1095. * @return string BCC Address[es] inwhich to send mail to
  1096. */
  1097. function getBCC()
  1098. {
  1099. return $this->get_email_list('bcc');
  1100. }
  1101. /**
  1102. * Message Subject
  1103. *
  1104. * @param string $_strSubject Message Subject
  1105. * @return void
  1106. */
  1107. function setSubject($_strSubject = '')
  1108. {
  1109. if ( $_strSubject )
  1110. $this->_msgSubject = $_strSubject;
  1111. }
  1112. /**
  1113. * Retrieves the Message Subject
  1114. *
  1115. * @return string Message Subject
  1116. */
  1117. function getSubject()
  1118. {
  1119. return $this->_msgSubject;
  1120. }
  1121. /**
  1122. * Constructes and returns message header
  1123. *
  1124. * @return string Complete message header
  1125. */
  1126. function getHeader()
  1127. {
  1128. global $conf;
  1129. $_header = 'From: ' . $this->getFrom('org') . "\r\n"
  1130. . 'To: ' . $this->getTO() . "\r\n";
  1131. if ( $this->getCC() )
  1132. $_header .= 'Cc: ' . $this->getCC() . "\r\n";
  1133. /* Note:
  1134. * BCC email addresses must be listed in the RCPT TO command list,
  1135. * but the BCC header should not be printed under the DATA command.
  1136. * So it is included into the function sendMsg() but not here.
  1137. * http://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server
  1138. */
  1139. /*
  1140. if ( $this->getBCC() )
  1141. $_header .= 'Bcc: ' . $this->getBCC() . "\r\n";
  1142. */
  1143. $host=$this->getHost();
  1144. $usetls = preg_match('@tls://@i',$host);
  1145. $host=preg_replace('@tcp://@i','',$host); // Remove prefix
  1146. $host=preg_replace('@ssl://@i','',$host); // Remove prefix
  1147. $host=preg_replace('@tls://@i','',$host); // Remove prefix
  1148. $host=dol_getprefix('email');
  1149. //NOTE: Message-ID should probably contain the username of the user who sent the msg
  1150. $_header .= 'Subject: ' . $this->getSubject() . "\r\n";
  1151. $_header .= 'Date: ' . date("r") . "\r\n";
  1152. $trackid = $this->getTrackId();
  1153. if ($trackid)
  1154. {
  1155. // References is kept in response and Message-ID is returned into In-Reply-To:
  1156. $_header .= 'Message-ID: <' . time() . '.SMTPs-dolibarr-'.$trackid.'@' . $host . ">\r\n";
  1157. $_header .= 'References: <' . time() . '.SMTPs-dolibarr-'.$trackid.'@' . $host . ">\r\n";
  1158. $_header .= 'X-Dolibarr-TRACKID: ' . $trackid . '@' . $host . "\r\n";
  1159. }
  1160. else
  1161. {
  1162. $_header .= 'Message-ID: <' . time() . '.SMTPs@' . $host . ">\r\n";
  1163. }
  1164. if (! empty($_SERVER['REMOTE_ADDR'])) $_header .= "X-RemoteAddr: " . $_SERVER['REMOTE_ADDR']. "\r\n";
  1165. if ( $this->getMoreInHeader() )
  1166. $_header .= $this->getMoreInHeader(); // Value must include the "\r\n";
  1167. //$_header .=
  1168. // 'Read-Receipt-To: ' . $this->getFrom( 'org' ) . "\r\n"
  1169. // 'Return-Receipt-To: ' . $this->getFrom( 'org' ) . "\r\n";
  1170. if ( $this->getSensitivity() )
  1171. $_header .= 'Sensitivity: ' . $this->getSensitivity() . "\r\n";
  1172. if ( $this->_msgPriority != 3 )
  1173. $_header .= $this->getPriority();
  1174. // @CHANGE LDR
  1175. if ( $this->getDeliveryReceipt() )
  1176. $_header .= 'Disposition-Notification-To: '.$this->getFrom('addr') . "\r\n";
  1177. if ( $this->getErrorsTo() )
  1178. $_header .= 'Errors-To: '.$this->getErrorsTo('addr') . "\r\n";
  1179. if ( $this->getReplyTo() )
  1180. $_header .= "Reply-To: ".$this->getReplyTo('addr') ."\r\n";
  1181. $_header .= 'X-Mailer: Dolibarr version ' . DOL_VERSION .' (using SMTPs Mailer)' . "\r\n";
  1182. $_header .= 'X-Dolibarr-Option: '.($conf->global->MAIN_MAIL_USE_MULTI_PART?'MAIN_MAIL_USE_MULTI_PART':'No MAIN_MAIL_USE_MULTI_PART') . "\r\n";
  1183. $_header .= 'Mime-Version: 1.0' . "\r\n";
  1184. return $_header;
  1185. }
  1186. /**
  1187. * Message Content
  1188. *
  1189. * @param string $strContent Message Content
  1190. * @param string $strType Type
  1191. * @return void
  1192. */
  1193. function setBodyContent($strContent, $strType = 'plain')
  1194. {
  1195. //if ( $strContent )
  1196. //{
  1197. if ( $strType == 'html' )
  1198. $strMimeType = 'text/html';
  1199. else
  1200. $strMimeType = 'text/plain';
  1201. // Make RFC821 Compliant, replace bare linefeeds
  1202. $strContent = preg_replace("/(?<!\r)\n/si", "\r\n", $strContent);
  1203. $strContentAltText = '';
  1204. if ($strType == 'html')
  1205. {
  1206. // Similar code to forge a text from html is also in CMailFile.class.php
  1207. $strContentAltText = preg_replace("/<br\s*[^>]*>/"," ", $strContent);
  1208. $strContentAltText = html_entity_decode(strip_tags($strContentAltText));
  1209. $strContentAltText = rtrim(wordwrap($strContentAltText, 75, "\r\n"));
  1210. }
  1211. // Make RFC2045 Compliant
  1212. //$strContent = rtrim(chunk_split($strContent)); // Function chunck_split seems ko if not used on a base64 content
  1213. $strContent = rtrim(wordwrap($strContent, 75, "\r\n")); // TODO Using this method creates unexpected line break on text/plain content.
  1214. $this->_msgContent[$strType] = array();
  1215. $this->_msgContent[$strType]['mimeType'] = $strMimeType;
  1216. $this->_msgContent[$strType]['data'] = $strContent;
  1217. $this->_msgContent[$strType]['dataText'] = $strContentAltText;
  1218. if ( $this->getMD5flag() )
  1219. $this->_msgContent[$strType]['md5'] = dol_hash($strContent, 3);
  1220. //}
  1221. }
  1222. /**
  1223. * Retrieves the Message Content
  1224. *
  1225. * @return string Message Content
  1226. */
  1227. function getBodyContent()
  1228. {
  1229. global $conf;
  1230. // Generate a new Boundary string
  1231. $this->_setBoundary();
  1232. // What type[s] of content do we have
  1233. $_types = array_keys($this->_msgContent);
  1234. // How many content types do we have
  1235. $keyCount = count($_types);
  1236. // If we have ZERO, we have a problem
  1237. if( $keyCount === 0 )
  1238. die ("Sorry, no content");
  1239. // If we have ONE, we can use the simple format
  1240. else if( $keyCount === 1 && empty($conf->global->MAIN_MAIL_USE_MULTI_PART))
  1241. {
  1242. $_msgData = $this->_msgContent;
  1243. $_msgData = $_msgData[$_types[0]];
  1244. $content = 'Content-Type: ' . $_msgData['mimeType'] . '; charset="' . $this->getCharSet() . '"' . "\r\n"
  1245. . 'Content-Transfer-Encoding: ' . $this->getTransEncodeType() . "\r\n"
  1246. . 'Content-Disposition: inline' . "\r\n"
  1247. . 'Content-Description: Message' . "\r\n";
  1248. if ( $this->getMD5flag() )
  1249. $content .= 'Content-MD5: ' . $_msgData['md5'] . "\r\n";
  1250. $content .= "\r\n"
  1251. . $_msgData['data'] . "\r\n";
  1252. }
  1253. // If we have more than ONE, we use the multi-part format
  1254. else if( $keyCount >= 1 || ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART))
  1255. {
  1256. // Since this is an actual multi-part message
  1257. // We need to define a content message Boundary
  1258. // NOTE: This was 'multipart/alternative', but Windows based mail servers have issues with this.
  1259. //$content = 'Content-Type: multipart/related; boundary="' . $this->_getBoundary() . '"' . "\r\n";
  1260. $content = 'Content-Type: multipart/mixed; boundary="' . $this->_getBoundary('mixed') . '"' . "\r\n";
  1261. // . "\r\n"
  1262. // . 'This is a multi-part message in MIME format.' . "\r\n";
  1263. $content .= "Content-Transfer-Encoding: 8bit\r\n";
  1264. $content .= "\r\n";
  1265. $content .= "--" . $this->_getBoundary('mixed') . "\r\n";
  1266. if (key_exists('image', $this->_msgContent)) // If inline image found
  1267. {
  1268. $content.= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"' . "\r\n";
  1269. $content .= "\r\n";
  1270. $content .= "--" . $this->_getBoundary('alternative') . "\r\n";
  1271. }
  1272. // $this->_msgContent must be sorted with key 'text' or 'html' first then 'image' then 'attachment'
  1273. // Loop through message content array
  1274. foreach ($this->_msgContent as $type => $_content )
  1275. {
  1276. if ( $type == 'attachment' )
  1277. {
  1278. // loop through all attachments
  1279. foreach ( $_content as $_file => $_data )
  1280. {
  1281. $content .= "--" . $this->_getBoundary('mixed') . "\r\n"
  1282. . 'Content-Disposition: attachment; filename="' . $_data['fileName'] . '"' . "\r\n"
  1283. . 'Content-Type: ' . $_data['mimeType'] . '; name="' . $_data['fileName'] . '"' . "\r\n"
  1284. . 'Content-Transfer-Encoding: base64' . "\r\n"
  1285. . 'Content-Description: ' . $_data['fileName'] ."\r\n";
  1286. if ( $this->getMD5flag() )
  1287. $content .= 'Content-MD5: ' . $_data['md5'] . "\r\n";
  1288. $content .= "\r\n" . $_data['data'] . "\r\n\r\n";
  1289. }
  1290. }
  1291. // @CHANGE LDR
  1292. else if ( $type == 'image' )
  1293. {
  1294. // loop through all images
  1295. foreach ( $_content as $_image => $_data )
  1296. {
  1297. $content .= "--" . $this->_getBoundary('related') . "\r\n"; // always related for an inline image
  1298. $content .= 'Content-Type: ' . $_data['mimeType'] . '; name="' . $_data['imageName'] . '"' . "\r\n"
  1299. . 'Content-Transfer-Encoding: base64' . "\r\n"
  1300. . 'Content-Disposition: inline; filename="' . $_data['imageName'] . '"' . "\r\n"
  1301. . 'Content-ID: <' . $_data['cid'] . '> ' . "\r\n";
  1302. if ( $this->getMD5flag() )
  1303. $content .= 'Content-MD5: ' . $_data['md5'] . "\r\n";
  1304. $content .= "\r\n"
  1305. . $_data['data'] . "\r\n";
  1306. }
  1307. // always end related and end alternative after inline images
  1308. $content.= "--" . $this->_getBoundary('related') . "--" . "\r\n";
  1309. $content.= "\r\n" . "--" . $this->_getBoundary('alternative') . "--" . "\r\n";
  1310. $content.= "\r\n";
  1311. }
  1312. else
  1313. {
  1314. if (key_exists('image', $this->_msgContent))
  1315. {
  1316. $content.= "Content-Type: text/plain; charset=" . $this->getCharSet() . "\r\n";
  1317. $content.= "\r\n" . ($_content['dataText']?$_content['dataText']:strip_tags($_content['data'])) . "\r\n"; // Add plain text message
  1318. $content.= "--" . $this->_getBoundary('alternative') . "\r\n";
  1319. $content.= 'Content-Type: multipart/related; boundary="' . $this->_getBoundary('related') . '"' . "\r\n";
  1320. $content.= "\r\n";
  1321. $content.= "--" . $this->_getBoundary('related') . "\r\n";
  1322. }
  1323. if (! key_exists('image', $this->_msgContent) && $_content['dataText'] && ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) // Add plain text message part before html part
  1324. {
  1325. $content.= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"' . "\r\n";
  1326. $content .= "\r\n";
  1327. $content .= "--" . $this->_getBoundary('alternative') . "\r\n";
  1328. $content.= "Content-Type: text/plain; charset=" . $this->getCharSet() . "\r\n";
  1329. $content.= "\r\n". $_content['dataText'] . "\r\n";
  1330. $content.= "--" . $this->_getBoundary('alternative') . "\r\n";
  1331. }
  1332. $content .= 'Content-Type: ' . $_content['mimeType'] . '; '
  1333. // . 'charset="' . $this->getCharSet() . '"';
  1334. . 'charset=' . $this->getCharSet() . '';
  1335. // $content .= ( $type == 'html') ? '; name="HTML Part"' : '';
  1336. $content .= "\r\n";
  1337. // $content .= 'Content-Transfer-Encoding: ';
  1338. // $content .= ($type == 'html') ? 'quoted-printable' : $this->getTransEncodeType();
  1339. // $content .= "\r\n"
  1340. // . 'Content-Disposition: inline' . "\r\n"
  1341. // . 'Content-Description: ' . $type . ' message' . "\r\n";
  1342. if ( $this->getMD5flag() )
  1343. $content .= 'Content-MD5: ' . $_content['md5'] . "\r\n";
  1344. $content .= "\r\n" . $_content['data'] . "\r\n";
  1345. if (! key_exists('image', $this->_msgContent) && $_content['dataText'] && ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) // Add plain text message part after html part
  1346. {
  1347. $content.= "--" . $this->_getBoundary('alternative') . "--". "\r\n";
  1348. }
  1349. $content .= "\r\n";
  1350. }
  1351. }
  1352. // Close message boundries
  1353. // $content .= "\r\n--" . $this->_getBoundary() . '--' . "\r\n" ;
  1354. $content .= "--" . $this->_getBoundary('mixed') . '--' . "\r\n" ;
  1355. }
  1356. return $content;
  1357. }
  1358. /**
  1359. * File attachments are added to the content array as sub-arrays,
  1360. * allowing for multiple attachments for each outbound email
  1361. *
  1362. * @param string $strContent File data to attach to message
  1363. * @param string $strFileName File Name to give to attachment
  1364. * @param string $strMimeType File Mime Type of attachment
  1365. * @return void
  1366. */
  1367. function setAttachment($strContent, $strFileName = 'unknown', $strMimeType = 'unknown')
  1368. {
  1369. if ( $strContent )
  1370. {
  1371. $strContent = rtrim(chunk_split(base64_encode($strContent), 76, "\r\n")); // 76 max is defined into http://tools.ietf.org/html/rfc2047
  1372. $this->_msgContent['attachment'][$strFileName]['mimeType'] = $strMimeType;
  1373. $this->_msgContent['attachment'][$strFileName]['fileName'] = $strFileName;
  1374. $this->_msgContent['attachment'][$strFileName]['data'] = $strContent;
  1375. if ( $this->getMD5flag() )
  1376. $this->_msgContent['attachment'][$strFileName]['md5'] = dol_hash($strContent, 3);
  1377. }
  1378. }
  1379. // @CHANGE LDR
  1380. /**
  1381. * Image attachments are added to the content array as sub-arrays,
  1382. * allowing for multiple images for each outbound email
  1383. *
  1384. * @param string $strContent Image data to attach to message
  1385. * @param string $strImageName Image Name to give to attachment
  1386. * @param string $strMimeType Image Mime Type of attachment
  1387. * @param string $strImageCid CID
  1388. * @return void
  1389. */
  1390. function setImageInline($strContent, $strImageName = 'unknown', $strMimeType = 'unknown', $strImageCid = 'unknown')
  1391. {
  1392. if ($strContent)
  1393. {
  1394. $this->_msgContent['image'][$strImageName]['mimeType'] = $strMimeType;
  1395. $this->_msgContent['image'][$strImageName]['imageName'] = $strImageName;
  1396. $this->_msgContent['image'][$strImageName]['cid'] = $strImageCid;
  1397. $this->_msgContent['image'][$strImageName]['data'] = $strContent;
  1398. if ( $this->getMD5flag() )
  1399. $this->_msgContent['image'][$strImageName]['md5'] = dol_hash($strContent, 3);
  1400. }
  1401. }
  1402. // END @CHANGE LDR
  1403. /**
  1404. * Message Content Sensitivity
  1405. * Message Sensitivity values:
  1406. * - [0] None - default
  1407. * - [1] Personal
  1408. * - [2] Private
  1409. * - [3] Company Confidential
  1410. *
  1411. * @param integer $_value Message Sensitivity
  1412. * @return void
  1413. */
  1414. function setSensitivity($_value = 0)
  1415. {
  1416. if ( ( is_numeric($_value) ) &&
  1417. ( ( $_value >= 0 ) && ( $_value <= 3 ) ) )
  1418. $this->_msgSensitivity = $_value;
  1419. }
  1420. /**
  1421. * Returns Message Content Sensitivity string
  1422. * Message Sensitivity values:
  1423. * - [0] None - default
  1424. * - [1] Personal
  1425. * - [2] Private
  1426. * - [3] Company Confidential
  1427. *
  1428. * @return void
  1429. */
  1430. function getSensitivity()
  1431. {
  1432. return $this->_arySensitivity[$this->_msgSensitivity];
  1433. }
  1434. /**
  1435. * Message Content Priority
  1436. * Message Priority values:
  1437. * - [0] 'Bulk'
  1438. * - [1] 'Highest'
  1439. * - [2] 'High'
  1440. * - [3] 'Normal' - default
  1441. * - [4] 'Low'
  1442. * - [5] 'Lowest'
  1443. *
  1444. * @param integer $_value Message Priority
  1445. * @return void
  1446. */
  1447. function setPriority( $_value = 3 )
  1448. {
  1449. if ( ( is_numeric($_value) ) &&
  1450. ( ( $_value >= 0 ) && ( $_value <= 5 ) ) )
  1451. $this->_msgPriority = $_value;
  1452. }
  1453. /**
  1454. * Message Content Priority
  1455. * Message Priority values:
  1456. * - [0] 'Bulk'
  1457. * - [1] 'Highest'
  1458. * - [2] 'High'
  1459. * - [3] 'Normal' - default
  1460. * - [4] 'Low'
  1461. * - [5] 'Lowest'
  1462. *
  1463. * @return string
  1464. */
  1465. function getPriority()
  1466. {
  1467. return 'Importance: ' . $this->_aryPriority[$this->_msgPriority] . "\r\n"
  1468. . 'Priority: ' . $this->_aryPriority[$this->_msgPriority] . "\r\n"
  1469. . 'X-Priority: ' . $this->_msgPriority . ' (' . $this->_aryPriority[$this->_msgPriority] . ')' . "\r\n";
  1470. }
  1471. /**
  1472. * Set flag which determines whether to calculate message MD5 checksum.
  1473. *
  1474. * @param string $_flag Message Priority
  1475. * @return void
  1476. */
  1477. function setMD5flag($_flag = false)
  1478. {
  1479. $this->_smtpMD5 = $_flag;
  1480. }
  1481. /**
  1482. * Gets flag which determines whether to calculate message MD5 checksum.
  1483. *
  1484. * @return boolean Message Priority
  1485. */
  1486. function getMD5flag()
  1487. {
  1488. return $this->_smtpMD5;
  1489. }
  1490. /**
  1491. * Message X-Header Content
  1492. * This is a simple "insert". Whatever is given will be placed
  1493. * "as is" into the Xheader array.
  1494. *
  1495. * @param string $strXdata Message X-Header Content
  1496. * @return void
  1497. */
  1498. function setXheader($strXdata)
  1499. {
  1500. if ( $strXdata )
  1501. $this->_msgXheader[] = $strXdata;
  1502. }
  1503. /**
  1504. * Retrieves the Message X-Header Content
  1505. *
  1506. * @return string[] $_msgContent Message X-Header Content
  1507. */
  1508. function getXheader()
  1509. {
  1510. return $this->_msgXheader;
  1511. }
  1512. /**
  1513. * Generates Random string for MIME message Boundary
  1514. *
  1515. * @return void
  1516. */
  1517. function _setBoundary()
  1518. {
  1519. $this->_smtpsBoundary = "multipart_x." . time() . ".x_boundary";
  1520. $this->_smtpsRelatedBoundary = 'mul_'.dol_hash(uniqid("dolibarr2"), 3);
  1521. $this->_smtpsAlternativeBoundary = 'mul_'.dol_hash(uniqid("dolibarr3"), 3);
  1522. }
  1523. /**
  1524. * Retrieves the MIME message Boundary
  1525. *
  1526. * @param string $type Type of boundary
  1527. * @return string $_smtpsBoundary MIME message Boundary
  1528. */
  1529. function _getBoundary($type='mixed')
  1530. {
  1531. if ($type == 'mixed') return $this->_smtpsBoundary;
  1532. else if ($type == 'related') return $this->_smtpsRelatedBoundary;
  1533. else if ($type == 'alternative') return $this->_smtpsAlternativeBoundary;
  1534. }
  1535. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  1536. /**
  1537. * This function has been modified as provided by SirSir to allow multiline responses when
  1538. * using SMTP Extensions
  1539. *
  1540. * @param Handler $socket Socket handler
  1541. * @param string $response Response. Example: "550 5.7.1 https://support.google.com/a/answer/6140680#invalidcred j21sm814390wre.3"
  1542. * @return boolean True or false
  1543. */
  1544. function server_parse($socket, $response)
  1545. {
  1546. // phpcs:enable
  1547. /**
  1548. * Returns constructed SELECT Object string or boolean upon failure
  1549. * Default value is set at true
  1550. */
  1551. $_retVal = true;
  1552. $server_response = '';
  1553. // avoid infinite loop
  1554. $limit=0;
  1555. while (substr($server_response,3,1) != ' ' && $limit<100)
  1556. {
  1557. if (! ($server_response = fgets($socket, 256)))
  1558. {
  1559. $this->_setErr(121, "Couldn't get mail server response codes");
  1560. $_retVal = false;
  1561. break;
  1562. }
  1563. $limit++;
  1564. }
  1565. if (! (substr($server_response, 0, 3) == $response))
  1566. {
  1567. $this->_setErr(120, "Ran into problems sending Mail.\r\nResponse: $server_response");
  1568. $_retVal = false;
  1569. }
  1570. return $_retVal;
  1571. }
  1572. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  1573. /**
  1574. * Send str
  1575. *
  1576. * @param string $_strSend String to send
  1577. * @param string $_returnCode Return code
  1578. * @param string $CRLF CRLF
  1579. * @return boolean|null True or false
  1580. */
  1581. function socket_send_str( $_strSend, $_returnCode = null, $CRLF = "\r\n" )
  1582. {
  1583. // phpcs:enable
  1584. if ($this->_debug) $this->log.=$_strSend; // @CHANGE LDR for log
  1585. fputs($this->socket, $_strSend . $CRLF);
  1586. if ($this->_debug) $this->log.=' ('.$_returnCode.')' . $CRLF;
  1587. if ( $_returnCode )
  1588. return $this->server_parse($this->socket, $_returnCode);
  1589. }
  1590. // =============================================================
  1591. // ** Error handling methods
  1592. /**
  1593. * Defines errors codes and messages for Class
  1594. *
  1595. * @param int $_errNum Error Code Number
  1596. * @param string $_errMsg Error Message
  1597. * @return void
  1598. */
  1599. function _setErr( $_errNum, $_errMsg )
  1600. {
  1601. $this->_smtpsErrors[] = array(
  1602. 'num' => $_errNum,
  1603. 'msg' => $_errMsg,
  1604. );
  1605. }
  1606. /**
  1607. * Returns errors codes and messages for Class
  1608. *
  1609. * @return string $_errMsg Error Message
  1610. */
  1611. function getErrors()
  1612. {
  1613. $_errMsg = array();
  1614. if (is_array($this->_smtpsErrors))
  1615. {
  1616. foreach ( $this->_smtpsErrors as $_err => $_info )
  1617. {
  1618. $_errMsg[] = 'Error [' . $_info['num'] .']: '. $_info['msg'];
  1619. }
  1620. }
  1621. return implode("\n", $_errMsg);
  1622. }
  1623. }
  1624. // =============================================================
  1625. // ** CSV Version Control Info
  1626. /**
  1627. * Revision 2011/09/12 07:49:59 eldy
  1628. * Doxygen
  1629. *
  1630. * Revision 2011/09/06 06:53:53 hregis
  1631. * Fix: use dol_hash instead md5 php function
  1632. *
  1633. * Revision 2011/09/03 00:14:27 eldy
  1634. * Doxygen
  1635. *
  1636. * Revision 2011/08/28 14:24:23 eldy
  1637. * Doxygen
  1638. *
  1639. * Revision 2011/07/12 22:19:02 eldy
  1640. * Fix: Attachment fails if content was empty
  1641. *
  1642. * Revision 2011/06/20 23:17:50 hregis
  1643. * Fix: use best structure of mail
  1644. *
  1645. * Revision 2010/04/13 20:58:37 eldy
  1646. * Fix: Can provide ip address on smtps. Better error reporting.
  1647. *
  1648. * Revision 2010/04/13 20:30:25 eldy
  1649. * Fix: Can provide ip address on smtps. Better error reporting.
  1650. *
  1651. * Revision 2010/01/12 13:02:07 hregis
  1652. * Fix: missing attach-files
  1653. *
  1654. * Revision 2009/11/01 14:16:30 eldy
  1655. * Fix: Sending mail with SMTPS was not working.
  1656. *
  1657. * Revision 2009/10/20 13:14:47 hregis
  1658. * Fix: function "split" is deprecated since php 5.3.0
  1659. *
  1660. * Revision 2009/05/13 19:10:07 eldy
  1661. * New: Can use inline images.Everything seems to work with thunderbird and webmail gmail. New to be tested on other mail browsers.
  1662. *
  1663. * Revision 2009/05/13 14:49:30 eldy
  1664. * Fix: Make code so much simpler and solve a lot of problem with new version.
  1665. *
  1666. * Revision 2009/02/09 00:04:35 eldy
  1667. * Added support for SMTPS protocol
  1668. *
  1669. * Revision 2008/04/16 23:11:45 eldy
  1670. * New: Add action "Test server connectivity"
  1671. *
  1672. * Revision 1.18 2007/01/12 22:17:08 ongardie
  1673. * - Added full_http_site_root() to utils-misc.php
  1674. * - Made SMTPs' getError() easier to use
  1675. * - Improved activity modified emails
  1676. *
  1677. * Revision 1.17 2006/04/05 03:15:40 ongardie
  1678. * -Fixed method name typo that resulted in a fatal error.
  1679. *
  1680. * Revision 1.16 2006/03/08 04:05:25 jswalter
  1681. * - '$_smtpsTransEncode' was removed and '$_smtpsTransEncodeType' is now used
  1682. * - '$_smtpsTransEncodeType' is defaulted to ZERO
  1683. * - corrected 'setCharSet()' internal vars
  1684. * - defined '$_mailPath'
  1685. * - added '$_smtpMD5' as a class property
  1686. * - added 'setMD5flag()' to set above property
  1687. * - added 'getMD5flag()' to retrieve above property
  1688. * - 'setAttachment()' will add an MD5 checksum to attachements if above property is set
  1689. * - 'setBodyContent()' will add an MD5 checksum to message parts if above property is set
  1690. * - 'getBodyContent()' will insert the MD5 checksum for messages and attachments if above property is set
  1691. * - removed leading dashes from message boundry
  1692. * - added propery "Close message boundry" tomessage block
  1693. * - corrected some comments in various places
  1694. * - removed some incorrect comments in others
  1695. *
  1696. * Revision 1.15 2006/02/21 02:00:07 vanmer
  1697. * - patch to add support for sending to exim mail server
  1698. * - thanks to Diego Ongaro at ETSZONE (diego@etszone.com)
  1699. *
  1700. * Revision 1.14 2005/08/29 16:22:10 jswalter
  1701. * - change 'multipart/alternative' to 'multipart/mixed', but Windows based mail servers have issues with this.
  1702. * Bug 594
  1703. *
  1704. * Revision 1.13 2005/08/21 01:57:30 vanmer
  1705. * - added initialization for array if no recipients exist
  1706. *
  1707. * Revision 1.12 2005/08/20 12:04:30 braverock
  1708. * - remove potentially binary characters from Message-ID
  1709. * - add getHost to get the hostname of the mailserver
  1710. * - add username to Message-ID header
  1711. *
  1712. * Revision 1.11 2005/08/20 11:49:48 braverock
  1713. * - fix typos in boundary
  1714. * - remove potentially illegal characters from boundary
  1715. *
  1716. * Revision 1.10 2005/08/19 20:39:32 jswalter
  1717. * - added _server_connect()' as a seperate method to handle server connectivity.
  1718. * - added '_server_authenticate()' as a seperate method to handle server authentication.
  1719. * - 'sendMsg()' now uses the new methods to handle server communication.
  1720. * - modified 'server_parse()' and 'socket_send_str()' to give error codes and messages.
  1721. *
  1722. * Revision 1.9 2005/08/19 15:40:18 jswalter
  1723. * - IMPORTANT: 'setAttachement()' is now spelled correctly: 'setAttachment()'
  1724. * - added additional comment to several methods
  1725. * - added '$_smtpsTransEncodeTypes' array to limit encode types
  1726. * - added parameters to 'sendMsg()' for future development around debugging and logging
  1727. * - added error code within 'setConfig()' if the given path is not found
  1728. * - 'setTransportType()' now has parameter validation
  1729. * [this still is not implemented]
  1730. * - 'setPort()' now does parameter validation
  1731. * - 'setTransEncode()' now has parameter validation against '$_smtpsTransEncodeTypes'
  1732. * - modified 'get_email_list()' to handle error handling
  1733. * - 'setSensitivity()' now has parameter validation
  1734. * - 'setPriority()' now has parameter validation
  1735. *
  1736. * Revision 1.8 2005/06/24 21:00:20 jswalter
  1737. * - corrected comments
  1738. * - corrected the defualt value for 'setPriority()'
  1739. * - modified 'setAttachement()' to process multiple attachments correctly
  1740. * - modified 'getBodyContent()' to handle multiple attachments
  1741. * Bug 310
  1742. *
  1743. * Revision 1.7 2005/05/19 21:12:34 braverock
  1744. * - replace chunk_split() with wordwrap() to fix funky wrapping of templates
  1745. *
  1746. * Revision 1.6 2005/04/25 04:55:06 jswalter
  1747. * - cloned from Master Version
  1748. *
  1749. * Revision 1.10 2005/04/25 04:54:10 walter
  1750. * - "fixed" 'getBodyContent()' to handle a "simple" text only message
  1751. *
  1752. * Revision 1.9 2005/04/25 03:52:01 walter
  1753. * - replace closing curly bracket. Removed it in last revision!
  1754. *
  1755. * Revision 1.8 2005/04/25 02:29:49 walter
  1756. * - added '$_transportType' and its getter/setter methods.
  1757. * for future use. NOT yet implemented.
  1758. * - in 'sendMsg()', added HOST validation check
  1759. * - added error check for initial Socket Connection
  1760. * - created new method 'socket_send_str()' to process socket
  1761. * communication in a unified means. Socket calls within
  1762. * 'sendMsg()' have been modified to use this new method.
  1763. * - expanded comments in 'setConfig()'
  1764. * - added "error" check on PHP ini file properties. If these
  1765. * properties not set within the INI file, the default values
  1766. * will be used.
  1767. * - modified 'get_RCPT_list()' to reset itself each time it is called
  1768. * - modified 'setBodyContent()' to store data in a sub-array for better
  1769. * parsing within the 'getBodyContent()' method
  1770. * - modified 'getBodyContent()' to process contents array better.
  1771. * Also modified to handle attachements.
  1772. * - added 'setAttachement()' so files and other data can be attached
  1773. * to messages
  1774. * - added '_setErr()' and 'getErrors()' as an attempt to begin an error
  1775. * handling process within this class
  1776. *
  1777. * Revision 1.7 2005/04/13 15:23:50 walter
  1778. * - made 'CC' a conditional insert
  1779. * - made 'BCC' a conditional insert
  1780. * - fixed 'Message-ID'
  1781. * - corrected 'getSensitivity()'
  1782. * - modified '$_aryPriority[]' to proper values
  1783. * - updated 'setConfig()' to handle external Ini or 'php.ini'
  1784. *
  1785. * Revision 1.6 2005/03/15 17:34:06 walter
  1786. * - corrected Message Sensitivity property and method comments
  1787. * - added array to Message Sensitivity
  1788. * - added getSensitivity() method to use new Sensitivity array
  1789. * - created seters and getter for Priority with new Prioity value array property
  1790. * - changed config file include from 'include_once'
  1791. * - modified getHeader() to ustilize new Message Sensitivity and Priorty properties
  1792. *
  1793. * Revision 1.5 2005/03/14 22:25:27 walter
  1794. * - added references
  1795. * - added Message sensitivity as a property with Getter/Setter methods
  1796. * - boundary is now a property with Getter/Setter methods
  1797. * - added 'builtRCPTlist()'
  1798. * - 'sendMsg()' now uses Object properties and methods to build message
  1799. * - 'setConfig()' to load external file
  1800. * - 'setForm()' will "strip" the email address out of "address" string
  1801. * - modifed 'getFrom()' to handle "striping" the email address
  1802. * - '_buildArrayList()' creates a multi-dimensional array of addresses
  1803. * by domain, TO, CC & BCC and then by User Name.
  1804. * - '_strip_email()' pulls email address out of "full Address" string'
  1805. * - 'get_RCPT_list()' pulls out "bare" emaill address form address array
  1806. * - 'getHeader()' builds message Header from Object properties
  1807. * - 'getBodyContent()' builds full messsage body, even multi-part
  1808. *
  1809. * Revision 1.4 2005/03/02 20:53:35 walter
  1810. * - core Setters & Getters defined
  1811. * - added additional Class Properties
  1812. *
  1813. * Revision 1.3 2005/03/02 18:51:51 walter
  1814. * - added base 'Class Properties'
  1815. *
  1816. * Revision 1.2 2005/03/01 19:37:52 walter
  1817. * - CVS logging tags
  1818. * - more comments
  1819. * - more "shell"
  1820. * - some constants
  1821. *
  1822. * Revision 1.1 2005/03/01 19:22:49 walter
  1823. * - initial commit
  1824. * - basic shell with some commets
  1825. *
  1826. */