PluginProbe
Mailgun for WordPress / trunk
Mailgun for WordPress vtrunk
2.2.3 2.2.2 2.2.1 trunk 1.9.9 2.0.0 2.0.1 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0
mailgun / includes / mg-filter.php

mg-filter.php in Mailgun for WordPress trunk, at includes/mg-filter.php

365 lines 10.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * mailgun-wordpress-plugin - Sending mail from Wordpress using Mailgun
4 * Copyright (C) 2016 Mailgun, et al.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * @package Mailgun
21 */
22
23 /**
24 * Tries several methods to get the MIME Content-Type of a file.
25 *
26 * @param string $filepath
27 * @param string $default_type If all methods fail, fallback to $default_type
28 *
29 * @return string Content-Type
30 *
31 * @since 1.5.4
32 */
33 function get_mime_content_type( string $filepath, string $default_type = 'text/plain' ): string {
34 if (function_exists('mime_content_type')) {
35 return mime_content_type($filepath);
36 }
37
38 if (function_exists('finfo_file')) {
39 $fi = finfo_open(FILEINFO_MIME_TYPE);
40 $ret = finfo_file($fi, $filepath);
41 finfo_close($fi);
42
43 return $ret;
44 }
45
46 return $default_type;
47 }
48
49 /**
50 * Find the sending "From Name" with a similar process used in `wp_mail`.
51 * This operates as a filter for the from name. If the override is set,
52 * a given name will clobbered except in ONE case.
53 * If the override is not enabled this is the from name resolution order:
54 * 1. From name given by headers - {@param $from_name_header}
55 * 2. From name set in Mailgun settings
56 * 3. From `MAILGUN_FROM_NAME` constant
57 * 4. From name constructed as `<your_site_title>` or "WordPress"
58 *
59 * If the `wp_mail_from` filter is available, it is applied to the resulting
60 * `$from_addr` before being returned. The filtered result is null-tested
61 * before being returned.
62 *
63 * @param string $from_name_header
64 * @return string
65 *
66 * @since 1.5.8
67 */
68 function mg_detect_from_name( $from_name_header = null ): string {
69 // Get options to avoid strict mode problems
70 $mg_opts = get_option('mailgun');
71 $mg_override_from = $mg_opts['override-from'] ?? null;
72 $mg_from_name = $mg_opts['from-name'] ?? null;
73
74 $from_name = null;
75
76 if ($mg_override_from && ! is_null($mg_from_name)) {
77 $from_name = $mg_from_name;
78 } elseif ( ! is_null($from_name_header)) {
79 $from_name = $from_name_header;
80 } elseif (defined('MAILGUN_FROM_NAME') && MAILGUN_FROM_NAME) {
81 $from_name = MAILGUN_FROM_NAME;
82 } elseif (empty($mg_from_name)) {
83 if (function_exists('get_current_site')) {
84 $from_name = get_current_site()->site_name;
85 } else {
86 $from_name = 'WordPress';
87 }
88 } else {
89 $from_name = $mg_from_name;
90 }
91
92 $filter_from_name = null;
93
94 if (( ! isset($mg_override_from) || $mg_override_from === '0' ) && has_filter('wp_mail_from_name')) {
95 $filter_from_name = apply_filters(
96 'wp_mail_from_name',
97 $from_name
98 );
99 if ( ! empty($filter_from_name)) {
100 $from_name = $filter_from_name;
101 }
102 }
103
104 return $from_name;
105 }
106
107 /**
108 * Find the sending "From Address" with a similar process used in `wp_mail`.
109 * This operates as a filter for the from address. If the override is set,
110 * a given address will except in ONE case.
111 * If the override is not enabled this is the from address resolution order:
112 * 1. From address given by headers - {$from_addr_header}
113 * 2. From address set in Mailgun settings
114 * 3. From `MAILGUN_FROM_ADDRESS` constant
115 * 4. From address constructed as `wordpress@<your_site_domain>`
116 *
117 * If the `wp_mail_from` filter is available, it is applied to the resulting
118 * `$from_addr` before being returned. The filtered result is null-tested
119 * before being returned.
120 *
121 * If we don't have `From` input headers, use wordpress@$sitedomain
122 * Some hosts will block outgoing mail from this address if it doesn't
123 * exist but there's no easy alternative. Defaulting to admin_email
124 * might appear to be another option but some hosts may refuse to
125 * relay mail from an unknown domain.
126 *
127 * @param null $from_addr_header
128 * @return string
129 *
130 * @since 1.5.8
131 */
132 function mg_detect_from_address( $from_addr_header = null ): string {
133 // Get options to avoid strict mode problems
134 $mg_opts = get_option('mailgun');
135 $mg_override_from = $mg_opts['override-from'] ?? null;
136 $mg_from_addr = $mg_opts['from-address'] ?? null;
137
138 if ($mg_override_from && ! is_null($mg_from_addr)) {
139 $from_addr = $mg_from_addr;
140 } elseif ( ! is_null($from_addr_header)) {
141 $from_addr = $from_addr_header;
142 } elseif (defined('MAILGUN_FROM_ADDRESS') && MAILGUN_FROM_ADDRESS) {
143 $from_addr = MAILGUN_FROM_ADDRESS;
144 } elseif (empty($mg_from_addr)) {
145 if (function_exists('get_current_site')) {
146 $sitedomain = get_current_site()->domain;
147 } else {
148 $sitedomain = isset($_SERVER['SERVER_NAME']) && !empty($_SERVER['SERVER_NAME'])
149 ? $_SERVER['SERVER_NAME']
150 : wp_parse_url(site_url(), PHP_URL_HOST);
151
152 $sitedomain = strtolower(sanitize_text_field($sitedomain));
153
154 if (substr($sitedomain, 0, 4) === 'www.') {
155 $sitedomain = substr($sitedomain, 4);
156 }
157 }
158
159 $from_addr = 'wordpress@' . $sitedomain;
160 } else {
161 $from_addr = $mg_from_addr;
162 }
163
164 $filter_from_addr = null;
165 if (( ! isset($mg_override_from) || $mg_override_from === '0' ) && has_filter('wp_mail_from')) {
166 $filter_from_addr = apply_filters(
167 'wp_mail_from',
168 $from_addr
169 );
170 if (!is_null($filter_from_addr)) {
171 $from_addr = $filter_from_addr;
172 }
173 }
174
175 return $from_addr;
176 }
177
178 /**
179 * Parses mail headers into an array of arrays so they can be easily modified.
180 * We have to deal with headers that may have boundaries or parts, so a single
181 * header like:
182 *
183 * From: Excited User <user@samples.mailgun.com>
184 *
185 * Will look like this in array format:
186 *
187 * array(
188 * 'from' => array(
189 * 'value' => 'Excited User <user@samples.mailgun.com>',
190 * 'boundary' => null,
191 * 'parts' => null,
192 * )
193 * )
194 *
195 * @param string|array $headers
196 *
197 * @return array
198 *
199 * @since 1.5.8
200 */
201 function mg_parse_headers( $headers = []): array {
202 if (empty($headers)) {
203 return [];
204 }
205
206 if ( ! is_array($headers)) {
207 $tmp = explode("\n", str_replace("\r\n", "\n", $headers));
208 } else {
209 $tmp = $headers;
210 }
211
212 $new_headers = [];
213 if ( ! empty($tmp)) {
214 $name = null;
215 $value = null;
216 $boundary = null;
217 $parts = null;
218
219 foreach ( (array) $tmp as $header) {
220 // If this header does not contain a ':', is it a fold?
221 if (false === strpos($header, ':')) {
222 // Does this header have a boundary?
223 if (false !== stripos($header, 'boundary=')) {
224 $parts = preg_split('/boundary=/i', trim($header));
225 $boundary = trim(str_replace(array( '"', '\'' ), '', $parts[1]));
226 }
227 $value .= $header;
228
229 continue;
230 }
231
232 // Explode the header
233 [$name, $value] = explode(':', trim($header), 2);
234
235 // Clean up the values
236 $name = trim($name);
237 $value = trim($value);
238
239 if ( ! isset($new_headers[ $name ])) {
240 $new_headers[ $name ] = [];
241 }
242
243 $new_headers[ $name ][] = array(
244 'value' => $value,
245 'boundary' => $boundary,
246 'parts' => $parts,
247 );
248 }
249 }
250
251 return $new_headers;
252 }
253
254 /**
255 * Takes a header array in the format produced by mg_parse_headers and
256 * dumps them down in to a submittable header format.
257 *
258 * @param array|null $headers Headers to dump
259 *
260 * @return string String of \r\n separated headers
261 *
262 * @since 1.5.8
263 */
264 function mg_dump_headers( ?array $headers = null ): string {
265 if ( ! is_array($headers)) {
266 return '';
267 }
268
269 $header_string = '';
270 foreach ($headers as $name => $values) {
271 $header_string .= sprintf('%s: ', $name);
272 $header_values = [];
273
274 foreach ($values as $content) {
275 // XXX - Is it actually okay to discard `parts` and `boundary`?
276 $header_values[] = $content['value'];
277 }
278
279 $header_string .= sprintf("%s\r\n", implode(', ', $header_values));
280 }
281
282 return $header_string;
283 }
284
285 /**
286 * Set the API endpoint based on the region selected.
287 * Value can be "0" if not selected, "us" or "eu"
288 *
289 * @param string $getRegion Region value set either in config or Mailgun plugin settings.
290 *
291 * @return bool|string
292 *
293 * @since 1.5.12
294 */
295 function mg_api_get_region( $getRegion ) {
296 switch ($getRegion) {
297 case 'us':
298 return 'https://api.mailgun.net/v3/';
299 case 'eu':
300 return 'https://api.eu.mailgun.net/v3/';
301 default:
302 return false;
303 }
304 }
305
306 /**
307 * Set the SMTP endpoint based on the region selected.
308 * Value can be "0" if not selected, "us" or "eu"
309 *
310 * @param string $getRegion Region value set either in config or Mailgun plugin settings.
311 *
312 * @return bool|string
313 *
314 * @since 1.5.12
315 */
316 function mg_smtp_get_region( $getRegion ) {
317 switch ($getRegion) {
318 case 'us':
319 return 'smtp.mailgun.org';
320 case 'eu':
321 return 'smtp.eu.mailgun.org';
322 default:
323 return false;
324 }
325 }
326
327 /**
328 * Override WP VIP GO filter
329 * It sets default email address to `donotreply@wordpress.com`
330 */
331 if (( defined('WPCOM_IS_VIP_ENV') && WPCOM_IS_VIP_ENV ) || ( defined('VIP_GO_ENV') && VIP_GO_ENV )) {
332
333 global $mg_from_mail;
334
335 /**
336 * @param string $from_mail
337 * @return string
338 */
339 function mg_wp_mail_from_standard( string $from_mail ): string {
340 global $mg_from_mail;
341
342 $mg_from_mail = $from_mail;
343
344 return $from_mail;
345 }
346
347 add_filter('wp_mail_from', 'mg_wp_mail_from_standard', 0);
348
349 /**
350 * @param string $from_mail
351 * @return string
352 */
353 function mg_wp_mail_from_new( string $from_mail ): string {
354 global $mg_from_mail;
355
356 if ( ! empty($mg_from_mail) && is_email($mg_from_mail)) {
357 return $mg_from_mail;
358 }
359
360 return $from_mail;
361 }
362
363 add_filter('wp_mail_from', 'mg_wp_mail_from_new', 2);
364 }
365