Passed
Branch develop (5cbde9)
by
unknown
26:38
created

SMTPs   F

Complexity

Total Complexity 187

Size/Duplication

Total Lines 1812
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 0

Importance

Changes 0
Metric Value
dl 0
loc 1812
rs 0.8
c 0
b 0
f 0
wmc 187
lcom 3
cbo 0

66 Methods

Rating   Name   Duplication   Size   Complexity  
A setErrorsTo() 0 4 2
A _strip_email() 0 34 3
A getMD5flag() 0 3 1
A setPW() 0 3 1
A getTo() 0 3 1
D getBodyContent() 0 163 24
A setMailPath() 0 4 1
A getHost() 0 3 1
A setDeliveryReceipt() 0 3 1
A setXheader() 0 4 2
A getFrom() 0 10 2
A setPriority() 0 5 4
A setAttachment() 0 12 3
A setTrackId() 0 3 1
A setFrom() 0 4 2
A getPW() 0 3 1
F getHeader() 0 75 11
A getDeliveryReceipt() 0 3 1
A setSubject() 0 4 2
A socket_send_str() 0 9 4
A setSensitivity() 0 5 4
A _setErr() 0 5 1
A setTransEncode() 0 4 2
A setBodyContent() 0 33 4
A setMoreInHeader() 0 3 1
A setID() 0 3 1
A _setBoundary() 0 5 1
A setCC() 0 4 2
A getBCC() 0 3 1
A getSensitivity() 0 3 1
A getTrackId() 0 3 1
B get_email_list() 0 42 7
A setMD5flag() 0 3 1
A getPort() 0 3 1
A getTransportType() 0 3 1
A getCharSet() 0 3 1
A getSubject() 0 3 1
A setCharSet() 0 4 2
B _server_authenticate() 0 101 10
A setImageInline() 0 11 3
B _server_connect() 0 55 7
A _getBoundary() 0 5 4
A setDebug() 0 3 1
A getPriority() 0 5 1
A getTransEncode() 0 3 1
A setTransportType() 0 4 4
A setBCC() 0 4 2
A setConfig() 0 37 6
A get_RCPT_list() 0 22 4
B _buildAddrList() 0 54 6
B sendMsg() 0 90 7
A buildRCPTlist() 0 4 1
A getErrorsTo() 0 10 2
A getReplyTo() 0 10 2
A getXheader() 0 3 1
A server_parse() 0 32 5
A getMoreInHeader() 0 3 1
A setPort() 0 5 4
A setReplyTo() 0 4 2
A setTO() 0 4 2
A getID() 0 3 1
A getTransEncodeType() 0 3 1
A getCC() 0 3 1
A setHost() 0 4 2
A getErrors() 0 13 3
A setTransEncodeType() 0 4 2

How to fix   Complexity   

Complex Class

Complex classes like SMTPs often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SMTPs, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 * Copyright (C)           Walter Torres        <[email protected]> [with a *lot* of help!]
4
 * Copyright (C) 2005-2015 Laurent Destailleur  <[email protected]>
5
 * Copyright (C) 2006-2011 Regis Houssin
6
 * Copyright (C) 2016      Jonathan TISSEAU     <[email protected]>
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
/**
23
 *	\file       htdocs/core/class/smtps.class.php
24
 *	\brief      Class to construct and send SMTP compliant email, even to a secure
25
 *              SMTP server, regardless of platform.
26
 * Goals:
27
 *  - mime compliant
28
 *  - multiple Reciptiants
29
 *    - TO
30
 *    - CC
31
 *    - BCC
32
 *  - multi-part message
33
 *    - plain text
34
 *    - HTML
35
 *    - inline attachments
36
 *    - attachments
37
 *  - GPG access
38
 * This Class is based off of 'SMTP PHP MAIL' by Dirk Paehl, http://www.paehl.de
39
 */
40
41
42
/**
43
 * 	Class to construct and send SMTP compliant email, even
44
 * 	to a secure SMTP server, regardless of platform.
45
 */
