server = $server; $this->port = $port; $this->username = $username; $this->password = $password; $this->security = $security; } public function __destruct() { if ( $this->isConnected ) { $this->write( 'QUIT' . "\r\n" ); $this->read(); } if ( ! empty( $this->conn ) ) { fclose( $this->conn ); } } private function connect() { if ( $this->security == 'ssl' ) { $this->server = 'ssl://' . $this->server; } $this->conn = fsockopen( $this->server, $this->port, $errno, $errstr, $this->timeout ); if ( ! $this->conn ) { $this->lastError = 101; return FALSE; } if ( substr( $this->read(), 0, 3 ) != '220' ) { $this->lastError = 102; return FALSE; } $this->write( 'EHLO ' . $this->localhost ); if ( substr( $this->read(), 0, 3 ) != '250' ) { $this->lastError = 203; return FALSE; } if ( $this->security == 'tls' ) { $this->write( 'STARTTLS' ); if ( substr( $this->read(), 0, 3 ) != '220' ) { $this->lastError = 201; return FALSE; } stream_socket_enable_crypto( $this->conn, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT ); $this->write( 'EHLO ' . $this->localhost ); if ( substr( $this->read(), 0, 3 ) != '250' ) { $this->lastError = 202; return FALSE; } } if ( $this->server == 'localhost' ) { $this->isConnected = TRUE; return TRUE; } $this->write( 'AUTH LOGIN' ); if ( substr( $this->read(), 0, 3 ) != '334' ) { $this->lastError = 301; return FALSE; } $this->write( base64_encode( $this->username ) ); if ( substr( $this->read(), 0, 3 ) != '334' ) { $this->lastError = 302; return FALSE; } $this->write( base64_encode( $this->password ) ); if ( substr( $this->read(), 0, 3 ) != '235' ) { $this->lastError = 303; return FALSE; } $this->isConnected = TRUE; return TRUE; } public function send( $message, $sender = NULL, $recipients = NULL ) { if ( ! $this->isConnected && ! $this->connect() ) { return FALSE; } if ( empty( $sender ) ) { if ( empty( $message['from'] ) ) { $this->lastError = 701; return FALSE; } $sender = $message['from']; if ( ( $pos = strpos( $sender, '<' ) ) !== FALSE ){ $sender = substr( $sender, $pos + 1, strpos( $sender, '>' ) - $pos - 1 ); } } if ( empty( $recipients ) ) { if ( empty( $message['to'] ) ) { $this->lastError = 702; return FALSE; } $recipients = (array) $message['to']; if ( ! empty( $message['cc'] ) ) { $recipients = array_unique( array_merge( $recipients, (array) $message['cc'] ) ); } if ( ! empty( $message['bcc'] ) ) { $recipients = array_unique( array_merge( $recipients, (array) $message['bcc'] ) ); } } $data = $this->compose_message( $message ); if ( ! $data ) { $this->lastError = 711; return FALSE; } $this->write( "MAIL FROM: <{$sender}>" ); $this->read(); foreach ( (array) $recipients as $recipient ) { $this->write( "RCPT TO: <{$recipient}>" ); $this->read(); } $this->write('DATA'); $this->read(); $this->write( "{$data}\r\n." ); $response = $this->read(); if ( substr( $response, 0, 3 ) == '250' ) { return TRUE; } $this->lastError = 5000 + (int) $response; return FALSE; } public function compose_message( $message ) { if ( empty( $message['to'] ) || empty( $message['from'] ) || ( empty( $message['text'] ) && empty( $message['html'] ) ) || empty( $message['subject'] ) ) { return FALSE; } if ( empty( $message['id'] ) ){ $message['id'] = base_convert( time(), 10, 36 ) . '.'; for ( $i = 0; $i < 8; $i++ ){ $message['id'] .= base_convert( random_int( 0, 35 ), 10, 36 ); } $message['id'] .= strrchr( rtrim( $message['from'], '>' ), '@' ); } // compose message parts if ( ! empty( $message['text'] ) ) { $textPart = "Content-Type: text/plain; charset=\"utf-8\"\r\n"; $textPart .= "Content-Transfer-Encoding: quoted-printable\r\n"; $textPart .= "\r\n"; $textPart .= quoted_printable_encode( $message['text'] ) . "\r\n"; $textPart = preg_replace( '/^\./m', '..', $textPart ); } if ( ! empty( $message['html'] ) ) { $htmlPart = "Content-Type: text/html; charset=\"utf-8\"\r\n"; $htmlPart .= "Content-Transfer-Encoding: quoted-printable\r\n"; $htmlPart .= "\r\n"; $htmlPart .= quoted_printable_encode( $message['html'] ) . "\r\n"; $htmlPart = preg_replace( '/^\./m', '..', $htmlPart ); } if ( ! empty( $message['attachments'] ) ) { $boundary = '=Part.' . md5( microtime() ); $attPart = ''; foreach ( (array) $message['attachments'] as $attachment ) { $content = file_get_contents( $attachment ); $filename = basename( $attachment ); $suffix = pathinfo( $filename, PATHINFO_EXTENSION ); $attPart .= "--{$boundary}\r\n"; $attPart .= "Content-Type: application/{$suffix}; name=\"{$filename}\"\r\n"; $attPart .= "Content-Transfer-Encoding: base64\r\n"; $attPart .= "Content-Disposition: attachment; filename=\"{$filename}\"\r\n"; $attPart .= "\r\n"; $attPart .= chunk_split( base64_encode( $content ) ) . "\r\n"; } } // set common headers $email = "Date: " . date('r') . "\r\n"; $email .= "Message-ID: <{$message['id']}>\r\n"; $email .= "From: {$message['from']}\r\n"; if ( ! empty( $message['reply_to'] ) ) { $email .= "Reply-To: {$message['reply_to']}\r\n"; } $email .= 'To: ' . implode( ',', (array) $message['to'] ) . "\r\n"; if ( ! empty( $message['cc'] ) ) { $email .= 'CC: ' . implode( ',', (array) $message['cc'] ) . "\r\n"; } if ( ! empty( $message['headers'] ) ) { $email .= implode( "\r\n", (array) $message['headers'] ) . "\r\n"; } $email .= "Subject: {$message['subject']}\r\n"; $email .= "MIME-Version: 1.0" . "\r\n"; // compose single-part message if ( empty( $attPart ) && ( empty( $textPart ) xor empty( $htmlPart ) ) ) { $email .= empty( $textPart ) ? $htmlPart : $textPart; return $email; } // compose multi-part message if ( ! empty( $attPart ) ) { $email .= "Content-Type: multipart/mixed;" . "\r\n"; $email .= " boundary=\"{$boundary}\"" . "\r\n"; $email .= "\r\n"; $email .= "--{$boundary}\r\n"; } if ( ! empty( $message['html'] ) && ! empty( $message['text'] ) ) { $altBoundary = '=Part.' . md5( microtime() ); $email .= "Content-Type: multipart/alternative;" . "\r\n"; $email .= " boundary=\"$altBoundary\"" . "\r\n"; $email .= "\r\n"; $email .= "--" . $altBoundary . "\r\n"; $email .= $textPart; $email .= "--" . $altBoundary . "\r\n"; $email .= $htmlPart; $email .= "--" . $altBoundary . "--\r\n"; } else { $email .= empty( $textPart ) ? $htmlPart : $textPart; } $email .= empty( $attPart ) ? '' : $attPart . "--" . $boundary . "--" . "\r\n"; return $email; } public function mail( $to, $subject, $text, $from, $headers = array () ) { $message = compact( 'to', 'subject', 'text', 'from', 'headers' ); return $this->send( $message ); } private function write( $bytes ) { if ( $this->debug ) { $line = strpos( $bytes, "\n" ) ? strlen( $bytes ) . ' bytes sent' : $bytes; $this->protocol[] = '> ' . $line; } fputs( $this->conn, $bytes . "\r\n" ); } private function read() { $data = ''; while ( $str = fgets( $this->conn, 4096 ) ) { $data .= $str; if ( $str[3] == ' ' ) { break; } } if ( $this->debug ) { $this->protocol[] = trim( $data ); } return $data; } } // end of file smtp_mailer.class.php