1 | <?php |
||
28 | abstract class BaseMailer extends Component implements MailerInterface |
||
29 | { |
||
30 | /** |
||
31 | * @event MailEvent an event raised right before send. |
||
32 | * You may set [[MailEvent::isValid]] to be false to cancel the send. |
||
33 | */ |
||
34 | const EVENT_BEFORE_SEND = 'beforeSend'; |
||
35 | /** |
||
36 | * @event MailEvent an event raised right after send. |
||
37 | */ |
||
38 | const EVENT_AFTER_SEND = 'afterSend'; |
||
39 | |||
40 | /** |
||
41 | * @var array the configuration that should be applied to any newly created |
||
42 | * email message instance by [[createMessage()]] or [[compose()]]. Any valid property defined |
||
43 | * by [[MessageInterface]] can be configured, such as `from`, `to`, `subject`, `textBody`, `htmlBody`, etc. |
||
44 | * |
||
45 | * For example: |
||
46 | * |
||
47 | * ```php |
||
48 | * [ |
||
49 | * 'charset' => 'UTF-8', |
||
50 | * 'from' => '[email protected]', |
||
51 | * 'bcc' => '[email protected]', |
||
52 | * ] |
||
53 | * ``` |
||
54 | */ |
||
55 | public $messageConfig = []; |
||
56 | /** |
||
57 | * @var string the default class name of the new message instances created by [[createMessage()]] |
||
58 | */ |
||
59 | public $messageClass = BaseMessage::class; |
||
60 | /** |
||
61 | * @var bool whether to save email messages as files under [[fileTransportPath]] instead of sending them |
||
62 | * to the actual recipients. This is usually used during development for debugging purpose. |
||
63 | * @see fileTransportPath |
||
64 | */ |
||
65 | public $useFileTransport = false; |
||
66 | /** |
||
67 | * @var string the directory where the email messages are saved when [[useFileTransport]] is true. |
||
68 | */ |
||
69 | public $fileTransportPath = '@runtime/mail'; |
||
70 | /** |
||
71 | * @var callable a PHP callback that will be called by [[send()]] when [[useFileTransport]] is true. |
||
72 | * The callback should return a file name which will be used to save the email message. |
||
73 | * If not set, the file name will be generated based on the current timestamp. |
||
74 | * |
||
75 | * The signature of the callback is: |
||
76 | * |
||
77 | * ```php |
||
78 | * function ($mailer, $message) |
||
79 | * ``` |
||
80 | */ |
||
81 | public $fileTransportCallback; |
||
82 | |||
83 | /** |
||
84 | * @var Composer|array|string|callable message composer. |
||
85 | * @since 2.1 |
||
86 | */ |
||
87 | private $_composer; |
||
88 | |||
89 | |||
90 | /** |
||
91 | * @return Composer message composer instance. |
||
92 | * @since 2.1 |
||
93 | */ |
||
94 | 1 | public function getComposer() |
|
95 | { |
||
96 | 1 | if (!is_object($this->_composer) || $this->_composer instanceof \Closure) { |
|
97 | 1 | if (is_array($this->_composer) && !isset($this->_composer['class'])) { |
|
98 | 1 | $this->_composer['class'] = Composer::class; |
|
99 | } |
||
100 | 1 | $this->_composer = Yii::createObject($this->_composer); |
|
101 | } |
||
102 | 1 | return $this->_composer; |
|
103 | } |
||
104 | |||
105 | /** |
||
106 | * @param Composer|array|string|callable $composer message composer instance or DI compatible configuration. |
||
107 | * @since 2.1 |
||
108 | */ |
||
109 | 5 | public function setComposer($composer) |
|
110 | { |
||
111 | 5 | $this->_composer = $composer; |
|
112 | 5 | } |
|
113 | |||
114 | /** |
||
115 | * Creates a new message instance and optionally composes its body content via view rendering. |
||
116 | * |
||
117 | * @param string|array|null $view the view to be used for rendering the message body. This can be: |
||
118 | * |
||
119 | * - a string, which represents the view name or path alias for rendering the HTML body of the email. |
||
120 | * In this case, the text body will be generated by applying `strip_tags()` to the HTML body. |
||
121 | * - an array with 'html' and/or 'text' elements. The 'html' element refers to the view name or path alias |
||
122 | * for rendering the HTML body, while 'text' element is for rendering the text body. For example, |
||
123 | * `['html' => 'contact-html', 'text' => 'contact-text']`. |
||
124 | * - null, meaning the message instance will be returned without body content. |
||
125 | * |
||
126 | * The view to be rendered can be specified in one of the following formats: |
||
127 | * |
||
128 | * - path alias (e.g. "@app/mail/contact"); |
||
129 | * - a relative view name (e.g. "contact") located under [[viewPath]]. |
||
130 | * |
||
131 | * @param array $params the parameters (name-value pairs) that will be extracted and made available in the view file. |
||
132 | * @return MessageInterface message instance. |
||
133 | */ |
||
134 | 6 | public function compose($view = null, array $params = []) |
|
135 | { |
||
136 | 6 | $message = $this->createMessage(); |
|
137 | 6 | if ($view === null) { |
|
138 | 5 | return $message; |
|
139 | } |
||
140 | |||
141 | 1 | $this->getComposer()->compose($message, $view, $params); |
|
142 | |||
143 | 1 | return $message; |
|
144 | } |
||
145 | |||
146 | /** |
||
147 | * Creates a new message instance. |
||
148 | * The newly created instance will be initialized with the configuration specified by [[messageConfig]]. |
||
149 | * If the configuration does not specify a 'class', the [[messageClass]] will be used as the class |
||
150 | * of the new message instance. |
||
151 | * @return MessageInterface message instance. |
||
152 | */ |
||
153 | 6 | protected function createMessage() |
|
154 | { |
||
155 | 6 | $config = $this->messageConfig; |
|
156 | 6 | if (!array_key_exists('class', $config)) { |
|
157 | 6 | $config['class'] = $this->messageClass; |
|
158 | } |
||
159 | 6 | $config['mailer'] = $this; |
|
160 | 6 | return Yii::createObject($config); |
|
161 | } |
||
162 | |||
163 | /** |
||
164 | * Sends the given email message. |
||
165 | * This method will log a message about the email being sent. |
||
166 | * If [[useFileTransport]] is true, it will save the email as a file under [[fileTransportPath]]. |
||
167 | * Otherwise, it will call [[sendMessage()]] to send the email to its recipient(s). |
||
168 | * Child classes should implement [[sendMessage()]] with the actual email sending logic. |
||
169 | * @param MessageInterface $message email message instance to be sent |
||
170 | * @return bool whether the message has been sent successfully |
||
171 | */ |
||
172 | 3 | public function send($message) |
|
173 | { |
||
174 | 3 | if (!$this->beforeSend($message)) { |
|
175 | return false; |
||
176 | } |
||
177 | |||
178 | 3 | $address = $message->getTo(); |
|
179 | 3 | if (is_array($address)) { |
|
180 | $address = implode(', ', array_keys($address)); |
||
181 | } |
||
182 | 3 | Yii::info('Sending email "' . $message->getSubject() . '" to "' . $address . '"', __METHOD__); |
|
183 | |||
184 | 3 | if ($this->useFileTransport) { |
|
185 | 1 | $isSuccessful = $this->saveMessage($message); |
|
186 | } else { |
||
187 | 2 | $isSuccessful = $this->sendMessage($message); |
|
188 | } |
||
189 | 3 | $this->afterSend($message, $isSuccessful); |
|
190 | |||
191 | 3 | return $isSuccessful; |
|
192 | } |
||
193 | |||
194 | /** |
||
195 | * Sends multiple messages at once. |
||
196 | * |
||
197 | * The default implementation simply calls [[send()]] multiple times. |
||
198 | * Child classes may override this method to implement more efficient way of |
||
199 | * sending multiple messages. |
||
200 | * |
||
201 | * @param array $messages list of email messages, which should be sent. |
||
202 | * @return int number of messages that are successfully sent. |
||
203 | */ |
||
204 | public function sendMultiple(array $messages) |
||
205 | { |
||
206 | $successCount = 0; |
||
207 | foreach ($messages as $message) { |
||
208 | if ($this->send($message)) { |
||
209 | $successCount++; |
||
210 | } |
||
211 | } |
||
212 | |||
213 | return $successCount; |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * Sends the specified message. |
||
218 | * This method should be implemented by child classes with the actual email sending logic. |
||
219 | * @param MessageInterface $message the message to be sent |
||
220 | * @return bool whether the message is sent successfully |
||
221 | */ |
||
222 | abstract protected function sendMessage($message); |
||
223 | |||
224 | /** |
||
225 | * Saves the message as a file under [[fileTransportPath]]. |
||
226 | * @param MessageInterface $message |
||
227 | * @return bool whether the message is saved successfully |
||
228 | */ |
||
229 | 1 | protected function saveMessage($message) |
|
244 | |||
245 | /** |
||
246 | * @return string the file name for saving the message when [[useFileTransport]] is true. |
||
247 | */ |
||
248 | public function generateMessageFileName() |
||
254 | |||
255 | /** |
||
256 | * This method is invoked right before mail send. |
||
257 | * You may override this method to do last-minute preparation for the message. |
||
258 | * If you override this method, please make sure you call the parent implementation first. |
||
259 | * @param MessageInterface $message |
||
260 | * @return bool whether to continue sending an email. |
||
261 | */ |
||
262 | 2 | public function beforeSend($message) |
|
269 | |||
270 | /** |
||
271 | * This method is invoked right after mail was send. |
||
272 | * You may override this method to do some postprocessing or logging based on mail send status. |
||
273 | * If you override this method, please make sure you call the parent implementation first. |
||
274 | * @param MessageInterface $message |
||
275 | * @param bool $isSuccessful |
||
276 | */ |
||
277 | 2 | public function afterSend($message, $isSuccessful) |
|
282 | } |
||
283 |