46
class SMTPs
47
{
48
    /**
49
     * Host Name or IP of SMTP Server to use
50
     */
51
    private $_smtpsHost = 'localhost';
52
53
    /**
54
     * SMTP Server Port definition. 25 is default value
55
     * This can be defined via a INI file or via a setter method
56
     */
57
    private $_smtpsPort = '25';
58
59
    /**
60
     * Secure SMTP Server access ID
61
     * This can be defined via a INI file or via a setter method
62
     */
63
    private $_smtpsID = null;
64
65
    /**
66
     * Secure SMTP Server access Password
67
     * This can be defined via a INI file or via a setter method
68
     */
69
    private $_smtpsPW = null;
70
71
    /**
72
     * Who sent the Message
73
     * This can be defined via a INI file or via a setter method
74
     */
75
    private $_msgFrom = null;
76
77
    /**
78
     * Where are replies and errors to be sent to
79
     * This can be defined via a INI file or via a setter method
80
     */
81
    private $_msgReplyTo = null;
82
83
    /**
84
     * Who will the Message be sent to; TO, CC, BCC
85
     * Multi-diminsional array containg addresses the message will
86
     * be sent TO, CC or BCC
87
     */
88
    private $_msgRecipients = null;
89
90
    /**
91
     * Message Subject
92
     */
93
    private $_msgSubject = null;
94
95
    /**
96
     * Message Content
97
     */
98
    private $_msgContent = null;
99
100
    /**
101
     * Custom X-Headers
102
     */
103
    private $_msgXheader = null;
104
105
    /**
106
     * Character set
107
     * Defaulted to 'iso-8859-1'
108
     */
109
    private $_smtpsCharSet = 'iso-8859-1';
110
111
    /**
112
     * Message Sensitivity
113
     * Defaults to ZERO - None
114
     */
115
    private $_msgSensitivity = 0;
116
117
    /**
118
     * Message Sensitivity
119
     */
120
    private $_arySensitivity = array ( false,
121
                                  'Personal',
122
                                  'Private',
123
                                  'Company Confidential' );
124
125
    /**
126
     * Message Sensitivity
127
     * Defaults to 3 - Normal
128
     */
129
    private $_msgPriority = 3;
130
131
    /**
132
     * Message Priority
133
     */
134
    private $_aryPriority = array ( 'Bulk',
135
                                'Highest',
136
                                'High',
137
                                'Normal',
138
                                'Low',
139
                                'Lowest' );
140
141
    /**
142
     * Content-Transfer-Encoding
143
     * Defaulted to 0 - 7bit
144
     */
145
    private $_smtpsTransEncodeType = 0;
146
147
    /**
148
     * Content-Transfer-Encoding
149
     */
150
    private $_smtpsTransEncodeTypes = array( '7bit',               // Simple 7-bit ASCII
151
                                         '8bit',               // 8-bit coding with line termination characters
152
                                         'base64',             // 3 octets encoded into 4 sextets with offset
153
                                         'binary',             // Arbitrary binary stream
154
                                         'mac-binhex40',       // Macintosh binary to hex encoding
155
                                         'quoted-printable',   // Mostly 7-bit, with 8-bit characters encoded as "=HH"
156
                                         'uuencode' );         // UUENCODE encoding
157
158
    /**
159
     * Content-Transfer-Encoding
160
     * Defaulted to '7bit'
161
     */
162
    private $_smtpsTransEncode = '7bit';
163
164
    /**
165
     * Boundary String for MIME seperation
166
     */
167
    private $_smtpsBoundary = null;
168
169
    /**
170
     * Related Boundary
171
     */
172
    private $_smtpsRelatedBoundary = null;
173
174
    /**
175
     * Alternative Boundary
176
     */
177
    private $_smtpsAlternativeBoundary = null;
178
179
    /**
180
     * Determines the method inwhich the message are to be sent.
181
     * - 'sockets' [0] - conect via network to SMTP server - default
182
     * - 'pipe     [1] - use UNIX path to EXE
183
     * - 'phpmail  [2] - use the PHP built-in mail function
184
     * NOTE: Only 'sockets' is implemented
185
     */
186
    private $_transportType = 0;
187
188
    /**
189
     * If '$_transportType' is set to '1', then this variable is used
190
     * to define the UNIX file system path to the sendmail execuable
191
     */
192
    private $_mailPath = '/usr/lib/sendmail';
193
194
    /**
195
     * Sets the SMTP server timeout in seconds.
196
     */
197
    private $_smtpTimeout = 10;
198
199
    /**
200
     * Determines whether to calculate message MD5 checksum.
201
     */
202
    private $_smtpMD5 = false;
203
204
    /**
205
     * Class error codes and messages
206
     */
207
    private $_smtpsErrors = null;
208
209
    /**
210
     * Defines log level
211
     *  0 - no logging
212
     *  1 - connectivity logging
213
     *  2 - message generation logging
214
     *  3 - detail logging
215
     */
216
    private $_log_level = 0;
217
218
    /**
219
     * Place Class in" debug" mode
220
     */
221
    private $_debug = false;
222
223
224
    // @CHANGE LDR
225
    public $log = '';
226
    private $_errorsTo = '';
227
    private $_deliveryReceipt = 0;
228
    private $_trackId = '';
229
    private $_moreInHeader = '';
230
231
232
    /**
233
     * Set delivery receipt
234
     *
235
     * @param	int		$_val		Value
236
     * @return	void
237
     */
238
    public function setDeliveryReceipt($_val = 0)
239
    {
240
        $this->_deliveryReceipt = $_val;
241
    }
242
243
    /**
244
     * get delivery receipt
245
     *
246
     * @return	int		Delivery receipt
247
     */
248
    public function getDeliveryReceipt()
249
    {
250
        return $this->_deliveryReceipt;
251
    }
252
253
    /**
254
     * Set trackid
255
     *
256
     * @param	string		$_val		Value
257
     * @return	void
258
     */
259
    public function setTrackId($_val = '')
260
    {
261
        $this->_trackId = $_val;
262
    }
263
264
    /**
265
     * Set moreInHeader
266
     *
267
     * @param	string		$_val		Value
268
     * @return	void
269
     */
270
    public function setMoreInHeader($_val = '')
271
    {
272
        $this->_moreinheader = $_val;
273
    }
274
275
    /**
276
     * get trackid
277
     *
278
     * @return	string		Track id
279
     */
280
    public function getTrackId()
281
    {
282
        return $this->_trackId;
283
    }
284
285
    /**
286
     * get moreInHeader
287
     *
288
     * @return	string		moreInHeader
289
     */
290
    public function getMoreInHeader()
291
    {
292
        return $this->_moreinheader;
293
    }
294
295
    /**
296
     * Set errors to
297
     *
298
     * @param	string		$_strErrorsTo		Errors to
299
     * @return	void
300
     */
301
    public function setErrorsTo($_strErrorsTo)
302
    {
303
        if ( $_strErrorsTo )
304
        $this->_errorsTo = $this->_strip_email($_strErrorsTo);
305
    }
306
307
    /**
308
     * Get errors to
309
     *
310
     * @param	boolean		$_part		Variant
311
     * @return	string					Errors to
312
     */
313
    public function getErrorsTo($_part = true)
314
    {
315
        $_retValue = '';
316
317
        if ( $_part === true )
318
        $_retValue = $this->_errorsTo;
319
        else
320
        $_retValue = $this->_errorsTo[$_part];
321
322
        return $_retValue;
323
    }
324
325
    /**
326
     * Set debug
327
     *
328
     * @param	boolean		$_vDebug		Value for debug
329
     * @return 	void
330
     */
331
    public function setDebug($_vDebug = false)
332
    {
333
        $this->_debug = $_vDebug;
334
    }
335
336
    /**
337
     * build RECIPIENT List, all addresses who will recieve this message
338
     *
339
     * @return void
340
     */
341
    public function buildRCPTlist()
342
    {
343
        // Pull TO list
344
        $_aryToList = $this->getTO();
345
    }
346
347
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
348
    /**
349
     * Attempt a connection to mail server
350
     *
351
     * @return mixed  $_retVal   Boolean indicating success or failure on connection
352
     */
353
    private function _server_connect()
354
    {
355
        // phpcs:enable
356
        // Default return value
357
        $_retVal = true;
358
359
        // We have to make sure the HOST given is valid
360
        // This is done here because '@fsockopen' will not give me this
361
        // information if it failes to connect because it can't find the HOST
362
        $host=$this->getHost();
363
        $usetls = preg_match('@tls://@i', $host);
364
365
        $host=preg_replace('@tcp://@i', '', $host);	// Remove prefix
366
        $host=preg_replace('@ssl://@i', '', $host);	// Remove prefix
367
        $host=preg_replace('@tls://@i', '', $host);	// Remove prefix
368
369
        // @CHANGE LDR
370
        include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
371
372
        if ( (! is_ip($host)) && ((gethostbyname($host)) == $host))
373
        {
374
            $this->_setErr(99, $host . ' is either offline or is an invalid host name.');
375
            $_retVal = false;
376
        }
377
        else
378
        {
379
            //See if we can connect to the SMTP server
380
            if ($this->socket = @fsockopen(
381
                preg_replace('@tls://@i', '', $this->getHost()),       // Host to 'hit', IP or domain
382
                $this->getPort(),       // which Port number to use
383
                $this->errno,           // actual system level error
0 ignored issues
show
Bug Best Practice introduced by
The property errno does not exist on SMTPs. Did you maybe forget to declare it?
Loading history...
384
                $this->errstr,          // and any text that goes with the error
385
                $this->_smtpTimeout     // timeout for reading/writing data over the socket
386
            )) {
387
                // Fix from PHP SMTP class by 'Chris Ryan'
388
                // Sometimes the SMTP server takes a little longer to respond
389
                // so we will give it a longer timeout for the first read
390
                // Windows still does not have support for this timeout function
391
                if (function_exists('stream_set_timeout')) stream_set_timeout($this->socket, $this->_smtpTimeout, 0);
392
393
                // Check response from Server
394
                if ( $_retVal = $this->server_parse($this->socket, "220") )
395
                $_retVal = $this->socket;
396
            }
397
            // This connection attempt failed.
398
            else
399
            {
400
                // @CHANGE LDR
401
                if (empty($this->errstr)) $this->errstr='Failed to connect with fsockopen host='.$this->getHost().' port='.$this->getPort();
402
                $this->_setErr($this->errno, $this->errstr);
403
                $_retVal = false;
404
            }
405
        }
406
407
        return $_retVal;
408
    }
409
410
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
411
    /**
412
     * Attempt mail server authentication for a secure connection
413
     *
414
     * @return boolean|null  $_retVal   Boolean indicating success or failure of authentication
415
     */
416
    private function _server_authenticate()
417
    {
418
        // phpcs:enable
419
        global $conf;
420
421
        // Send the RFC2554 specified EHLO.
422
        // This improvment as provided by 'SirSir' to
423
        // accomodate both SMTP AND ESMTP capable servers
424
        $host=$this->getHost();
425
        $usetls = preg_match('@tls://@i', $host);
426
427
        $host=preg_replace('@tcp://@i', '', $host);	// Remove prefix
428
        $host=preg_replace('@ssl://@i', '', $host);	// Remove prefix
429
        $host=preg_replace('@tls://@i', '', $host);	// Remove prefix
430
431
        if ($usetls) $host='tls://'.$host;
432
433
        $hosth = $host;
434
435
        if (! empty($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO))
436
        {
437
            // If the from to is 'aaa <[email protected]>', we will keep 'ccc.com'
438
            $hosth = $this->getFrom('addr');
439
            $hosth = preg_replace('/^.*</', '', $hosth);
440
            $hosth = preg_replace('/>.*$/', '', $hosth);
441
            $hosth = preg_replace('/.*@/', '', $hosth);
442
        }
443
444
        if ( $_retVal = $this->socket_send_str('EHLO ' . $hosth, '250') )
445
        {
446
            if ($usetls)
447
            {
448
                /*
449
                The following dialog illustrates how a client and server can start a TLS STARTTLS session
450
                S: <waits for connection on TCP port 25>
451
                C: <opens connection>
452
                S: 220 mail.imc.org SMTP service ready
453
                C: EHLO mail.ietf.org
454
                S: 250-mail.imc.org offers a warm hug of welcome
455
                S: 250 STARTTLS
456
                C: STARTTLS
457
                S: 220 Go ahead
458
                C: <starts TLS negotiation>
459
                C & S: <negotiate a TLS session>
460
                C & S: <check result of negotiation>
461
                // Second pass EHLO
462
                C: EHLO client-domain.com
463
                S: 250-server-domain.com
464
                S: 250 AUTH LOGIN
465
                C: <continues by sending an SMTP command
466
                */
467
                if (!$_retVal = $this->socket_send_str('STARTTLS', 220))
468
                {
469
                    $this->_setErr(131, 'STARTTLS connection is not supported.');
470
                    return $_retVal;
471
                }
472
473
                // Before 5.6.7:
474
                // STREAM_CRYPTO_METHOD_SSLv23_CLIENT = STREAM_CRYPTO_METHOD_SSLv2_CLIENT|STREAM_CRYPTO_METHOD_SSLv3_CLIENT
475
                // STREAM_CRYPTO_METHOD_TLS_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
476
                // PHP >= 5.6.7:
477
                // STREAM_CRYPTO_METHOD_SSLv23_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT|STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
478
                // STREAM_CRYPTO_METHOD_TLS_CLIENT = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
479
480
                $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
481
                if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
482
                    $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
483
                    $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
484
                }
485
486
                if (!stream_socket_enable_crypto($this->socket, true, $crypto_method))
487
                {
488
                    $this->_setErr(132, 'STARTTLS connection failed.');
489
                    return $_retVal;
490
                }
491
                // Most server servers expect a 2nd pass of EHLO after TLS is established to get another time
492
                // the answer with list of supported AUTH methods. They may differs between non STARTTLS and with STARTTLS.
493
                if (!$_retVal = $this->socket_send_str('EHLO '.$host, '250'))
494
                {
495
                    $this->_setErr(126, '"' . $host . '" does not support authenticated connections.');
496
                    return $_retVal;
497
                }
498
            }
499
            // Send Authentication to Server
500
            // Check for errors along the way
501
            $this->socket_send_str('AUTH LOGIN', '334');
502
503
            // User name will not return any error, server will take anything we give it.
504
            $this->socket_send_str(base64_encode($this->_smtpsID), '334');
505
506
            // The error here just means the ID/password combo doesn't work.
507
            // There is not a method to determine which is the problem, ID or password
508
            if ( ! $_retVal = $this->socket_send_str(base64_encode($this->_smtpsPW), '235') )
509
            $this->_setErr(130, 'Invalid Authentication Credentials.');
510
        }
511
        else
512
        {
513
            $this->_setErr(126, '"' . $host . '" does not support authenticated connections.');
514
        }
515
516
        return $_retVal;
517
    }
518
519
    /**
520
     * Now send the message
521
     *
522
     * @param  boolean $_bolTestMsg  whether to run this method in 'Test' mode.
523
     * @param  boolean $_bolDebug    whether to log all communication between this Class and the Mail Server.
524
     * @return boolean|null   void
525
     *                 $_strMsg      If this is run in 'Test' mode, the actual message structure will be returned
526
     */
527
    public function sendMsg($_bolTestMsg = false, $_bolDebug = false)
