PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / trunk
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress vtrunk
11.0.5 11.0.4 11.0.3 11.0.2 11.0.1 11.0.0 10.11.1 10.11.0 10.10.2 10.10.1 10.10.0 10.9.1 trunk 10.0.0 10.0.1 10.1.0 10.1.1 10.1.2 10.1.3 10.1.4 10.2.0 10.2.1 10.2.2 10.3.0 10.4.0 All 60 releases
acymailing / back / dynamics / outlook / plugin.php

plugin.php in AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress trunk, at back/dynamics/outlook/plugin.php

302 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use AcyMailing\Core\AcymPlugin;
4 use AcyMailing\Helpers\MailerHelper;
5
6 class plgAcymOutlook extends AcymPlugin
7 {
8 const SENDING_METHOD_ID = 'outlook';
9 const SENDING_METHOD_NAME = 'Outlook';
10 const SCOPE_SMTP = 'openid offline_access https://outlook.office.com/SMTP.Send';
11 const SCOPE_IMAP = 'openid offline_access https://outlook.office.com/IMAP.AccessAsUser.All';
12
13 public function __construct()
14 {
15 parent::__construct();
16 $this->pluginDescription->name = acym_translation('ACYM_OUTLOOK');
17 }
18
19 public function onAcymGetSendingMethods(&$data, $isMailer = false)
20 {
21 if ($isMailer) {
22 return;
23 }
24
25 $data['sendingMethods'][self::SENDING_METHOD_ID] = [
26 'name' => $this->pluginDescription->name,
27 'image' => ACYM_IMAGES.'mailers/outlook.svg',
28 ];
29 }
30
31 public function onAcymGetSendingMethodsHtmlSetting(&$data)
32 {
33 $username = $this->config->get('outlook_username', $this->config->get('from_email'));
34 $setupDocumentation = ACYM_DOCUMENTATION.'setup/configuration/mail-configuration/set-up-oauth-2.0';
35 $redirectUrl = trim($this->config->get('outlook_redirect_url', acym_baseURI()));
36
37 $refreshToken = $this->config->get('outlook_refresh_token');
38 $refreshTokenExpiration = $this->config->get('outlook_refresh_token_expiration');
39 $mustAuthenticate = empty($refreshToken) || (!empty($refreshTokenExpiration) && $refreshTokenExpiration < time());
40
41 $mailerHelper = new MailerHelper();
42
43 ob_start();
44 ?>
45 <div class="send_settings grid-x cell large-6 xlarge-5 xxlarge-4 margin-auto" id="<?php echo esc_attr(self::SENDING_METHOD_ID); ?>_settings">
46 <div class="acym_port_465_closed is-hidden">
47 <?php acym_display(acym_translation('ACYM_PORT_NEEDED'), 'error', false); ?>
48 </div>
49 <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings">
50 <label for="outlook_username" class="cell">
51 <?php echo esc_html(acym_translation('ACYM_SMTP_USERNAME'));
52 acym_info(['textShownInTooltip' => 'ACYM_SMTP_USERNAME_DESC']); ?>
53 </label>
54 <input id="outlook_username"
55 class="cell"
56 type="text"
57 name="config[outlook_username]"
58 value="<?php echo esc_attr($username); ?>">
59 </div>
60 <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings">
61 <label for="outlook_tenant" class="cell"><?php acym_externalLink('ACYM_TENANT', $setupDocumentation, false); ?></label>
62 <?php
63 $value = $this->config->get('outlook_tenant');
64 acym_select(
65 [
66 'common' => 'ACYM_ANY_ACCOUNT_TYPE',
67 'consumers' => 'ACYM_MICROSOFT_ACCOUNTS',
68 'organizations' => 'ACYM_ORGANIZATIONS',
69 ],
70 'config[outlook_tenant]',
71 empty($value) ? 'consumers' : $value,
72 [
73 'class' => 'acym__select',
74 ],
75 '',
76 '',
77 '',
78 true,
79 true
80 );
81 ?>
82 </div>
83 <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings">
84 <label for="outlook_client_id" class="cell"><?php acym_externalLink('ACYM_SMTP_CLIENT_ID', $setupDocumentation, false); ?></label>
85 <input id="outlook_client_id"
86 class="cell"
87 type="text"
88 name="config[outlook_client_id]"
89 value="<?php echo esc_attr($this->config->get('outlook_client_id')); ?>">
90 </div>
91 <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings">
92 <label for="outlook_client_secret" class="cell"><?php acym_externalLink('ACYM_SMTP_CLIENT_SECRET', $setupDocumentation, false); ?></label>
93 <input id="outlook_client_secret"
94 class="cell"
95 type="text"
96 name="config[outlook_client_secret]"
97 value="<?php echo esc_attr($this->config->get('outlook_client_secret')); ?>">
98 </div>
99 <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings">
100 <label for="outlook_redirect_url" class="cell"><?php echo esc_html(acym_translation('ACYM_SMTP_REDIRECT_URL')); ?></label>
101 <input id="outlook_redirect_url"
102 class="cell"
103 type="text"
104 name="config[outlook_redirect_url]"
105 value="<?php echo esc_attr($redirectUrl); ?>">
106 </div>
107 <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings">
108 <?php if ($mustAuthenticate) { ?>
109 <button data-before-action="configSave"
110 data-task="loginForOAuth2Smtp"
111 class="button acy_button_submit margin-next-1">
112 <?php echo esc_html(acym_translation('ACYM_AUTHENTICATE')); ?>
113 </button>
114 <?php $this->getCopySettingsButton($data, self::SENDING_METHOD_ID, 'wp_mail_smtp', false); ?>
115 <?php } else { ?>
116 <button data-before-action="configSave"
117 data-task="logoutForOAuth2Smtp"
118 class="button acy_button_submit button-secondary margin-bottom-1">
119 <?php echo esc_html(acym_translation('ACYM_REVOKE_PERMISSIONS')); ?>
120 </button>
121 <?php
122 if (!empty($refreshTokenExpiration)) {
123 echo esc_html(acym_translationSprintf('ACYM_AUTHENTICATION_WILL_EXPIRE', acym_date($refreshTokenExpiration, 'ACYM_DATE_FORMAT_LC2')));
124 }
125 ?>
126 <?php } ?>
127 </div>
128 </div>
129 <?php
130 $data['sendingMethodsHtmlSettings'][self::SENDING_METHOD_ID] = ob_get_clean();
131 }
132
133 public function onAcymGetSettingsSendingMethodFromPlugin(&$data, $plugin, $method)
134 {
135 if ($method !== self::SENDING_METHOD_ID) {
136 return;
137 }
138
139 if (ACYM_CMS === 'wordpress' && $plugin === 'wp_mail_smtp') {
140 $wpMailSmtpSetting = get_option('wp_mail_smtp', '');
141
142 if (empty($wpMailSmtpSetting['outlook'])) {
143 return;
144 }
145
146 $data['outlook_client_id'] = $wpMailSmtpSetting['outlook']['client_id'] ?? '';
147 $data['outlook_client_secret'] = $wpMailSmtpSetting['outlook']['client_secret'] ?? '';
148 }
149 }
150
151 /**
152 * Doc: https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow#request-an-authorization-code
153 */
154 public function onAcymOauthAuthenticate(string &$consentUrl, bool $isSmtp): void
155 {
156 if ($isSmtp) {
157 if ($this->config->get('mailer_method') !== self::SENDING_METHOD_ID) {
158 return;
159 }
160
161 $clientId = $this->config->get('outlook_client_id');
162 $clientSecret = $this->config->get('outlook_client_secret');
163 $tenant = $this->config->get('outlook_tenant');
164 $redirectUrl = $this->config->get('outlook_redirect_url');
165 $scope = self::SCOPE_SMTP;
166 } else {
167 if ($this->config->get('bounce_server') !== 'outlook.office365.com') {
168 return;
169 }
170
171 $clientId = $this->config->get('bounce_client_id');
172 $clientSecret = $this->config->get('bounce_client_secret');
173 $tenant = $this->config->get('bounce_tenant');
174 $redirectUrl = acym_baseURI();
175 $scope = self::SCOPE_IMAP;
176 }
177
178 if (empty($clientId) || empty($clientSecret) || empty($redirectUrl)) {
179 acym_enqueueMessage(acym_translation('ACYM_PLEASE_FILL_CLIENT_ID_SECRET'), 'error', false);
180
181 return;
182 }
183
184 $consentUrl = 'https://login.microsoftonline.com/'.$tenant.'/oauth2/v2.0/authorize';
185 $consentUrl .= '?response_mode=query';
186 $consentUrl .= '&client_id='.urlencode($clientId);
187 $consentUrl .= '&prompt=consent';
188 $consentUrl .= '&response_type=code';
189 $consentUrl .= '&redirect_uri='.urlencode($redirectUrl);
190 $consentUrl .= '&scope='.urlencode($scope);
191 $consentUrl .= '&state=acymailing'.($isSmtp ? 'smtp' : 'bounce');
192 }
193
194 /**
195 * Doc: https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow#redeem-a-code-for-an-access-token
196 */
197 public function onAcymOauthCredentialsCreation(bool $isSmtp, string $code): void
198 {
199 if ($isSmtp) {
200 if ($this->config->get('mailer_method') !== self::SENDING_METHOD_ID) {
201 return;
202 }
203
204 $clientId = trim($this->config->get('outlook_client_id'));
205 $clientSecret = trim($this->config->get('outlook_client_secret'));
206 $tenant = trim($this->config->get('outlook_tenant', 'consumers'));
207 $redirectUrl = trim($this->config->get('outlook_redirect_url', acym_baseURI()));
208 $scope = self::SCOPE_SMTP;
209 } else {
210 if ($this->config->get('bounce_server') !== 'outlook.office365.com') {
211 return;
212 }
213
214 $clientId = trim($this->config->get('bounce_client_id'));
215 $clientSecret = trim($this->config->get('bounce_client_secret'));
216 $tenant = trim($this->config->get('bounce_tenant', 'consumers'));
217 $redirectUrl = acym_baseURI();
218 $scope = self::SCOPE_IMAP;
219 }
220
221 if (empty($clientId) || empty($clientSecret)) {
222 acym_enqueueMessage(acym_translation('ACYM_PLEASE_FILL_CLIENT_ID_SECRET'), 'error', false);
223
224 return;
225 }
226
227 $response = acym_makeCurlCall(
228 'https://login.microsoftonline.com/'.$tenant.'/oauth2/v2.0/token',
229 [
230 'method' => 'POST',
231 'data' => [
232 'grant_type' => 'authorization_code',
233 'code' => $code,
234 'client_id' => $clientId,
235 'client_secret' => $clientSecret,
236 'redirect_uri' => $redirectUrl,
237 'scope' => $scope,
238 ],
239 ]
240 );
241
242 acym_logError('Response from OAuth call: '.json_encode($response), self::SENDING_METHOD_ID);
243
244 if (!empty($response['error'])) {
245 acym_enqueueMessage(acym_translationSprintf('ACYM_SMTP_OAUTH_ERROR', $response['error']), 'error', false);
246
247 return;
248 }
249
250 $expiringTime = time() + (int)$response['expires_in'];
251
252 if (!empty($response['refresh_token_expires_in'])) {
253 $refreshExpiringTime = time() + (int)$response['refresh_token_expires_in'];
254
255 acym_enqueueMessage(
256 acym_translationSprintf(
257 'ACYM_OAUTH_TEMPORARY',
258 acym_date($refreshExpiringTime, 'ACYM_DATE_FORMAT_LC2')
259 ),
260 'info',
261 false
262 );
263 } else {
264 $refreshExpiringTime = 0;
265 acym_enqueueMessage(acym_translation('ACYM_SMTP_OAUTH_OK'), 'info');
266 }
267
268 if ($isSmtp) {
269 $newConfig = [
270 'outlook_access_token' => $response['access_token'],
271 'outlook_access_token_expiration' => $expiringTime,
272 'outlook_refresh_token' => $response['refresh_token'],
273 'outlook_refresh_token_expiration' => $refreshExpiringTime,
274 ];
275 } else {
276 $newConfig = [
277 'bounce_access_token' => $response['access_token'],
278 'bounce_access_token_expiration' => $expiringTime,
279 'bounce_refresh_token' => $response['refresh_token'],
280 'bounce_refresh_token_expiration' => $refreshExpiringTime,
281 ];
282 }
283
284 $this->config->saveConfig($newConfig);
285 acym_config(true);
286 }
287
288 public function onAcymOauthRevoke(): void
289 {
290 if ($this->config->get('mailer_method') !== self::SENDING_METHOD_ID) {
291 return;
292 }
293
294 $this->config->saveConfig(
295 [
296 'outlook_refresh_token' => '',
297 'outlook_refresh_token_expiration' => '',
298 ]
299 );
300 }
301 }
302