shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

smtp.php (9341B)


      1 <?php
      2 namespace Mail;
      3 class Smtp {
      4 	public $smtp_hostname;
      5 	public $smtp_username;
      6 	public $smtp_password;
      7 	public $smtp_port = 25;
      8 	public $smtp_timeout = 5;
      9 	public $verp = false;
     10 
     11 	public function send() {
     12 		if (is_array($this->to)) {
     13 			$to = implode(',', $this->to);
     14 		} else {
     15 			$to = $this->to;
     16 		}
     17 
     18 		$boundary = '----=_NextPart_' . md5(time());
     19 
     20 		$header  = 'MIME-Version: 1.0' . PHP_EOL;
     21 		$header .= 'To: <' . $to . '>' . PHP_EOL;
     22 		$header .= 'Subject: =?UTF-8?B?' . base64_encode($this->subject) . '?=' . PHP_EOL;
     23 		$header .= 'Date: ' . date('D, d M Y H:i:s O') . PHP_EOL;
     24 		$header .= 'From: =?UTF-8?B?' . base64_encode($this->sender) . '?= <' . $this->from . '>' . PHP_EOL;
     25 		
     26 		if (!$this->reply_to) {
     27 			$header .= 'Reply-To: =?UTF-8?B?' . base64_encode($this->sender) . '?= <' . $this->from . '>' . PHP_EOL;
     28 		} else {
     29 			$header .= 'Reply-To: =?UTF-8?B?' . base64_encode($this->reply_to) . '?= <' . $this->reply_to . '>' . PHP_EOL;
     30 		}
     31 		
     32 		$header .= 'Return-Path: ' . $this->from . PHP_EOL;
     33 		$header .= 'X-Mailer: PHP/' . phpversion() . PHP_EOL;
     34 		$header .= 'Content-Type: multipart/mixed; boundary="' . $boundary . '"' . PHP_EOL . PHP_EOL;
     35 
     36 		if (!$this->html) {
     37 			$message  = '--' . $boundary . PHP_EOL;
     38 			$message .= 'Content-Type: text/plain; charset="utf-8"' . PHP_EOL;
     39 			$message .= 'Content-Transfer-Encoding: 8bit' . PHP_EOL . PHP_EOL;
     40 			$message .= $this->text . PHP_EOL;
     41 		} else {
     42 			$message  = '--' . $boundary . PHP_EOL;
     43 			$message .= 'Content-Type: multipart/alternative; boundary="' . $boundary . '_alt"' . PHP_EOL . PHP_EOL;
     44 			$message .= '--' . $boundary . '_alt' . PHP_EOL;
     45 			$message .= 'Content-Type: text/plain; charset="utf-8"' . PHP_EOL;
     46 			$message .= 'Content-Transfer-Encoding: 8bit' . PHP_EOL . PHP_EOL;
     47 
     48 			if ($this->text) {
     49 				$message .= $this->text . PHP_EOL;
     50 			} else {
     51 				$message .= 'This is a HTML email and your email client software does not support HTML email!' . PHP_EOL;
     52 			}
     53 
     54 			$message .= '--' . $boundary . '_alt' . PHP_EOL;
     55 			$message .= 'Content-Type: text/html; charset="utf-8"' . PHP_EOL;
     56 			$message .= 'Content-Transfer-Encoding: 8bit' . PHP_EOL . PHP_EOL;
     57 			$message .= $this->html . PHP_EOL;
     58 			$message .= '--' . $boundary . '_alt--' . PHP_EOL;
     59 		}
     60 
     61 		foreach ($this->attachments as $attachment) {
     62 			if (file_exists($attachment)) {
     63 				$handle = fopen($attachment, 'r');
     64 
     65 				$content = fread($handle, filesize($attachment));
     66 
     67 				fclose($handle);
     68 
     69 				$message .= '--' . $boundary . PHP_EOL;
     70 				$message .= 'Content-Type: application/octet-stream; name="' . basename($attachment) . '"' . PHP_EOL;
     71 				$message .= 'Content-Transfer-Encoding: base64' . PHP_EOL;
     72 				$message .= 'Content-Disposition: attachment; filename="' . basename($attachment) . '"' . PHP_EOL;
     73 				$message .= 'Content-ID: <' . urlencode(basename($attachment)) . '>' . PHP_EOL;
     74 				$message .= 'X-Attachment-Id: ' . urlencode(basename($attachment)) . PHP_EOL . PHP_EOL;
     75 				$message .= chunk_split(base64_encode($content));
     76 			}
     77 		}
     78 
     79 		$message .= '--' . $boundary . '--' . PHP_EOL;
     80 
     81 		if (substr($this->smtp_hostname, 0, 3) == 'tls') {
     82 			$hostname = substr($this->smtp_hostname, 6);
     83 		} else {
     84 			$hostname = $this->smtp_hostname;
     85 		}
     86 
     87 		$handle = fsockopen($hostname, $this->smtp_port, $errno, $errstr, $this->smtp_timeout);
     88 
     89 		if (!$handle) {
     90 			throw new \Exception('Error: ' . $errstr . ' (' . $errno . ')');
     91 		} else {
     92 			if (substr(PHP_OS, 0, 3) != 'WIN') {
     93 				socket_set_timeout($handle, $this->smtp_timeout, 0);
     94 			}
     95 	
     96 			while ($line = fgets($handle, 515)) {
     97 				if (substr($line, 3, 1) == ' ') {
     98 					break;
     99 				}
    100 			}
    101 
    102 			fputs($handle, 'EHLO ' . getenv('SERVER_NAME') . "\r\n");
    103 
    104 			$reply = '';
    105 
    106 			while ($line = fgets($handle, 515)) {
    107 				$reply .= $line;
    108 
    109 				//some SMTP servers respond with 220 code before responding with 250. hence, we need to ignore 220 response string
    110 				if (substr($reply, 0, 3) == 220 && substr($line, 3, 1) == ' ') {
    111 					$reply = '';
    112 					continue;
    113 				}
    114 				else if (substr($line, 3, 1) == ' ') {
    115 					break;
    116 				}
    117 			}
    118 
    119 			if (substr($reply, 0, 3) != 250) {
    120 				throw new \Exception('Error: EHLO not accepted from server!');
    121 			}
    122 
    123 			if (substr($this->smtp_hostname, 0, 3) == 'tls') {
    124 				fputs($handle, 'STARTTLS' . "\r\n");
    125 
    126 				$reply = '';
    127 
    128 				while ($line = fgets($handle, 515)) {
    129 					$reply .= $line;
    130 
    131 					if (substr($line, 3, 1) == ' ') {
    132 						break;
    133 					}
    134 				}
    135 
    136 				if (substr($reply, 0, 3) != 220) {
    137 					throw new \Exception('Error: STARTTLS not accepted from server!');
    138 				}
    139 
    140 				stream_socket_enable_crypto($handle, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
    141 			}
    142 
    143 			if (!empty($this->smtp_username)  && !empty($this->smtp_password)) {
    144 				fputs($handle, 'EHLO ' . getenv('SERVER_NAME') . "\r\n");
    145 
    146 				$reply = '';
    147 
    148 				while ($line = fgets($handle, 515)) {
    149 					$reply .= $line;
    150 
    151 					if (substr($line, 3, 1) == ' ') {
    152 						break;
    153 					}
    154 				}
    155 
    156 				if (substr($reply, 0, 3) != 250) {
    157 					throw new \Exception('Error: EHLO not accepted from server!');
    158 				}
    159 
    160 				fputs($handle, 'AUTH LOGIN' . "\r\n");
    161 
    162 				$reply = '';
    163 
    164 				while ($line = fgets($handle, 515)) {
    165 					$reply .= $line;
    166 
    167 					if (substr($line, 3, 1) == ' ') {
    168 						break;
    169 					}
    170 				}
    171 
    172 				if (substr($reply, 0, 3) != 334) {
    173 					throw new \Exception('Error: AUTH LOGIN not accepted from server!');
    174 				}
    175 
    176 				fputs($handle, base64_encode($this->smtp_username) . "\r\n");
    177 
    178 				$reply = '';
    179 
    180 				while ($line = fgets($handle, 515)) {
    181 					$reply .= $line;
    182 
    183 					if (substr($line, 3, 1) == ' ') {
    184 						break;
    185 					}
    186 				}
    187 
    188 				if (substr($reply, 0, 3) != 334) {
    189 					throw new \Exception('Error: Username not accepted from server!');
    190 				}
    191 
    192 				fputs($handle, base64_encode($this->smtp_password) . "\r\n");
    193 
    194 				$reply = '';
    195 
    196 				while ($line = fgets($handle, 515)) {
    197 					$reply .= $line;
    198 
    199 					if (substr($line, 3, 1) == ' ') {
    200 						break;
    201 					}
    202 				}
    203 
    204 				if (substr($reply, 0, 3) != 235) {
    205 					throw new \Exception('Error: Password not accepted from server!');
    206 				}
    207 			} else {
    208 				fputs($handle, 'HELO ' . getenv('SERVER_NAME') . "\r\n");
    209 
    210 				$reply = '';
    211 
    212 				while ($line = fgets($handle, 515)) {
    213 					$reply .= $line;
    214 
    215 					if (substr($line, 3, 1) == ' ') {
    216 						break;
    217 					}
    218 				}
    219 
    220 				if (substr($reply, 0, 3) != 250) {
    221 					throw new \Exception('Error: HELO not accepted from server!');
    222 				}
    223 			}
    224 
    225 			if ($this->verp) {
    226 				fputs($handle, 'MAIL FROM: <' . $this->from . '>XVERP' . "\r\n");
    227 			} else {
    228 				fputs($handle, 'MAIL FROM: <' . $this->from . '>' . "\r\n");
    229 			}
    230 
    231 			$reply = '';
    232 
    233 			while ($line = fgets($handle, 515)) {
    234 				$reply .= $line;
    235 
    236 				if (substr($line, 3, 1) == ' ') {
    237 					break;
    238 				}
    239 			}
    240 
    241 			if (substr($reply, 0, 3) != 250) {
    242 				throw new \Exception('Error: MAIL FROM not accepted from server!');
    243 			}
    244 
    245 			if (!is_array($this->to)) {
    246 				fputs($handle, 'RCPT TO: <' . $this->to . '>' . "\r\n");
    247 
    248 				$reply = '';
    249 
    250 				while ($line = fgets($handle, 515)) {
    251 					$reply .= $line;
    252 
    253 					if (substr($line, 3, 1) == ' ') {
    254 						break;
    255 					}
    256 				}
    257 
    258 				if ((substr($reply, 0, 3) != 250) && (substr($reply, 0, 3) != 251)) {
    259 					throw new \Exception('Error: RCPT TO not accepted from server!');
    260 				}
    261 			} else {
    262 				foreach ($this->to as $recipient) {
    263 					fputs($handle, 'RCPT TO: <' . $recipient . '>' . "\r\n");
    264 
    265 					$reply = '';
    266 
    267 					while ($line = fgets($handle, 515)) {
    268 						$reply .= $line;
    269 
    270 						if (substr($line, 3, 1) == ' ') {
    271 							break;
    272 						}
    273 					}
    274 
    275 					if ((substr($reply, 0, 3) != 250) && (substr($reply, 0, 3) != 251)) {
    276 						throw new \Exception('Error: RCPT TO not accepted from server!');
    277 					}
    278 				}
    279 			}
    280 
    281 			fputs($handle, 'DATA' . "\r\n");
    282 
    283 			$reply = '';
    284 
    285 			while ($line = fgets($handle, 515)) {
    286 				$reply .= $line;
    287 
    288 				if (substr($line, 3, 1) == ' ') {
    289 					break;
    290 				}
    291 			}
    292 
    293 			if (substr($reply, 0, 3) != 354) {
    294 				throw new \Exception('Error: DATA not accepted from server!');
    295 			}
    296 
    297 			// According to rfc 821 we should not send more than 1000 including the CRLF
    298 			$message = str_replace("\r\n", "\n", $header . $message);
    299 			$message = str_replace("\r", "\n", $message);
    300 
    301 			$lines = explode("\n", $message);
    302 
    303 			foreach ($lines as $line) {
    304 				$results = str_split($line, 998);
    305 
    306 				foreach ($results as $result) {
    307 					if (substr(PHP_OS, 0, 3) != 'WIN') {
    308 						fputs($handle, $result . "\r\n");
    309 					} else {
    310 						fputs($handle, str_replace("\n", "\r\n", $result) . "\r\n");
    311 					}
    312 				}
    313 			}
    314 
    315 			fputs($handle, '.' . "\r\n");
    316 
    317 			$reply = '';
    318 
    319 			while ($line = fgets($handle, 515)) {
    320 				$reply .= $line;
    321 
    322 				if (substr($line, 3, 1) == ' ') {
    323 					break;
    324 				}
    325 			}
    326 
    327 			if (substr($reply, 0, 3) != 250) {
    328 				throw new \Exception('Error: DATA not accepted from server!');
    329 			}
    330 
    331 			fputs($handle, 'QUIT' . "\r\n");
    332 
    333 			$reply = '';
    334 
    335 			while ($line = fgets($handle, 515)) {
    336 				$reply .= $line;
    337 
    338 				if (substr($line, 3, 1) == ' ') {
    339 					break;
    340 				}
    341 			}
    342 
    343 			if (substr($reply, 0, 3) != 221) {
    344 				throw new \Exception('Error: QUIT not accepted from server!');
    345 			}
    346 
    347 			fclose($handle);
    348 		}
    349 	}
    350 }