diff options
author | Urban Müller | 2007-07-26 13:02:24 +0000 |
---|---|---|
committer | Urban Müller | 2007-07-26 13:02:24 +0000 |
commit | 806a5297e7e99d455b97a4f0acaba2f40f470584 (patch) | |
tree | b9fc43ef227da87d873cf3676c08c49fa0dc1240 /mail.class | |
parent | c3cba034c8009b65c25dd4ef5f54b18d9c8ee7d4 (diff) | |
download | itools-806a5297e7e99d455b97a4f0acaba2f40f470584.tar.gz itools-806a5297e7e99d455b97a4f0acaba2f40f470584.tar.bz2 itools-806a5297e7e99d455b97a4f0acaba2f40f470584.zip |
renamed files for autoloader
Diffstat (limited to 'mail.class')
-rw-r--r-- | mail.class | 483 |
1 files changed, 0 insertions, 483 deletions
diff --git a/mail.class b/mail.class deleted file mode 100644 index f10e84d..0000000 --- a/mail.class +++ /dev/null @@ -1,483 +0,0 @@ -<?php -/* -** $Id$ -** -** mail.class - Create a mail object, add header and content and send it -** -** ITools - the Internet Tools Library -** -** Copyright (C) 1995-2003 by the ITools Authors. -** This program is free software; you can redistribute it and/or -** modify it under the terms of either the GNU General Public License -** or the GNU Lesser General Public License, as published by the Free -** Software Foundation. See http://www.gnu.org/licenses/ for details. -*/ - -define('IT_MAIL_PLAIN', 0); -define('IT_MAIL_HTML', 1); - -/* Return codes of it_mail::check_email() */ -define('IT_MAIL_CHECKEMAIL_INVALID', 0); -define('IT_MAIL_CHECKEMAIL_MAILBOXFULL', 5); -define('IT_MAIL_CHECKEMAIL_OK', 10); - -/** - * Construct an email message with headers, body (plaintext and/or HTML) and - * send it. Also provides utility function to check email address validity.<br> - * <em>Example:</em><br> - * <code><nobr> - * if (!it_mail::check_email($to))<br> - * die("Invalid email address '$to'\n");<br> - * <br> - * $mail = new it_mail(array('To' => $to, 'From' => 'itools@gna.ch', 'Subject' => 'Example'));<br> - * $mail->add_body('Plain text message body');<br> - * $mail->add_body('HTML message with <a href="http://gna.ch/">link</a>', IT_MAIL_HTML);<br> - * $mail->send();<br> - * </nobr></code> - */ -class it_mail -{ - var $header_names = array(); - var $header_values = array(); - var $body = array(); - var $attachments = array(); - - var $to = array(); - var $subject = ""; - var $cc = array(); - var $bcc = array(); - var $flags = ""; - var $charset = 'iso-8859-1'; - -/** - * Construct a new email message. Headers and body can be added later. - * Note: Headers To, Cc, Bcc can be arrays - * @param $headers Array of headers for this email, e.g. From, To and Subject - */ -function it_mail($headers = "") -{ - if (is_array($headers)) - { - foreach ($headers as $header => $value) - $this->add_header($header, $value); - } -} - - -/** - * Add header line to the this email message. Can be called repeatedly. - * Note: Headers To, Cc, Bcc can be arrays - * @param $header Header to be added, e.g. Cc, Bcc or X-My-Header - * @param $value Value of header, e.g. itools@gna.ch for Bcc header - */ -function add_header($header, $value) -{ - $value = $this->header_escape($value); - - switch ($header) - { - case 'To': - if (is_array($value)) - { - foreach ($value as $val) - $this->to[] = $val; - } - else - $this->to[] = $value; - break; - - case 'Subject': - $this->subject .= $value; - break; - - case 'Cc': - if (is_array($value)) - { - foreach ($value as $val) - $this->cc[] = $val; - } - else - $this->cc[] = $value; - break; - - case 'Bcc': - if (is_array($value)) - { - foreach ($value as $val) - $this->bcc[] = $val; - } - else - $this->bcc[] = $value; - break; - - case 'charset': - $this->charset = $value; - break; - - case 'Errors-To': - $this->flags = "-f " . escapeshellarg(preg_replace('/.*<([^>]+)>.*/', '$1', $value)); - /* FALLTHROUGH */ - default: - $this->header_names[] = $header; - $this->header_values[] = $value; - break; - } -} - - -/** - * Add body part to this email message. Can be called repeatedly. - * @param $text Text to be added to email message - * @param $type Type of text, one of IT_MAIL_PLAIN (default) or IT_MAIL_HTML - */ -function add_body($text, $type = IT_MAIL_PLAIN) -{ - switch ($type) - { - case IT_MAIL_PLAIN: - case IT_MAIL_HTML: - $this->body[$type] .= $text; - break; - - default: - it::fatal("it_mail::add_body invalid type $type"); - break; - } -} - - -/** - * Add attachment to this email message. Can be called repeatedly. - * @param $data Data to be attached - * @param $name Name of attached file - * @param $mimetype MIME-Type of attached file - * @return 'cid:'.Content-ID of this attachment - */ -function add_attachment($data, $mimetype = "application/octet-stream", $name = '') -{ - if ($name == '') - $name = 'Attachment' . (count($this->attachments) + 1); - - $cid = md5(uniqid(rand())); - $this->attachments[] = array ('mimetype' => $mimetype, 'data' => $data, 'encode' => $encode, 'name' => $name, 'cid' => $cid); - - return 'cid:'.$cid; -} - - -/** - * Add file attachment to this email message. Can be called repeatedly. - * @param $filename File to be attached - * @param $name Name of attached file as stored in mail - * @param $mimetype MIME-Type of attached file - */ -function add_file($filename, $mimetype = "application/octet-stream", $name = '') -{ - if ($name == '') - $name = basename($filename); - - if ($file = @fopen($filename, "r")) - { - if ($data = fread($file, @filesize($filename))) - $result = $this->add_attachment($data, $mimetype, $name); - - fclose($file); - } - - return $result; -} - - -/** - * Send this email message - * @return True if mail was sent - */ -function send() -{ - $to = join(",", $this->to); - $headers = array(); - - if (count($this->cc) > 0) - $headers[] = "Cc: " . join(",", $this->cc); - - if (count($this->bcc) > 0) - $headers[] = "Bcc: " . join(",", $this->bcc); - - for ($i = 0; $i < count($this->header_names); $i++) - $headers[] = $this->header_names[$i] . ': ' . $this->header_values[$i]; - - - /* Automatically add doctype if none given */ - if ($this->body[IT_MAIL_HTML] && !eregi('^<!doctype', $this->body[IT_MAIL_HTML])) - { - $this->body[IT_MAIL_HTML] = '<!doctype html public "-//w3c//dtd html 4.01 transitional//en">' . "\n" . $this->body[IT_MAIL_HTML]; - } - - - $headers[] = "MIME-Version: 1.0"; - - if ($this->attachments) - { - /* Attachments need multipart MIME mail */ - $boundary1 = md5(uniqid(rand())); - $mixedtype = "Content-Type: multipart/mixed; boundary=\"$boundary1\""; - - $headers[] = $mixedtype; - $text .= "This is a multi-part message in MIME format."; - $text .= "\n--$boundary1\n"; - } - - /* Headers for plain and HTML content */ - $plaintype = "Content-Type: text/plain; charset=".$this->charset."\nContent-Transfer-Encoding: 8bit"; - $htmltype = "Content-Type: text/html; charset=".$this->charset."\nContent-Transfer-Encoding: 8bit"; - - if ($this->body[IT_MAIL_PLAIN]) - { - if ($this->body[IT_MAIL_HTML]) - { - $boundary2 = md5(uniqid(rand())); - $alternativetype = "Content-Type: multipart/alternative; boundary=\"$boundary2\""; - - /* Plain and HTML */ - if ($this->attachments) - $text .= "$alternativetype\n\n"; - else - $headers[] = $alternativetype; - - $text .= "--$boundary2\n$plaintype\n\n"; - $text .= $this->body[IT_MAIL_PLAIN]; - $text .= "\n--$boundary2\n$htmltype\n\n"; - $text .= $this->body[IT_MAIL_HTML]; - $text .= "\n--$boundary2--\n"; - } - else - { - /* Just plain */ - if ($this->attachments) - $text .= "$plaintype\n\n"; - else - $headers[] = $plaintype; - - $text .= $this->body[IT_MAIL_PLAIN]; - } - } - else if ($this->body[IT_MAIL_HTML]) - { - /* Just HTML */ - if ($this->attachments) - { - if (strstr($this->body[IT_MAIL_HTML], "cid:")) - { - $boundary3 = md5(uniqid(rand())); - $text .= "Content-Type: multipart/related; boundary=\"$boundary3\"\n\n--$boundary3\n"; - } - - $text .= "$htmltype\n\n"; - } - else - $headers[] = $htmltype; - - $text .= $this->body[IT_MAIL_HTML]; - } - - if ($this->attachments) - { - $text .= "\n"; - $boundary = $boundary3 ? $boundary3 : $boundary1; - - foreach ($this->attachments as $attachment) - { - $text .= "\n--$boundary\nContent-Type: {$attachment['mimetype']}; name=\"{$attachment['name']}\"\nContent-Transfer-Encoding: base64\nContent-ID: <{$attachment['cid']}>\nContent-Disposition: inline; filename=\"{$attachment['name']}\"\n\n"; - $text .= chunk_split(base64_encode($attachment['data'])); - } - - if ($boundary3) - $text .= "\n--$boundary3--\n\n"; - - $text .= "--$boundary1--\n"; - } - - return mail($to, $this->subject, $text, join("\n", $headers), $this->flags); -} - - -/** - * INTERNAL: Escape header line with ?=iso-8859-1? if necessary, e.g. in Subject line - * @param $string String to be escaped - * @return String escape suitable for sending in header line - */ -function header_escape($string) -{ - return preg_replace('/[\x80-\xff]/e', "sprintf('=?iso-8859-1?Q?=%02X?=', ord('\\0'))", $string); -} - -/** - * Make string safe to be used in "$fullname <$email>": Remove illegal - * characters and enclose in double quotes. - * @param $string Fulle name to be escaped - * @return String to be safely used in "$fullname <$email>" for To: etc. - */ -function fullname_escape($string) -{ - return '"' . preg_replace('/["\x00-\x1f]/', '', $string) . '"'; -} - -/** - * INTERNAL: Send SMTP command and return true if result is 2XX - * @param $fp Connection to SMTP server opened using fsockopen - * @param $command Command to send, e.g. HELO gna.ch - * @param $anwer String containing full answer from SMTP server - * @param timeoutok Whether a timeout is considered ok - * @param $failcode Lowest SMTP result code which is considered a failure (default 300) - * @return True if SMTP result code is lower than $failcode - * - */ -function send_smtp_cmd($fp, $cmd, &$answer, $timeoutok = false, $failcode = 300) -{ - $result = false; - $answer = ''; - - if (!$cmd || (!feof($fp) && fwrite($fp, "$cmd\r\n"))) - { - while (!feof($fp) && ereg('^(...)(.?)(.*)$', fgets($fp, 1024), $regs)) - { - $answer .= $regs[0]; - $resultcode = intval($regs[1]); - - if ($regs[2] != '-') /* Multi line response? */ - { - if (($resultcode >= 100) && ($resultcode < $failcode)) - $result = true; - - break; - } - } - } - - /* A timeout can be considered ok for SLOW mail servers */ - if ($answer == '') - $result = $timeoutok; - - //echo ">>it_mail::send_smtp_cmd " . time() . " '$cmd' => $result: $answer"; - - return $result; -} - - -/** - * Check if given email address is valid (syntax, MX record). If you set - * checkmailbox to true it also connects to MX and asks if mailbox is valid. - * Note: Connecting to the MX can be slow. - * @param $email email to be check - * @param $checkmailbox True if you want to connect to MX and check account - * @return One of IT_MAIL_CHECKEMAIL_INVALID (0), IT_MAIL_CHECKEMAIL_MAILBOXFULL - * or IT_MAIL_CHECKEMAIL_OK (both != 0). - */ -function check_email($email, $checkmailbox = true) -{ - $result = IT_MAIL_CHECKEMAIL_INVALID; - - /* Check if username starts with www. or not well-formed => reject */ - if (!ereg('^www\.', $email) && eregi('^[a-z0-9&_+.-]+@([a-z0-9.-]+\.[a-z]+)$', $email, $regs)) - { - $domain = $regs[1]; - - if (!getmxrr($domain, $mxhosts, $weights)) - { - /* If we find no MX we check if domain exists */ - if (gethostbynamel($domain)) - { - $mxhosts = array($domain); - $weights = array(1); - } - } - - if ($mxhosts) /* We need at least one valid MX */ - { - if ($checkmailbox) - { - $mx = array(); - - for ($i = 0; $i < count($mxhosts); $i++) - $mx[$mxhosts[$i]] = $weights[$i]; - - asort($mx, SORT_NUMERIC); - $port = getservbyname('smtp', 'tcp'); - $from = 'itools@gna.ch'; - - /* Determine domain and email for test, skip if called as it_mail::check_email() */ - if (is_object($this)) - { - for ($i = 0; $i < count($this->header_names); $i++) - { - if ($this->header_names[$i] == 'From') - { - $from = $this->header_values[$i]; - break; - } - } - } - - if (eregi('@([a-z0-9.-]+\.[a-z]+)$', $from, $regs)) - $fromdomain = $regs[1]; - else - $fromdomain = 'gna.ch'; - - $finished = false; - $connected = 0; - - if (function_exists('stream_set_timeout')) - $timeout = 'stream_set_timeout'; - else - $timeout = 'socket_set_timeout'; - - foreach ($mx as $mxhost => $weight) - { - //echo ">>it_mail::check_email: " . time() . " checking $mxhost\n"; - if ($fp = @fsockopen($mxhost, $port, $errno, $errstr, 5)) - { - $connected++; - $timeout($fp, 45); - $answer = ''; - - if (it_mail::send_smtp_cmd($fp, '', $answer) && it_mail::send_smtp_cmd($fp, "HELO $fromdomain", $answer) && it_mail::send_smtp_cmd($fp, "MAIL FROM: <$from>", $answer)) - { - $timeout($fp, 2); - $timeoutok = ($domain != 'bluewin.ch'); - - if (it_mail::send_smtp_cmd($fp, "RCPT TO: <$email>", $answer, $timeoutok, 500)) # 450 is often used for Greylisting - $result = IT_MAIL_CHECKEMAIL_OK; - else if (eregi('quota|full|exceeded storage', $answer)) - $result = IT_MAIL_CHECKEMAIL_MAILBOXFULL; - - /* Do not try other MX if we got this far */ - $finished = true; - } - - $timeout($fp, 0, 1); - - it_mail::send_smtp_cmd($fp, 'RSET', $answer); - - it_mail::send_smtp_cmd($fp, 'QUIT', $answer); - fclose($fp); - } - - if ($finished) - break; - } - - /* If we cannot connect to _any_ MX it could be because of temporary overload / virus attack */ - if (!$connected) - $result = IT_MAIL_CHECKEMAIL_OK; - } - else - $result = IT_MAIL_CHECKEMAIL_OK; - } - } - - return $result; -} - -} - -?> |