[wp-trac] [WordPress Trac] #29513: Move heavy lifting of wp_mail() to child class of PHPMailer

WordPress Trac noreply at wordpress.org
Thu Sep 4 18:10:11 UTC 2014


#29513: Move heavy lifting of wp_mail() to child class of PHPMailer
---------------------------+-----------------------------
 Reporter:  stephenharris  |      Owner:
     Type:  enhancement    |     Status:  new
 Priority:  normal         |  Milestone:  Awaiting Review
Component:  Mail           |    Version:  trunk
 Severity:  normal         |   Keywords:
  Focuses:                 |
---------------------------+-----------------------------
 If a plug-in is sending an e-mail, the class `PHPMailer` has a lot of
 useful methods (e.g. `addStringAttachment()`), but these are not available
 when using `wp_mail()`, which is a requirement to work with numerous other
 plug-ins owing to the hooks it triggers.

 `wp_mail()` does a number of things:

 1. Instantiates a `PHPMailer` instance
 2. Sets default values (e.g. "from" headers, charset, content type etc. )
 3. Parses the passed arguments and feeds it to the `PHPMalier` instance.
 4. Executes a "pre-send" routine, (e.g. triggering hooks `wp_mail_from`,
 `phpmailer_init` etc)
 5. Sends the e-mail


 The attached patch does a number of things:

 1. Defines a `WPMailer` class  ( a child of `PHPMailer`)
 2. Defines a `WPMailerFactory` class which creates an instance with
 appropriate default values
 3. Defines 'helper' methods which do the 'heavy lifting' of (3) above
 4. Overrides the preSend method of PHPMailer to execute the 'pre-send
 routine' present in `wp_mail()`  (i.e. (4) above)
 5. Refactors `wp_mail()` to "operate" `WPMailer()` instance

 The result is that developers can either use `wp_mail()` or `$wpmailer =
 WPMailerFactory::getMailer()` to send e-mails, and both will behave
 identically (in terms of default values, and hooks being triggered), while
 maintaining backwards compatibility.

 This would also effectively close tickets #28407, #28059, #23291, #15539 ,
 #11376 and maybe others.



 == Remarks ==

 '''Why just not use `phpmailer_init`?'''
 This hook is very useful, but offers no context in which `wp_mail()` is
 called. As an example, suppose a plug-ins sends an e-mail with an "on-the-
 fly" purchase receipt attached. At `phpmailer_init` I don't know the
 purchase ID from which to generate and attach the receipt.

 '''Class/method naming standards'''
 I've used PHPMailer's naming standards which I understand conflicts
 slightly with WordPress' naming standards. A future iteration of this
 patch could well change this if that is deemed best.

 '''Global $phpmailer'''
 The global `$phpmailer` is redundant, as the factory creates a fresh
 instance for each request. Or at least it ''would''. The ''only'' reason
 the patch still uses this global, is that all the relevant unit tests pass
 without any further changes. Subject to this ticket being accepted in
 principle, these tests should be updated along with the patch.

 '''Backwards compatability'''
 Assuming `wp_mail()` hasn't been overriden by a plug-in/theme, then the is
 no change in behaviour. If it has been overridden, it's clear from the
 original function that the `$_GLOBAL['phpmailer']` should not be expected
 to exist, nor even the required classes to be loaded. As such they can be
 expected to operate independently of the changes made here, which are non-
 destructive.

 '''Uni tests'''
 For me, the mail group unit tests pass with 1 skipped. For some reason
 some tests failed (e.g. `Tests_DB::test_bail()`), but these failed even
 without this patch.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/29513>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list