528
    {
529
        global $conf;
530
531
        /**
532
         * Default return value
533
         */
534
        $_retVal = false;
535
536
        // Connect to Server
537
        if ( $this->socket = $this->_server_connect() )
538
        {
539
            // If a User ID *and* a password is given, assume Authentication is desired
540
            if( !empty($this->_smtpsID) && !empty($this->_smtpsPW) )
541
            {
542
                // Send the RFC2554 specified EHLO.
543
                $_retVal = $this->_server_authenticate();
544
            }
545
546
            // This is a "normal" SMTP Server "handshack"
547
            else
548
            {
549
                // Send the RFC821 specified HELO.
550
                $host=$this->getHost();
551
                $usetls = preg_match('@tls://@i', $host);
552
553
                $host=preg_replace('@tcp://@i', '', $host);	// Remove prefix
554
                $host=preg_replace('@ssl://@i', '', $host);	// Remove prefix
555
                $host=preg_replace('@tls://@i', '', $host);	// Remove prefix
556
557
                $hosth = $host;
558
559
                if (! empty($conf->global->MAIL_SMTP_USE_FROM_FOR_HELO))
560
                {
561
                    // If the from to is 'aaa <[email protected]>', we will keep 'ccc.com'
562
                    $hosth = $this->getFrom('addr');
563
                    $hosth = preg_replace('/^.*</', '', $hosth);
564
                    $hosth = preg_replace('/>.*$/', '', $hosth);
565
                    $hosth = preg_replace('/.*@/', '', $hosth);
566
                }
567
568
                $_retVal = $this->socket_send_str('HELO ' . $hosth, '250');
569
            }
570
571
            // Well, did we get to the server?
572
            if ( $_retVal )
573
            {
574
                // From this point onward most server response codes should be 250
575
                // Specify who the mail is from....
576
                // This has to be the raw email address, strip the "name" off
577
                $this->socket_send_str('MAIL FROM: ' . $this->getFrom('addr'), '250');
578
579
                // 'RCPT TO:' must be given a single address, so this has to loop
580
                // through the list of addresses, regardless of TO, CC or BCC
581
                // and send it out "single file"
582
                foreach ($this->get_RCPT_list() as $_address)
583
                {
584
                    /* Note:
585
                     * BCC email addresses must be listed in the RCPT TO command list,
586
                     * but the BCC header should not be printed under the DATA command.
587
                     * http://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server
588
                     */
589
590
                    /*
591
                     * TODO
592
                     * After each 'RCPT TO:' is sent, we need to make sure it was kosher,
593
                     * if not, the whole message will fail
594
                     * If any email address fails, we will need to RESET the connection,
595
                     * mark the last address as "bad" and start the address loop over again.
596
                     * If any address fails, the entire message fails.
597
                     */
598
                    $this->socket_send_str('RCPT TO: <' . $_address . '>', '250');
599
                }
600
601
                // Tell the server we are ready to start sending data
602
                // with any custom headers...
603
                // This is the last response code we look for until the end of the message.
604
                $this->socket_send_str('DATA', '354');
605
606
                // Now we are ready for the message...
607
                // Ok, all the ingredients are mixed in let's cook this puppy...
608
                $this->socket_send_str($this->getHeader().$this->getBodyContent() . "\r\n" . '.', '250');
609
610
                // Now tell the server we are done and close the socket...
611
                fputs($this->socket, 'QUIT');
612
                fclose($this->socket);
613
            }
614
        }
615
616
        return $_retVal;
617
    }
618
619
    // =============================================================
620
    // ** Setter & Getter methods
621
622
    // ** Basic System configuration
623
624
    /**
625
     * setConfig() is used to populate select class properties from either
626
     * a user defined INI file or the systems 'php.ini' file
627
     *
628
     * If a user defined INI is to be used, the files complete path is passed
629
     * as the method single parameter. The INI can define any class and/or
630
     * user properties. Only properties defined within this file will be setter
631
     * and/or orverwritten
632
     *
633
     * If the systems 'php.ini' file is to be used, the method is called without
634
     * parameters. In this case, only HOST, PORT and FROM properties will be set
635
     * as they are the only properties that are defined within the 'php.ini'.
636
     *
637
     * If secure SMTP is to be used, the user ID and Password can be defined with
638
     * the user INI file, but the properties are not defined with the systems
639
     * 'php.ini'file, they must be defined via their setter methods
640
     *
641
     * This method can be called twice, if desired. Once without a parameter to
642
     * load the properties as defined within the systems 'php.ini' file, and a
643
     * second time, with a path to a user INI file for other properties to be
644
     * defined.
645
     *
646
     * @param mixed $_strConfigPath path to config file or VOID
647
     * @return boolean
648
     */
649
    public function setConfig($_strConfigPath = null)
650
    {
651
        /**
652
         * Returns constructed SELECT Object string or boolean upon failure
653
         * Default value is set at true
654
         */
655
        $_retVal = true;
656
657
        // if we have a path...
658
        if ( ! empty($_strConfigPath) )
659
        {
660
            // If the path is not valid, this will NOT generate an error,
661
            // it will simply return false.
662
            if ( ! @include $_strConfigPath)
663
            {
664
                $this->_setErr(110, '"' . $_strConfigPath . '" is not a valid path.');
665
                $_retVal = false;
666
            }
667
        }
668
669
        // Read the Systems php.ini file
670
        else
671
        {
672
            // Set these properties ONLY if they are set in the php.ini file.
673
            // Otherwise the default values will be used.
674
            if ( $_host = ini_get('SMTPs') )
675
            $this->setHost($_host);
676
677
            if ( $_port = ini_get('smtp_port') )
678
            $this->setPort($_port);
679
680
            if ( $_from = ini_get('sendmail_from') )
681
            $this->setFrom($_from);
682
        }
683
684
        // Send back what we have
685
        return $_retVal;
686
    }
687
688
    /**
689
     * Determines the method inwhich the messages are to be sent.
690
     * - 'sockets' [0] - conect via network to SMTP server
691
     * - 'pipe     [1] - use UNIX path to EXE
692
     * - 'phpmail  [2] - use the PHP built-in mail function
693
     *
694
     * @param int $_type  Interger value representing Mail Transport Type
695
     * @return void
696
     */
697
    public function setTransportType($_type = 0)
698
    {
699
        if ((is_numeric($_type)) && (($_type >= 0) && ($_type <= 3))) {
700
            $this->_transportType = $_type;
701
        }
702
    }
703
704
    /**
705
     * Return the method inwhich the message is to be sent.
706
     * - 'sockets' [0] - conect via network to SMTP server
707
     * - 'pipe     [1] - use UNIX path to EXE
708
     * - 'phpmail  [2] - use the PHP built-in mail function
709
     *
710
     * @return int $_strHost Host Name or IP of the Mail Server to use
711
     */
712
    public function getTransportType()
713
    {
714
        return $this->_transportType;
715
    }
716
717
    /**
718
     * Path to the sendmail execuable
719
     *
720
     * @param string $_path Path to the sendmail execuable
721
     * @return boolean
722
     *
723
     */
724
    public function setMailPath($_path)
725
    {
726
        // This feature is not yet implemented
727
        return true;
728
729
        //if ( $_path ) $this->_mailPath = $_path;
730
    }
731
732
    /**
733
     * Defines the Host Name or IP of the Mail Server to use.
734
     * This is defaulted to 'localhost'
735
     * This is  used only with 'socket' based mail transmission
736
     *
737
     * @param 	string 	$_strHost 		Host Name or IP of the Mail Server to use
738
     * @return 	void
739
     */
740
    public function setHost($_strHost)
741
    {
742
        if ( $_strHost )
743
        $this->_smtpsHost = $_strHost;
744
    }
745
746
    /**
747
     * Retrieves the Host Name or IP of the Mail Server to use
748
     * This is  used only with 'socket' based mail transmission
749
     *
750
     * @return 	string 	$_strHost 		Host Name or IP of the Mail Server to use
751
     */
752
    public function getHost()
753
    {
754
        return $this->_smtpsHost;
755
    }
756
757
    /**
758
     * Defines the Port Number of the Mail Server to use
759
     * This is defaulted to '25'
760
     * This is  used only with 'socket' based mail transmission
761
     *
762
     * @param 	int 	$_intPort 		Port Number of the Mail Server to use
763
     * @return 	void
764
     */
765
    public function setPort($_intPort)
766
    {
767
        if ( ( is_numeric($_intPort) ) &&
768
        ( ( $_intPort >= 1 ) && ( $_intPort <= 65536 ) ) )
769
        $this->_smtpsPort = $_intPort;
770
    }
771
772
    /**
773
     * Retrieves the Port Number of the Mail Server to use
774
     * This is  used only with 'socket' based mail transmission
775
     *
776
     * @return 	string 		Port Number of the Mail Server to use
777
     */
778
    public function getPort()
779
    {
780
        return $this->_smtpsPort;
781
    }
782
783
    /**
784
     * User Name for authentication on Mail Server
785
     *
786
     * @param 	string 	$_strID 	User Name for authentication on Mail Server
787
     * @return 	void
788
     */
789
    public function setID($_strID)
790
    {
791
        $this->_smtpsID = $_strID;
792
    }
793
794
    /**
795
     * Retrieves the User Name for authentication on Mail Server
796
     *
797
     * @return string 	User Name for authentication on Mail Server
798
     */
799
    public function getID()
800
    {
801
        return $this->_smtpsID;
802
    }
803
804
    /**
805
     * User Password for authentication on Mail Server
806
     *
807
     * @param 	string 	$_strPW 	User Password for authentication on Mail Server
808
     * @return 	void
809
     */
810
    public function setPW($_strPW)
811
    {
812
        $this->_smtpsPW = $_strPW;
813
    }
814
815
    /**
816
     * Retrieves the User Password for authentication on Mail Server
817
     *
818
     * @return 	string 		User Password for authentication on Mail Server
819
     */
820
    public function getPW()
821
    {
822
        return $this->_smtpsPW;
823
    }
824
825
    /**
826
     * Character set used for current message
827
     * Character set is defaulted to 'iso-8859-1';
828
     *
829
     * @param string $_strCharSet Character set used for current message
830
     * @return void
831
     */
832
    public function setCharSet($_strCharSet)
833
    {
834
        if ( $_strCharSet )
835
        $this->_smtpsCharSet = $_strCharSet;
836
    }
837
838
    /**
839
     * Retrieves the Character set used for current message
840
     *
841
     * @return string $_smtpsCharSet Character set used for current message
842
     */
843
    public function getCharSet()
844
    {
845
        return $this->_smtpsCharSet;
846
    }
847
848
    /**
849
     * Content-Transfer-Encoding, Defaulted to '7bit'
850
     * This can be changed for 2byte characers sets
851
     * Known Encode Types
852
     *  - 7bit               Simple 7-bit ASCII
853
     *  - 8bit               8-bit coding with line termination characters
854
     *  - base64             3 octets encoded into 4 sextets with offset
855
     *  - binary             Arbitrary binary stream
856
     *  - mac-binhex40       Macintosh binary to hex encoding
857
     *  - quoted-printable   Mostly 7-bit, with 8-bit characters encoded as "=HH"
858
     *  - uuencode           UUENCODE encoding
859
     *
860
     * @param string $_strTransEncode Content-Transfer-Encoding
861
     * @return void
862
     */
