1
|
<?php
|
2
|
/*
|
3
|
* smtp.php
|
4
|
*
|
5
|
* @(#) $Header: /opt2/ena/metal/smtp/smtp.php,v 1.50 2016/01/19 00:16:06 mlemos Exp $
|
6
|
*
|
7
|
*/
|
8
|
|
9
|
/*
|
10
|
{metadocument}<?xml version="1.0" encoding="ISO-8859-1"?>
|
11
|
<class>
|
12
|
|
13
|
<package>net.manuellemos.smtp</package>
|
14
|
|
15
|
<version>@(#) $Id: smtp.php,v 1.50 2016/01/19 00:16:06 mlemos Exp $</version>
|
16
|
<copyright>Copyright (C) Manuel Lemos 1999-2011</copyright>
|
17
|
<title>Sending e-mail messages via SMTP protocol</title>
|
18
|
<author>Manuel Lemos</author>
|
19
|
<authoraddress>mlemos-at-acm.org</authoraddress>
|
20
|
|
21
|
<documentation>
|
22
|
<idiom>en</idiom>
|
23
|
<purpose>Sending e-mail messages via SMTP protocol</purpose>
|
24
|
<translation>If you are interested in translating the documentation of
|
25
|
this class to your own idiom, please <link>
|
26
|
<data>contact the author</data>
|
27
|
<url>mailto:<getclassproperty>authoraddress</getclassproperty></url>
|
28
|
</link>.</translation>
|
29
|
<support>Technical support for using this class may be obtained in the
|
30
|
<tt>smtpclass</tt> support forum. Just go to the support forum pages
|
31
|
page to browse the forum archives and post support request
|
32
|
messages:<paragraphbreak />
|
33
|
<link>
|
34
|
<data>http://www.phpclasses.org/discuss/package/14/</data>
|
35
|
<url>http://www.phpclasses.org/discuss/package/14/</url>
|
36
|
</link></support>
|
37
|
<usage>To use this class just create a new object, set any variables
|
38
|
to configure its options and call the
|
39
|
<functionlink>SendMessage</functionlink> function to send a
|
40
|
message.<paragraphbreak />It is not recommended that you use this
|
41
|
class alone unless you have deep understanding of Internet mail
|
42
|
standards on how to compose compliant e-mail messages. Instead, use
|
43
|
the <link>
|
44
|
<data>MIME message composing and sending class</data>
|
45
|
<url>http://www.phpclasses.org/mimemessage</url>
|
46
|
</link> and its sub-class SMTP message together with this SMTP class
|
47
|
to properly compose e-mail messages, so your messages are not
|
48
|
discarded for not being correctly composed.</usage>
|
49
|
</documentation>
|
50
|
|
51
|
{/metadocument}
|
52
|
*/
|
53
|
|
54
|
class smtp_class
|
55
|
{
|
56
|
/*
|
57
|
{metadocument}
|
58
|
<variable>
|
59
|
<name>user</name>
|
60
|
<type>STRING</type>
|
61
|
<value></value>
|
62
|
<documentation>
|
63
|
<purpose>Define the authorized user when sending messages to a SMTP
|
64
|
server.</purpose>
|
65
|
<usage>Set this variable to the user name when the SMTP server
|
66
|
requires authentication.</usage>
|
67
|
</documentation>
|
68
|
</variable>
|
69
|
{/metadocument}
|
70
|
*/
|
71
|
var $user="";
|
72
|
|
73
|
/*
|
74
|
{metadocument}
|
75
|
<variable>
|
76
|
<name>realm</name>
|
77
|
<type>STRING</type>
|
78
|
<value></value>
|
79
|
<documentation>
|
80
|
<purpose>Define the authentication realm when sending messages to a
|
81
|
SMTP server.</purpose>
|
82
|
<usage>Set this variable when the SMTP server requires
|
83
|
authentication and if more than one authentication realm is
|
84
|
supported.</usage>
|
85
|
</documentation>
|
86
|
</variable>
|
87
|
{/metadocument}
|
88
|
*/
|
89
|
var $realm="";
|
90
|
|
91
|
/*
|
92
|
{metadocument}
|
93
|
<variable>
|
94
|
<name>password</name>
|
95
|
<type>STRING</type>
|
96
|
<value></value>
|
97
|
<documentation>
|
98
|
<purpose>Define the authorized user password when sending messages
|
99
|
to a SMTP server.</purpose>
|
100
|
<usage>Set this variable to the user password when the SMTP server
|
101
|
requires authentication.</usage>
|
102
|
</documentation>
|
103
|
</variable>
|
104
|
{/metadocument}
|
105
|
*/
|
106
|
var $password="";
|
107
|
|
108
|
/*
|
109
|
{metadocument}
|
110
|
<variable>
|
111
|
<name>workstation</name>
|
112
|
<type>STRING</type>
|
113
|
<value></value>
|
114
|
<documentation>
|
115
|
<purpose>Define the client workstation name when sending messages
|
116
|
to a SMTP server.</purpose>
|
117
|
<usage>Set this variable to the client workstation when the SMTP
|
118
|
server requires authentication identifiying the origin workstation
|
119
|
name.</usage>
|
120
|
</documentation>
|
121
|
</variable>
|
122
|
{/metadocument}
|
123
|
*/
|
124
|
var $workstation="";
|
125
|
|
126
|
/*
|
127
|
{metadocument}
|
128
|
<variable>
|
129
|
<name>authentication_mechanism</name>
|
130
|
<type>STRING</type>
|
131
|
<value></value>
|
132
|
<documentation>
|
133
|
<purpose>Force the use of a specific authentication mechanism.</purpose>
|
134
|
<usage>Set it to an empty string to let the class determine the
|
135
|
authentication mechanism to use automatically based on the
|
136
|
supported mechanisms by the server and by the SASL client library
|
137
|
classes.<paragraphbreak />
|
138
|
Set this variable to a specific mechanism name if you want to
|
139
|
override the automatic authentication mechanism selection.</usage>
|
140
|
</documentation>
|
141
|
</variable>
|
142
|
{/metadocument}
|
143
|
*/
|
144
|
var $authentication_mechanism="";
|
145
|
|
146
|
/*
|
147
|
{metadocument}
|
148
|
<variable>
|
149
|
<name>host_name</name>
|
150
|
<type>STRING</type>
|
151
|
<value></value>
|
152
|
<documentation>
|
153
|
<purpose>Define the SMTP server host name.</purpose>
|
154
|
<usage>Set to the host name of the SMTP server to which you want to
|
155
|
relay the messages.</usage>
|
156
|
</documentation>
|
157
|
</variable>
|
158
|
{/metadocument}
|
159
|
*/
|
160
|
var $host_name="";
|
161
|
|
162
|
/*
|
163
|
{metadocument}
|
164
|
<variable>
|
165
|
<name>host_port</name>
|
166
|
<type>INTEGER</type>
|
167
|
<value>25</value>
|
168
|
<documentation>
|
169
|
<purpose>Define the SMTP server host port.</purpose>
|
170
|
<usage>Set to the TCP port of the SMTP server host to connect.</usage>
|
171
|
</documentation>
|
172
|
</variable>
|
173
|
{/metadocument}
|
174
|
*/
|
175
|
var $host_port=25;
|
176
|
|
177
|
/*
|
178
|
{metadocument}
|
179
|
<variable>
|
180
|
<name>socks_host_name</name>
|
181
|
<type>STRING</type>
|
182
|
<value></value>
|
183
|
<documentation>
|
184
|
<purpose>Define the SOCKS server host name.</purpose>
|
185
|
<usage>Set to the SOCKS server host name through which the SMTP
|
186
|
connection should be routed. Leave it empty if you do not want the
|
187
|
connections to be established through a SOCKS server.</usage>
|
188
|
</documentation>
|
189
|
</variable>
|
190
|
{/metadocument}
|
191
|
*/
|
192
|
var $socks_host_name = '';
|
193
|
|
194
|
/*
|
195
|
{metadocument}
|
196
|
<variable>
|
197
|
<name>socks_host_port</name>
|
198
|
<type>INTEGER</type>
|
199
|
<value>1080</value>
|
200
|
<documentation>
|
201
|
<purpose>Define the SOCKS server host port.</purpose>
|
202
|
<usage>Set to the port of the SOCKS server host through which the
|
203
|
the SMTP connection should be routed.</usage>
|
204
|
</documentation>
|
205
|
</variable>
|
206
|
{/metadocument}
|
207
|
*/
|
208
|
var $socks_host_port=1080;
|
209
|
|
210
|
/*
|
211
|
{metadocument}
|
212
|
<variable>
|
213
|
<name>socks_version</name>
|
214
|
<type>STRING</type>
|
215
|
<value>5</value>
|
216
|
<documentation>
|
217
|
<purpose>Set the SOCKS protocol version.</purpose>
|
218
|
<usage>Change this value if SOCKS server you want to use is
|
219
|
listening to a different port.</usage>
|
220
|
</documentation>
|
221
|
</variable>
|
222
|
{/metadocument}
|
223
|
*/
|
224
|
var $socks_version='5';
|
225
|
|
226
|
/*
|
227
|
{metadocument}
|
228
|
<variable>
|
229
|
<name>http_proxy_host_name</name>
|
230
|
<type>STRING</type>
|
231
|
<value></value>
|
232
|
<documentation>
|
233
|
<purpose>Define the HTTP proxy server host name.</purpose>
|
234
|
<usage>Set to the HTTP proxy server host name through which the
|
235
|
SMTP connection should be routed. Leave it empty if you do not
|
236
|
want the connections to be established through an HTTP proxy.</usage>
|
237
|
</documentation>
|
238
|
</variable>
|
239
|
{/metadocument}
|
240
|
*/
|
241
|
var $http_proxy_host_name = '';
|
242
|
|
243
|
/*
|
244
|
{metadocument}
|
245
|
<variable>
|
246
|
<name>http_proxy_host_port</name>
|
247
|
<type>INTEGER</type>
|
248
|
<value>80</value>
|
249
|
<documentation>
|
250
|
<purpose>Define the HTTP proxy server host port.</purpose>
|
251
|
<usage>Set to the port of the HTTP proxy server host through which
|
252
|
the SMTP connection should be routed.</usage>
|
253
|
</documentation>
|
254
|
</variable>
|
255
|
{/metadocument}
|
256
|
*/
|
257
|
var $http_proxy_host_port=80;
|
258
|
|
259
|
/*
|
260
|
{metadocument}
|
261
|
<variable>
|
262
|
<name>user_agent</name>
|
263
|
<type>STRING</type>
|
264
|
<value>SMTP Class (http://www.phpclasses.org/smtpclass $Revision: 1.50 $)</value>
|
265
|
<documentation>
|
266
|
<purpose>Set the user agent used when connecting via an HTTP proxy.</purpose>
|
267
|
<usage>Change this value only if for some reason you want emulate a
|
268
|
certain e-mail client.</usage>
|
269
|
</documentation>
|
270
|
</variable>
|
271
|
{/metadocument}
|
272
|
*/
|
273
|
var $user_agent='SMTP Class (http://www.phpclasses.org/smtpclass $Revision: 1.50 $)';
|
274
|
|
275
|
/*
|
276
|
{metadocument}
|
277
|
<variable>
|
278
|
<name>ssl</name>
|
279
|
<type>BOOLEAN</type>
|
280
|
<value>0</value>
|
281
|
<documentation>
|
282
|
<purpose>Define whether the connection to the SMTP server should be
|
283
|
established securely using SSL protocol.</purpose>
|
284
|
<usage>Set to <booleanvalue>1</booleanvalue> if the SMTP server
|
285
|
requires secure connections using SSL protocol.</usage>
|
286
|
</documentation>
|
287
|
</variable>
|
288
|
{/metadocument}
|
289
|
*/
|
290
|
var $ssl=0;
|
291
|
|
292
|
/*
|
293
|
{metadocument}
|
294
|
<variable>
|
295
|
<name>start_tls</name>
|
296
|
<type>BOOLEAN</type>
|
297
|
<value>0</value>
|
298
|
<documentation>
|
299
|
<purpose>Define whether the connection to the SMTP server should use
|
300
|
encryption after the connection is established using TLS
|
301
|
protocol.</purpose>
|
302
|
<usage>Set to <booleanvalue>1</booleanvalue> if the SMTP server
|
303
|
requires that authentication be done securely starting the TLS
|
304
|
protocol after the connection is established.</usage>
|
305
|
</documentation>
|
306
|
</variable>
|
307
|
{/metadocument}
|
308
|
*/
|
309
|
var $start_tls = 0;
|
310
|
|
311
|
/*
|
312
|
{metadocument}
|
313
|
<variable>
|
314
|
<name>localhost</name>
|
315
|
<type>STRING</type>
|
316
|
<value></value>
|
317
|
<documentation>
|
318
|
<purpose>Name of the local host computer</purpose>
|
319
|
<usage>Set to the name of the computer connecting to the SMTP
|
320
|
server from the local network.</usage>
|
321
|
</documentation>
|
322
|
</variable>
|
323
|
{/metadocument}
|
324
|
*/
|
325
|
var $localhost="";
|
326
|
|
327
|
/*
|
328
|
{metadocument}
|
329
|
<variable>
|
330
|
<name>timeout</name>
|
331
|
<type>INTEGER</type>
|
332
|
<value>0</value>
|
333
|
<documentation>
|
334
|
<purpose>Specify the connection timeout period in seconds.</purpose>
|
335
|
<usage>Leave it set to <integervalue>0</integervalue> if you want
|
336
|
the connection attempts to wait forever. Change this value if for
|
337
|
some reason the timeout period seems insufficient or otherwise it
|
338
|
seems too long.</usage>
|
339
|
</documentation>
|
340
|
</variable>
|
341
|
{/metadocument}
|
342
|
*/
|
343
|
var $timeout=0;
|
344
|
|
345
|
/*
|
346
|
{metadocument}
|
347
|
<variable>
|
348
|
<name>data_timeout</name>
|
349
|
<type>INTEGER</type>
|
350
|
<value>0</value>
|
351
|
<documentation>
|
352
|
<purpose>Specify the timeout period in seconds to wait for data from
|
353
|
the server.</purpose>
|
354
|
<usage>Leave it set to <integervalue>0</integervalue> if you want
|
355
|
to use the same value defined in the
|
356
|
<variablelink>timeout</variablelink> variable. Change this value
|
357
|
if for some reason the default data timeout period seems
|
358
|
insufficient or otherwise it seems too long.</usage>
|
359
|
</documentation>
|
360
|
</variable>
|
361
|
{/metadocument}
|
362
|
*/
|
363
|
var $data_timeout=0;
|
364
|
|
365
|
/*
|
366
|
{metadocument}
|
367
|
<variable>
|
368
|
<name>direct_delivery</name>
|
369
|
<type>BOOLEAN</type>
|
370
|
<value>0</value>
|
371
|
<documentation>
|
372
|
<purpose>Boolean flag that indicates whether the message should be
|
373
|
sent in direct delivery mode, i.e. the message is sent to the SMTP
|
374
|
server associated to the domain of the recipient instead of
|
375
|
relaying to the server specified by the
|
376
|
<variablelink>host_name</variablelink> variable.</purpose>
|
377
|
<usage>Set this to <tt><booleanvalue>1</booleanvalue></tt> if you
|
378
|
want to send urgent messages directly to the recipient domain SMTP
|
379
|
server.</usage>
|
380
|
</documentation>
|
381
|
</variable>
|
382
|
{/metadocument}
|
383
|
*/
|
384
|
var $direct_delivery=0;
|
385
|
|
386
|
/*
|
387
|
{metadocument}
|
388
|
<variable>
|
389
|
<name>error</name>
|
390
|
<type>STRING</type>
|
391
|
<value></value>
|
392
|
<documentation>
|
393
|
<purpose>Message that describes the error when a call to a class
|
394
|
function fails.</purpose>
|
395
|
<usage>Check this variable when an error occurs to understand what
|
396
|
happened.</usage>
|
397
|
</documentation>
|
398
|
</variable>
|
399
|
{/metadocument}
|
400
|
*/
|
401
|
var $error="";
|
402
|
|
403
|
/*
|
404
|
{metadocument}
|
405
|
<variable>
|
406
|
<name>debug</name>
|
407
|
<type>BOOLEAN</type>
|
408
|
<value>0</value>
|
409
|
<documentation>
|
410
|
<purpose>Specify whether it is necessary to output SMTP connection
|
411
|
debug information.</purpose>
|
412
|
<usage>Set this variable to
|
413
|
<tt><booleanvalue>1</booleanvalue></tt> if you need to see
|
414
|
the progress of the SMTP connection and protocol dialog when you
|
415
|
need to understand the reason for delivery problems.</usage>
|
416
|
</documentation>
|
417
|
</variable>
|
418
|
{/metadocument}
|
419
|
*/
|
420
|
var $debug=0;
|
421
|
|
422
|
/*
|
423
|
{metadocument}
|
424
|
<variable>
|
425
|
<name>html_debug</name>
|
426
|
<type>BOOLEAN</type>
|
427
|
<value>0</value>
|
428
|
<documentation>
|
429
|
<purpose>Specify whether the debug information should be outputted in
|
430
|
HTML format.</purpose>
|
431
|
<usage>Set this variable to
|
432
|
<tt><booleanvalue>1</booleanvalue></tt> if you need to see
|
433
|
the debug output in a Web page.</usage>
|
434
|
</documentation>
|
435
|
</variable>
|
436
|
{/metadocument}
|
437
|
*/
|
438
|
var $html_debug=0;
|
439
|
|
440
|
/*
|
441
|
{metadocument}
|
442
|
<variable>
|
443
|
<name>esmtp</name>
|
444
|
<type>BOOLEAN</type>
|
445
|
<value>1</value>
|
446
|
<documentation>
|
447
|
<purpose>Specify whether the class should attempt to use ESMTP
|
448
|
extensions supported by the server.</purpose>
|
449
|
<usage>Set this variable to
|
450
|
<tt><booleanvalue>0</booleanvalue></tt> if for some reason you
|
451
|
want to avoid benefitting from ESMTP extensions.</usage>
|
452
|
</documentation>
|
453
|
</variable>
|
454
|
{/metadocument}
|
455
|
*/
|
456
|
var $esmtp=1;
|
457
|
|
458
|
/*
|
459
|
{metadocument}
|
460
|
<variable>
|
461
|
<name>esmtp_extensions</name>
|
462
|
<type>HASH</type>
|
463
|
<value></value>
|
464
|
<documentation>
|
465
|
<purpose>Associative array with the list of ESMTP extensions
|
466
|
supported by the SMTP server.</purpose>
|
467
|
<usage>Check this variable after connecting to the SMTP server to
|
468
|
determine which ESMTP extensions are supported.</usage>
|
469
|
</documentation>
|
470
|
</variable>
|
471
|
{/metadocument}
|
472
|
*/
|
473
|
var $esmtp_extensions=array();
|
474
|
|
475
|
/*
|
476
|
{metadocument}
|
477
|
<variable>
|
478
|
<name>exclude_address</name>
|
479
|
<type>STRING</type>
|
480
|
<value></value>
|
481
|
<documentation>
|
482
|
<purpose>Specify an address that should be considered invalid
|
483
|
when resolving host name addresses.</purpose>
|
484
|
<usage>In some networks any domain name that does not exist is
|
485
|
resolved as a sub-domain of the default local domain. If the DNS is
|
486
|
configured in such way that it always resolves any sub-domain of
|
487
|
the default local domain to a given address, it is hard to
|
488
|
determine whether a given domain does not exist.<paragraphbreak />
|
489
|
If your network is configured this way, you may set this variable
|
490
|
to the address that all sub-domains of the default local domain
|
491
|
resolves, so the class can assume that such address is invalid.</usage>
|
492
|
</documentation>
|
493
|
</variable>
|
494
|
{/metadocument}
|
495
|
*/
|
496
|
var $exclude_address="";
|
497
|
|
498
|
/*
|
499
|
{metadocument}
|
500
|
<variable>
|
501
|
<name>getmxrr</name>
|
502
|
<type>STRING</type>
|
503
|
<value>getmxrr</value>
|
504
|
<documentation>
|
505
|
<purpose>Specify the name of the function that is called to determine
|
506
|
the SMTP server address of a given domain.</purpose>
|
507
|
<usage>Change this to a working replacement of the PHP
|
508
|
<tt>getmxrr()</tt> function if this is not working in your system
|
509
|
and you want to send messages in direct delivery mode.</usage>
|
510
|
</documentation>
|
511
|
</variable>
|
512
|
{/metadocument}
|
513
|
*/
|
514
|
var $getmxrr="GetMXRR";
|
515
|
|
516
|
/*
|
517
|
{metadocument}
|
518
|
<variable>
|
519
|
<name>pop3_auth_host</name>
|
520
|
<type>STRING</type>
|
521
|
<value></value>
|
522
|
<documentation>
|
523
|
<purpose>Specify the server address for POP3 based authentication.</purpose>
|
524
|
<usage>Set this variable to the address of the POP3 server if the
|
525
|
SMTP server requires POP3 based authentication.</usage>
|
526
|
</documentation>
|
527
|
</variable>
|
528
|
{/metadocument}
|
529
|
*/
|
530
|
var $pop3_auth_host="";
|
531
|
|
532
|
/*
|
533
|
{metadocument}
|
534
|
<variable>
|
535
|
<name>pop3_auth_port</name>
|
536
|
<type>INTEGER</type>
|
537
|
<value>110</value>
|
538
|
<documentation>
|
539
|
<purpose>Specify the server port for POP3 based authentication.</purpose>
|
540
|
<usage>Set this variable to the port of the POP3 server if the
|
541
|
SMTP server requires POP3 based authentication.</usage>
|
542
|
</documentation>
|
543
|
</variable>
|
544
|
{/metadocument}
|
545
|
*/
|
546
|
var $pop3_auth_port=110;
|
547
|
|
548
|
/* private variables - DO NOT ACCESS */
|
549
|
|
550
|
var $state="Disconnected";
|
551
|
var $connection=0;
|
552
|
var $pending_recipients=0;
|
553
|
var $next_token="";
|
554
|
var $direct_sender="";
|
555
|
var $connected_domain="";
|
556
|
var $result_code;
|
557
|
var $disconnected_error=0;
|
558
|
var $esmtp_host="";
|
559
|
var $maximum_piped_recipients=100;
|
560
|
|
561
|
/* Private methods - DO NOT CALL */
|
562
|
|
563
|
Function Tokenize($string,$separator="")
|
564
|
{
|
565
|
if(!strcmp($separator,""))
|
566
|
{
|
567
|
$separator=$string;
|
568
|
$string=$this->next_token;
|
569
|
}
|
570
|
for($character=0;$character<strlen($separator);$character++)
|
571
|
{
|
572
|
if(GetType($position=strpos($string,$separator[$character]))=="integer")
|
573
|
$found=(IsSet($found) ? min($found,$position) : $position);
|
574
|
}
|
575
|
if(IsSet($found))
|
576
|
{
|
577
|
$this->next_token=substr($string,$found+1);
|
578
|
return(substr($string,0,$found));
|
579
|
}
|
580
|
else
|
581
|
{
|
582
|
$this->next_token="";
|
583
|
return($string);
|
584
|
}
|
585
|
}
|
586
|
|
587
|
Function OutputDebug($message)
|
588
|
{
|
589
|
$message.="\n";
|
590
|
if($this->html_debug)
|
591
|
$message=str_replace("\n","<br />\n",HtmlEntities($message));
|
592
|
echo $message;
|
593
|
flush();
|
594
|
}
|
595
|
|
596
|
Function SetDataAccessError($error)
|
597
|
{
|
598
|
$this->error=$error;
|
599
|
if(function_exists("socket_get_status"))
|
600
|
{
|
601
|
$status=socket_get_status($this->connection);
|
602
|
if($status["timed_out"])
|
603
|
$this->error.=": data access time out";
|
604
|
elseif($status["eof"])
|
605
|
{
|
606
|
$this->error.=": the server disconnected";
|
607
|
$this->disconnected_error=1;
|
608
|
}
|
609
|
}
|
610
|
return($this->error);
|
611
|
}
|
612
|
|
613
|
Function SetError($error)
|
614
|
{
|
615
|
return($this->error=$error);
|
616
|
}
|
617
|
|
618
|
Function GetLine()
|
619
|
{
|
620
|
for($line="";;)
|
621
|
{
|
622
|
if(feof($this->connection))
|
623
|
{
|
624
|
$this->error="reached the end of data while reading from the SMTP server conection";
|
625
|
return("");
|
626
|
}
|
627
|
if(GetType($data=@fgets($this->connection,100))!="string"
|
628
|
|| strlen($data)==0)
|
629
|
{
|
630
|
$this->SetDataAccessError("it was not possible to read line from the SMTP server");
|
631
|
return("");
|
632
|
}
|
633
|
$line.=$data;
|
634
|
$length=strlen($line);
|
635
|
if($length>=2
|
636
|
&& substr($line,$length-2,2)=="\r\n")
|
637
|
{
|
638
|
$line=substr($line,0,$length-2);
|
639
|
if($this->debug)
|
640
|
$this->OutputDebug("S $line");
|
641
|
return($line);
|
642
|
}
|
643
|
}
|
644
|
}
|
645
|
|
646
|
Function PutLine($line)
|
647
|
{
|
648
|
if($this->debug)
|
649
|
$this->OutputDebug("C $line");
|
650
|
if(!@fputs($this->connection,"$line\r\n"))
|
651
|
{
|
652
|
$this->SetDataAccessError("it was not possible to send a line to the SMTP server");
|
653
|
return(0);
|
654
|
}
|
655
|
return(1);
|
656
|
}
|
657
|
|
658
|
Function PutData(&$data)
|
659
|
{
|
660
|
if(strlen($data))
|
661
|
{
|
662
|
if($this->debug)
|
663
|
$this->OutputDebug("C $data");
|
664
|
if(!@fputs($this->connection,$data))
|
665
|
{
|
666
|
$this->SetDataAccessError("it was not possible to send data to the SMTP server");
|
667
|
return(0);
|
668
|
}
|
669
|
}
|
670
|
return(1);
|
671
|
}
|
672
|
|
673
|
Function VerifyResultLines($code,&$responses)
|
674
|
{
|
675
|
$responses=array();
|
676
|
Unset($this->result_code);
|
677
|
while(strlen($line=$this->GetLine($this->connection)))
|
678
|
{
|
679
|
if(IsSet($this->result_code))
|
680
|
{
|
681
|
if(strcmp($this->Tokenize($line," -"),$this->result_code))
|
682
|
{
|
683
|
$this->error=$line;
|
684
|
return(0);
|
685
|
}
|
686
|
}
|
687
|
else
|
688
|
{
|
689
|
$this->result_code=$this->Tokenize($line," -");
|
690
|
if(GetType($code)=="array")
|
691
|
{
|
692
|
for($codes=0;$codes<count($code) && strcmp($this->result_code,$code[$codes]);$codes++);
|
693
|
if($codes>=count($code))
|
694
|
{
|
695
|
$this->error=$line;
|
696
|
return(0);
|
697
|
}
|
698
|
}
|
699
|
else
|
700
|
{
|
701
|
if(strcmp($this->result_code,$code))
|
702
|
{
|
703
|
$this->error=$line;
|
704
|
return(0);
|
705
|
}
|
706
|
}
|
707
|
}
|
708
|
$responses[]=$this->Tokenize("");
|
709
|
if(!strcmp($this->result_code,$this->Tokenize($line," ")))
|
710
|
return(1);
|
711
|
}
|
712
|
return(-1);
|
713
|
}
|
714
|
|
715
|
Function FlushRecipients()
|
716
|
{
|
717
|
if($this->pending_sender)
|
718
|
{
|
719
|
if($this->VerifyResultLines("250",$responses)<=0)
|
720
|
return(0);
|
721
|
$this->pending_sender=0;
|
722
|
}
|
723
|
for(;$this->pending_recipients;$this->pending_recipients--)
|
724
|
{
|
725
|
if($this->VerifyResultLines(array("250","251"),$responses)<=0)
|
726
|
return(0);
|
727
|
}
|
728
|
return(1);
|
729
|
}
|
730
|
|
731
|
Function Resolve($domain, &$ip, $server_type)
|
732
|
{
|
733
|
if(preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/',$domain))
|
734
|
$ip=$domain;
|
735
|
else
|
736
|
{
|
737
|
if($this->debug)
|
738
|
$this->OutputDebug('Resolving '.$server_type.' server domain "'.$domain.'"...');
|
739
|
if(!strcmp($ip=@gethostbyname($domain),$domain))
|
740
|
$ip="";
|
741
|
}
|
742
|
if(strlen($ip)==0
|
743
|
|| (strlen($this->exclude_address)
|
744
|
&& !strcmp(@gethostbyname($this->exclude_address),$ip)))
|
745
|
return($this->SetError("could not resolve the host domain \"".$domain."\""));
|
746
|
return('');
|
747
|
}
|
748
|
|
749
|
Function ConnectToHost($domain, $port, $resolve_message)
|
750
|
{
|
751
|
if($this->ssl)
|
752
|
{
|
753
|
$version=explode(".",function_exists("phpversion") ? phpversion() : "3.0.7");
|
754
|
$php_version=intval($version[0])*1000000+intval($version[1])*1000+intval($version[2]);
|
755
|
if($php_version<4003000)
|
756
|
return("establishing SSL connections requires at least PHP version 4.3.0");
|
757
|
if(!function_exists("extension_loaded")
|
758
|
|| !extension_loaded("openssl"))
|
759
|
return("establishing SSL connections requires the OpenSSL extension enabled");
|
760
|
}
|
761
|
if(strlen($this->Resolve($domain, $ip, 'SMTP')))
|
762
|
return($this->error);
|
763
|
if(strlen($this->socks_host_name))
|
764
|
{
|
765
|
switch($this->socks_version)
|
766
|
{
|
767
|
case '4':
|
768
|
$version = 4;
|
769
|
break;
|
770
|
case '5':
|
771
|
$version = 5;
|
772
|
break;
|
773
|
default:
|
774
|
return('it was not specified a supported SOCKS protocol version');
|
775
|
break;
|
776
|
}
|
777
|
$host_ip = $ip;
|
778
|
$host_port = $port;
|
779
|
if(strlen($this->error = $this->Resolve($this->socks_host_name, $ip, 'SOCKS')))
|
780
|
return($this->error);
|
781
|
if($this->ssl)
|
782
|
$ip="ssl://".($socks_host = $this->socks_host_name);
|
783
|
else
|
784
|
$socks_host = $ip;
|
785
|
if($this->debug)
|
786
|
$this->OutputDebug("Connecting to SOCKS server \"".$socks_host."\" port ".$this->http_proxy_host_port."...");
|
787
|
if(($this->connection=($this->timeout ? fsockopen($ip, $this->socks_host_port, $errno, $error, $this->timeout) : fsockopen($ip, $this->socks_host_port, $errno, $error))))
|
788
|
{
|
789
|
$timeout=($this->data_timeout ? $this->data_timeout : $this->timeout);
|
790
|
if($timeout
|
791
|
&& function_exists("socket_set_timeout"))
|
792
|
socket_set_timeout($this->connection,$timeout,0);
|
793
|
if(strlen($this->socks_host_name))
|
794
|
{
|
795
|
if($this->debug)
|
796
|
$this->OutputDebug('Connected to the SOCKS server '.$this->socks_host_name);
|
797
|
$send_error = 'it was not possible to send data to the SOCKS server';
|
798
|
$receive_error = 'it was not possible to receive data from the SOCKS server';
|
799
|
switch($version)
|
800
|
{
|
801
|
case 4:
|
802
|
$command = 1;
|
803
|
$user = '';
|
804
|
if(!fputs($this->connection, chr($version).chr($command).pack('nN', $host_port, ip2long($host_ip)).$user.Chr(0)))
|
805
|
$error = $this->SetDataAccessError($send_error);
|
806
|
else
|
807
|
{
|
808
|
$response = fgets($this->connection, 9);
|
809
|
if(strlen($response) != 8)
|
810
|
$error = $this->SetDataAccessError($receive_error);
|
811
|
else
|
812
|
{
|
813
|
$socks_errors = array(
|
814
|
"\x5a"=>'',
|
815
|
"\x5b"=>'request rejected',
|
816
|
"\x5c"=>'request failed because client is not running identd (or not reachable from the server)',
|
817
|
"\x5d"=>'request failed because client\'s identd could not confirm the user ID string in the request',
|
818
|
);
|
819
|
$error_code = $response[1];
|
820
|
$error = (IsSet($socks_errors[$error_code]) ? $socks_errors[$error_code] : 'unknown');
|
821
|
if(strlen($error))
|
822
|
$error = 'SOCKS error: '.$error;
|
823
|
}
|
824
|
}
|
825
|
break;
|
826
|
case 5:
|
827
|
if($this->debug)
|
828
|
$this->OutputDebug('Negotiating the authentication method ...');
|
829
|
$methods = 1;
|
830
|
$method = 0;
|
831
|
if(!fputs($this->connection, chr($version).chr($methods).chr($method)))
|
832
|
$error = $this->SetDataAccessError($send_error);
|
833
|
else
|
834
|
{
|
835
|
$response = fgets($this->connection, 3);
|
836
|
if(strlen($response) != 2)
|
837
|
$error = $this->SetDataAccessError($receive_error);
|
838
|
elseif(Ord($response[1]) != $method)
|
839
|
$error = 'the SOCKS server requires an authentication method that is not yet supported';
|
840
|
else
|
841
|
{
|
842
|
if($this->debug)
|
843
|
$this->OutputDebug('Connecting to SMTP server IP '.$host_ip.' port '.$host_port.'...');
|
844
|
$command = 1;
|
845
|
$address_type = 1;
|
846
|
if(!fputs($this->connection, chr($version).chr($command)."\x00".chr($address_type).pack('Nn', ip2long($host_ip), $host_port)))
|
847
|
$error = $this->SetDataAccessError($send_error);
|
848
|
else
|
849
|
{
|
850
|
$response = fgets($this->connection, 11);
|
851
|
if(strlen($response) != 10)
|
852
|
$error = $this->SetDataAccessError($receive_error);
|
853
|
else
|
854
|
{
|
855
|
$socks_errors = array(
|
856
|
"\x00"=>'',
|
857
|
"\x01"=>'general SOCKS server failure',
|
858
|
"\x02"=>'connection not allowed by ruleset',
|
859
|
"\x03"=>'Network unreachable',
|
860
|
"\x04"=>'Host unreachable',
|
861
|
"\x05"=>'Connection refused',
|
862
|
"\x06"=>'TTL expired',
|
863
|
"\x07"=>'Command not supported',
|
864
|
"\x08"=>'Address type not supported'
|
865
|
);
|
866
|
$error_code = $response[1];
|
867
|
$error = (IsSet($socks_errors[$error_code]) ? $socks_errors[$error_code] : 'unknown');
|
868
|
if(strlen($error))
|
869
|
$error = 'SOCKS error: '.$error;
|
870
|
}
|
871
|
}
|
872
|
}
|
873
|
}
|
874
|
break;
|
875
|
default:
|
876
|
$error = 'support for SOCKS protocol version '.$this->socks_version.' is not yet implemented';
|
877
|
break;
|
878
|
}
|
879
|
if(strlen($this->error = $error))
|
880
|
{
|
881
|
fclose($this->connection);
|
882
|
return($error);
|
883
|
}
|
884
|
}
|
885
|
return('');
|
886
|
}
|
887
|
}
|
888
|
elseif(strlen($this->http_proxy_host_name))
|
889
|
{
|
890
|
if(strlen($error = $this->Resolve($this->http_proxy_host_name, $ip, 'SMTP')))
|
891
|
return($error);
|
892
|
if($this->ssl)
|
893
|
$ip = 'ssl://'.($proxy_host = $this->http_proxy_host_name);
|
894
|
else
|
895
|
$proxy_host = $ip;
|
896
|
if($this->debug)
|
897
|
$this->OutputDebug("Connecting to HTTP proxy server \"".$ip."\" port ".$this->http_proxy_host_port."...");
|
898
|
if(($this->connection=($this->timeout ? @fsockopen($ip, $this->http_proxy_host_port, $errno, $error, $this->timeout) : @fsockopen($ip, $this->http_proxy_host_port, $errno, $error))))
|
899
|
{
|
900
|
if($this->debug)
|
901
|
$this->OutputDebug('Connected to HTTP proxy host "'.$this->http_proxy_host_name.'".');
|
902
|
$timeout=($this->data_timeout ? $this->data_timeout : $this->timeout);
|
903
|
if($timeout
|
904
|
&& function_exists("socket_set_timeout"))
|
905
|
socket_set_timeout($this->connection,$timeout,0);
|
906
|
if($this->PutLine('CONNECT '.$domain.':'.$port.' HTTP/1.0')
|
907
|
&& $this->PutLine('User-Agent: '.$this->user_agent)
|
908
|
&& $this->PutLine(''))
|
909
|
{
|
910
|
if(GetType($response = $this->GetLine()) == 'string')
|
911
|
{
|
912
|
if(!preg_match('/^http\\/[0-9]+\\.[0-9]+[ \t]+([0-9]+)[ \t]*(.*)$/i', $response,$matches))
|
913
|
return($this->SetError("3 it was received an unexpected HTTP response status"));
|
914
|
$error = $matches[1];
|
915
|
switch($error)
|
916
|
{
|
917
|
case '200':
|
918
|
for(;;)
|
919
|
{
|
920
|
if(GetType($response = $this->GetLine()) != 'string')
|
921
|
break;
|
922
|
if(strlen($response) == 0)
|
923
|
return('');
|
924
|
}
|
925
|
break;
|
926
|
default:
|
927
|
$this->error = 'the HTTP proxy returned error '.$error.' '.$matches[2];
|
928
|
break;
|
929
|
}
|
930
|
}
|
931
|
}
|
932
|
if($this->debug)
|
933
|
$this->OutputDebug("Disconnected.");
|
934
|
fclose($this->connection);
|
935
|
$this->connection = 0;
|
936
|
return($this->error);
|
937
|
}
|
938
|
}
|
939
|
else
|
940
|
{
|
941
|
if($this->ssl)
|
942
|
$ip = 'ssl://'.($host = $domain);
|
943
|
elseif($this->start_tls)
|
944
|
$ip = $host = $domain;
|
945
|
else
|
946
|
$host = $ip;
|
947
|
if($this->debug)
|
948
|
$this->OutputDebug("Connecting to SMTP server \"".$host."\" port ".$port."...");
|
949
|
if(($this->connection=($this->timeout ? @fsockopen($ip, $port, $errno, $error, $this->timeout) : @fsockopen($ip, $port, $errno, $error))))
|
950
|
return("");
|
951
|
}
|
952
|
$error=($this->timeout ? strval($error) : "??");
|
953
|
switch($error)
|
954
|
{
|
955
|
case "-3":
|
956
|
return("-3 socket could not be created");
|
957
|
case "-4":
|
958
|
return("-4 dns lookup on hostname \"".$domain."\" failed");
|
959
|
case "-5":
|
960
|
return("-5 connection refused or timed out");
|
961
|
case "-6":
|
962
|
return("-6 fdopen() call failed");
|
963
|
case "-7":
|
964
|
return("-7 setvbuf() call failed");
|
965
|
}
|
966
|
return("could not connect to the host \"".$domain."\": ".$error);
|
967
|
}
|
968
|
|
969
|
Function SASLAuthenticate($mechanisms, $credentials, &$authenticated, &$mechanism)
|
970
|
{
|
971
|
$authenticated=0;
|
972
|
if(!function_exists("class_exists")
|
973
|
|| !class_exists("sasl_client_class"))
|
974
|
{
|
975
|
$this->error="it is not possible to authenticate using the specified mechanism because the SASL library class is not loaded";
|
976
|
return(0);
|
977
|
}
|
978
|
$sasl=new sasl_client_class;
|
979
|
$sasl->SetCredential("user",$credentials["user"]);
|
980
|
$sasl->SetCredential("password",$credentials["password"]);
|
981
|
if(IsSet($credentials["realm"]))
|
982
|
$sasl->SetCredential("realm",$credentials["realm"]);
|
983
|
if(IsSet($credentials["workstation"]))
|
984
|
$sasl->SetCredential("workstation",$credentials["workstation"]);
|
985
|
if(IsSet($credentials["mode"]))
|
986
|
$sasl->SetCredential("mode",$credentials["mode"]);
|
987
|
do
|
988
|
{
|
989
|
$status=$sasl->Start($mechanisms,$message,$interactions);
|
990
|
}
|
991
|
while($status==SASL_INTERACT);
|
992
|
switch($status)
|
993
|
{
|
994
|
case SASL_CONTINUE:
|
995
|
break;
|
996
|
case SASL_NOMECH:
|
997
|
if(strlen($this->authentication_mechanism))
|
998
|
{
|
999
|
$this->error="authenticated mechanism ".$this->authentication_mechanism." may not be used: ".$sasl->error;
|
1000
|
return(0);
|
1001
|
}
|
1002
|
break;
|
1003
|
default:
|
1004
|
$this->error="Could not start the SASL authentication client: ".$sasl->error;
|
1005
|
return(0);
|
1006
|
}
|
1007
|
if(strlen($mechanism=$sasl->mechanism))
|
1008
|
{
|
1009
|
if($this->PutLine("AUTH ".$sasl->mechanism.(IsSet($message) ? " ".base64_encode($message) : ""))==0)
|
1010
|
{
|
1011
|
$this->error="Could not send the AUTH command";
|
1012
|
return(0);
|
1013
|
}
|
1014
|
if(!$this->VerifyResultLines(array("235","334"),$responses))
|
1015
|
return(0);
|
1016
|
switch($this->result_code)
|
1017
|
{
|
1018
|
case "235":
|
1019
|
$response="";
|
1020
|
$authenticated=1;
|
1021
|
break;
|
1022
|
case "334":
|
1023
|
$response=base64_decode($responses[0]);
|
1024
|
break;
|
1025
|
default:
|
1026
|
$this->error="Authentication error: ".$responses[0];
|
1027
|
return(0);
|
1028
|
}
|
1029
|
for(;!$authenticated;)
|
1030
|
{
|
1031
|
do
|
1032
|
{
|
1033
|
$status=$sasl->Step($response,$message,$interactions);
|
1034
|
}
|
1035
|
while($status==SASL_INTERACT);
|
1036
|
switch($status)
|
1037
|
{
|
1038
|
case SASL_CONTINUE:
|
1039
|
if($this->PutLine(base64_encode($message))==0)
|
1040
|
{
|
1041
|
$this->error="Could not send the authentication step message";
|
1042
|
return(0);
|
1043
|
}
|
1044
|
if(!$this->VerifyResultLines(array("235","334"),$responses))
|
1045
|
return(0);
|
1046
|
switch($this->result_code)
|
1047
|
{
|
1048
|
case "235":
|
1049
|
$response="";
|
1050
|
$authenticated=1;
|
1051
|
break;
|
1052
|
case "334":
|
1053
|
$response=base64_decode($responses[0]);
|
1054
|
break;
|
1055
|
default:
|
1056
|
$this->error="Authentication error: ".$responses[0];
|
1057
|
return(0);
|
1058
|
}
|
1059
|
break;
|
1060
|
default:
|
1061
|
$this->error="Could not process the SASL authentication step: ".$sasl->error;
|
1062
|
return(0);
|
1063
|
}
|
1064
|
}
|
1065
|
}
|
1066
|
return(1);
|
1067
|
}
|
1068
|
|
1069
|
Function StartSMTP($localhost)
|
1070
|
{
|
1071
|
$success = 1;
|
1072
|
$this->esmtp_extensions = array();
|
1073
|
$fallback=1;
|
1074
|
if($this->esmtp
|
1075
|
|| strlen($this->user))
|
1076
|
{
|
1077
|
if($this->PutLine('EHLO '.$localhost))
|
1078
|
{
|
1079
|
if(($success_code=$this->VerifyResultLines('250',$responses))>0)
|
1080
|
{
|
1081
|
$this->esmtp_host=$this->Tokenize($responses[0]," ");
|
1082
|
for($response=1;$response<count($responses);$response++)
|
1083
|
{
|
1084
|
$extension=strtoupper($this->Tokenize($responses[$response]," "));
|
1085
|
$this->esmtp_extensions[$extension]=$this->Tokenize("");
|
1086
|
}
|
1087
|
$success=1;
|
1088
|
$fallback=0;
|
1089
|
}
|
1090
|
else
|
1091
|
{
|
1092
|
if($success_code==0)
|
1093
|
{
|
1094
|
$code=$this->Tokenize($this->error," -");
|
1095
|
switch($code)
|
1096
|
{
|
1097
|
case "421":
|
1098
|
$fallback=0;
|
1099
|
break;
|
1100
|
}
|
1101
|
}
|
1102
|
}
|
1103
|
}
|
1104
|
else
|
1105
|
$fallback=0;
|
1106
|
}
|
1107
|
if($fallback)
|
1108
|
{
|
1109
|
if($this->PutLine("HELO $localhost")
|
1110
|
&& $this->VerifyResultLines("250",$responses)>0)
|
1111
|
$success=1;
|
1112
|
}
|
1113
|
return($success);
|
1114
|
}
|
1115
|
|
1116
|
/* Public methods */
|
1117
|
|
1118
|
/*
|
1119
|
{metadocument}
|
1120
|
<function>
|
1121
|
<name>Connect</name>
|
1122
|
<type>BOOLEAN</type>
|
1123
|
<documentation>
|
1124
|
<purpose>Connect to an SMTP server.</purpose>
|
1125
|
<usage>Call this function as first step to send e-mail messages.</usage>
|
1126
|
<returnvalue>The function returns
|
1127
|
<tt><booleanvalue>1</booleanvalue></tt> if the connection is
|
1128
|
successfully established.</returnvalue>
|
1129
|
</documentation>
|
1130
|
<argument>
|
1131
|
<name>domain</name>
|
1132
|
<type>STRING</type>
|
1133
|
<defaultvalue></defaultvalue>
|
1134
|
<documentation>
|
1135
|
<purpose>Specify the domain of the recipient when using the direct
|
1136
|
delivery mode.</purpose>
|
1137
|
</documentation>
|
1138
|
</argument>
|
1139
|
<do>
|
1140
|
{/metadocument}
|
1141
|
*/
|
1142
|
Function Connect($domain="")
|
1143
|
{
|
1144
|
if(strcmp($this->state,"Disconnected"))
|
1145
|
{
|
1146
|
$this->error="connection is already established";
|
1147
|
return(0);
|
1148
|
}
|
1149
|
$this->disconnected_error=0;
|
1150
|
$this->error=$error="";
|
1151
|
$this->esmtp_host="";
|
1152
|
$this->esmtp_extensions=array();
|
1153
|
$hosts=array();
|
1154
|
if($this->direct_delivery)
|
1155
|
{
|
1156
|
if(strlen($domain)==0)
|
1157
|
return(1);
|
1158
|
$hosts=$weights=$mxhosts=array();
|
1159
|
$getmxrr=$this->getmxrr;
|
1160
|
if(function_exists($getmxrr)
|
1161
|
&& $getmxrr($domain,$hosts,$weights))
|
1162
|
{
|
1163
|
for($host=0;$host<count($hosts);$host++)
|
1164
|
$mxhosts[$weights[$host]]=$hosts[$host];
|
1165
|
KSort($mxhosts);
|
1166
|
for(Reset($mxhosts),$host=0;$host<count($mxhosts);Next($mxhosts),$host++)
|
1167
|
$hosts[$host]=$mxhosts[Key($mxhosts)];
|
1168
|
}
|
1169
|
else
|
1170
|
{
|
1171
|
if(strcmp(@gethostbyname($domain),$domain)!=0)
|
1172
|
$hosts[]=$domain;
|
1173
|
}
|
1174
|
}
|
1175
|
else
|
1176
|
{
|
1177
|
if(strlen($this->host_name))
|
1178
|
$hosts[]=$this->host_name;
|
1179
|
if(strlen($this->pop3_auth_host))
|
1180
|
{
|
1181
|
$user=$this->user;
|
1182
|
if(strlen($user)==0)
|
1183
|
{
|
1184
|
$this->error="it was not specified the POP3 authentication user";
|
1185
|
return(0);
|
1186
|
}
|
1187
|
$password=$this->password;
|
1188
|
if(strlen($password)==0)
|
1189
|
{
|
1190
|
$this->error="it was not specified the POP3 authentication password";
|
1191
|
return(0);
|
1192
|
}
|
1193
|
$domain=$this->pop3_auth_host;
|
1194
|
$this->error=$this->ConnectToHost($domain, $this->pop3_auth_port, "Resolving POP3 authentication host \"".$domain."\"...");
|
1195
|
if(strlen($this->error))
|
1196
|
return(0);
|
1197
|
if(strlen($response=$this->GetLine())==0)
|
1198
|
return(0);
|
1199
|
if(strcmp($this->Tokenize($response," "),"+OK"))
|
1200
|
{
|
1201
|
$this->error="POP3 authentication server greeting was not found";
|
1202
|
return(0);
|
1203
|
}
|
1204
|
if(!$this->PutLine("USER ".$this->user)
|
1205
|
|| strlen($response=$this->GetLine())==0)
|
1206
|
return(0);
|
1207
|
if(strcmp($this->Tokenize($response," "),"+OK"))
|
1208
|
{
|
1209
|
$this->error="POP3 authentication user was not accepted: ".$this->Tokenize("\r\n");
|
1210
|
return(0);
|
1211
|
}
|
1212
|
if(!$this->PutLine("PASS ".$password)
|
1213
|
|| strlen($response=$this->GetLine())==0)
|
1214
|
return(0);
|
1215
|
if(strcmp($this->Tokenize($response," "),"+OK"))
|
1216
|
{
|
1217
|
$this->error="POP3 authentication password was not accepted: ".$this->Tokenize("\r\n");
|
1218
|
return(0);
|
1219
|
}
|
1220
|
fclose($this->connection);
|
1221
|
$this->connection=0;
|
1222
|
}
|
1223
|
}
|
1224
|
if(count($hosts)==0)
|
1225
|
{
|
1226
|
$this->error="could not determine the SMTP to connect";
|
1227
|
return(0);
|
1228
|
}
|
1229
|
for($host=0, $error="not connected";strlen($error) && $host<count($hosts);$host++)
|
1230
|
{
|
1231
|
$domain=$hosts[$host];
|
1232
|
$error=$this->ConnectToHost($domain, $this->host_port, "Resolving SMTP server domain \"$domain\"...");
|
1233
|
}
|
1234
|
if(strlen($error))
|
1235
|
{
|
1236
|
$this->error=$error;
|
1237
|
return(0);
|
1238
|
}
|
1239
|
$timeout=($this->data_timeout ? $this->data_timeout : $this->timeout);
|
1240
|
if($timeout
|
1241
|
&& function_exists("socket_set_timeout"))
|
1242
|
socket_set_timeout($this->connection,$timeout,0);
|
1243
|
if($this->debug)
|
1244
|
$this->OutputDebug("Connected to SMTP server \"".$domain."\".");
|
1245
|
if(!strcmp($localhost=$this->localhost,"")
|
1246
|
&& !strcmp($localhost=getenv("HTTP_HOST"),"")
|
1247
|
&& !strcmp($localhost=getenv("HOST"),""))
|
1248
|
$localhost="localhost";
|
1249
|
$success=0;
|
1250
|
if($this->VerifyResultLines("220",$responses)>0)
|
1251
|
{
|
1252
|
$success = $this->StartSMTP($localhost);
|
1253
|
if($this->start_tls)
|
1254
|
{
|
1255
|
if(!IsSet($this->esmtp_extensions["STARTTLS"]))
|
1256
|
{
|
1257
|
$this->error="server does not support starting TLS";
|
1258
|
$success=0;
|
1259
|
}
|
1260
|
elseif(!function_exists('stream_socket_enable_crypto'))
|
1261
|
{
|
1262
|
$this->error="this PHP installation or version does not support starting TLS";
|
1263
|
$success=0;
|
1264
|
}
|
1265
|
elseif($success = ($this->PutLine('STARTTLS')
|
1266
|
&& $this->VerifyResultLines('220',$responses)>0))
|
1267
|
{
|
1268
|
if($this->debug)
|
1269
|
$this->OutputDebug('Starting TLS cryptograpic protocol');
|
1270
|
if(!($success = @stream_socket_enable_crypto($this->connection, 1, STREAM_CRYPTO_METHOD_TLS_CLIENT)))
|
1271
|
$this->error = 'could not start TLS connection encryption protocol';
|
1272
|
else
|
1273
|
{
|
1274
|
if($this->debug)
|
1275
|
$this->OutputDebug('TLS started');
|
1276
|
$success = $this->StartSMTP($localhost);
|
1277
|
}
|
1278
|
}
|
1279
|
}
|
1280
|
if($success
|
1281
|
&& strlen($this->user)
|
1282
|
&& strlen($this->pop3_auth_host)==0)
|
1283
|
{
|
1284
|
if(!IsSet($this->esmtp_extensions["AUTH"]))
|
1285
|
{
|
1286
|
$this->error="server does not require authentication";
|
1287
|
if(IsSet($this->esmtp_extensions["STARTTLS"]))
|
1288
|
$this->error .= ', it probably requires starting TLS';
|
1289
|
$success=0;
|
1290
|
}
|
1291
|
else
|
1292
|
{
|
1293
|
if(strlen($this->authentication_mechanism))
|
1294
|
$mechanisms=array($this->authentication_mechanism);
|
1295
|
else
|
1296
|
{
|
1297
|
$mechanisms=array();
|
1298
|
for($authentication=$this->Tokenize($this->esmtp_extensions["AUTH"]," ");strlen($authentication);$authentication=$this->Tokenize(" "))
|
1299
|
$mechanisms[]=$authentication;
|
1300
|
}
|
1301
|
$credentials=array(
|
1302
|
"user"=>$this->user,
|
1303
|
"password"=>$this->password
|
1304
|
);
|
1305
|
if(strlen($this->realm))
|
1306
|
$credentials["realm"]=$this->realm;
|
1307
|
if(strlen($this->workstation))
|
1308
|
$credentials["workstation"]=$this->workstation;
|
1309
|
$success=$this->SASLAuthenticate($mechanisms,$credentials,$authenticated,$mechanism);
|
1310
|
if(!$success
|
1311
|
&& !strcmp($mechanism,"PLAIN"))
|
1312
|
{
|
1313
|
/*
|
1314
|
* Author: Russell Robinson, 25 May 2003, http://www.tectite.com/
|
1315
|
* Purpose: Try various AUTH PLAIN authentication methods.
|
1316
|
*/
|
1317
|
$mechanisms=array("PLAIN");
|
1318
|
$credentials=array(
|
1319
|
"user"=>$this->user,
|
1320
|
"password"=>$this->password
|
1321
|
);
|
1322
|
if(strlen($this->realm))
|
1323
|
{
|
1324
|
/*
|
1325
|
* According to: http://www.sendmail.org/~ca/email/authrealms.html#authpwcheck_method
|
1326
|
* some sendmails won't accept the realm, so try again without it
|
1327
|
*/
|
1328
|
$success=$this->SASLAuthenticate($mechanisms,$credentials,$authenticated,$mechanism);
|
1329
|
}
|
1330
|
if(!$success)
|
1331
|
{
|
1332
|
/*
|
1333
|
* It was seen an EXIM configuration like this:
|
1334
|
* user^password^unused
|
1335
|
*/
|
1336
|
$credentials["mode"]=SASL_PLAIN_EXIM_DOCUMENTATION_MODE;
|
1337
|
$success=$this->SASLAuthenticate($mechanisms,$credentials,$authenticated,$mechanism);
|
1338
|
}
|
1339
|
if(!$success)
|
1340
|
{
|
1341
|
/*
|
1342
|
* ... though: http://exim.work.de/exim-html-3.20/doc/html/spec_36.html
|
1343
|
* specifies: ^user^password
|
1344
|
*/
|
1345
|
$credentials["mode"]=SASL_PLAIN_EXIM_MODE;
|
1346
|
$success=$this->SASLAuthenticate($mechanisms,$credentials,$authenticated,$mechanism);
|
1347
|
}
|
1348
|
}
|
1349
|
if($success
|
1350
|
&& strlen($mechanism)==0)
|
1351
|
{
|
1352
|
$this->error="it is not supported any of the authentication mechanisms required by the server";
|
1353
|
$success=0;
|
1354
|
}
|
1355
|
}
|
1356
|
}
|
1357
|
}
|
1358
|
if($success)
|
1359
|
{
|
1360
|
$this->state="Connected";
|
1361
|
$this->connected_domain=$domain;
|
1362
|
}
|
1363
|
else
|
1364
|
{
|
1365
|
fclose($this->connection);
|
1366
|
$this->connection=0;
|
1367
|
}
|
1368
|
return($success);
|
1369
|
}
|
1370
|
/*
|
1371
|
{metadocument}
|
1372
|
</do>
|
1373
|
</function>
|
1374
|
{/metadocument}
|
1375
|
*/
|
1376
|
|
1377
|
/*
|
1378
|
{metadocument}
|
1379
|
<function>
|
1380
|
<name>MailFrom</name>
|
1381
|
<type>BOOLEAN</type>
|
1382
|
<documentation>
|
1383
|
<purpose>Set the address of the message sender.</purpose>
|
1384
|
<usage>Call this function right after establishing a connection with
|
1385
|
the <functionlink>Connect</functionlink> function.</usage>
|
1386
|
<returnvalue>The function returns
|
1387
|
<tt><booleanvalue>1</booleanvalue></tt> if the sender address is
|
1388
|
successfully set.</returnvalue>
|
1389
|
</documentation>
|
1390
|
<argument>
|
1391
|
<name>sender</name>
|
1392
|
<type>STRING</type>
|
1393
|
<documentation>
|
1394
|
<purpose>E-mail address of the sender.</purpose>
|
1395
|
</documentation>
|
1396
|
</argument>
|
1397
|
<do>
|
1398
|
{/metadocument}
|
1399
|
*/
|
1400
|
Function MailFrom($sender)
|
1401
|
{
|
1402
|
if($this->direct_delivery)
|
1403
|
{
|
1404
|
switch($this->state)
|
1405
|
{
|
1406
|
case "Disconnected":
|
1407
|
$this->direct_sender=$sender;
|
1408
|
return(1);
|
1409
|
case "Connected":
|
1410
|
$sender=$this->direct_sender;
|
1411
|
break;
|
1412
|
default:
|
1413
|
$this->error="direct delivery connection is already established and sender is already set";
|
1414
|
return(0);
|
1415
|
}
|
1416
|
}
|
1417
|
else
|
1418
|
{
|
1419
|
if(strcmp($this->state,"Connected"))
|
1420
|
{
|
1421
|
$this->error="connection is not in the initial state";
|
1422
|
return(0);
|
1423
|
}
|
1424
|
}
|
1425
|
$this->error="";
|
1426
|
if(!$this->PutLine("MAIL FROM:<$sender>"))
|
1427
|
return(0);
|
1428
|
if(!IsSet($this->esmtp_extensions["PIPELINING"])
|
1429
|
&& $this->VerifyResultLines("250",$responses)<=0)
|
1430
|
return(0);
|
1431
|
$this->state="SenderSet";
|
1432
|
if(IsSet($this->esmtp_extensions["PIPELINING"]))
|
1433
|
$this->pending_sender=1;
|
1434
|
$this->pending_recipients=0;
|
1435
|
return(1);
|
1436
|
}
|
1437
|
/*
|
1438
|
{metadocument}
|
1439
|
</do>
|
1440
|
</function>
|
1441
|
{/metadocument}
|
1442
|
*/
|
1443
|
|
1444
|
/*
|
1445
|
{metadocument}
|
1446
|
<function>
|
1447
|
<name>SetRecipient</name>
|
1448
|
<type>BOOLEAN</type>
|
1449
|
<documentation>
|
1450
|
<purpose>Set the address of a message recipient.</purpose>
|
1451
|
<usage>Call this function repeatedly for each recipient right after
|
1452
|
setting the message sender with the
|
1453
|
<functionlink>MailFrom</functionlink> function.</usage>
|
1454
|
<returnvalue>The function returns
|
1455
|
<tt><booleanvalue>1</booleanvalue></tt> if the recipient address is
|
1456
|
successfully set.</returnvalue>
|
1457
|
</documentation>
|
1458
|
<argument>
|
1459
|
<name>recipient</name>
|
1460
|
<type>STRING</type>
|
1461
|
<documentation>
|
1462
|
<purpose>E-mail address of a recipient.</purpose>
|
1463
|
</documentation>
|
1464
|
</argument>
|
1465
|
<do>
|
1466
|
{/metadocument}
|
1467
|
*/
|
1468
|
Function SetRecipient($recipient)
|
1469
|
{
|
1470
|
if($this->direct_delivery)
|
1471
|
{
|
1472
|
if(GetType($at=strrpos($recipient,"@"))!="integer")
|
1473
|
return("it was not specified a valid direct recipient");
|
1474
|
$domain=substr($recipient,$at+1);
|
1475
|
switch($this->state)
|
1476
|
{
|
1477
|
case "Disconnected":
|
1478
|
if(!$this->Connect($domain))
|
1479
|
return(0);
|
1480
|
if(!$this->MailFrom(""))
|
1481
|
{
|
1482
|
$error=$this->error;
|
1483
|
$this->Disconnect();
|
1484
|
$this->error=$error;
|
1485
|
return(0);
|
1486
|
}
|
1487
|
break;
|
1488
|
case "SenderSet":
|
1489
|
case "RecipientSet":
|
1490
|
if(strcmp($this->connected_domain,$domain))
|
1491
|
{
|
1492
|
$this->error="it is not possible to deliver directly to recipients of different domains";
|
1493
|
return(0);
|
1494
|
}
|
1495
|
break;
|
1496
|
default:
|
1497
|
$this->error="connection is already established and the recipient is already set";
|
1498
|
return(0);
|
1499
|
}
|
1500
|
}
|
1501
|
else
|
1502
|
{
|
1503
|
switch($this->state)
|
1504
|
{
|
1505
|
case "SenderSet":
|
1506
|
case "RecipientSet":
|
1507
|
break;
|
1508
|
default:
|
1509
|
$this->error="connection is not in the recipient setting state";
|
1510
|
return(0);
|
1511
|
}
|
1512
|
}
|
1513
|
$this->error="";
|
1514
|
if(!$this->PutLine("RCPT TO:<$recipient>"))
|
1515
|
return(0);
|
1516
|
if(IsSet($this->esmtp_extensions["PIPELINING"]))
|
1517
|
{
|
1518
|
$this->pending_recipients++;
|
1519
|
if($this->pending_recipients>=$this->maximum_piped_recipients)
|
1520
|
{
|
1521
|
if(!$this->FlushRecipients())
|
1522
|
return(0);
|
1523
|
}
|
1524
|
}
|
1525
|
else
|
1526
|
{
|
1527
|
if($this->VerifyResultLines(array("250","251"),$responses)<=0)
|
1528
|
return(0);
|
1529
|
}
|
1530
|
$this->state="RecipientSet";
|
1531
|
return(1);
|
1532
|
}
|
1533
|
/*
|
1534
|
{metadocument}
|
1535
|
</do>
|
1536
|
</function>
|
1537
|
{/metadocument}
|
1538
|
*/
|
1539
|
|
1540
|
/*
|
1541
|
{metadocument}
|
1542
|
<function>
|
1543
|
<name>StartData</name>
|
1544
|
<type>BOOLEAN</type>
|
1545
|
<documentation>
|
1546
|
<purpose>Tell the SMTP server that the message data will start being
|
1547
|
sent.</purpose>
|
1548
|
<usage>Call this function right after you are done setting all the
|
1549
|
message recipients with the
|
1550
|
<functionlink>SetRecipient</functionlink> function.</usage>
|
1551
|
<returnvalue>The function returns
|
1552
|
<tt><booleanvalue>1</booleanvalue></tt> if the server is ready to
|
1553
|
start receiving the message data.</returnvalue>
|
1554
|
</documentation>
|
1555
|
<do>
|
1556
|
{/metadocument}
|
1557
|
*/
|
1558
|
Function StartData()
|
1559
|
{
|
1560
|
if(strcmp($this->state,"RecipientSet"))
|
1561
|
{
|
1562
|
$this->error="connection is not in the start sending data state";
|
1563
|
return(0);
|
1564
|
}
|
1565
|
$this->error="";
|
1566
|
if(!$this->PutLine("DATA"))
|
1567
|
return(0);
|
1568
|
if($this->pending_recipients)
|
1569
|
{
|
1570
|
if(!$this->FlushRecipients())
|
1571
|
return(0);
|
1572
|
}
|
1573
|
if($this->VerifyResultLines("354",$responses)<=0)
|
1574
|
return(0);
|
1575
|
$this->state="SendingData";
|
1576
|
return(1);
|
1577
|
}
|
1578
|
/*
|
1579
|
{metadocument}
|
1580
|
</do>
|
1581
|
</function>
|
1582
|
{/metadocument}
|
1583
|
*/
|
1584
|
|
1585
|
/*
|
1586
|
{metadocument}
|
1587
|
<function>
|
1588
|
<name>PrepareData</name>
|
1589
|
<type>STRING</type>
|
1590
|
<documentation>
|
1591
|
<purpose>Prepare message data to normalize line breaks and escaping
|
1592
|
lines that contain single dots.</purpose>
|
1593
|
<usage>Call this function if the message data you want to send may
|
1594
|
contain line breaks that are not the
|
1595
|
<stringvalue> </stringvalue> sequence or it may contain
|
1596
|
lines that just have a single dot.</usage>
|
1597
|
<returnvalue>Resulting normalized messages data.</returnvalue>
|
1598
|
</documentation>
|
1599
|
<argument>
|
1600
|
<name>data</name>
|
1601
|
<type>STRING</type>
|
1602
|
<documentation>
|
1603
|
<purpose>Message data to be prepared.</purpose>
|
1604
|
</documentation>
|
1605
|
</argument>
|
1606
|
<do>
|
1607
|
{/metadocument}
|
1608
|
*/
|
1609
|
Function PrepareData($data)
|
1610
|
{
|
1611
|
return(preg_replace(array("/\n\n|\r\r/","/(^|[^\r])\n/","/\r([^\n]|\$)/D","/(^|\n)\\./"),array("\r\n\r\n","\\1\r\n","\r\n\\1","\\1.."),$data));
|
1612
|
}
|
1613
|
/*
|
1614
|
{metadocument}
|
1615
|
</do>
|
1616
|
</function>
|
1617
|
{/metadocument}
|
1618
|
*/
|
1619
|
|
1620
|
/*
|
1621
|
{metadocument}
|
1622
|
<function>
|
1623
|
<name>SendData</name>
|
1624
|
<type>BOOLEAN</type>
|
1625
|
<documentation>
|
1626
|
<purpose>Send message data.</purpose>
|
1627
|
<usage>Call this function repeatedly for all message data blocks
|
1628
|
to be sent right after start sending message data with the
|
1629
|
<functionlink>StartData</functionlink> function.</usage>
|
1630
|
<returnvalue>The function returns
|
1631
|
<tt><booleanvalue>1</booleanvalue></tt> if the message data was
|
1632
|
sent to the SMTP server successfully.</returnvalue>
|
1633
|
</documentation>
|
1634
|
<argument>
|
1635
|
<name>data</name>
|
1636
|
<type>STRING</type>
|
1637
|
<documentation>
|
1638
|
<purpose>Message data to be sent.</purpose>
|
1639
|
</documentation>
|
1640
|
</argument>
|
1641
|
<do>
|
1642
|
{/metadocument}
|
1643
|
*/
|
1644
|
Function SendData($data)
|
1645
|
{
|
1646
|
if(strcmp($this->state,"SendingData"))
|
1647
|
{
|
1648
|
$this->error="connection is not in the sending data state";
|
1649
|
return(0);
|
1650
|
}
|
1651
|
$this->error="";
|
1652
|
return($this->PutData($data));
|
1653
|
}
|
1654
|
/*
|
1655
|
{metadocument}
|
1656
|
</do>
|
1657
|
</function>
|
1658
|
{/metadocument}
|
1659
|
*/
|
1660
|
|
1661
|
/*
|
1662
|
{metadocument}
|
1663
|
<function>
|
1664
|
<name>EndSendingData</name>
|
1665
|
<type>BOOLEAN</type>
|
1666
|
<documentation>
|
1667
|
<purpose>Tell the server that all the message data was sent.</purpose>
|
1668
|
<usage>Call this function when you are done with sending the message
|
1669
|
data with the <functionlink>SendData</functionlink> function.</usage>
|
1670
|
<returnvalue>The function returns
|
1671
|
<tt><booleanvalue>1</booleanvalue></tt> if the server accepted the
|
1672
|
message.</returnvalue>
|
1673
|
</documentation>
|
1674
|
<do>
|
1675
|
{/metadocument}
|
1676
|
*/
|
1677
|
Function EndSendingData()
|
1678
|
{
|
1679
|
if(strcmp($this->state,"SendingData"))
|
1680
|
{
|
1681
|
$this->error="connection is not in the sending data state";
|
1682
|
return(0);
|
1683
|
}
|
1684
|
$this->error="";
|
1685
|
if(!$this->PutLine("\r\n.")
|
1686
|
|| $this->VerifyResultLines("250",$responses)<=0)
|
1687
|
return(0);
|
1688
|
$this->state="Connected";
|
1689
|
return(1);
|
1690
|
}
|
1691
|
/*
|
1692
|
{metadocument}
|
1693
|
</do>
|
1694
|
</function>
|
1695
|
{/metadocument}
|
1696
|
*/
|
1697
|
|
1698
|
/*
|
1699
|
{metadocument}
|
1700
|
<function>
|
1701
|
<name>ResetConnection</name>
|
1702
|
<type>BOOLEAN</type>
|
1703
|
<documentation>
|
1704
|
<purpose>Reset an already established SMTP connection to the initial
|
1705
|
state.</purpose>
|
1706
|
<usage>Call this function when there was an error sending a message
|
1707
|
and you need to skip to sending another message without
|
1708
|
disconnecting.</usage>
|
1709
|
<returnvalue>The function returns
|
1710
|
<tt><booleanvalue>1</booleanvalue></tt> if the connection was
|
1711
|
resetted successfully.</returnvalue>
|
1712
|
</documentation>
|
1713
|
<do>
|
1714
|
{/metadocument}
|
1715
|
*/
|
1716
|
Function ResetConnection()
|
1717
|
{
|
1718
|
switch($this->state)
|
1719
|
{
|
1720
|
case "Connected":
|
1721
|
return(1);
|
1722
|
case "SendingData":
|
1723
|
$this->error="can not reset the connection while sending data";
|
1724
|
return(0);
|
1725
|
case "Disconnected":
|
1726
|
$this->error="can not reset the connection before it is established";
|
1727
|
return(0);
|
1728
|
}
|
1729
|
$this->error="";
|
1730
|
if(!$this->PutLine("RSET")
|
1731
|
|| $this->VerifyResultLines("250",$responses)<=0)
|
1732
|
return(0);
|
1733
|
$this->state="Connected";
|
1734
|
return(1);
|
1735
|
}
|
1736
|
/*
|
1737
|
{metadocument}
|
1738
|
</do>
|
1739
|
</function>
|
1740
|
{/metadocument}
|
1741
|
*/
|
1742
|
|
1743
|
/*
|
1744
|
{metadocument}
|
1745
|
<function>
|
1746
|
<name>Disconnect</name>
|
1747
|
<type>BOOLEAN</type>
|
1748
|
<documentation>
|
1749
|
<purpose>Terminate a previously opened connection.</purpose>
|
1750
|
<usage>Call this function after you are done sending your
|
1751
|
messages.</usage>
|
1752
|
<returnvalue>The function returns
|
1753
|
<tt><booleanvalue>1</booleanvalue></tt> if the connection was
|
1754
|
successfully closed.</returnvalue>
|
1755
|
</documentation>
|
1756
|
<argument>
|
1757
|
<name>quit</name>
|
1758
|
<type>BOOLEAN</type>
|
1759
|
<defaultvalue>1</defaultvalue>
|
1760
|
<documentation>
|
1761
|
<purpose>Boolean option that tells whether the class should
|
1762
|
perform the final connection quit handshake, or just close the
|
1763
|
connection without waiting.</purpose>
|
1764
|
</documentation>
|
1765
|
</argument>
|
1766
|
<do>
|
1767
|
{/metadocument}
|
1768
|
*/
|
1769
|
Function Disconnect($quit=1)
|
1770
|
{
|
1771
|
if(!strcmp($this->state,"Disconnected"))
|
1772
|
{
|
1773
|
$this->error="it was not previously established a SMTP connection";
|
1774
|
return(0);
|
1775
|
}
|
1776
|
$this->error="";
|
1777
|
if(!strcmp($this->state,"Connected")
|
1778
|
&& $quit
|
1779
|
&& (!$this->PutLine("QUIT")
|
1780
|
|| ($this->VerifyResultLines("221",$responses)<=0
|
1781
|
&& !$this->disconnected_error)))
|
1782
|
return(0);
|
1783
|
if($this->disconnected_error)
|
1784
|
$this->disconnected_error=0;
|
1785
|
else
|
1786
|
fclose($this->connection);
|
1787
|
$this->connection=0;
|
1788
|
$this->state="Disconnected";
|
1789
|
if($this->debug)
|
1790
|
$this->OutputDebug("Disconnected.");
|
1791
|
return(1);
|
1792
|
}
|
1793
|
/*
|
1794
|
{metadocument}
|
1795
|
</do>
|
1796
|
</function>
|
1797
|
{/metadocument}
|
1798
|
*/
|
1799
|
|
1800
|
/*
|
1801
|
{metadocument}
|
1802
|
<function>
|
1803
|
<name>SendMessage</name>
|
1804
|
<type>BOOLEAN</type>
|
1805
|
<documentation>
|
1806
|
<purpose>Send a message in a single call.</purpose>
|
1807
|
<usage>Call this function if you want to send a single messages to a
|
1808
|
small number of recipients in a single call.</usage>
|
1809
|
<returnvalue>The function returns
|
1810
|
<tt><booleanvalue>1</booleanvalue></tt> if the message was sent
|
1811
|
successfully.</returnvalue>
|
1812
|
</documentation>
|
1813
|
<argument>
|
1814
|
<name>sender</name>
|
1815
|
<type>STRING</type>
|
1816
|
<documentation>
|
1817
|
<purpose>E-mail address of the sender.</purpose>
|
1818
|
</documentation>
|
1819
|
</argument>
|
1820
|
<argument>
|
1821
|
<name>recipients</name>
|
1822
|
<type>STRING</type>
|
1823
|
<documentation>
|
1824
|
<purpose>Array with a list of the e-mail addresses of the
|
1825
|
recipients of the message.</purpose>
|
1826
|
</documentation>
|
1827
|
</argument>
|
1828
|
<argument>
|
1829
|
<name>headers</name>
|
1830
|
<type>ARRAY</type>
|
1831
|
<documentation>
|
1832
|
<purpose>Array with a list of the header lines of the message.</purpose>
|
1833
|
</documentation>
|
1834
|
</argument>
|
1835
|
<argument>
|
1836
|
<name>body</name>
|
1837
|
<type>STRING</type>
|
1838
|
<documentation>
|
1839
|
<purpose>Body data of the message.</purpose>
|
1840
|
</documentation>
|
1841
|
</argument>
|
1842
|
<do>
|
1843
|
{/metadocument}
|
1844
|
*/
|
1845
|
Function SendMessage($sender,$recipients,$headers,$body)
|
1846
|
{
|
1847
|
if(($success=$this->Connect()))
|
1848
|
{
|
1849
|
if(($success=$this->MailFrom($sender)))
|
1850
|
{
|
1851
|
for($recipient=0;$recipient<count($recipients);$recipient++)
|
1852
|
{
|
1853
|
if(!($success=$this->SetRecipient($recipients[$recipient])))
|
1854
|
break;
|
1855
|
}
|
1856
|
if($success
|
1857
|
&& ($success=$this->StartData()))
|
1858
|
{
|
1859
|
for($header_data="",$header=0;$header<count($headers);$header++)
|
1860
|
$header_data.=$headers[$header]."\r\n";
|
1861
|
$success=($this->SendData($header_data."\r\n")
|
1862
|
&& $this->SendData($this->PrepareData($body))
|
1863
|
&& $this->EndSendingData());
|
1864
|
}
|
1865
|
}
|
1866
|
$error=$this->error;
|
1867
|
$disconnect_success=$this->Disconnect($success);
|
1868
|
if($success)
|
1869
|
$success=$disconnect_success;
|
1870
|
else
|
1871
|
$this->error=$error;
|
1872
|
}
|
1873
|
return($success);
|
1874
|
}
|
1875
|
/*
|
1876
|
{metadocument}
|
1877
|
</do>
|
1878
|
</function>
|
1879
|
{/metadocument}
|
1880
|
*/
|
1881
|
|
1882
|
};
|
1883
|
|
1884
|
/*
|
1885
|
|
1886
|
{metadocument}
|
1887
|
</class>
|
1888
|
{/metadocument}
|
1889
|
|
1890
|
*/
|
1891
|
|
1892
|
?>
|