root/phpmailer/class.phpmailer.php

Revision 2202, 46.0 kB (checked in by Andrew Dolgov <fox@bah.spb.su>, 1 year ago)

[project @ fix vulnerability in PHPMailer]

Line 
1 <?php
2 ////////////////////////////////////////////////////
3 // PHPMailer - PHP email class
4 //
5 // Class for sending email using either
6 // sendmail, PHP mail(), or SMTP.  Methods are
7 // based upon the standard AspEmail(tm) classes.
8 //
9 // Copyright (C) 2001 - 2003  Brent R. Matzelle
10 //
11 // License: LGPL, see LICENSE
12 ////////////////////////////////////////////////////
13
14 /**
15  * PHPMailer - PHP email transport class
16  * @package PHPMailer
17  * @author Brent R. Matzelle
18  * @copyright 2001 - 2003 Brent R. Matzelle
19  */
20 class PHPMailer
21 {
22     /////////////////////////////////////////////////
23     // PUBLIC VARIABLES
24     /////////////////////////////////////////////////
25
26     /**
27      * Email priority (1 = High, 3 = Normal, 5 = low).
28      * @var int
29      */
30     var $Priority          = 3;
31
32     /**
33      * Sets the CharSet of the message.
34      * @var string
35      */
36     var $CharSet           = "iso-8859-1";
37
38     /**
39      * Sets the Content-type of the message.
40      * @var string
41      */
42     var $ContentType        = "text/plain";
43
44     /**
45      * Sets the Encoding of the message. Options for this are "8bit",
46      * "7bit", "binary", "base64", and "quoted-printable".
47      * @var string
48      */
49     var $Encoding          = "8bit";
50
51     /**
52      * Holds the most recent mailer error message.
53      * @var string
54      */
55     var $ErrorInfo         = "";
56
57     /**
58      * Sets the From email address for the message.
59      * @var string
60      */
61     var $From               = "root@localhost";
62
63     /**
64      * Sets the From name of the message.
65      * @var string
66      */
67     var $FromName           = "Root User";
68
69     /**
70      * Sets the Sender email (Return-Path) of the message.  If not empty,
71      * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
72      * @var string
73      */
74     var $Sender            = "";
75
76     /**
77      * Sets the Subject of the message.
78      * @var string
79      */
80     var $Subject           = "";
81
82     /**
83      * Sets the Body of the message.  This can be either an HTML or text body.
84      * If HTML then run IsHTML(true).
85      * @var string
86      */
87     var $Body               = "";
88
89     /**
90      * Sets the text-only body of the message.  This automatically sets the
91      * email to multipart/alternative.  This body can be read by mail
92      * clients that do not have HTML email capability such as mutt. Clients
93      * that can read HTML will view the normal Body.
94      * @var string
95      */
96     var $AltBody           = "";
97
98     /**
99      * Sets word wrapping on the body of the message to a given number of
100      * characters.
101      * @var int
102      */
103     var $WordWrap          = 0;
104
105     /**
106      * Method to send mail: ("mail", "sendmail", or "smtp").
107      * @var string
108      */
109     var $Mailer            = "mail";
110
111     /**
112      * Sets the path of the sendmail program.
113      * @var string
114      */
115     var $Sendmail          = "/usr/sbin/sendmail";
116     
117     /**
118      * Path to PHPMailer plugins.  This is now only useful if the SMTP class
119      * is in a different directory than the PHP include path. 
120      * @var string
121      */
122     var $PluginDir         = "";
123
124     /**
125      *  Holds PHPMailer version.
126      *  @var string
127      */
128     var $Version           = "1.73";
129
130     /**
131      * Sets the email address that a reading confirmation will be sent.
132      * @var string
133      */
134     var $ConfirmReadingTo  = "";
135
136     /**
137      *  Sets the hostname to use in Message-Id and Received headers
138      *  and as default HELO string. If empty, the value returned
139      *  by SERVER_NAME is used or 'localhost.localdomain'.
140      *  @var string
141      */
142     var $Hostname          = "";
143
144     /////////////////////////////////////////////////
145     // SMTP VARIABLES
146     /////////////////////////////////////////////////
147
148     /**
149      *  Sets the SMTP hosts.  All hosts must be separated by a
150      *  semicolon.  You can also specify a different port
151      *  for each host by using this format: [hostname:port]
152      *  (e.g. "smtp1.example.com:25;smtp2.example.com").
153      *  Hosts will be tried in order.
154      *  @var string
155      */
156     var $Host        = "localhost";
157
158     /**
159      *  Sets the default SMTP server port.
160      *  @var int
161      */
162     var $Port        = 25;
163
164     /**
165      *  Sets the SMTP HELO of the message (Default is $Hostname).
166      *  @var string
167      */
168     var $Helo        = "";
169
170     /**
171      *  Sets SMTP authentication. Utilizes the Username and Password variables.
172      *  @var bool
173      */
174     var $SMTPAuth     = false;
175
176     /**
177      *  Sets SMTP username.
178      *  @var string
179      */
180     var $Username     = "";
181
182     /**
183      *  Sets SMTP password.
184      *  @var string
185      */
186     var $Password     = "";
187
188     /**
189      *  Sets the SMTP server timeout in seconds. This function will not
190      *  work with the win32 version.
191      *  @var int
192      */
193     var $Timeout      = 10;
194
195     /**
196      *  Sets SMTP class debugging on or off.
197      *  @var bool
198      */
199     var $SMTPDebug    = false;
200
201     /**
202      * Prevents the SMTP connection from being closed after each mail
203      * sending.  If this is set to true then to close the connection
204      * requires an explicit call to SmtpClose().
205      * @var bool
206      */
207     var $SMTPKeepAlive = false;
208
209     /**#@+
210      * @access private
211      */
212     var $smtp            = NULL;
213     var $to              = array();
214     var $cc              = array();
215     var $bcc             = array();
216     var $ReplyTo         = array();
217     var $attachment      = array();
218     var $CustomHeader    = array();
219     var $message_type    = "";
220     var $boundary        = array();
221     var $language        = array();
222     var $error_count     = 0;
223     var $LE              = "\n";
224     /**#@-*/
225     
226     /////////////////////////////////////////////////
227     // VARIABLE METHODS
228     /////////////////////////////////////////////////
229
230     /**
231      * Sets message type to HTML. 
232      * @param bool $bool
233      * @return void
234      */
235     function IsHTML($bool) {
236         if($bool == true)
237             $this->ContentType = "text/html";
238         else
239             $this->ContentType = "text/plain";
240     }
241
242     /**
243      * Sets Mailer to send message using SMTP.
244      * @return void
245      */
246     function IsSMTP() {
247         $this->Mailer = "smtp";
248     }
249
250     /**
251      * Sets Mailer to send message using PHP mail() function.
252      * @return void
253      */
254     function IsMail() {
255         $this->Mailer = "mail";
256     }
257
258     /**
259      * Sets Mailer to send message using the $Sendmail program.
260      * @return void
261      */
262     function IsSendmail() {
263         $this->Mailer = "sendmail";
264     }
265
266     /**
267      * Sets Mailer to send message using the qmail MTA.
268      * @return void
269      */
270     function IsQmail() {
271         $this->Sendmail = "/var/qmail/bin/sendmail";
272         $this->Mailer = "sendmail";
273     }
274
275
276     /////////////////////////////////////////////////
277     // RECIPIENT METHODS
278     /////////////////////////////////////////////////
279
280     /**
281      * Adds a "To" address. 
282      * @param string $address
283      * @param string $name
284      * @return void
285      */
286     function AddAddress($address, $name = "") {
287         $cur = count($this->to);
288         $this->to[$cur][0] = trim($address);
289         $this->to[$cur][1] = $name;
290     }
291
292     /**
293      * Adds a "Cc" address. Note: this function works
294      * with the SMTP mailer on win32, not with the "mail"
295      * mailer. 
296      * @param string $address
297      * @param string $name
298      * @return void
299     */
300     function AddCC($address, $name = "") {
301         $cur = count($this->cc);
302         $this->cc[$cur][0] = trim($address);
303         $this->cc[$cur][1] = $name;
304     }
305
306     /**
307      * Adds a "Bcc" address. Note: this function works
308      * with the SMTP mailer on win32, not with the "mail"
309      * mailer. 
310      * @param string $address
311      * @param string $name
312      * @return void
313      */
314     function AddBCC($address, $name = "") {
315         $cur = count($this->bcc);
316         $this->bcc[$cur][0] = trim($address);
317         $this->bcc[$cur][1] = $name;
318     }
319
320     /**
321      * Adds a "Reply-to" address. 
322      * @param string $address
323      * @param string $name
324      * @return void
325      */
326     function AddReplyTo($address, $name = "") {
327         $cur = count($this->ReplyTo);
328         $this->ReplyTo[$cur][0] = trim($address);
329         $this->ReplyTo[$cur][1] = $name;
330     }
331
332
333     /////////////////////////////////////////////////
334     // MAIL SENDING METHODS
335     /////////////////////////////////////////////////
336
337     /**
338      * Creates message and assigns Mailer. If the message is
339      * not sent successfully then it returns false.  Use the ErrorInfo
340      * variable to view description of the error. 
341      * @return bool
342      */
343     function Send() {
344         $header = "";
345         $body = "";
346         $result = true;
347
348         if((count($this->to) + count($this->cc) + count($this->bcc)) < 1)
349         {
350             $this->SetError($this->Lang("provide_address"));
351             return false;
352         }
353
354         // Set whether the message is multipart/alternative
355         if(!empty($this->AltBody))
356             $this->ContentType = "multipart/alternative";
357
358         $this->error_count = 0; // reset errors
359         $this->SetMessageType();
360         $header .= $this->CreateHeader();
361         $body = $this->CreateBody();
362
363         if($body == "") { return false; }
364
365         // Choose the mailer
366         switch($this->Mailer)
367         {
368             case "sendmail":
369                 $result = $this->SendmailSend($header, $body);
370                 break;
371             case "mail":
372                 $result = $this->MailSend($header, $body);
373                 break;
374             case "smtp":
375                 $result = $this->SmtpSend($header, $body);
376                 break;
377             default:
378             $this->SetError($this->Mailer . $this->Lang("mailer_not_supported"));
379                 $result = false;
380                 break;
381         }
382
383         return $result;
384     }
385     
386     /**
387      * Sends mail using the $Sendmail program. 
388      * @access private
389      * @return bool
390      */
391     function SendmailSend($header, $body) {
392         if ($this->Sender != "")
393             $sendmail = sprintf("%s -oi -f %s -t",
394                 escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
395         else
396             $sendmail = sprintf("%s -oi -t",
397                 escapeshellcmd($this->Sendmail));
398
399         if(!@$mail = popen($sendmail, "w"))
400         {
401             $this->SetError($this->Lang("execute") . $this->Sendmail);
402             return false;
403         }
404
405         fputs($mail, $header);
406         fputs($mail, $body);
407         
408         $result = pclose($mail) >> 8 & 0xFF;
409         if($result != 0)
410         {
411             $this->SetError($this->Lang("execute") . $this->Sendmail);
412             return false;
413         }
414
415         return true;
416     }
417
418     /**
419      * Sends mail using the PHP mail() function. 
420      * @access private
421      * @return bool
422      */
423     function MailSend($header, $body) {
424         $to = "";
425         for($i = 0; $i < count($this->to); $i++)
426         {
427             if($i != 0) { $to .= ", "; }
428             $to .= $this->to[$i][0];
429         }
430
431         if ($this->Sender != "" && strlen(ini_get("safe_mode"))< 1)
432         {
433             $old_from = ini_get("sendmail_from");
434             ini_set("sendmail_from", $this->Sender);
435             $params = sprintf("-oi -f %s", $this->Sender);
436             $rt = @mail($to, $this->EncodeHeader($this->Subject), $body,
437                         $header, $params);
438         }
439         else
440             $rt = @mail($to, $this->EncodeHeader($this->Subject), $body, $header);
441
442         if (isset($old_from))
443             ini_set("sendmail_from", $old_from);
444
445         if(!$rt)
446         {
447             $this->SetError($this->Lang("instantiate"));
448             return false;
449         }
450
451         return true;
452     }
453
454     /**
455      * Sends mail via SMTP using PhpSMTP (Author:
456      * Chris Ryan).  Returns bool.  Returns false if there is a
457      * bad MAIL FROM, RCPT, or DATA input.
458      * @access private
459      * @return bool
460      */
461     function SmtpSend($header, $body) {
462         include_once($this->PluginDir . "class.smtp.php");
463         $error = "";
464         $bad_rcpt = array();
465
466         if(!$this->SmtpConnect())
467             return false;
468
469         $smtp_from = ($this->Sender == "") ? $this->From : $this->Sender;
470         if(!$this->smtp->Mail($smtp_from))
471         {
472             $error = $this->Lang("from_failed") . $smtp_from;
473             $this->SetError($error);
474             $this->smtp->Reset();
475             return false;
476         }
477
478         // Attempt to send attach all recipients
479         for($i = 0; $i < count($this->to); $i++)
480         {
481             if(!$this->smtp->Recipient($this->to[$i][0]))
482                 $bad_rcpt[] = $this->to[$i][0];
483         }
484         for($i = 0; $i < count($this->cc); $i++)
485         {
486             if(!$this->smtp->Recipient($this->cc[$i][0]))
487                 $bad_rcpt[] = $this->cc[$i][0];
488         }
489         for($i = 0; $i < count($this->bcc); $i++)
490         {
491             if(!$this->smtp->Recipient($this->bcc[$i][0]))
492                 $bad_rcpt[] = $this->bcc[$i][0];
493         }
494
495         if(count($bad_rcpt) > 0) // Create error message
496         {
497             for($i = 0; $i < count($bad_rcpt); $i++)
498             {
499                 if($i != 0) { $error .= ", "; }
500                 $error .= $bad_rcpt[$i];
501             }
502             $error = $this->Lang("recipients_failed") . $error;
503             $this->SetError($error);
504             $this->smtp->Reset();
505             return false;
506         }
507
508         if(!$this->smtp->Data($header . $body))
509         {
510             $this->SetError($this->Lang("data_not_accepted"));
511             $this->smtp->Reset();
512             return false;
513         }
514         if($this->SMTPKeepAlive == true)
515             $this->smtp->Reset();
516         else
517             $this->SmtpClose();
518
519         return true;
520     }
521
522     /**
523      * Initiates a connection to an SMTP server.  Returns false if the
524      * operation failed.
525      * @access private
526      * @return bool
527      */
528     function SmtpConnect() {
529         if($this->smtp == NULL) { $this->smtp = new SMTP(); }
530
531         $this->smtp->do_debug = $this->SMTPDebug;
532         $hosts = explode(";", $this->Host);
533         $index = 0;
534         $connection = ($this->smtp->Connected());
535
536         // Retry while there is no connection
537         while($index < count($hosts) && $connection == false)
538         {
539             if(strstr($hosts[$index], ":"))
540                 list($host, $port) = explode(":", $hosts[$index]);
541             else
542             {
543                 $host = $hosts[$index];
544                 $port = $this->Port;
545             }
546
547             if($this->smtp->Connect($host, $port, $this->Timeout))
548             {
549                 if ($this->Helo != '')
550                     $this->smtp->Hello($this->Helo);
551                 else
552                     $this->smtp->Hello($this->ServerHostname());
553         
554                 if($this->SMTPAuth)
555                 {
556                     if(!$this->smtp->Authenticate($this->Username,
557                                                   $this->Password))
558                     {
559                         $this->SetError($this->Lang("authenticate"));
560                         $this->smtp->Reset();
561                         $connection = false;
562                     }
563                 }
564                 $connection = true;
565             }
566             $index++;
567         }
568         if(!$connection)
569             $this->SetError($this->Lang("connect_host"));
570
571         return $connection;
572     }
573
574     /**
575