863
    public function setTransEncode($_strTransEncode)
864
    {
865
        if (array_search($_strTransEncode, $this->_smtpsTransEncodeTypes))
866
        $this->_smtpsTransEncode = $_strTransEncode;
867
    }
868
869
    /**
870
     * Retrieves the Content-Transfer-Encoding
871
     *
872
     * @return string $_smtpsTransEncode Content-Transfer-Encoding
873
     */
874
    public function getTransEncode()
875
    {
876
        return $this->_smtpsTransEncode;
877
    }
878
879
    /**
880
     * Content-Transfer-Encoding, Defaulted to '0' [ZERO]
881
     * This can be changed for 2byte characers sets
882
     * Known Encode Types
883
     *  - [0] 7bit               Simple 7-bit ASCII
884
     *  - [1] 8bit               8-bit coding with line termination characters
885
     *  - [2] base64             3 octets encoded into 4 sextets with offset
886
     *  - [3] binary             Arbitrary binary stream
887
     *  - [4] mac-binhex40       Macintosh binary to hex encoding
888
     *  - [5] quoted-printable   Mostly 7-bit, with 8-bit characters encoded as "=HH"
889
     *  - [6] uuencode           UUENCODE encoding
890
     *
891
     * @param string $_strTransEncodeType Content-Transfer-Encoding
892
     * @return void
893
     *
894
     */
895
    public function setTransEncodeType($_strTransEncodeType)
896
    {
897
        if (array_search($_strTransEncodeType, $this->_smtpsTransEncodeTypes))
898
        $this->_smtpsTransEncodeType = $_strTransEncodeType;
899
    }
900
901
    /**
902
     * Retrieves the Content-Transfer-Encoding
903
     *
904
     * @return 	string 		Content-Transfer-Encoding
905
     */
906
    public function getTransEncodeType()
907
    {
908
        return $this->_smtpsTransEncodeTypes[$this->_smtpsTransEncodeType];
909
    }
910
911
912
    // ** Message Construction
913
914
    /**
915
     * FROM Address from which mail will be sent
916
     *
917
     * @param 	string 	$_strFrom 	Address from which mail will be sent
918
     * @return 	void
919
     */
920
    public function setFrom($_strFrom)
921
    {
922
        if ( $_strFrom )
923
        $this->_msgFrom = $this->_strip_email($_strFrom);
924
    }
925
926
    /**
927
     * Retrieves the Address from which mail will be sent
928
     *
929
     * @param  	boolean $_part		To "strip" 'Real name' from address
930
     * @return 	string 				Address from which mail will be sent
931
     */
932
    public function getFrom($_part = true)
933
    {
934
        $_retValue = '';
935
936
        if ( $_part === true )
937
        $_retValue = $this->_msgFrom;
938
        else
939
        $_retValue = $this->_msgFrom[$_part];
940
941
        return $_retValue;
942
    }
943
944
    /**
945
     * Reply-To Address from which mail will be the reply-to
946
     *
947
     * @param 	string 	$_strReplyTo 	Address from which mail will be the reply-to
948
     * @return 	void
949
     */
950
    public function setReplyTo($_strReplyTo)
951
    {
952
        if ( $_strReplyTo )
953
            $this->_msgReplyTo = $this->_strip_email($_strReplyTo);
954
    }
955
956
    /**
957
     * Retrieves the Address from which mail will be the reply-to
958
     *
959
     * @param  	boolean $_part		To "strip" 'Real name' from address
960
     * @return 	string 				Address from which mail will be the reply-to
961
     */
962
    public function getReplyTo($_part = true)
963
    {
964
        $_retValue = '';
965
966
        if ( $_part === true )
967
            $_retValue = $this->_msgReplyTo;
968
        else
969
            $_retValue = $this->_msgReplyTo[$_part];
970
971
        return $_retValue;
972
    }
973
974
    /**
975
     * Inserts given addresses into structured format.
976
     * This method takes a list of given addresses, via an array
977
     * or a COMMA delimted string, and inserts them into a highly
978
     * structured array. This array is designed to remove duplicate
979
     * addresses and to sort them by Domain.
980
     *
981
     * @param 	string 	$_type 			TO, CC, or BCC lists to add addrresses into
982
     * @param 	mixed 	$_addrList 		Array or COMMA delimited string of addresses
983
     * @return void
984
     *
985
     */
986
    private function _buildAddrList($_type, $_addrList)
987
    {
988
        // Pull existing list
989
        $aryHost = $this->_msgRecipients;
990
991
        // Only run this if we have something
992
        if ( !empty($_addrList))
993
        {
994
            // $_addrList can be a STRING or an array
995
            if ( is_string($_addrList) )
996
            {
997
                // This could be a COMMA delimited string
998
                if ( strstr($_addrList, ',') )
999
                // "explode "list" into an array
1000
                $_addrList = explode(',', $_addrList);
1001
1002
                // Stick it in an array
1003
                else
1004
                $_addrList = array($_addrList);
1005
            }
1006
1007
            // take the array of addresses and split them further
1008
            foreach ($_addrList as $_strAddr)
1009
            {
1010
                // Strip off the end '>'
1011
                $_strAddr = str_replace('>', '', $_strAddr);
1012
1013
                // Seperate "Real Name" from eMail address
1014
                $_tmpaddr = null;
1015
                $_tmpaddr = explode('<', $_strAddr);
1016
1017
                // We have a "Real Name" and eMail address
1018
                if ( count($_tmpaddr) == 2 )
1019
                {
1020
                    $_tmpHost = explode('@', $_tmpaddr[1]);
1021
                    $_tmpaddr[0] = trim($_tmpaddr[0], ' ">');
1022
                    $aryHost[$_tmpHost[1]][$_type][$_tmpHost[0]] = $_tmpaddr[0];
1023
                }
1024
                // We only have an eMail address
1025
                else
1026
                {
1027
                    // Strip off the beggining '<'
1028
                    $_strAddr = str_replace('<', '', $_strAddr);
1029
1030
                    $_tmpHost = explode('@', $_strAddr);
1031
                    $_tmpHost[0] = trim($_tmpHost[0]);
1032
                    $_tmpHost[1] = trim($_tmpHost[1]);
1033
1034
                    $aryHost[$_tmpHost[1]][$_type][$_tmpHost[0]] = '';
1035
                }
1036
            }
1037
        }
1038
        // replace list
1039
        $this->_msgRecipients = $aryHost;
1040
    }
1041
1042
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1043
    /**
1044
     * Returns an array of the various parts of an email address
1045
     * This assumes a well formed address:
1046
     * - "Real name" <[email protected]>
1047
     * - "Real Name" is optional
1048
     * - if "Real Name" does not exist, the angle brackets are optional
1049
     * This will split an email address into 4 or 5 parts.
1050
     * - $_aryEmail[org]  = orignal string
1051
     * - $_aryEmail[real] = "real name" - if there is one
1052
     * - $_aryEmail[addr] = address part "[email protected]"
1053
     * - $_aryEmail[host] = "domain.tld"
1054
     * - $_aryEmail[user] = "userName"
1055
     *
1056
     *	@param		string		$_strAddr		Email address
1057
     * 	@return 	array	 					An array of the various parts of an email address
1058
     */
1059
    private function _strip_email($_strAddr)
1060
    {
1061
        // phpcs:enable
1062
        // Keep the orginal
1063
        $_aryEmail['org'] = $_strAddr;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$_aryEmail was never initialized. Although not strictly required by PHP, it is generally a good practice to add $_aryEmail = array(); before regardless.
Loading history...
1064
1065
        // Set entire string to Lower Case
1066
        $_strAddr = strtolower($_strAddr);
1067
1068
        // Drop "stuff' off the end
1069
        $_strAddr = trim($_strAddr, ' ">');
1070
1071
        // Seperate "Real Name" from eMail address, if we have one
1072
        $_tmpAry = explode('<', $_strAddr);
1073
1074
        // Do we have a "Real name"
1075
        if ( count($_tmpAry) == 2 )
1076
        {
1077
            // We may not really have a "Real Name"
1078
            if ( $_tmpAry[0])
1079
            $_aryEmail['real'] = trim($_tmpAry[0], ' ">');
1080
1081
            $_aryEmail['addr'] = $_tmpAry[1];
1082
        }
1083
        else
1084
        $_aryEmail['addr'] = $_tmpAry[0];
1085
1086
        // Pull User Name and Host.tld apart
1087
        list($_aryEmail['user'], $_aryEmail['host'] ) = explode('@', $_aryEmail['addr']);
1088
1089
        // Put the brackets back around the address
1090
        $_aryEmail['addr'] = '<' . $_aryEmail['addr'] . '>';
1091
1092
        return $_aryEmail;
1093
    }
1094
1095
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1096
    /**
1097
     * Returns an array of bares addresses for use with 'RCPT TO:'
1098
     * This is a "build as you go" method. Each time this method is called
1099
     * the underlaying array is destroyed and reconstructed.
1100
     *
1101
     * @return 		array		Returns an array of bares addresses
1102
     */
1103
    public function get_RCPT_list()
1104
    {
1105
        // phpcs:enable
1106
        /**
1107
         * An array of bares addresses for use with 'RCPT TO:'
1108
         */
1109
        $_RCPT_list=array();
1110
1111
        // walk down Recipients array and pull just email addresses
1112
        foreach ($this->_msgRecipients as $_host => $_list)
1113
        {
1114
            foreach ($_list as $_subList)
1115
            {
1116
                foreach ($_subList as $_name => $_addr)
1117
                {
1118
                    // build RCPT list
1119
                    $_RCPT_list[] = $_name . '@' . $_host;
1120
                }
1121
            }
1122
        }
1123
1124
        return $_RCPT_list;
1125
    }
1126
1127
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1128
    /**
1129
     * Returns an array of addresses for a specific type; TO, CC or BCC
1130
     *
1131
     * @param 		string 	       $_which 	    Which collection of addresses to return ('to', 'cc', 'bcc')
1132
     * @return 		string|false 				Array of emaill address
1133
     */
