Smtp::write()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Email\SMTP
5
 *
6
 * Email\SMTP PHP driver.
7
 *
8
 * @package core
9
 * @author [email protected]
10
 * @copyright Caffeina srl - 2015 - http://caffeina.it
11
 */
12
13
namespace Email;
14
15
class Smtp implements Driver {
16
17
  protected
18
    $socket,
19
    $host,
20
    $secure,
21
    $port,
22
    $lastCode,
23
    $lastMessage,
24
    $username,
25
    $password;
26
27
  public function onInit($options) {
28
    $options        = (object)$options;
29
    $this->host     = isset($options->host)     ? $options->host     : 'localhost';
30
    $this->username = isset($options->username) ? $options->username : false;
31
    $this->secure   = isset($options->secure)   ? $options->secure   : !empty($this->username);
32
    $this->port     = isset($options->port)     ? $options->port     : ($this->secure ? 465 : 25);
33
    $this->password = isset($options->password) ? $options->password : false;
34
  }
35
36
  protected function connect(){
37
    if ($this->socket) $this->close();
38
    $url = ($this->secure ? 'tls' : 'tcp') ."://{$this->host}";
39
    $this->socket = fsockopen( $url, $this->port, $errno, $errstr, 30 );
40
    if (!$this->socket) throw new \Exception("Unable to connect to $url on port {$this->port}.");
41
    $this->lastMessage = '';
42
    $this->lastCode = 0;
43
  }
44
45
  public function close(){
46
    $this->socket && @fclose($this->socket);
47
  }
48
49
  protected function write($data, $nl = 1){
50
    $payload = $data . str_repeat("\r\n",$nl);
51
    fwrite($this->socket, $payload);
52
    \Email::trigger("smtp.console",$payload);
53
  }
54
55
  protected function expectCode($code){
56
57
    $this->lastMessage = '';
58
    while (substr($this->lastMessage, 3, 1) != ' '){
59
      $this->lastMessage = fgets($this->socket, 256);
60
    }
61
    $this->lastCode = 1 * substr($this->lastMessage, 0, 3);
62
    \Email::trigger("smtp.console",$this->lastMessage);
63
    if ($code != $this->lastCode) {
64
      throw new \Exception("Expected $code returned {$this->lastMessage}");
65
    }
66
    return true;
67
  }
68
69
  protected function cleanAddr($email){
70
    return preg_replace('((.*?)<([\w.@-]+)>(.*?))','$2',$email);
71
  }
72
73
  protected function SMTPmail($from,$to,$body){
74
    try {
75
    $this->connect();
76
    $this->expectCode(220);
77
78
    $this->write("EHLO {$this->host}");
79
    $this->expectCode(250);
80
81
    if ($this->username){
82
      $this->write("AUTH LOGIN");
83
      $this->expectCode(334);
84
      $this->write(base64_encode($this->username));
85
      $this->expectCode(334);
86
      $this->write(base64_encode($this->password));
87
      $this->expectCode(235);
88
    }
89
90
    $from = $this->cleanAddr($from);
91
92
    $this->write("MAIL FROM: <{$from}>");
93
    $this->expectCode(250);
94
95
    $to = $this->cleanAddr($to);
96
97
    $this->write("RCPT TO: <{$to}>");
98
    $this->expectCode(250);
99
100
    $this->write("DATA");
101
    $this->expectCode(354);
102
103
    $this->write($body);
104
105
    $this->write(".");
106
    $this->expectCode(250);
107
108
    $this->write("QUIT");
109
110
    $this->close();
111
    } catch (\Exception $e) {
112
      \Email::trigger('error',$e->getMessage());
113
      return false;
114
    }
115
    return true;
116
  }
117
118
  public function onSend(Envelope $envelope){
119
    $results = [];
120
    foreach ($envelope->to() as $to) {
121
      $results[$to] = $this->SMTPmail($envelope->from(), $to, $envelope->build());
122
    }
123
    return $results;
124
  }
125
126
}
127
128