PageRenderTime 38ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/wp-content/plugins/wp-mail-smtp/src/Providers/MailerAbstract.php

https://gitlab.com/VTTE/sitios-vtte
PHP | 467 lines | 202 code | 69 blank | 196 comment | 24 complexity | 8ea0fe3fa3f19b2d09937de3d3bbd094 MD5 | raw file
  1. <?php
  2. namespace WPMailSMTP\Providers;
  3. use WPMailSMTP\Conflicts;
  4. use WPMailSMTP\Debug;
  5. use WPMailSMTP\MailCatcher;
  6. use WPMailSMTP\Options;
  7. use WPMailSMTP\WP;
  8. /**
  9. * Class MailerAbstract.
  10. *
  11. * @since 1.0.0
  12. */
  13. abstract class MailerAbstract implements MailerInterface {
  14. /**
  15. * Which response code from HTTP provider is considered to be successful?
  16. *
  17. * @since 1.0.0
  18. *
  19. * @var int
  20. */
  21. protected $email_sent_code = 200;
  22. /**
  23. * @since 1.0.0
  24. *
  25. * @var Options
  26. */
  27. protected $options;
  28. /**
  29. * @since 1.0.0
  30. *
  31. * @var MailCatcher
  32. */
  33. protected $phpmailer;
  34. /**
  35. * @since 1.0.0
  36. *
  37. * @var string
  38. */
  39. protected $mailer = '';
  40. /**
  41. * URL to make an API request to.
  42. *
  43. * @since 1.0.0
  44. *
  45. * @var string
  46. */
  47. protected $url = '';
  48. /**
  49. * @since 1.0.0
  50. *
  51. * @var array
  52. */
  53. protected $headers = array();
  54. /**
  55. * @since 1.0.0
  56. *
  57. * @var array
  58. */
  59. protected $body = array();
  60. /**
  61. * @since 1.0.0
  62. *
  63. * @var mixed
  64. */
  65. protected $response = array();
  66. /**
  67. * Mailer constructor.
  68. *
  69. * @since 1.0.0
  70. *
  71. * @param MailCatcher $phpmailer
  72. */
  73. public function __construct( MailCatcher $phpmailer ) {
  74. $this->options = new Options();
  75. $this->mailer = $this->options->get( 'mail', 'mailer' );
  76. // Only non-SMTP mailers need URL and extra processing for PHPMailer class.
  77. if ( ! $this->options->is_mailer_smtp() && empty( $this->url ) ) {
  78. return;
  79. }
  80. $this->process_phpmailer( $phpmailer );
  81. }
  82. /**
  83. * Re-use the MailCatcher class methods and properties.
  84. *
  85. * @since 1.0.0
  86. *
  87. * @param MailCatcher $phpmailer
  88. */
  89. public function process_phpmailer( $phpmailer ) {
  90. // Make sure that we have access to MailCatcher class methods.
  91. if (
  92. ! $phpmailer instanceof MailCatcher &&
  93. ! $phpmailer instanceof \PHPMailer
  94. ) {
  95. return;
  96. }
  97. $this->phpmailer = $phpmailer;
  98. // Prevent working with those methods, as they are not needed for SMTP-like mailers.
  99. if ( $this->options->is_mailer_smtp() ) {
  100. return;
  101. }
  102. $this->set_headers( $this->phpmailer->getCustomHeaders() );
  103. $this->set_from( $this->phpmailer->From, $this->phpmailer->FromName );
  104. $this->set_recipients(
  105. array(
  106. 'to' => $this->phpmailer->getToAddresses(),
  107. 'cc' => $this->phpmailer->getCcAddresses(),
  108. 'bcc' => $this->phpmailer->getBccAddresses(),
  109. )
  110. );
  111. $this->set_subject( $this->phpmailer->Subject );
  112. if ( $this->phpmailer->ContentType === 'text/plain' ) {
  113. $this->set_content( $this->phpmailer->Body );
  114. } else {
  115. $this->set_content(
  116. array(
  117. 'text' => $this->phpmailer->AltBody,
  118. 'html' => $this->phpmailer->Body,
  119. )
  120. );
  121. }
  122. $this->set_return_path( $this->phpmailer->From );
  123. $this->set_reply_to( $this->phpmailer->getReplyToAddresses() );
  124. /*
  125. * In some cases we will need to modify the internal structure
  126. * of the body content, if attachments are present.
  127. * So lets make this call the last one.
  128. */
  129. $this->set_attachments( $this->phpmailer->getAttachments() );
  130. }
  131. /**
  132. * Set the email headers.
  133. *
  134. * @since 1.0.0
  135. *
  136. * @param array $headers List of key=>value pairs.
  137. */
  138. public function set_headers( $headers ) {
  139. foreach ( $headers as $header ) {
  140. $name = isset( $header[0] ) ? $header[0] : false;
  141. $value = isset( $header[1] ) ? $header[1] : false;
  142. if ( empty( $name ) || empty( $value ) ) {
  143. continue;
  144. }
  145. $this->set_header( $name, $value );
  146. }
  147. }
  148. /**
  149. * Set individual header key=>value pair for the email.
  150. *
  151. * @since 1.0.0
  152. *
  153. * @param string $name
  154. * @param string $value
  155. */
  156. public function set_header( $name, $value ) {
  157. $name = sanitize_text_field( $name );
  158. $this->headers[ $name ] = WP::sanitize_value( $value );
  159. }
  160. /**
  161. * Set email subject.
  162. *
  163. * @since 1.0.0
  164. *
  165. * @param string $subject
  166. */
  167. public function set_subject( $subject ) {
  168. $this->set_body_param(
  169. array(
  170. 'subject' => $subject,
  171. )
  172. );
  173. }
  174. /**
  175. * Set the request params, that goes to the body of the HTTP request.
  176. *
  177. * @since 1.0.0
  178. *
  179. * @param array $param Key=>value of what should be sent to a 3rd party API.
  180. *
  181. * @internal param array $params
  182. */
  183. protected function set_body_param( $param ) {
  184. $this->body = Options::array_merge_recursive( $this->body, $param );
  185. }
  186. /**
  187. * Get the email body.
  188. *
  189. * @since 1.0.0
  190. *
  191. * @return string|array
  192. */
  193. public function get_body() {
  194. return apply_filters( 'wp_mail_smtp_providers_mailer_get_body', $this->body, $this->mailer );
  195. }
  196. /**
  197. * Get the email headers.
  198. *
  199. * @since 1.0.0
  200. *
  201. * @return array
  202. */
  203. public function get_headers() {
  204. return apply_filters( 'wp_mail_smtp_providers_mailer_get_headers', $this->headers, $this->mailer );
  205. }
  206. /**
  207. * Send the email.
  208. *
  209. * @since 1.0.0
  210. * @since 1.8.0 Added timeout for requests, same as max_execution_time.
  211. */
  212. public function send() {
  213. $timeout = (int) ini_get( 'max_execution_time' );
  214. $params = Options::array_merge_recursive(
  215. $this->get_default_params(),
  216. array(
  217. 'headers' => $this->get_headers(),
  218. 'body' => $this->get_body(),
  219. 'timeout' => $timeout ? $timeout : 30,
  220. )
  221. );
  222. $response = wp_safe_remote_post( $this->url, $params );
  223. $this->process_response( $response );
  224. }
  225. /**
  226. * We might need to do something after the email was sent to the API.
  227. * In this method we preprocess the response from the API.
  228. *
  229. * @since 1.0.0
  230. *
  231. * @param mixed $response
  232. */
  233. protected function process_response( $response ) {
  234. if ( is_wp_error( $response ) ) {
  235. // Save the error text.
  236. $errors = $response->get_error_messages();
  237. foreach ( $errors as $error ) {
  238. Debug::set( $error );
  239. }
  240. return;
  241. }
  242. if ( isset( $response['body'] ) && WP::is_json( $response['body'] ) ) {
  243. $response['body'] = \json_decode( $response['body'] );
  244. }
  245. $this->response = $response;
  246. }
  247. /**
  248. * Get the default params, required for wp_safe_remote_post().
  249. *
  250. * @since 1.0.0
  251. *
  252. * @return array
  253. */
  254. protected function get_default_params() {
  255. return apply_filters(
  256. 'wp_mail_smtp_providers_mailer_get_default_params',
  257. array(
  258. 'timeout' => 15,
  259. 'httpversion' => '1.1',
  260. 'blocking' => true,
  261. ),
  262. $this->mailer
  263. );
  264. }
  265. /**
  266. * Whether the email is sent or not.
  267. * We basically check the response code from a request to provider.
  268. * Might not be 100% correct, not guarantees that email is delivered.
  269. *
  270. * @since 1.0.0
  271. *
  272. * @return bool
  273. */
  274. public function is_email_sent() {
  275. $is_sent = false;
  276. if ( wp_remote_retrieve_response_code( $this->response ) === $this->email_sent_code ) {
  277. $is_sent = true;
  278. } else {
  279. $error = $this->get_response_error();
  280. if ( ! empty( $error ) ) {
  281. // Add mailer to the beginning and save to display later.
  282. $message = 'Mailer: ' . esc_html( wp_mail_smtp()->get_providers()->get_options( $this->mailer )->get_title() ) . "\r\n";
  283. $conflicts = new Conflicts();
  284. if ( $conflicts->is_detected() ) {
  285. $message .= 'Conflicts: ' . esc_html( $conflicts->get_conflict_name() ) . "\r\n";
  286. }
  287. Debug::set( $message . $error );
  288. }
  289. }
  290. // Clear debug messages if email is successfully sent.
  291. if ( $is_sent ) {
  292. Debug::clear();
  293. }
  294. return apply_filters( 'wp_mail_smtp_providers_mailer_is_email_sent', $is_sent, $this->mailer );
  295. }
  296. /**
  297. * Should be overwritten when appropriate.
  298. *
  299. * @since 1.2.0
  300. *
  301. * @return string
  302. */
  303. protected function get_response_error() {
  304. return '';
  305. }
  306. /**
  307. * Whether the mailer supports the current PHP version or not.
  308. *
  309. * @since 1.0.0
  310. *
  311. * @return bool
  312. */
  313. public function is_php_compatible() {
  314. $options = wp_mail_smtp()->get_providers()->get_options( $this->mailer );
  315. return version_compare( phpversion(), $options->get_php_version(), '>=' );
  316. }
  317. /**
  318. * This method is relevant to SMTP and Pepipost.
  319. * All other custom mailers should override it with own information.
  320. *
  321. * @since 1.2.0
  322. *
  323. * @return string
  324. */
  325. public function get_debug_info() {
  326. global $phpmailer;
  327. $smtp_text = array();
  328. // Mail mailer has nothing to return.
  329. if ( $this->options->is_mailer_smtp() ) {
  330. // phpcs:disable
  331. $smtp_text[] = '<strong>ErrorInfo:</strong> ' . make_clickable( wp_strip_all_tags( $phpmailer->ErrorInfo ) );
  332. $smtp_text[] = '<strong>Host:</strong> ' . $phpmailer->Host;
  333. $smtp_text[] = '<strong>Port:</strong> ' . $phpmailer->Port;
  334. $smtp_text[] = '<strong>SMTPSecure:</strong> ' . Debug::pvar( $phpmailer->SMTPSecure );
  335. $smtp_text[] = '<strong>SMTPAutoTLS:</strong> ' . Debug::pvar( $phpmailer->SMTPAutoTLS );
  336. $smtp_text[] = '<strong>SMTPAuth:</strong> ' . Debug::pvar( $phpmailer->SMTPAuth );
  337. if ( ! empty( $phpmailer->SMTPOptions ) ) {
  338. $smtp_text[] = '<strong>SMTPOptions:</strong> <code>' . wp_json_encode( $phpmailer->SMTPOptions ) . '</code>';
  339. }
  340. // phpcs:enable
  341. }
  342. $smtp_text[] = '<br><strong>Server:</strong>';
  343. $smtp_text[] = '<strong>OpenSSL:</strong> ' . ( extension_loaded( 'openssl' ) && defined( 'OPENSSL_VERSION_TEXT' ) ? OPENSSL_VERSION_TEXT : 'No' );
  344. if ( function_exists( 'apache_get_modules' ) ) {
  345. $modules = apache_get_modules();
  346. $smtp_text[] = '<strong>Apache.mod_security:</strong> ' . ( in_array( 'mod_security', $modules, true ) || in_array( 'mod_security2', $modules, true ) ? 'Yes' : 'No' );
  347. }
  348. if ( function_exists( 'selinux_is_enabled' ) ) {
  349. $smtp_text[] = '<strong>OS.SELinux:</strong> ' . ( selinux_is_enabled() ? 'Yes' : 'No' );
  350. }
  351. if ( function_exists( 'grsecurity_is_enabled' ) ) {
  352. $smtp_text[] = '<strong>OS.grsecurity:</strong> ' . ( grsecurity_is_enabled() ? 'Yes' : 'No' );
  353. }
  354. return implode( '<br>', $smtp_text );
  355. }
  356. /**
  357. * Get the email addresses for the reply to email parameter.
  358. *
  359. * @deprecated 2.1.1
  360. *
  361. * @since 2.1.0
  362. * @since 2.1.1 Not used anymore.
  363. *
  364. * @return array
  365. */
  366. public function get_reply_to_addresses() {
  367. _deprecated_function( __CLASS__ . '::' . __METHOD__, '2.1.1 of WP Mail SMTP plugin' );
  368. $reply_to = $this->phpmailer->getReplyToAddresses();
  369. // Return the passed reply to addresses, if defined.
  370. if ( ! empty( $reply_to ) ) {
  371. return $reply_to;
  372. }
  373. // Return the default reply to addresses.
  374. return apply_filters(
  375. 'wp_mail_smtp_providers_mailer_default_reply_to_addresses',
  376. $this->default_reply_to_addresses()
  377. );
  378. }
  379. /**
  380. * Get the default email addresses for the reply to email parameter.
  381. *
  382. * @deprecated 2.1.1
  383. *
  384. * @since 2.1.0
  385. * @since 2.1.1 Not used anymore.
  386. *
  387. * @return array
  388. */
  389. public function default_reply_to_addresses() {
  390. _deprecated_function( __CLASS__ . '::' . __METHOD__, '2.1.1 of WP Mail SMTP plugin' );
  391. return [
  392. $this->phpmailer->From => [
  393. $this->phpmailer->From,
  394. $this->phpmailer->FromName,
  395. ],
  396. ];
  397. }
  398. }