1134
    public function get_email_list($_which = null)
1135
    {
1136
        // phpcs:enable
1137
        // We need to know which address segment to pull
1138
        if ( $_which )
1139
        {
1140
            // Make sure we have addresses to process
1141
            if ( $this->_msgRecipients )
1142
            {
1143
                $_RCPT_list=array();
1144
                // walk down Recipients array and pull just email addresses
1145
                foreach ($this->_msgRecipients as $_host => $_list)
1146
                {
1147
                    if ( $this->_msgRecipients[$_host][$_which] )
1148
                    {
1149
                        foreach ($this->_msgRecipients[$_host][$_which] as $_addr => $_realName)
1150
                        {
1151
                            if ( $_realName )	// @CHANGE LDR
1152
                            {
1153
                                $_realName = '"' . $_realName . '"';
1154
                                $_RCPT_list[] = $_realName . ' <' . $_addr . '@' . $_host . '>';
1155
                            }
1156
                            else
1157
                            {
1158
                                $_RCPT_list[] = $_addr . '@' . $_host;
1159
                            }
1160
                        }
1161
                    }
1162
                }
1163
1164
                return implode(', ', $_RCPT_list);
1165
            }
1166
            else
1167
            {
1168
                $this->_setErr(101, 'No eMail Address for message to be sent to.');
1169
                return false;
1170
            }
1171
        }
1172
        else
1173
        {
1174
            $this->_setErr(102, 'eMail type not defined.');
1175
            return false;
1176
        }
1177
    }
1178
1179
    /**
1180
     * TO Address[es] inwhich to send mail to
1181
     *
1182
     * @param 	string 	$_addrTo 	TO Address[es] inwhich to send mail to
1183
     * @return 	void
1184
     */
1185
    public function setTO($_addrTo)
1186
    {
1187
        if ( $_addrTo )
1188
        $this->_buildAddrList('to', $_addrTo);
1189
    }
1190
1191
    /**
1192
     * Retrieves the TO Address[es] inwhich to send mail to
1193
     *
1194
     * @return 	string 	TO Address[es] inwhich to send mail to
1195
     */
1196
    public function getTo()
1197
    {
1198
        return $this->get_email_list('to');
1199
    }
1200
1201
    /**
1202
     * CC Address[es] inwhich to send mail to
1203
     *
1204
     * @param 	string	$_strCC		CC Address[es] inwhich to send mail to
1205
     * @return 	void
1206
     */
1207
    public function setCC($_strCC)
1208
    {
1209
        if ( $_strCC )
1210
        $this->_buildAddrList('cc', $_strCC);
1211
    }
1212
1213
    /**
1214
     * Retrieves the CC Address[es] inwhich to send mail to
1215
     *
1216
     * @return 	string 		CC Address[es] inwhich to send mail to
1217
     */
1218
    public function getCC()
1219
    {
1220
        return $this->get_email_list('cc');
1221
    }
1222
1223
    /**
1224
     * BCC Address[es] inwhich to send mail to
1225
     *
1226
     * @param 	string		$_strBCC	Recipients BCC Address[es] inwhich to send mail to
1227
     * @return 	void
1228
     */
1229
    public function setBCC($_strBCC)
1230
    {
1231
        if ( $_strBCC )
1232
        $this->_buildAddrList('bcc', $_strBCC);
1233
    }
1234
1235
    /**
1236
     * Retrieves the BCC Address[es] inwhich to send mail to
1237
     *
1238
     * @return 	string		BCC Address[es] inwhich to send mail to
1239
     */
1240
    public function getBCC()
1241
    {
1242
        return $this->get_email_list('bcc');
1243
    }
1244
1245
    /**
1246
     * Message Subject
1247
     *
1248
     * @param 	string 	$_strSubject	Message Subject
1249
     * @return 	void
1250
     */
1251
    public function setSubject($_strSubject = '')
1252
    {
1253
        if ( $_strSubject )
1254
        $this->_msgSubject = $_strSubject;
1255
    }
1256
1257
    /**
1258
     * Retrieves the Message Subject
1259
     *
1260
     * @return 	string 		Message Subject
1261
     */
1262
    public function getSubject()
1263
    {
1264
        return $this->_msgSubject;
1265
    }
1266
1267
    /**
1268
     * Constructes and returns message header
1269
     *
1270
     * @return string Complete message header
1271
     */
1272
    public function getHeader()
1273
    {
1274
        global $conf;
1275
1276
        $_header = 'From: '       . $this->getFrom('org') . "\r\n"
1277
        . 'To: '         . $this->getTO()          . "\r\n";
1278
1279
        if ( $this->getCC() )
1280
        $_header .= 'Cc: ' . $this->getCC()  . "\r\n";
1281
1282
        /* Note:
1283
         * BCC email addresses must be listed in the RCPT TO command list,
1284
         * but the BCC header should not be printed under the DATA command.
1285
         * So it is included into the function sendMsg() but not here.
1286
         * http://stackoverflow.com/questions/2750211/sending-bcc-emails-using-a-smtp-server
1287
         */
1288
        /*
1289
        if ( $this->getBCC() )
1290
        $_header .= 'Bcc: ' . $this->getBCC()  . "\r\n";
1291
        */
1292
1293
        $host=$this->getHost();
1294
        $usetls = preg_match('@tls://@i', $host);
1295
1296
        $host=preg_replace('@tcp://@i', '', $host);	// Remove prefix
1297
        $host=preg_replace('@ssl://@i', '', $host);	// Remove prefix
1298
        $host=preg_replace('@tls://@i', '', $host);	// Remove prefix
1299
1300
        $host=dol_getprefix('email');
1301
1302
        //NOTE: Message-ID should probably contain the username of the user who sent the msg
1303
        $_header .= 'Subject: '    . $this->getSubject()     . "\r\n";
1304
        $_header .= 'Date: '       . date("r")               . "\r\n";
1305
1306
        $trackid = $this->getTrackId();
1307
        if ($trackid)
1308
        {
1309
            // References is kept in response and Message-ID is returned into In-Reply-To:
1310
            $_header .= 'Message-ID: <' . time() . '.SMTPs-dolibarr-'.$trackid.'@' . $host . ">\r\n";
1311
            $_header .= 'References: <' . time() . '.SMTPs-dolibarr-'.$trackid.'@' . $host . ">\r\n";
1312
            $_header .= 'X-Dolibarr-TRACKID: ' . $trackid . '@' . $host . "\r\n";
1313
        }
1314
        else
1315
        {
1316
            $_header .= 'Message-ID: <' . time() . '.SMTPs@' . $host . ">\r\n";
1317
        }
1318
        if (! empty($_SERVER['REMOTE_ADDR'])) $_header .= "X-RemoteAddr: " . $_SERVER['REMOTE_ADDR']. "\r\n";
1319
        if ( $this->getMoreInHeader() )
1320
            $_header .= $this->getMoreInHeader();     // Value must include the "\r\n";
1321
1322
        //$_header .=
1323
        //                 'Read-Receipt-To: '   . $this->getFrom( 'org' ) . "\r\n"
1324
        //                 'Return-Receipt-To: ' . $this->getFrom( 'org' ) . "\r\n";
1325
1326
        if ( $this->getSensitivity() )
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getSensitivity() targeting SMTPs::getSensitivity() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
1327
        $_header .= 'Sensitivity: ' . $this->getSensitivity()  . "\r\n";
1 ignored issue
show
Bug introduced by
Are you sure the usage of $this->getSensitivity() targeting SMTPs::getSensitivity() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
Are you sure $this->getSensitivity() of type void can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1327
        $_header .= 'Sensitivity: ' . /** @scrutinizer ignore-type */ $this->getSensitivity()  . "\r\n";
Loading history...
1328
1329
        if ( $this->_msgPriority != 3 )
1330
        $_header .= $this->getPriority();
1331
1332
1333
        // @CHANGE LDR
1334
        if ( $this->getDeliveryReceipt() )
1335
            $_header .= 'Disposition-Notification-To: '.$this->getFrom('addr') . "\r\n";
1336
        if ( $this->getErrorsTo() )
1337
            $_header .= 'Errors-To: '.$this->getErrorsTo('addr') . "\r\n";
1338
        if ( $this->getReplyTo() )
1339
            $_header .= "Reply-To: ".$this->getReplyTo('addr') ."\r\n";
1340
1341
        $_header .= 'X-Mailer: Dolibarr version ' . DOL_VERSION .' (using SMTPs Mailer)' . "\r\n";
1342
        $_header .= 'X-Dolibarr-Option: '.($conf->global->MAIN_MAIL_USE_MULTI_PART?'MAIN_MAIL_USE_MULTI_PART':'No MAIN_MAIL_USE_MULTI_PART') . "\r\n";
1343
        $_header .= 'Mime-Version: 1.0' . "\r\n";
1344
1345
1346
        return $_header;
1347
    }
1348
1349
    /**
1350
     * Message Content
1351
     *
1352
     * @param 	string 	$strContent		Message Content
1353
     * @param	string	$strType		Type
1354
     * @return 	void
1355
     */
1356
    public function setBodyContent($strContent, $strType = 'plain')
1357
    {
1358
        //if ( $strContent )
1359
        //{
1360
        if ( $strType == 'html' )
1361
        $strMimeType = 'text/html';
1362
        else
1363
        $strMimeType = 'text/plain';
1364
1365
        // Make RFC821 Compliant, replace bare linefeeds
1366
        $strContent = preg_replace("/(?<!\r)\n/si", "\r\n", $strContent);
1367
1368
        $strContentAltText = '';
1369
        if ($strType == 'html')
1370
        {
1371
            // Similar code to forge a text from html is also in CMailFile.class.php
1372
            $strContentAltText = preg_replace("/<br\s*[^>]*>/", " ", $strContent);
1373
            $strContentAltText = html_entity_decode(strip_tags($strContentAltText));
1374
            $strContentAltText = rtrim(wordwrap($strContentAltText, 75, "\r\n"));
1375
        }
1376
1377
        // Make RFC2045 Compliant
1378
        //$strContent = rtrim(chunk_split($strContent));    // Function chunck_split seems ko if not used on a base64 content
1379
        $strContent = rtrim(wordwrap($strContent, 75, "\r\n"));   // TODO Using this method creates unexpected line break on text/plain content.
1380
1381
        $this->_msgContent[$strType] = array();
1382
1383
        $this->_msgContent[$strType]['mimeType'] = $strMimeType;
1384
        $this->_msgContent[$strType]['data']     = $strContent;
1385
        $this->_msgContent[$strType]['dataText'] = $strContentAltText;
1386
1387
        if ( $this->getMD5flag() )
1388
        $this->_msgContent[$strType]['md5']      = dol_hash($strContent, 3);
1389
        //}
1390
    }
1391
1392
    /**
1393
     * Retrieves the Message Content
1394
     *
1395
     * @return 	string			Message Content
1396
     */
1397
    public function getBodyContent()
1398
    {
1399
        global $conf;
1400
1401
        // Generate a new Boundary string
1402
        $this->_setBoundary();
1403
1404
        // What type[s] of content do we have
1405
        $_types = array_keys($this->_msgContent);
1406
1407
        // How many content types do we have
1408
        $keyCount = count($_types);
1409
1410
        // If we have ZERO, we have a problem
1411
        if( $keyCount === 0 )
1412
        die("Sorry, no content");
1 ignored issue
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1413
1414
        // If we have ONE, we can use the simple format
1415
        elseif( $keyCount === 1 && empty($conf->global->MAIN_MAIL_USE_MULTI_PART))
1416
        {
1417
            $_msgData = $this->_msgContent;
1418
            $_msgData = $_msgData[$_types[0]];
1419
1420
            $content = 'Content-Type: ' . $_msgData['mimeType'] . '; charset="' . $this->getCharSet() . '"' . "\r\n"
1421
            . 'Content-Transfer-Encoding: ' . $this->getTransEncodeType() . "\r\n"
1422
            . 'Content-Disposition: inline'  . "\r\n"
1423
            . 'Content-Description: Message' . "\r\n";
1424
1425
            if ( $this->getMD5flag() )
1426
            $content .= 'Content-MD5: ' . $_msgData['md5'] . "\r\n";
1427
1428
            $content .= "\r\n"
1429
            .  $_msgData['data'] . "\r\n";
1430
        }
1431
1432
        // If we have more than ONE, we use the multi-part format
1433
        elseif( $keyCount >= 1 || ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART))
1434
        {
1435
            // Since this is an actual multi-part message
1436
            // We need to define a content message Boundary
1437
            // NOTE: This was 'multipart/alternative', but Windows based mail servers have issues with this.
1438
1439
            //$content = 'Content-Type: multipart/related; boundary="' . $this->_getBoundary() . '"'   . "\r\n";
1440
            $content = 'Content-Type: multipart/mixed; boundary="' . $this->_getBoundary('mixed') . '"'   . "\r\n";
1441
1442
            //                     . "\r\n"
1443
            //                     . 'This is a multi-part message in MIME format.' . "\r\n";
1444
            $content .= "Content-Transfer-Encoding: 8bit\r\n";
1445
            $content .= "\r\n";
1446
1447
            $content .= "--" . $this->_getBoundary('mixed') . "\r\n";
1448
1449
            if (key_exists('image', $this->_msgContent))     // If inline image found
1450
            {
1451
                $content.= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"' . "\r\n";
1452
                $content .= "\r\n";
1453
                $content .= "--" . $this->_getBoundary('alternative') . "\r\n";
1454
            }
1455
1456
1457
            // $this->_msgContent must be sorted with key 'text' or 'html' first then 'image' then 'attachment'
1458
1459
1460
            // Loop through message content array
1461
            foreach ($this->_msgContent as $type => $_content)
1462
            {
1463
                if ( $type == 'attachment' )
1464
                {
1465
                    // loop through all attachments
1466
                    foreach ($_content as $_file => $_data)
1467
                    {
1468
                        $content .= "--" . $this->_getBoundary('mixed') . "\r\n"
1469
                        .  'Content-Disposition: attachment; filename="' . $_data['fileName'] . '"' . "\r\n"
1470
                        .  'Content-Type: ' . $_data['mimeType'] . '; name="' . $_data['fileName'] . '"' . "\r\n"
1471
                        .  'Content-Transfer-Encoding: base64' . "\r\n"
1472
                        .  'Content-Description: ' . $_data['fileName'] ."\r\n";
1473
1474
                        if ( $this->getMD5flag() )
1475
                        $content .= 'Content-MD5: ' . $_data['md5'] . "\r\n";
1476
1477
                        $content .= "\r\n" .  $_data['data'] . "\r\n\r\n";
1478
                    }
1479
                }
1480
                // @CHANGE LDR
1481
                elseif ( $type == 'image' )
1482
                {
1483
                    // loop through all images
1484
                    foreach ($_content as $_image => $_data)
1485
                    {
1486
                        $content .= "--" . $this->_getBoundary('related') . "\r\n";  // always related for an inline image
1487
1488
                        $content .= 'Content-Type: ' . $_data['mimeType'] . '; name="' . $_data['imageName'] . '"' . "\r\n"
1489
                        .  'Content-Transfer-Encoding: base64' . "\r\n"
1490
                        .  'Content-Disposition: inline; filename="' . $_data['imageName'] . '"' . "\r\n"
1491
                        .  'Content-ID: <' . $_data['cid'] . '> ' . "\r\n";
1492
1493
                        if ( $this->getMD5flag() )
1494
                        $content .= 'Content-MD5: ' . $_data['md5'] . "\r\n";
1495
1496
                        $content .= "\r\n"
1497
                        . $_data['data'] . "\r\n";
1498
                    }
1499
1500
                    // always end related and end alternative after inline images
1501
                    $content.= "--" . $this->_getBoundary('related') . "--" . "\r\n";
1502
                    $content.= "\r\n" . "--" . $this->_getBoundary('alternative') . "--" . "\r\n";
1503
                    $content.= "\r\n";
1504
                }
1505
                else
1506
                {
1507
                    if (key_exists('image', $this->_msgContent))
1508
                    {
1509
                        $content.= "Content-Type: text/plain; charset=" . $this->getCharSet() . "\r\n";
1510
                        $content.= "\r\n" . ($_content['dataText']?$_content['dataText']:strip_tags($_content['data'])) . "\r\n"; // Add plain text message
1511
                        $content.= "--" . $this->_getBoundary('alternative') . "\r\n";
1512
                        $content.= 'Content-Type: multipart/related; boundary="' . $this->_getBoundary('related') . '"' . "\r\n";
1513
                        $content.= "\r\n";
1514
                        $content.= "--" . $this->_getBoundary('related') . "\r\n";
1515
                    }
1516
1517
                    if (! key_exists('image', $this->_msgContent) && $_content['dataText'] && ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART))  // Add plain text message part before html part
1518
                    {
1519
                        $content.= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"' . "\r\n";
1520
                        $content .= "\r\n";
1521
                           $content .= "--" . $this->_getBoundary('alternative') . "\r\n";
1522
1523
                           $content.= "Content-Type: text/plain; charset=" . $this->getCharSet() . "\r\n";
1524
                           $content.= "\r\n". $_content['dataText'] . "\r\n";
1525
                           $content.= "--" . $this->_getBoundary('alternative') . "\r\n";
1526
                    }
1527
1528
                    $content .= 'Content-Type: ' . $_content['mimeType'] . '; '
1529
                    //                             . 'charset="' . $this->getCharSet() . '"';
1530
                    . 'charset=' . $this->getCharSet() . '';
1531
1532
                    //                    $content .= ( $type == 'html') ? '; name="HTML Part"' : '';
1533
                    $content .=  "\r\n";
1534
                    //                    $content .= 'Content-Transfer-Encoding: ';
1535
                    //                    $content .= ($type == 'html') ? 'quoted-printable' : $this->getTransEncodeType();
1536
                    //                    $content .=  "\r\n"
1537
                    //                             . 'Content-Disposition: inline'  . "\r\n"
1538
                    //                             . 'Content-Description: ' . $type . ' message' . "\r\n";
1539
1540
                    if ( $this->getMD5flag() )
1541
                    $content .= 'Content-MD5: ' . $_content['md5'] . "\r\n";
1542
1543
                    $content .= "\r\n"	. $_content['data'] . "\r\n";
1544
1545
                    if (! key_exists('image', $this->_msgContent) && $_content['dataText'] && ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART))  // Add plain text message part after html part
1546
                    {
1547
                        $content.= "--" . $this->_getBoundary('alternative') . "--". "\r\n";
1548
                    }
1549
1550
                    $content .= "\r\n";
1551
                }
1552
            }
1553
1554
            // Close message boundries
1555
            //            $content .= "\r\n--" . $this->_getBoundary() . '--' . "\r\n" ;
1556
            $content .= "--" . $this->_getBoundary('mixed') . '--' . "\r\n" ;
1557
        }
1558
1559
        return $content;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $content does not seem to be defined for all execution paths leading up to this point.
Loading history...
1560
    }
1561
1562
    /**
1563
     * File attachments are added to the content array as sub-arrays,
1564
     * allowing for multiple attachments for each outbound email
1565
     *
1566
     * @param string $strContent  File data to attach to message
1567
     * @param string $strFileName File Name to give to attachment
1568
     * @param string $strMimeType File Mime Type of attachment
1569
     * @return void
1570
     */
1571
    public function setAttachment($strContent, $strFileName = 'unknown', $strMimeType = 'unknown')
1572
    {
1573
        if ( $strContent )
1574
        {
1575
            $strContent = rtrim(chunk_split(base64_encode($strContent), 76, "\r\n"));    // 76 max is defined into http://tools.ietf.org/html/rfc2047
1576
1577
            $this->_msgContent['attachment'][$strFileName]['mimeType'] = $strMimeType;
1578
            $this->_msgContent['attachment'][$strFileName]['fileName'] = $strFileName;
1579
            $this->_msgContent['attachment'][$strFileName]['data']     = $strContent;
1580
1581
            if ( $this->getMD5flag() )
1582
            $this->_msgContent['attachment'][$strFileName]['md5']      = dol_hash($strContent, 3);
1583
        }
1584
    }
1585
1586
1587
    // @CHANGE LDR
