PluginProbe
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress / 11.1.0
AcyMailing – An Ultimate Newsletter Plugin and Marketing Automation Solution for WordPress v11.1.0
11.1.1 11.1.0 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 All 62 releases
← All changes | back/dynamics/outlook/plugin.php +296 -0 10.2.0 → 11.1.0 View file →
@@ -1,0 +1,296 @@
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 + <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">
42 + <div class="acym_port_465_closed is-hidden">
43 + <?php acym_display(acym_translation('ACYM_PORT_NEEDED'), 'error', false); ?>
44 + </div>
45 + <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings">
46 + <label for="outlook_username" class="cell">
47 + <?php echo esc_html(acym_translation('ACYM_SMTP_USERNAME'));
48 + acym_info(['textShownInTooltip' => 'ACYM_SMTP_USERNAME_DESC']); ?>
49 + </label>
50 + <input id="outlook_username"
51 + class="cell"
52 + type="text"
53 + name="config[outlook_username]"
54 + value="<?php echo esc_attr($username); ?>">
55 + </div>
56 + <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings">
57 + <label for="outlook_tenant" class="cell"><?php acym_externalLink('ACYM_TENANT', $setupDocumentation, false); ?></label>
58 + <?php
59 + $value = $this->config->get('outlook_tenant');
60 + acym_select(
61 + [
62 + 'common' => 'ACYM_ANY_ACCOUNT_TYPE',
63 + 'consumers' => 'ACYM_MICROSOFT_ACCOUNTS',
64 + 'organizations' => 'ACYM_ORGANIZATIONS',
65 + ],
66 + 'config[outlook_tenant]',
67 + empty($value) ? 'consumers' : $value,
68 + [
69 + 'class' => 'acym__select',
70 + ],
71 + '',
72 + '',
73 + '',
74 + true,
75 + true
76 + );
77 + ?>
78 + </div>
79 + <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings">
80 + <label for="outlook_client_id" class="cell"><?php acym_externalLink('ACYM_SMTP_CLIENT_ID', $setupDocumentation, false); ?></label>
81 + <input id="outlook_client_id"
82 + class="cell"
83 + type="text"
84 + name="config[outlook_client_id]"
85 + value="<?php echo esc_attr($this->config->get('outlook_client_id')); ?>">
86 + </div>
87 + <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings">
88 + <label for="outlook_client_secret" class="cell"><?php acym_externalLink('ACYM_SMTP_CLIENT_SECRET', $setupDocumentation, false); ?></label>
89 + <input id="outlook_client_secret"
90 + class="cell"
91 + type="text"
92 + name="config[outlook_client_secret]"
93 + value="<?php echo esc_attr($this->config->get('outlook_client_secret')); ?>">
94 + </div>
95 + <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings">
96 + <label for="outlook_redirect_url" class="cell"><?php echo esc_html(acym_translation('ACYM_SMTP_REDIRECT_URL')); ?></label>
97 + <input id="outlook_redirect_url"
98 + class="cell"
99 + type="text"
100 + name="config[outlook_redirect_url]"
101 + value="<?php echo esc_attr($redirectUrl); ?>">
102 + </div>
103 + <div class="cell grid-x acym_vcenter acym__sending__methods__one__settings">
104 + <?php if ($mustAuthenticate) { ?>
105 + <button data-before-action="configSave"
106 + data-task="loginForOAuth2Smtp"
107 + class="button acy_button_submit margin-next-1">
108 + <?php echo esc_html(acym_translation('ACYM_AUTHENTICATE')); ?>
109 + </button>
110 + <?php $this->getCopySettingsButton($data, self::SENDING_METHOD_ID, 'wp_mail_smtp', false); ?>
111 + <?php } else { ?>
112 + <button data-before-action="configSave"
113 + data-task="logoutForOAuth2Smtp"
114 + class="button acy_button_submit button-secondary margin-bottom-1">
115 + <?php echo esc_html(acym_translation('ACYM_REVOKE_PERMISSIONS')); ?>
116 + </button>
117 + <?php
118 + if (!empty($refreshTokenExpiration)) {
119 + echo esc_html(acym_translationSprintf('ACYM_AUTHENTICATION_WILL_EXPIRE', acym_date($refreshTokenExpiration, 'ACYM_DATE_FORMAT_LC2')));
120 + }
121 + ?>
122 + <?php } ?>
123 + </div>
124 + </div>
125 + <?php
126 + }
127 +
128 + public function onAcymGetSettingsSendingMethodFromPlugin(&$data, $plugin, $method)
129 + {
130 + if ($method !== self::SENDING_METHOD_ID) {
131 + return;
132 + }
133 +
134 + if (ACYM_CMS === 'wordpress' && $plugin === 'wp_mail_smtp') {
135 + $wpMailSmtpSetting = get_option('wp_mail_smtp', '');
136 +
137 + if (empty($wpMailSmtpSetting['outlook'])) {
138 + return;
139 + }
140 +
141 + $data['outlook_client_id'] = $wpMailSmtpSetting['outlook']['client_id'] ?? '';
142 + $data['outlook_client_secret'] = $wpMailSmtpSetting['outlook']['client_secret'] ?? '';
143 + }
144 + }
145 +
146 + /**
147 + * Doc: https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow#request-an-authorization-code
148 + */
149 + public function onAcymOauthAuthenticate(string &$consentUrl, bool $isSmtp): void
150 + {
151 + if ($isSmtp) {
152 + if ($this->config->get('mailer_method') !== self::SENDING_METHOD_ID) {
153 + return;
154 + }
155 +
156 + $clientId = $this->config->get('outlook_client_id');
157 + $clientSecret = $this->config->get('outlook_client_secret');
158 + $tenant = $this->config->get('outlook_tenant');
159 + $redirectUrl = $this->config->get('outlook_redirect_url');
160 + $scope = self::SCOPE_SMTP;
161 + } else {
162 + if ($this->config->get('bounce_server') !== 'outlook.office365.com') {
163 + return;
164 + }
165 +
166 + $clientId = $this->config->get('bounce_client_id');
167 + $clientSecret = $this->config->get('bounce_client_secret');
168 + $tenant = $this->config->get('bounce_tenant');
169 + $redirectUrl = acym_baseURI();
170 + $scope = self::SCOPE_IMAP;
171 + }
172 +
173 + if (empty($clientId) || empty($clientSecret) || empty($redirectUrl)) {
174 + acym_enqueueMessage(acym_translation('ACYM_PLEASE_FILL_CLIENT_ID_SECRET'), 'error', false);
175 +
176 + return;
177 + }
178 +
179 + $consentUrl = 'https://login.microsoftonline.com/'.$tenant.'/oauth2/v2.0/authorize';
180 + $consentUrl .= '?response_mode=query';
181 + $consentUrl .= '&client_id='.urlencode($clientId);
182 + $consentUrl .= '&prompt=consent';
183 + $consentUrl .= '&response_type=code';
184 + $consentUrl .= '&redirect_uri='.urlencode($redirectUrl);
185 + $consentUrl .= '&scope='.urlencode($scope);
186 + $consentUrl .= '&state=acymailing'.($isSmtp ? 'smtp' : 'bounce');
187 + }
188 +
189 + /**
190 + * Doc: https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow#redeem-a-code-for-an-access-token
191 + */
192 + public function onAcymOauthCredentialsCreation(bool $isSmtp, string $code): void
193 + {
194 + if ($isSmtp) {
195 + if ($this->config->get('mailer_method') !== self::SENDING_METHOD_ID) {
196 + return;
197 + }
198 +
199 + $clientId = trim($this->config->get('outlook_client_id'));
200 + $clientSecret = trim($this->config->get('outlook_client_secret'));
201 + $tenant = trim($this->config->get('outlook_tenant', 'consumers'));
202 + $redirectUrl = trim($this->config->get('outlook_redirect_url', acym_baseURI()));
203 + $scope = self::SCOPE_SMTP;
204 + } else {
205 + if ($this->config->get('bounce_server') !== 'outlook.office365.com') {
206 + return;
207 + }
208 +
209 + $clientId = trim($this->config->get('bounce_client_id'));
210 + $clientSecret = trim($this->config->get('bounce_client_secret'));
211 + $tenant = trim($this->config->get('bounce_tenant', 'consumers'));
212 + $redirectUrl = acym_baseURI();
213 + $scope = self::SCOPE_IMAP;
214 + }
215 +
216 + if (empty($clientId) || empty($clientSecret)) {
217 + acym_enqueueMessage(acym_translation('ACYM_PLEASE_FILL_CLIENT_ID_SECRET'), 'error', false);
218 +
219 + return;
220 + }
221 +
222 + $response = acym_makeCurlCall(
223 + 'https://login.microsoftonline.com/'.$tenant.'/oauth2/v2.0/token',
224 + [
225 + 'method' => 'POST',
226 + 'data' => [
227 + 'grant_type' => 'authorization_code',
228 + 'code' => $code,
229 + 'client_id' => $clientId,
230 + 'client_secret' => $clientSecret,
231 + 'redirect_uri' => $redirectUrl,
232 + 'scope' => $scope,
233 + ],
234 + ]
235 + );
236 +
237 + acym_logError('Response from OAuth call: '.json_encode($response), self::SENDING_METHOD_ID);
238 +
239 + if (!empty($response['error'])) {
240 + acym_enqueueMessage(acym_translationSprintf('ACYM_SMTP_OAUTH_ERROR', $response['error']), 'error', false);
241 +
242 + return;
243 + }
244 +
245 + $expiringTime = time() + (int)$response['expires_in'];
246 +
247 + if (!empty($response['refresh_token_expires_in'])) {
248 + $refreshExpiringTime = time() + (int)$response['refresh_token_expires_in'];
249 +
250 + acym_enqueueMessage(
251 + acym_translationSprintf(
252 + 'ACYM_OAUTH_TEMPORARY',
253 + acym_date($refreshExpiringTime, 'ACYM_DATE_FORMAT_LC2')
254 + ),
255 + 'info',
256 + false
257 + );
258 + } else {
259 + $refreshExpiringTime = 0;
260 + acym_enqueueMessage(acym_translation('ACYM_SMTP_OAUTH_OK'), 'info');
261 + }
262 +
263 + if ($isSmtp) {
264 + $newConfig = [
265 + 'outlook_access_token' => $response['access_token'],
266 + 'outlook_access_token_expiration' => $expiringTime,
267 + 'outlook_refresh_token' => $response['refresh_token'],
268 + 'outlook_refresh_token_expiration' => $refreshExpiringTime,
269 + ];
270 + } else {
271 + $newConfig = [
272 + 'bounce_access_token' => $response['access_token'],
273 + 'bounce_access_token_expiration' => $expiringTime,
274 + 'bounce_refresh_token' => $response['refresh_token'],
275 + 'bounce_refresh_token_expiration' => $refreshExpiringTime,
276 + ];
277 + }
278 +
279 + $this->config->saveConfig($newConfig);
280 + acym_config(true);
281 + }
282 +
283 + public function onAcymOauthRevoke(): void
284 + {
285 + if ($this->config->get('mailer_method') !== self::SENDING_METHOD_ID) {
286 + return;
287 + }
288 +
289 + $this->config->saveConfig(
290 + [
291 + 'outlook_refresh_token' => '',
292 + 'outlook_refresh_token_expiration' => '',
293 + ]
294 + );
295 + }
296 +}