99 * @license MIT
1010 * @link http://ddrv.ru/
1111 *
12- * @property string $sender
13- * @property string $subject
14- * @property array $headers
15- * @property array $body
16- * @property array $attachments
12+ * @property array $sender
13+ * @property string $subject
14+ * @property array $headers
15+ * @property array $body
16+ * @property array $attachments
17+ * @property array $address
18+ * @property string $log
19+ * @property boolean $smtp
20+ * @property resource $socket
1721 */
1822class Mailer {
1923 /**
2024 * Version of Mailer
2125 */
22- const MAILER_VERSION = '2.0.0 ' ;
26+ const MAILER_VERSION = '2.1.0 ' ;
27+
28+ /**
29+ * End of line symbol
30+ */
31+ const EOL = "\r\n" ;
2332
2433 /**
2534 * Send from this Email.
2635 *
27- * @var string
36+ * @var array
2837 */
2938 protected $ sender ;
3039
@@ -56,6 +65,34 @@ class Mailer {
5665 */
5766 protected $ attachments ;
5867
68+ /**
69+ * Address.
70+ *
71+ * @var array
72+ */
73+ protected $ address ;
74+
75+ /**
76+ * SMTP Socket.
77+ *
78+ * @var resource
79+ */
80+ protected $ socket ;
81+
82+ /**
83+ * use SMTP.
84+ *
85+ * @var boolean
86+ */
87+ protected $ smtp ;
88+
89+ /**
90+ * Log.
91+ *
92+ * @var string
93+ */
94+ protected $ log ;
95+
5996 /**
6097 * Mailer constructor.
6198 *
@@ -65,6 +102,47 @@ public function __construct()
65102 $ this ->reset ();
66103 }
67104
105+ /**
106+ * Mailer destructor.
107+ *
108+ */
109+ public function __destruct ()
110+ {
111+ if ($ this ->smtp ) {
112+ $ this ->smtpCommand ('QUIT ' );
113+ $ this ->socket = null ;
114+ }
115+ }
116+
117+ /**
118+ * Set SMTP.
119+ *
120+ * @param string $host
121+ * @param integer $port
122+ * @param string $user
123+ * @param string $password
124+ * @void
125+ */
126+ public function smtp ($ host =null , $ port =null , $ user =null , $ password =null , $ domain =null )
127+ {
128+ $ this ->smtp = false ;
129+ $ host = (string )$ host ;
130+ $ port = (integer )$ port ;
131+ $ user = (string )$ user ;
132+ $ password = (string )$ password ;
133+ $ domain = (string )$ domain ;
134+ if ($ host && $ port ) {
135+ $ this ->smtp = true ;
136+ $ this ->socket = fsockopen ((string )$ host , (int )$ port , $ errno , $ errstr , 30 );
137+ $ test = fgets ($ this ->socket , 512 );
138+ unset($ test );
139+ $ this ->smtpCommand ('HELO ' .$ domain );
140+ $ this ->smtpCommand ('AUTH LOGIN ' );
141+ $ this ->smtpCommand (base64_encode ($ user ));
142+ $ this ->smtpCommand (base64_encode ($ password ));
143+ }
144+ }
145+
68146 /**
69147 * Set sender.
70148 *
@@ -74,12 +152,42 @@ public function __construct()
74152 */
75153 public function sender ($ senderEmail , $ senderName ='' )
76154 {
77- $ this -> sender = (string )$ senderEmail ;
155+ $ senderEmail = (string )$ senderEmail ;
78156 $ senderName = (string )$ senderName ;
79- if ($ senderName ) {
80- $ this ->sender .= '< ' .$ senderName .'> ' ;
157+ $ this ->sender = [
158+ 'address ' => $ senderEmail ,
159+ 'name ' => $ senderName ,
160+ ];
161+ $ from = empty ($ senderName )?'< ' .$ senderEmail .'> ' :$ senderName .' < ' .$ senderEmail .'> ' ;
162+ $ this ->setHeader ('From ' , $ from , true );
163+ $ this ->setHeader ('Reply-To ' , $ from , true );
164+ }
165+
166+ /**
167+ * Add address.
168+ *
169+ * @param string $addressEmail
170+ * @param string $addressName
171+ * @void
172+ */
173+ public function addAddress ($ addressEmail , $ addressName ='' )
174+ {
175+ $ addressEmail = (string )$ addressEmail ;
176+ $ addressName = (string )$ addressName ;
177+ $ this ->address [$ addressEmail ] = $ addressName ;
178+ }
179+
180+ /**
181+ * Remove address.
182+ *
183+ * @param string $addressEmail
184+ * @void
185+ */
186+ public function removeAddress ($ addressEmail )
187+ {
188+ if (isset ($ this ->address [$ addressEmail ])) {
189+ unset($ this ->address [$ addressEmail ]);
81190 }
82- $ this ->reset ();
83191 }
84192
85193 /**
@@ -160,17 +268,44 @@ public function attachFromFile($file, $attachmentName)
160268 /**
161269 * Send message.
162270 *
163- * @param string $address
164271 * @void
165272 */
166- public function send ($ address )
273+ public function send ()
167274 {
275+ if (empty ($ this ->address )) return ;
168276 $ body = empty ($ this ->attachments )?$ this ->getBodySimpleText ():$ this ->getBodyMultipart ();
169277 $ headers = implode ("\r\n" ,$ this ->headers );
170- mail ($ address , $ this ->subject , $ body , $ headers );
278+ if ($ this ->smtp ) {
279+ $ this ->smtpCommand ('MAIL FROM: < ' .$ this ->sender ['address ' ].'> ' );
280+ foreach ($ this ->address as $ address =>$ name ) {
281+ $ this ->smtpCommand ('RCPT TO: < ' .$ address .'> ' );
282+ }
283+ $ this ->smtpCommand ('DATA ' );
284+ $ headers = 'SUBJECT: ' .$ this ->subject .self ::EOL .$ headers ;
285+ $ data = $ headers .self ::EOL .self ::EOL .$ body .self ::EOL .'. ' ;
286+ $ this ->smtpCommand ($ data );
287+ } else {
288+ $ addresses = [];
289+ foreach ($ this ->address as $ address =>$ name ) {
290+ $ addresses [] = $ name .' < ' .$ address .'> ' ;
291+ }
292+ $ list = implode (', ' ,$ addresses );
293+ $ this ->log .= '> mail( \'' .$ list .'\', \'' .$ this ->subject .'\', \'' .$ body .'\', \'' .$ headers .'\'); ' .PHP_EOL ;
294+ mail ($ list , $ this ->subject , $ body , $ headers );
295+ }
171296 $ this ->reset ();
172297 }
173298
299+ /**
300+ * Return log
301+ *
302+ * @return string
303+ */
304+ public function getLog ()
305+ {
306+ return $ this ->log ;
307+ }
308+
174309 /**
175310 * Reset body and headers for nex mail
176311 * @void
@@ -181,8 +316,7 @@ protected function reset()
181316 $ this ->body = [];
182317 $ this ->headers = [];
183318 $ this ->attachments = [];
184- $ this ->setHeader ('From ' , $ this ->sender , false );
185- $ this ->setHeader ('Reply-To ' , $ this ->sender , false );
319+ $ this ->address = [];
186320 $ this ->setHeader ('MIME-Version ' ,'1.0 ' , false );
187321 $ this ->setHeader ('X-Mailer ' , 'Mailer- ' .self ::MAILER_VERSION .' (https://github.com/ddrv/mailer) ' , false );
188322 }
@@ -245,27 +379,44 @@ protected function getBodySimpleText()
245379 protected function getBodyMultipart ()
246380 {
247381 $ separator = md5 (time ());
248- $ eol = "\r\n" ;
249382 $ this ->setHeader ('Content-Type ' , 'multipart/mixed; boundary=" ' .$ separator .'" ' , true );
250383 $ this ->setHeader ('Content-Transfer-Encoding ' , '7bit ' , true );
251384 $ body [] = null ;
252- $ b = $ eol .'Content-type: text/html; charset=utf8 ' .$ eol ;
385+ $ b = self :: EOL .'Content-type: text/html; charset=utf8 ' .self :: EOL ;
253386 $ message = isset ($ this ->body ['content ' ])?$ this ->body ['content ' ]:null ;
254- $ b .= 'Content-Transfer-Encoding: 8bit ' .$ eol ;
255- $ b .= $ eol .$ message .$ eol ;
387+ $ b .= 'Content-Transfer-Encoding: 8bit ' .self :: EOL ;
388+ $ b .= self :: EOL .$ message .self :: EOL ;
256389 $ body [] = $ b ;
257390 foreach ($ this ->attachments as $ attachment =>$ data ) {
258- $ b = $ eol ;
391+ $ b = self :: EOL ;
259392 if (!empty ($ data ['headers ' ])) {
260393 foreach ($ data ['headers ' ] as $ header =>$ value ) {
261- $ b .= $ header .': ' .$ value .$ eol ;
394+ $ b .= $ header .': ' .$ value .self :: EOL ;
262395 }
263396 }
264397 $ content = isset ($ data ['content ' ])?$ data ['content ' ]:null ;
265- $ b .= $ eol .$ content .$ eol ;
398+ $ b .= self :: EOL .$ content .self :: EOL ;
266399 $ body [] = $ b ;
267400 }
268401 $ body [] = '-- ' ;
269402 return implode ('-- ' .$ separator ,$ body );
270403 }
404+
405+ /**
406+ * Run SMTP Command
407+ *
408+ * @param $command
409+ * @void
410+ */
411+ protected function smtpCommand ($ command )
412+ {
413+ $ this ->log .= '> ' . $ command .PHP_EOL ;
414+ if ($ this ->socket ) {
415+ fputs ($ this ->socket , $ command .self ::EOL );
416+ $ response = fgets ($ this ->socket , 512 );
417+ $ this ->log .= '< ' . $ response .PHP_EOL ;
418+ } else {
419+ $ this ->log .= '< SMTP socket undefined. ' .PHP_EOL ;
420+ }
421+ }
271422}
0 commit comments