Last active
June 28, 2024 12:00
-
-
Save HDDen/e70aa8db0f8c41e78f5c764d9ed99cf9 to your computer and use it in GitHub Desktop.
SMTP sending in one class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://212d.ru/blog/otpravka-pochty-cherez-smtp-s-pomoshchyu-php | |
<?php | |
/** | |
* SendMailSmtpClass | |
* | |
* Класс для отправки писем через SMTP с авторизацией | |
* Может работать через SSL протокол | |
* Тестировалось на почтовых серверах yandex.ru, mail.ru и gmail.com, smtp.beget.com | |
* | |
* v 1.1 | |
* Добавлено: | |
* - Приветствие сервера ehlo в приоритете, если не сервер не ответил, то шлется helo | |
* - Работа с кодировками utf-8 и windows-1251 | |
* - Возможность отправки нескольким получателям | |
* - Автоматическое формирование заголовков письма | |
* - Возможность фложения файлов в письмо | |
* | |
* @author Ipatov Evgeniy <[email protected]> | |
* @version 1.1 | |
*/ | |
class SendMailSmtpClass { | |
/** | |
* | |
* @var string $smtp_username - логин | |
* @var string $smtp_password - пароль | |
* @var string $smtp_host - хост | |
* @var string $smtp_from - от кого | |
* @var integer $smtp_port - порт | |
* @var string $smtp_charset - кодировка | |
* | |
*/ | |
public $smtp_username; | |
public $smtp_password; | |
public $smtp_host; | |
public $smtp_from; | |
public $smtp_port; | |
public $smtp_charset; | |
public $boundary; | |
public $addFile = false; | |
public $multipart; | |
public function __construct($smtp_username, $smtp_password, $smtp_host, $smtp_port = 25, $smtp_charset = "utf-8") { | |
$this->smtp_username = $smtp_username; | |
$this->smtp_password = $smtp_password; | |
$this->smtp_host = $smtp_host; | |
$this->smtp_port = $smtp_port; | |
$this->smtp_charset = $smtp_charset; | |
// разделитель файлов | |
$this->boundary = "--".md5(uniqid(time())); | |
$this->multipart = ""; | |
} | |
/** | |
* Отправка письма | |
* | |
* @param string $mailTo - получатель письма | |
* @param string $subject - тема письма | |
* @param string $message - тело письма | |
* @param string $smtp_from - отправитель. Массив с именем и e-mail | |
* | |
* @return bool|string В случаи отправки вернет true, иначе текст ошибки | |
* | |
*/ | |
function send($mailTo, $subject, $message, $smtp_from) { | |
// подготовка содержимого письма к отправке | |
$contentMail = $this->getContentMail($subject, $message, $smtp_from,$mailTo); | |
try { | |
if(!$socket = @fsockopen($this->smtp_host, $this->smtp_port, $errorNumber, $errorDescription, 30)){ | |
throw new Exception($errorNumber.".".$errorDescription); | |
} | |
if (!$this->_parseServer($socket, "220")){ | |
throw new Exception('Connection error'); | |
} | |
$server_name = $_SERVER["SERVER_NAME"]; | |
fputs($socket, "EHLO $server_name\r\n"); | |
if(!$this->_parseServer($socket, "250")){ | |
// если сервер не ответил на EHLO, то отправляем HELO | |
fputs($socket, "HELO $server_name\r\n"); | |
if (!$this->_parseServer($socket, "250")) { | |
fclose($socket); | |
throw new Exception('Error of command sending: HELO'); | |
} | |
} | |
fputs($socket, "AUTH LOGIN\r\n"); | |
if (!$this->_parseServer($socket, "334")) { | |
fclose($socket); | |
throw new Exception('Autorization error 1'); | |
} | |
fputs($socket, base64_encode($this->smtp_username) . "\r\n"); | |
if (!$this->_parseServer($socket, "334")) { | |
fclose($socket); | |
throw new Exception('Autorization error 2'); | |
} | |
fputs($socket, base64_encode($this->smtp_password) . "\r\n"); | |
if (!$this->_parseServer($socket, "235")) { | |
fclose($socket); | |
throw new Exception('Autorization error 3'); | |
} | |
fputs($socket, "MAIL FROM: <".$this->smtp_username.">\r\n"); | |
if (!$this->_parseServer($socket, "250")) { | |
fclose($socket); | |
throw new Exception('Error of command sending: MAIL FROM'); | |
} | |
$mailTo = str_replace(" ", "", $mailTo); | |
$emails_to_array = explode(',', $mailTo); | |
foreach($emails_to_array as $email) { | |
fputs($socket, "RCPT TO: <{$mailTo}>\r\n"); | |
if (!$this->_parseServer($socket, "250")) { | |
fclose($socket); | |
throw new Exception('Error of command sending: RCPT TO'); | |
} | |
} | |
fputs($socket, "DATA\r\n"); | |
if (!$this->_parseServer($socket, "354")) { | |
fclose($socket); | |
throw new Exception('Error of command sending: DATA'); | |
} | |
fputs($socket, $contentMail."\r\n.\r\n"); | |
if (!$this->_parseServer($socket, "250")) { | |
fclose($socket); | |
throw new Exception("E-mail didn't sent"); | |
} | |
fputs($socket, "QUIT\r\n"); | |
fclose($socket); | |
} catch (Exception $e) { | |
return $e->getMessage(); | |
} | |
return true; | |
} | |
// добавление файла в письмо | |
public function addFile($path){ | |
$file = @fopen($path, "rb"); | |
if(!$file) { | |
throw new Exception("File `{$path}` didn't open"); | |
} | |
$data = fread($file, filesize( $path ) ); | |
fclose($file); | |
$filename = basename($path); | |
$multipart = ''; | |
$multipart .= "\r\n--{$this->boundary}\r\n"; | |
$multipart .= "Content-Type: application/octet-stream; name=\"$filename\"\r\n"; | |
$multipart .= "Content-Transfer-Encoding: base64\r\n"; | |
$multipart .= "Content-Disposition: attachment; filename=\"$filename\"\r\n"; | |
$multipart .= "\r\n"; | |
$multipart .= chunk_split(base64_encode($data)); | |
$this->multipart .= $multipart; | |
$this->addFile = true; | |
} | |
// парсинг ответа сервера | |
private function _parseServer($socket, $response) { | |
while (@substr($responseServer, 3, 1) != ' ') { | |
if (!($responseServer = fgets($socket, 256))) { | |
return false; | |
} | |
} | |
if (!(substr($responseServer, 0, 3) == $response)) { | |
return false; | |
} | |
return true; | |
} | |
// подготовка содержимого письма | |
private function getContentMail($subject, $message, $smtp_from,$mailTo){ | |
// если кодировка windows-1251, то перекодируем тему | |
if( strtolower($this->smtp_charset) == "windows-1251" ){ | |
$subject = iconv('utf-8', 'windows-1251', $subject); | |
} | |
$contentMail = "Date: " . date("D, d M Y H:i:s") . " UT\r\n"; | |
$contentMail .= 'Subject: =?' . $this->smtp_charset . '?B?' . base64_encode($subject) . "=?=\r\n"; | |
// заголовок письма | |
$headers = "MIME-Version: 1.0\r\n"; | |
// кодировка письма | |
if($this->addFile){ | |
// если есть файлы | |
$headers .= "Content-Type: multipart/mixed; boundary=\"{$this->boundary}\"\r\n"; | |
}else{ | |
$headers .= "Content-type: text/html; charset={$this->smtp_charset}\r\n"; | |
} | |
$headers .= "From: {$smtp_from[0]} <{$smtp_from[1]}>\r\n"; // от кого письмо | |
$headers.= "To: ".$mailTo."\r\n"; | |
$contentMail .= $headers . "\r\n"; | |
if($this->addFile){ | |
// если есть файлы | |
$multipart = "--{$this->boundary}\r\n"; | |
$multipart .= "Content-Type: text/html; charset=utf-8\r\n"; | |
$multipart .= "Content-Transfer-Encoding: base64\r\n"; | |
$multipart .= "\r\n"; | |
$multipart .= chunk_split(base64_encode($message)); | |
// файлы | |
$multipart .= $this->multipart; | |
$multipart .= "\r\n--{$this->boundary}--\r\n"; | |
$contentMail .= $multipart; | |
}else{ | |
$contentMail .= $message ."\r\n"; | |
} | |
// если кодировка windows-1251, то все письмо перекодируем | |
if( strtolower($this->smtp_charset) == "windows-1251" ){ | |
$contentMail = iconv('utf-8', 'windows-1251', $contentMail); | |
} | |
return $contentMail; | |
} | |
} | |
?><?php | |
require_once "SendMailSmtpClass.php"; // подключаем класс | |
// beget | |
$mailSMTP = new SendMailSmtpClass('mail@local_domain.ru', 'pwd', 'ssl://smtp.beget.com', 465, "UTF-8"); | |
//ДЛЯ YANDEX.RU | |
//$mailSMTP = new SendMailSmtpClass('[email protected]', 'pass', 'ssl://smtp.yandex.ru', 465, "UTF-8"); | |
//ДЛЯ MAIL.RU | |
//$mailSMTP = new SendMailSmtpClass('[email protected]', 'pass', 'ssl://smtp.mail.ru', 465, "UTF-8"); | |
//РАСШИФРОВКА ЗНАЧЕНИЙ | |
//$mailSMTP = new SendMailSmtpClass('логин', 'пароль', 'хост', 'порт', 'кодировка письма'); | |
// файлы | |
$mailSMTP->addFile("file1.jpg"); | |
$mailSMTP->addFile("file2.jpg"); | |
$from = array("Блог программиста", // Имя отправителя | |
"mail@local_domain.ru" // почта отправителя | |
); | |
$result = $mailSMTP->send('[email protected]', 'Тема письма', 'Текст письма', $from); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment