1
1
<?php
2
2
/**
3
- * Copyright © Magento, Inc. All rights reserved.
4
- * See COPYING.txt for license details .
3
+ * Copyright 2015 Adobe
4
+ * All Rights Reserved .
5
5
*/
6
6
declare (strict_types=1 );
7
7
8
8
namespace Magento \Email \Model ;
9
9
10
- use Laminas \Mail \Transport \Smtp ;
11
- use Laminas \Mail \Transport \SmtpOptions ;
10
+ use Magento \Framework \Mail \EmailMessageInterface ;
11
+ use Symfony \Component \Mailer \Exception \TransportExceptionInterface ;
12
+ use Symfony \Component \Mailer \Mailer ;
13
+ use Symfony \Component \Mailer \Transport \NativeTransportFactory ;
14
+ use Symfony \Component \Mailer \Transport \Dsn ;
15
+ use Symfony \Component \Mailer \Transport \TransportInterface as SymfonyTransportInterface ;
16
+ use Symfony \Component \Mailer \Transport \Smtp \EsmtpTransport ;
17
+ use Symfony \Component \Mailer \Transport \Smtp \Auth \LoginAuthenticator ;
18
+ use Symfony \Component \Mailer \Transport \Smtp \Auth \PlainAuthenticator ;
12
19
use Magento \Framework \App \Config \ScopeConfigInterface ;
13
20
use Magento \Framework \App \ObjectManager ;
14
21
use Magento \Framework \Exception \MailException ;
15
- use Magento \Framework \Mail \MessageInterface ;
16
22
use Magento \Framework \Mail \TransportInterface ;
17
23
use Magento \Framework \Phrase ;
24
+ use Symfony \Component \Mime \Message as SymfonyMessage ;
18
25
use Magento \Store \Model \ScopeInterface ;
19
- use Laminas \Mail \Message ;
20
- use Laminas \Mail \Transport \Sendmail ;
21
- use Laminas \Mail \Transport \TransportInterface as LaminasTransportInterface ;
22
26
use Psr \Log \LoggerInterface ;
23
27
24
28
/**
25
29
* Class that responsible for filling some message data before transporting it.
26
- * @see \Laminas\Mail\Transport\Sendmail is used for transport
30
+ * @see \Symfony\Component\Mailer\Transport is used for transport
27
31
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
28
32
*/
29
33
class Transport implements TransportInterface
@@ -84,48 +88,41 @@ class Transport implements TransportInterface
84
88
*
85
89
* @var int
86
90
*/
87
- private $ isSetReturnPath ;
91
+ private int $ isSetReturnPath ;
88
92
89
93
/**
90
94
* @var string|null
91
95
*/
92
- private $ returnPathValue ;
96
+ private ? string $ returnPathValue ;
93
97
94
98
/**
95
99
* @var ScopeConfigInterface
96
100
*/
97
- private $ scopeConfig ;
101
+ private ScopeConfigInterface $ scopeConfig ;
98
102
99
103
/**
100
- * @var LaminasTransportInterface|null
104
+ * @var SymfonyTransportInterface
101
105
*/
102
- private $ laminasTransport ;
106
+ private SymfonyTransportInterface $ symfonyTransport ;
103
107
104
108
/**
105
- * @var null|string|array|\Traversable
109
+ * @var EmailMessageInterface
106
110
*/
107
- private $ parameters ;
108
-
109
- /**
110
- * @var MessageInterface
111
- */
112
- private $ message ;
111
+ private EmailMessageInterface $ message ;
113
112
114
113
/**
115
114
* @var LoggerInterface|null
116
115
*/
117
- private $ logger ;
116
+ private ? LoggerInterface $ logger ;
118
117
119
118
/**
120
- * @param MessageInterface $message Email message object
119
+ * @param EmailMessageInterface $message Email message object
121
120
* @param ScopeConfigInterface $scopeConfig Core store config
122
- * @param null|string|array|\Traversable $parameters Config options for sendmail parameters
123
121
* @param LoggerInterface|null $logger
124
122
*/
125
123
public function __construct (
126
- MessageInterface $ message ,
124
+ EmailMessageInterface $ message ,
127
125
ScopeConfigInterface $ scopeConfig ,
128
- $ parameters = null ,
129
126
?LoggerInterface $ logger = null
130
127
) {
131
128
$ this ->isSetReturnPath = (int ) $ scopeConfig ->getValue (
@@ -138,131 +135,126 @@ public function __construct(
138
135
);
139
136
$ this ->message = $ message ;
140
137
$ this ->scopeConfig = $ scopeConfig ;
141
- $ this ->parameters = $ parameters ;
142
138
$ this ->logger = $ logger ?: ObjectManager::getInstance ()->get (LoggerInterface::class);
143
139
}
144
140
145
141
/**
146
- * Get the LaminasTransport based on the configuration.
142
+ * Get the SymfonyTransport based on the configuration.
147
143
*
148
- * @return LaminasTransportInterface
144
+ * @return SymfonyTransportInterface
149
145
*/
150
- public function getTransport (): LaminasTransportInterface
146
+ public function getTransport (): SymfonyTransportInterface
151
147
{
152
- if ($ this ->laminasTransport === null ) {
153
- $ transport = $ this ->scopeConfig ->getValue (
154
- self ::XML_PATH_TRANSPORT ,
155
- ScopeInterface::SCOPE_STORE
156
- );
157
-
158
- if ($ transport === 'smtp ' ) {
159
- $ this ->laminasTransport = $ this ->createSmtpTransport ();
148
+ if (!isset ($ this ->symfonyTransport )) {
149
+ $ transportType = $ this ->scopeConfig ->getValue (self ::XML_PATH_TRANSPORT );
150
+ if ($ transportType === 'smtp ' ) {
151
+ $ this ->symfonyTransport = $ this ->createSmtpTransport ();
160
152
} else {
161
- $ this ->laminasTransport = $ this ->createSendmailTransport ();
153
+ $ this ->symfonyTransport = $ this ->createSendmailTransport ();
162
154
}
163
155
}
164
156
165
- return $ this ->laminasTransport ;
157
+ return $ this ->symfonyTransport ;
166
158
}
167
159
168
160
/**
169
- * @inheritdoc
161
+ * Build the DSN string for Symfony transport based on configuration.
162
+ *
163
+ * @return SymfonyTransportInterface
170
164
*/
171
- public function sendMessage ()
165
+ private function createSmtpTransport (): SymfonyTransportInterface
172
166
{
173
- try {
174
- $ laminasMessage = Message::fromString ($ this ->message ->getRawMessage ())->setEncoding ('utf-8 ' );
175
- if (2 === $ this ->isSetReturnPath && $ this ->returnPathValue ) {
176
- $ laminasMessage ->setSender ($ this ->returnPathValue );
177
- } elseif (1 === $ this ->isSetReturnPath && $ laminasMessage ->getFrom ()->count ()) {
178
- $ fromAddressList = $ laminasMessage ->getFrom ();
179
- $ fromAddressList ->rewind ();
180
- $ laminasMessage ->setSender ($ fromAddressList ->current ()->getEmail ());
181
- }
167
+ $ host = $ this ->scopeConfig ->getValue (self ::XML_PATH_HOST , ScopeInterface::SCOPE_STORE );
168
+ $ port = (int ) $ this ->scopeConfig ->getValue (self ::XML_PATH_PORT , ScopeInterface::SCOPE_STORE );
169
+ $ username = $ this ->scopeConfig ->getValue (self ::XML_PATH_USERNAME , ScopeInterface::SCOPE_STORE );
170
+ $ password = $ this ->scopeConfig ->getValue (self ::XML_PATH_PASSWORD , ScopeInterface::SCOPE_STORE );
171
+ $ auth = $ this ->scopeConfig ->getValue (self ::XML_PATH_AUTH , ScopeInterface::SCOPE_STORE );
172
+ $ ssl = $ this ->scopeConfig ->getValue (self ::XML_PATH_SSL , ScopeInterface::SCOPE_STORE );
173
+ $ tls = false ;
174
+
175
+ if ($ ssl === 'tls ' ) {
176
+ $ tls = true ;
177
+ }
182
178
183
- $ this ->getTransport ()->send ($ laminasMessage );
184
- } catch (\Exception $ e ) {
185
- $ this ->logger ->error ($ e );
186
- throw new MailException (new Phrase ('Unable to send mail. Please try again later. ' ), $ e );
179
+ $ transport = new EsmtpTransport ($ host , $ port , $ tls );
180
+ if ($ username ) {
181
+ $ transport ->setUsername ($ username );
182
+ }
183
+ if ($ password ) {
184
+ $ transport ->setPassword ($ password );
187
185
}
186
+
187
+ switch ($ auth ) {
188
+ case 'plain ' :
189
+ $ transport ->setAuthenticators ([new PlainAuthenticator ()]);
190
+ break ;
191
+ case 'login ' :
192
+ $ transport ->setAuthenticators ([new LoginAuthenticator ()]);
193
+ break ;
194
+ case 'none ' :
195
+ break ;
196
+ default :
197
+ throw new \InvalidArgumentException ('Invalid authentication type: ' . $ auth );
198
+ }
199
+
200
+ return $ transport ;
188
201
}
189
202
190
203
/**
191
- * @inheritdoc
204
+ * Create a Sendmail transport for Symfony Mailer.
205
+ *
206
+ * @return SymfonyTransportInterface
192
207
*/
193
- public function getMessage ()
208
+ private function createSendmailTransport (): SymfonyTransportInterface
194
209
{
195
- return $ this ->message ;
210
+ $ dsn = new Dsn ('native ' , 'default ' );
211
+ $ nativeTransportFactory = new NativeTransportFactory ();
212
+ return $ nativeTransportFactory ->create ($ dsn );
196
213
}
197
214
198
215
/**
199
- * Create a Smtp LaminasTransport.
200
- *
201
- * @return Smtp
216
+ * @inheritdoc
202
217
*/
203
- private function createSmtpTransport (): Smtp
218
+ public function sendMessage (): void
204
219
{
205
- $ host = $ this ->scopeConfig ->getValue (
206
- self ::XML_PATH_HOST ,
207
- ScopeInterface::SCOPE_STORE
208
- );
209
-
210
- $ port = $ this ->scopeConfig ->getValue (
211
- self ::XML_PATH_PORT ,
212
- ScopeInterface::SCOPE_STORE
213
- );
214
-
215
- $ username = $ this ->scopeConfig ->getValue (
216
- self ::XML_PATH_USERNAME ,
217
- ScopeInterface::SCOPE_STORE
218
- );
219
-
220
- $ password = $ this ->scopeConfig ->getValue (
221
- self ::XML_PATH_PASSWORD ,
222
- ScopeInterface::SCOPE_STORE
223
- );
224
-
225
- $ auth = $ this ->scopeConfig ->getValue (
226
- self ::XML_PATH_AUTH ,
227
- ScopeInterface::SCOPE_STORE
228
- );
229
-
230
- $ ssl = $ this ->scopeConfig ->getValue (
231
- self ::XML_PATH_SSL ,
232
- ScopeInterface::SCOPE_STORE
233
- );
234
-
235
- $ options = [
236
- 'name ' => 'localhost ' ,
237
- 'host ' => $ host ,
238
- 'port ' => $ port ,
239
- 'connection_config ' => [
240
- 'username ' => $ username ,
241
- 'password ' => $ password ,
242
- ]
243
- ];
244
-
245
- if ($ auth && $ auth !== 'none ' ) {
246
- $ options ['connection_class ' ] = $ auth ;
220
+ try {
221
+ $ email = $ this ->message ->getSymfonyMessage ();
222
+ $ this ->setReturnPath ($ email );
223
+ $ mailer = new Mailer ($ this ->getTransport ());
224
+ $ mailer ->send ($ email );
225
+ } catch (TransportExceptionInterface $ transportException ) {
226
+ $ this ->logger ->error ('Transport error while sending email: ' . $ transportException ->getMessage ());
227
+ throw new MailException (
228
+ new Phrase ('Transport error: Unable to send mail at this time. ' ),
229
+ $ transportException
230
+ );
231
+ } catch (\Exception $ e ) {
232
+ $ this ->logger ->error ($ e );
233
+ throw new MailException (new Phrase ('Unable to send mail. Please try again later. ' ), $ e );
247
234
}
235
+ }
248
236
249
- if ($ ssl && $ ssl !== 'none ' ) {
250
- $ options ['connection_config ' ]['ssl ' ] = $ ssl ;
237
+ /**
238
+ * Set the return path if configured.
239
+ *
240
+ * @param SymfonyMessage $email
241
+ */
242
+ private function setReturnPath (SymfonyMessage $ email ): void
243
+ {
244
+ if ($ this ->isSetReturnPath === 2 && $ this ->returnPathValue ) {
245
+ $ email ->getHeaders ()->addMailboxListHeader ('Sender ' , [$ this ->returnPathValue ]);
246
+ } elseif ($ this ->isSetReturnPath === 1 &&
247
+ !empty ($ fromAddresses = $ email ->getHeaders ()->get ('From ' )?->getAddresses())) {
248
+ reset ($ fromAddresses );
249
+ $ email ->getHeaders ()->addMailboxListHeader ('Sender ' , [current ($ fromAddresses )->getAddress ()]);
251
250
}
252
-
253
- $ transport = new Smtp ();
254
- $ transport ->setOptions (new SmtpOptions ($ options ));
255
-
256
- return $ transport ;
257
251
}
258
252
259
253
/**
260
- * Create a Sendmail Laminas Transport
261
- *
262
- * @return Sendmail
254
+ * @inheritdoc
263
255
*/
264
- private function createSendmailTransport (): Sendmail
256
+ public function getMessage (): EmailMessageInterface
265
257
{
266
- return new Sendmail ( $ this ->parameters ) ;
258
+ return $ this ->message ;
267
259
}
268
260
}
0 commit comments