1588
1589
    /**
1590
     * Image attachments are added to the content array as sub-arrays,
1591
     * allowing for multiple images for each outbound email
1592
     *
1593
     * @param 	string $strContent  	Image data to attach to message
1594
     * @param 	string $strImageName 	Image Name to give to attachment
1595
     * @param 	string $strMimeType 	Image Mime Type of attachment
1596
     * @param 	string $strImageCid		CID
1597
     * @return 	void
1598
     */
1599
    public function setImageInline($strContent, $strImageName = 'unknown', $strMimeType = 'unknown', $strImageCid = 'unknown')
1600
    {
1601
        if ($strContent)
1602
        {
1603
            $this->_msgContent['image'][$strImageName]['mimeType'] = $strMimeType;
1604
            $this->_msgContent['image'][$strImageName]['imageName'] = $strImageName;
1605
            $this->_msgContent['image'][$strImageName]['cid']      = $strImageCid;
1606
            $this->_msgContent['image'][$strImageName]['data']     = $strContent;
1607
1608
            if ( $this->getMD5flag() )
1609
            $this->_msgContent['image'][$strImageName]['md5']      = dol_hash($strContent, 3);
1610
        }
1611
    }
1612
    // END @CHANGE LDR
1613
1614
1615
    /**
1616
     * Message Content Sensitivity
1617
     * Message Sensitivity values:
1618
     *   - [0] None - default
1619
     *   - [1] Personal
1620
     *   - [2] Private
1621
     *   - [3] Company Confidential
1622
     *
1623
     * @param 	integer	$_value		Message Sensitivity
1624
     * @return 	void
1625
     */
1626
    public function setSensitivity($_value = 0)
1627
    {
1628
        if ( ( is_numeric($_value) ) &&
1629
        ( ( $_value >= 0 ) && ( $_value <= 3 ) ) )
1630
        $this->_msgSensitivity = $_value;
1631
    }
1632
1633
    /**
1634
     * Returns Message Content Sensitivity string
1635
     * Message Sensitivity values:
1636
     *   - [0] None - default
1637
     *   - [1] Personal
1638
     *   - [2] Private
1639
     *   - [3] Company Confidential
1640
     *
1641
     * @return 	void
1642
     */
1643
    public function getSensitivity()
1644
    {
1645
        return $this->_arySensitivity[$this->_msgSensitivity];
1646
    }
1647
1648
    /**
1649
     * Message Content Priority
1650
     * Message Priority values:
1651
     *  - [0] 'Bulk'
1652
     *  - [1] 'Highest'
1653
     *  - [2] 'High'
1654
     *  - [3] 'Normal' - default
1655
     *  - [4] 'Low'
1656
     *  - [5] 'Lowest'
1657
     *
1658
     * @param 	integer 	$_value 	Message Priority
1659
     * @return 	void
1660
     */
1661
    public function setPriority($_value = 3)
1662
    {
1663
        if ( ( is_numeric($_value) ) &&
1664
        ( ( $_value >= 0 ) && ( $_value <= 5 ) ) )
1665
        $this->_msgPriority = $_value;
1666
    }
1667
1668
    /**
1669
     * Message Content Priority
1670
     * Message Priority values:
1671
     *  - [0] 'Bulk'
1672
     *  - [1] 'Highest'
1673
     *  - [2] 'High'
1674
     *  - [3] 'Normal' - default
1675
     *  - [4] 'Low'
1676
     *  - [5] 'Lowest'
1677
     *
1678
     * @return string
1679
     */
1680
    public function getPriority()
1681
    {
1682
        return 'Importance: ' . $this->_aryPriority[$this->_msgPriority] . "\r\n"
1683
        . 'Priority: '   . $this->_aryPriority[$this->_msgPriority] . "\r\n"
1684
        . 'X-Priority: ' . $this->_msgPriority . ' (' . $this->_aryPriority[$this->_msgPriority] . ')' . "\r\n";
1685
    }
1686
1687
    /**
1688
     * Set flag which determines whether to calculate message MD5 checksum.
1689
     *
1690
     * @param 	string 	$_flag		Message Priority
1691
     * @return 	void
1692
     */
1693
    public function setMD5flag($_flag = false)
1694
    {
1695
        $this->_smtpMD5 = $_flag;
1696
    }
1697
1698
    /**
1699
     * Gets flag which determines whether to calculate message MD5 checksum.
1700
     *
1701
     * @return 	boolean 				Message Priority
1702
     */
1703
    public function getMD5flag()
1704
    {
1705
        return $this->_smtpMD5;
1706
    }
1707
1708
    /**
1709
     * Message X-Header Content
1710
     * This is a simple "insert". Whatever is given will be placed
1711
     * "as is" into the Xheader array.
1712
     *
1713
     * @param string $strXdata Message X-Header Content
1714
     * @return void
1715
     */
1716
    public function setXheader($strXdata)
1717
    {
1718
        if ( $strXdata )
1719
        $this->_msgXheader[] = $strXdata;
1720
    }
1721
1722
    /**
1723
     * Retrieves the Message X-Header Content
1724
     *
1725
     * @return string[] $_msgContent Message X-Header Content
1726
     */
1727
    public function getXheader()
1728
    {
1729
        return $this->_msgXheader;
1730
    }
1731
1732
    /**
1733
     * Generates Random string for MIME message Boundary
1734
     *
1735
     * @return void
1736
     */
1737
    private function _setBoundary()
1738
    {
1739
        $this->_smtpsBoundary = "multipart_x." . time() . ".x_boundary";
1740
        $this->_smtpsRelatedBoundary = 'mul_'.dol_hash(uniqid("dolibarr2"), 3);
1741
        $this->_smtpsAlternativeBoundary = 'mul_'.dol_hash(uniqid("dolibarr3"), 3);
1742
    }
1743
1744
    /**
1745
     * Retrieves the MIME message Boundary
1746
     *
1747
     * @param  string $type				Type of boundary
1748
     * @return string $_smtpsBoundary 	MIME message Boundary
1749
     */
1750
    private function _getBoundary($type = 'mixed')
1751
    {
1752
        if ($type == 'mixed') return $this->_smtpsBoundary;
1753
        elseif ($type == 'related') return $this->_smtpsRelatedBoundary;
1754
        elseif ($type == 'alternative') return $this->_smtpsAlternativeBoundary;
1755
    }
1756
1757
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1758
    /**
1759
     * This function has been modified as provided by SirSir to allow multiline responses when
1760
     * using SMTP Extensions
1761
     *
1762
     * @param	resource    $socket			Socket handler
1763
     * @param	string		$response		Response. Example: "550 5.7.1  https://support.google.com/a/answer/6140680#invalidcred j21sm814390wre.3"
1764
     * @return	boolean						True or false
1765
     */
1766
    public function server_parse($socket, $response)
1767
    {
1768
        // phpcs:enable
1769
        /**
1770
         * Returns constructed SELECT Object string or boolean upon failure
1771
         * Default value is set at true
1772
         */
1773
        $_retVal = true;
1774
1775
        $server_response = '';
1776
1777
        // avoid infinite loop
1778
        $limit=0;
1779
1780
        while (substr($server_response, 3, 1) != ' ' && $limit<100)
1781
        {
1782
            if (! ($server_response = fgets($socket, 256)))
1783
            {
1784
                $this->_setErr(121, "Couldn't get mail server response codes");
1785
                $_retVal = false;
1786
                break;
1787
            }
1788
            $limit++;
1789
        }
1790
1791
        if (! (substr($server_response, 0, 3) == $response))
1792
        {
1793
            $this->_setErr(120, "Ran into problems sending Mail.\r\nResponse: $server_response");
1794
            $_retVal = false;
1795
        }
1796
1797
        return $_retVal;
1798
    }
1799
1800
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1801
    /**
1802
     * Send str
1803
     *
1804
     * @param	string		$_strSend		String to send
1805
     * @param 	string		$_returnCode	Return code
1806
     * @param 	string		$CRLF			CRLF
1807
     * @return 	boolean|null						True or false
1808
     */
1809
    public function socket_send_str($_strSend, $_returnCode = null, $CRLF = "\r\n")
1810
    {
1811
        // phpcs:enable
1812
        if ($this->_debug) $this->log.=$_strSend;	// @CHANGE LDR for log
1813
        fputs($this->socket, $_strSend . $CRLF);
1814
        if ($this->_debug) $this->log.=' ('.$_returnCode.')' . $CRLF;
1815
1816
        if ( $_returnCode )
1817
        return $this->server_parse($this->socket, $_returnCode);
1818
    }
1819
1820
    // =============================================================
1821
    // ** Error handling methods
1822
1823
    /**
1824
     * Defines errors codes and messages for Class
1825
     *
1826
     * @param  int    $_errNum  Error Code Number
1827
     * @param  string $_errMsg  Error Message
1828
     * @return void
1829
     */
1830
    private function _setErr($_errNum, $_errMsg)
1831
    {
1832
        $this->_smtpsErrors[] = array(
1833
            'num' => $_errNum,
1834
            'msg' => $_errMsg,
1835
        );
1836
    }
1837
1838
    /**
1839
     * Returns errors codes and messages for Class
1840
     *
1841
     * @return string $_errMsg  Error Message
1842
     */
1843
    public function getErrors()
1844
    {
1845
        $_errMsg = array();
1846
1847
        if (is_array($this->_smtpsErrors))
1848
        {
1849
            foreach ($this->_smtpsErrors as $_err => $_info)
1850
            {
1851
                $_errMsg[] = 'Error [' . $_info['num'] .']: '. $_info['msg'];
1852
            }
1853
        }
1854
1855
        return implode("\n", $_errMsg);
1856
    }
