1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Omnimail; |
4
|
|
|
|
5
|
|
|
use Omnimail\Exception\EmailDeliveryException; |
6
|
|
|
use Omnimail\Exception\Exception; |
7
|
|
|
use Omnimail\Exception\InvalidRequestException; |
8
|
|
|
use Psr\Log\LoggerInterface; |
9
|
|
|
|
10
|
|
|
class Mandrill implements EmailSenderInterface |
11
|
|
|
{ |
12
|
|
|
private $apiKey; |
13
|
|
|
private $ipPool; |
14
|
|
|
private $logger; |
15
|
|
|
private $mandrill; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* @param string $apiKey |
19
|
|
|
* @param string $ipPool |
20
|
|
|
* @param LoggerInterface|null $logger |
21
|
|
|
*/ |
22
|
|
|
public function __construct($apiKey, $ipPool = null, LoggerInterface $logger = null) |
23
|
|
|
{ |
24
|
|
|
$this->apiKey = $apiKey; |
25
|
|
|
$this->ipPool = $ipPool; |
26
|
|
|
$this->logger = $logger; |
27
|
|
|
$this->mandrill = new \Mandrill($apiKey); |
28
|
|
|
} |
29
|
|
|
|
30
|
|
|
public function send(EmailInterface $email) |
31
|
|
|
{ |
32
|
|
|
try { |
33
|
|
|
$from = $email->getFrom(); |
34
|
|
|
|
35
|
|
|
$message = [ |
36
|
|
|
'subject' => 'example subject', |
37
|
|
|
'from_email' => $from['email'], |
38
|
|
|
'to' => $this->mapEmails($email->getTo()) |
39
|
|
|
]; |
40
|
|
|
|
41
|
|
|
if (!empty($from['name'])) { |
42
|
|
|
$message['from_name'] = $from['name']; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
if ($email->getReplyTo()) { |
46
|
|
|
$message['headers'] = [ |
47
|
|
|
'Reply-To' => $this->mapEmailsString($email->getReplyTo()) |
48
|
|
|
]; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
if ($email->getCc()) { |
52
|
|
|
$message['to'] = array_merge( |
53
|
|
|
$message['to'], |
54
|
|
|
$this->mapEmails($email->getCc(), 'cc') |
55
|
|
|
); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
if ($email->getBcc()) { |
59
|
|
|
$message['to'] = array_merge( |
60
|
|
|
$message['to'], |
61
|
|
|
$this->mapEmails($email->getBcc(), 'bcc') |
62
|
|
|
); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
if ($email->getTextBody()) { |
66
|
|
|
$message['text'] = $email->getTextBody(); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
if ($email->getHtmlBody()) { |
70
|
|
|
$message['html'] = $email->getHtmlBody(); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
View Code Duplication |
if ($email->getAttachements()) { |
|
|
|
|
74
|
|
|
$attachements = []; |
75
|
|
|
foreach ($email->getAttachements() as $attachement) { |
76
|
|
|
$item = [ |
77
|
|
|
'type' => $attachement->getMimeType(), |
78
|
|
|
'name' => $attachement->getName() |
79
|
|
|
]; |
80
|
|
|
if (!$attachement->getPath() && $attachement->getContent()) { |
81
|
|
|
$item['content'] = base64_encode($attachement->getContent()); |
82
|
|
|
} elseif ($attachement->getPath()) { |
83
|
|
|
$item['content'] = base64_encode(file_get_contents($attachement->getPath())); |
84
|
|
|
} |
85
|
|
|
$attachements[] = $item; |
86
|
|
|
} |
87
|
|
|
$message['attachments'] = $attachements; |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
$result = $this->mandrill->messages->send($message, false, $this->ipPool); |
|
|
|
|
91
|
|
|
if ($result && $result['status'] && |
92
|
|
|
($result['status'] === 'sent' || $result['status'] === 'queued' || $result['status'] === 'scheduled') |
93
|
|
|
) { |
94
|
|
|
if ($this->logger) { |
95
|
|
|
$this->logger->info("Email sent: '{$email->getSubject()}'", $email); |
|
|
|
|
96
|
|
|
} |
97
|
|
|
} else { |
98
|
|
|
if (!$result || !$result['status']) { |
99
|
|
|
$result = ['status' => 'invalid']; |
100
|
|
|
} |
101
|
|
|
if (!$result || !$result['reject_reason']) { |
102
|
|
|
$result = ['reject_reason' => 'Unknown']; |
103
|
|
|
} |
104
|
|
|
switch ($result['status']) { |
105
|
|
|
case 'invalid': |
106
|
|
|
throw new InvalidRequestException($result['reject_reason']); |
107
|
|
|
case 'rejected': |
108
|
|
|
throw new EmailDeliveryException($result['reject_reason']); |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
} catch (Exception $e) { |
112
|
|
|
throw $e; |
113
|
|
|
} catch (\Mandrill_Error $e) { |
114
|
|
|
throw new InvalidRequestException($e->getMessage(), 601, $e); |
115
|
|
|
} |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* @param array $emails |
120
|
|
|
* @param string $type |
121
|
|
|
* @return array |
122
|
|
|
*/ |
123
|
|
|
private function mapEmails(array $emails, $type = 'to') |
124
|
|
|
{ |
125
|
|
|
$returnValue = []; |
126
|
|
|
foreach ($emails as $email) { |
127
|
|
|
$returnValue[] = $this->mapEmail($email, $type); |
128
|
|
|
} |
129
|
|
|
return $returnValue; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* @param array $email |
134
|
|
|
* @param string $type |
135
|
|
|
* @return array |
136
|
|
|
*/ |
137
|
|
View Code Duplication |
private function mapEmail(array $email, $type = 'to') |
|
|
|
|
138
|
|
|
{ |
139
|
|
|
$returnValue = ['email' => $email['email'], 'type' => $type]; |
140
|
|
|
if ($email['name']) { |
141
|
|
|
$returnValue['name'] = $email['name']; |
142
|
|
|
} |
143
|
|
|
return $returnValue; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* @param array $emails |
148
|
|
|
* @return string |
149
|
|
|
*/ |
150
|
|
View Code Duplication |
private function mapEmailsString(array $emails) |
|
|
|
|
151
|
|
|
{ |
152
|
|
|
$returnValue = ''; |
153
|
|
|
foreach ($emails as $email) { |
154
|
|
|
$returnValue .= $this->mapEmailString($email) . ', '; |
155
|
|
|
} |
156
|
|
|
return $returnValue ? substr($returnValue, 0, -2) : ''; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* @param array $email |
161
|
|
|
* @return string |
162
|
|
|
*/ |
163
|
|
|
private function mapEmailString(array $email) |
164
|
|
|
{ |
165
|
|
|
return !empty($email['name']) ? "'{$email['name']}' <{$email['email']}>" : $email['email']; |
166
|
|
|
} |
167
|
|
|
} |
168
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.