1857
}
1858
1859
1860
// =============================================================
1861
// ** CSV Version Control Info
1862
1863
/**
1864
 * Revision      2011/09/12 07:49:59  eldy
1865
 * Doxygen
1866
 *
1867
 * Revision      2011/09/06 06:53:53  hregis
1868
 * Fix: use dol_hash instead md5 php function
1869
 *
1870
 * Revision      2011/09/03 00:14:27  eldy
1871
 * Doxygen
1872
 *
1873
 * Revision      2011/08/28 14:24:23  eldy
1874
 * Doxygen
1875
 *
1876
 * Revision      2011/07/12 22:19:02  eldy
1877
 * Fix: Attachment fails if content was empty
1878
 *
1879
 * Revision      2011/06/20 23:17:50  hregis
1880
 * Fix: use best structure of mail
1881
 *
1882
 * Revision      2010/04/13 20:58:37  eldy
1883
 * Fix: Can provide ip address on smtps. Better error reporting.
1884
 *
1885
 * Revision      2010/04/13 20:30:25  eldy
1886
 * Fix: Can provide ip address on smtps. Better error reporting.
1887
 *
1888
 * Revision      2010/01/12 13:02:07  hregis
1889
 * Fix: missing attach-files
1890
 *
1891
 * Revision      2009/11/01 14:16:30  eldy
1892
 * Fix: Sending mail with SMTPS was not working.
1893
 *
1894
 * Revision      2009/10/20 13:14:47  hregis
1895
 * Fix: function "split" is deprecated since php 5.3.0
1896
 *
1897
 * Revision      2009/05/13 19:10:07  eldy
1898
 * New: Can use inline images.Everything seems to work with thunderbird and webmail gmail. New to be tested on other mail browsers.
1899
 *
1900
 * Revision      2009/05/13 14:49:30  eldy
1901
 * Fix: Make code so much simpler and solve a lot of problem with new version.
1902
 *
1903
 * Revision      2009/02/09 00:04:35  eldy
1904
 * Added support for SMTPS protocol
1905
 *
1906
 * Revision       2008/04/16 23:11:45  eldy
1907
 * New: Add action "Test server connectivity"
1908
 *
1909
 * Revision 1.18  2007/01/12 22:17:08  ongardie
1910
 * - Added full_http_site_root() to utils-misc.php
1911
 * - Made SMTPs' getError() easier to use
1912
 * - Improved activity modified emails
1913
 *
1914
 * Revision 1.17  2006/04/05 03:15:40  ongardie
1915
 * -Fixed method name typo that resulted in a fatal error.
1916
 *
1917
 * Revision 1.16  2006/03/08 04:05:25  jswalter
1918
 *  - '$_smtpsTransEncode' was removed and '$_smtpsTransEncodeType' is now used
1919
 *  - '$_smtpsTransEncodeType' is defaulted to ZERO
1920
 *  - corrected 'setCharSet()'  internal vars
1921
 *  - defined '$_mailPath'
1922
 *  - added '$_smtpMD5' as a class property
1923
 *  - added 'setMD5flag()' to set above property
1924
 *  - added 'getMD5flag()' to retrieve above property
1925
 *  - 'setAttachment()' will add an MD5 checksum to attachements if above property is set
1926
 *  - 'setBodyContent()' will add an MD5 checksum to message parts if above property is set
1927
 *  - 'getBodyContent()' will insert the MD5 checksum for messages and attachments if above property is set
1928
 *  - removed leading dashes from message boundry
1929
 *  - added propery "Close message boundry" tomessage block
1930
 *  - corrected some comments in various places
1931
 *  - removed some incorrect comments in others
1932
 *
1933
 * Revision 1.15  2006/02/21 02:00:07  vanmer
1934
 * - patch to add support for sending to exim mail server
1935
 * - thanks to Diego Ongaro at ETSZONE ([email protected])
1936
 *
1937
 * Revision 1.14  2005/08/29 16:22:10  jswalter
1938
 *  - change 'multipart/alternative' to 'multipart/mixed', but Windows based mail servers have issues with this.
1939
 * Bug 594
1940
 *
1941
 * Revision 1.13  2005/08/21 01:57:30  vanmer
1942
 * - added initialization for array if no recipients exist
1943
 *
1944
 * Revision 1.12  2005/08/20 12:04:30  braverock
1945
 * - remove potentially binary characters from Message-ID
1946
 * - add getHost to get the hostname of the mailserver
1947
 * - add username to Message-ID header
1948
 *
1949
 * Revision 1.11  2005/08/20 11:49:48  braverock
1950
 * - fix typos in boundary
1951
 * - remove potentially illegal characters from boundary
1952
 *
1953
 * Revision 1.10  2005/08/19 20:39:32  jswalter
1954
 *  - added _server_connect()' as a seperate method to handle server connectivity.
1955
 *  - added '_server_authenticate()' as a seperate method to handle server authentication.
1956
 *  - 'sendMsg()' now uses the new methods to handle server communication.
1957
 *  - modified 'server_parse()' and 'socket_send_str()' to give error codes and messages.
1958
 *
1959
 * Revision 1.9  2005/08/19 15:40:18  jswalter
1960
 *  - IMPORTANT: 'setAttachement()' is now spelled correctly: 'setAttachment()'
1961
 *  - added additional comment to several methods
1962
 *  - added '$_smtpsTransEncodeTypes' array to limit encode types
1963
 *  - added parameters to 'sendMsg()' for future development around debugging and logging
1964
 *  - added error code within 'setConfig()' if the given path is not found
1965
 *  - 'setTransportType()' now has parameter validation
1966
 *     [this still is not implemented]
1967
 *  - 'setPort()' now does parameter validation
1968
 *  - 'setTransEncode()' now has parameter validation against '$_smtpsTransEncodeTypes'
1969
 *  - modified 'get_email_list()' to handle error handling
1970
 *  - 'setSensitivity()' now has parameter validation
1971
 *  - 'setPriority()' now has parameter validation
1972
 *
1973
 * Revision 1.8  2005/06/24 21:00:20  jswalter
1974
 *   - corrected comments
1975
 *   - corrected the defualt value for 'setPriority()'
1976
 *   - modified 'setAttachement()' to process multiple attachments correctly
1977
 *   - modified 'getBodyContent()' to handle multiple attachments
1978
 * Bug 310
1979
 *
1980
 * Revision 1.7  2005/05/19 21:12:34  braverock
1981
 * - replace chunk_split() with wordwrap() to fix funky wrapping of templates
1982
 *
1983
 * Revision 1.6  2005/04/25 04:55:06  jswalter
1984
 *  - cloned from Master Version
1985
 *
1986
 * Revision 1.10  2005/04/25 04:54:10  walter
1987
 *  - "fixed" 'getBodyContent()' to handle a "simple" text only message
1988
 *
1989
 * Revision 1.9  2005/04/25 03:52:01  walter
1990
 *  - replace closing curly bracket. Removed it in last revision!
1991
 *
1992
 * Revision 1.8  2005/04/25 02:29:49  walter
1993
 *  - added '$_transportType' and its getter/setter methods.
1994
 *    for future use. NOT yet implemented.
1995
 *  - in 'sendMsg()', added HOST validation check
1996
 *  - added error check for initial Socket Connection
1997
 *  - created new method 'socket_send_str()' to process socket
1998
 *    communication in a unified means. Socket calls within
1999
 *    'sendMsg()' have been modified to use this new method.
2000
 *  - expanded comments in 'setConfig()'
2001
 *  - added "error" check on PHP ini file properties. If these
2002
 *    properties not set within the INI file, the default values
2003
 *    will be used.
2004
 *  - modified 'get_RCPT_list()' to reset itself each time it is called
2005
 *  - modified 'setBodyContent()' to store data in a sub-array for better
2006
 *    parsing within the 'getBodyContent()' method
2007
 *  - modified 'getBodyContent()' to process contents array better.
2008
 *    Also modified to handle attachements.
2009
 *  - added 'setAttachement()' so files and other data can be attached
2010
 *    to messages
2011
 *  - added '_setErr()' and 'getErrors()' as an attempt to begin an error
2012
 *    handling process within this class
2013
 *
2014
 * Revision 1.7  2005/04/13 15:23:50  walter
2015
 *  - made 'CC' a conditional insert
2016
 *  - made 'BCC' a conditional insert
2017
 *  - fixed 'Message-ID'
2018
 *  - corrected 'getSensitivity()'
2019
 *  - modified '$_aryPriority[]' to proper values
2020
 *  - updated 'setConfig()' to handle external Ini or 'php.ini'
2021
 *
2022
 * Revision 1.6  2005/03/15 17:34:06  walter
2023
 *  - corrected Message Sensitivity property and method comments
2024
 *  - added array to Message Sensitivity
2025
 *  - added getSensitivity() method to use new Sensitivity array
2026
 *  - created seters and getter for Priority with new Prioity value array property
2027
 *  - changed config file include from 'include_once'
2028
 *  - modified getHeader() to ustilize new Message Sensitivity and Priorty properties
2029
 *
2030
 * Revision 1.5  2005/03/14 22:25:27  walter
2031
 *  - added references
2032
 *  - added Message sensitivity as a property with Getter/Setter methods
2033
 *  - boundary is now a property with Getter/Setter methods
2034
 *  - added 'builtRCPTlist()'
2035
 *  - 'sendMsg()' now uses Object properties and methods to build message
2036
 *  - 'setConfig()' to load external file
2037
 *  - 'setForm()' will "strip" the email address out of "address" string
2038
 *  - modifed 'getFrom()' to handle "striping" the email address
2039
 *  - '_buildArrayList()' creates a multi-dimensional array of addresses
2040
 *    by domain, TO, CC & BCC and then by User Name.
2041
 *  - '_strip_email()' pulls email address out of "full Address" string'
2042
 *  - 'get_RCPT_list()' pulls out "bare" emaill address form address array
2043
 *  - 'getHeader()' builds message Header from Object properties
2044
 *  - 'getBodyContent()' builds full messsage body, even multi-part
2045
 *
2046
 * Revision 1.4  2005/03/02 20:53:35  walter
2047
 *  - core Setters & Getters defined
2048
 *  - added additional Class Properties
2049
 *
2050
 * Revision 1.3  2005/03/02 18:51:51  walter
2051
 *  - added base 'Class Properties'
2052
 *
2053
 * Revision 1.2  2005/03/01 19:37:52  walter
2054
 *  - CVS logging tags
2055
 *  - more comments
2056
 *  - more "shell"
2057
 *  - some constants
2058
 *
2059
 * Revision 1.1  2005/03/01 19:22:49  walter
2060
 *  - initial commit
2061
 *  - basic shell with some commets
2062
 *
2063
 */
2064