Jump to content
teppo

Idea and proof of concept: Mailer class

Recommended Posts

So, I've been seeing some email-related topics around here and actually had quite a few struggles of my own with this very subject myself lately.

Thing is that sending email should be easy, but it's not always that; especially for those who have to work on multiple, low-price (and regrettably often low-quality) platforms that may or may not provide proper mail servers.. or prefer to host their services themselves and still want to avoid setting up and maintaining a mail server. Hosting a mail server can be real pain in the ass when things don't work like they should, not to mention that most people have very little knowledge about DNS entries etc. this requires.

Anyway, long story short: yesterday I started thinking that wouldn't it be sweet to have a layer of abstraction within ProcessWire for sending email? Of course one could still use PHP mail() -- there's no way and no sense in even trying to stop that -- but using a common gateway would definitely bring in some extra value.

This layer I'm talking about could by default use built-in PHP mail() but also make it possible to override it, thus allowing multitude of options that PHP mail(), being bound to Sendmail / it's alternatives, can't offer without additional server-side software (such as Nullmailer.)

By making sending emails hookable it could also enable all kinds of interesting tricks to be done when mail is sent -- such as writing a custom log file, sending another email to someone else, updating local content (I'd imagine that this could be useful for building newsletter platform, for an example) and so on.

Since words tend to fail me at times like these, I put together a quick proof of concept of what I'm talking about here, accompanied by one example of what could be achieved by doing this:

  • A very simple yet functional Mailer class
  • Two commits on top here list all the changes I've made in my PW fork to make this work -- including the fact that I've altered some default modules to use $mailer->send() instead of mail()
  • SwiftMailer module, again very simple but fully functional (though only tested with Gmail SMTP) drop-in replacement for PHP mail()

So, what do you folks think of this? Please keep in mind that this is just a suggestion and I'm not saying that this is the right path to take especially considering that it would add another API variable -- it just felt like best option here and I couldn't think of cleaner way to achieve it.

  • Like 14

Share this post


Link to post
Share on other sites

I like it! There is no better way to propose ideas than this Teppo. 

First: Yes, simple wrapper is definitely needed. I think it should take same params than mail() does - and just like your proposal works. 

What I am not sure is that if replace hook is way to go here though? Maybe having general config module (or just config.php) where one could select which mailer is used? Also - not sure about this one - but sometimes one might want to set mailer on code level, something like this:

$postmark = $modules->get("MailerPostmark");

$mailer->provider = $postmark;

$mailer->send(...);

That would allow to having multiple provider modules installed and still having control which one get's used (and possibility to use them in different parts of the application).

Having this supported in core there wouldn't be any reason not to build newsletter system in PW... :)

  • Like 5

Share this post


Link to post
Share on other sites

What I am not sure is that if replace hook is way to go here though? Maybe having general config module (or just config.php) where one could select which mailer is used? Also - not sure about this one - but sometimes one might want to set mailer on code level, something like this:

$postmark = $modules->get("MailerPostmark");

$mailer->provider = $postmark;

$mailer->send(...);

Agreed. This is something I thought of too.. right after posting that original topic :)

I haven't really had the need to switch mailer "on the fly" before (especially when using Swift Mailer, which has always been pretty damn effective at sending to multiple recipients / batch sending emails etc. out of the box) which is also why I considered replace best method here. This way once an alternative mailer module is installed and configured it just magically takes over and developer doesn't even need to know that anything has changed (other than the fact that suddenly Mailer has awesome super powers.)

On the other hand, I could imagine that in some cases (such as when sending those newsletters..) one might definitely want to switch to another provider -- perhaps even a web service like Mailchimp or Campaign Monitor. For this reason alone it would make a lot of sense to have Mailer configurable at code level. There would still be multiple ways to approach this need and I don't think any of them would need to eliminate the ability to create those "drop-in replacement modules":

// like posted above ...
$postmark = $modules->get("MailerPostmark");
$mailer->provider = $postmark;
$mailer->send(...);

// ... or you could also init another Mailer!
$myMailer = new Mailer("MailerPostmark");
  • Like 1

Share this post


Link to post
Share on other sites

This topic didn't get too much action earlier, but I do think something along these lines is definitely needed. I would love to send all PW-mails through mailgun or similar service, or at least smtp.

Ryan and others, do you see any drawbacks in Teppo's approach?

Share this post


Link to post
Share on other sites

I'd definitely like to see this. I use SwiftMailer at the moment and love its object orientated approach over php's mail(). I send most of my mail through Mandrill or Mailgun. I currently use SMTP but it would be nice to have transports that send via their APIs as these offer a few more options. It would also be a really easy route for ProcessWire to receive mail in a standardised manner - you ust provide an enpoint for their webhooks and a hookable method for consuming them.

  • Like 1

Share this post


Link to post
Share on other sites

This is just what I was hoping to see. I've come to not trust the reliability of mail() on shared hosts, and those seem to be all I deploy to. :)

Share this post


Link to post
Share on other sites

I love the idea of this. I'm getting to grips with sending most important email through Mandrill for web applications now as you can see some nice stats and handle bounces well with their API, so if there was a sensible way of overriding the default email functionality with a class like is being talked about above that would be great.

Glancing up this thread, it looks like we would have MailerSwiftMailer, MailerPostmark and MailerMandrill in a short space of time.

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By ngrmm
      I have a page which sends out an email based on queries in the url
      <?php // event ID $eventID = $input->get('eventID','int'); $event = $pages->get($eventID); // config $adminEmail = "events@test.com"; $fromEmail = "noreply@test.com"; $fromName = "test"; $emailSubject = "Test Email"; // HTML BODY $emailBody = ""; // HOW TO ??? … // send mail $m = new WireMail(); $m->to($adminEmail); $m->from($fromEmail, $fromName); $m->subject($emailSubject); $m->bodyHTML($emailBody); $m->send(); ?> The email body is a bit complex: standard html/css tables and some php (pw variables).
      I put my emailbody (html) in a seperate file emailbody.inc but don't know how to include it?
       
    • By Noel Boss
      To create a new gitlab issue, I'd like to send an Email to the following email address using FormBuilder: 
      incoming+account/repository@incoming.gitlab.com
      unfortunately, the / in the email gets striped by the sanitizer:
      wire('sanitizer')->email(incoming+account/repository@incoming.gitlab.com'); // output: incoming+accountrepository@incoming.gitlab.com Is there any way to configure the sanitizer? Any other Ideas how to send the mail to this address?
       
      Ps.: I can not define the email format as it is defined by gitlab. The format is also kind of "common" and known as email-alias in the form of emailaccount+alias@domain.com – gmail uses it to label mails…
      https://help.wodify.com/hc/en-us/articles/234441508-How-Do-I-Create-an-Email-Alias-
    • By ihathome
      Hi,
      I'm an abolute newbie in processwire an it's modules. But I have read huge amounts of posts in this forum and as many docs and i learnt a lot in the last days. For a contact-form i used this great module (many thanks) and i hooked it my first time. Everything is alright. Now i search for a possibility to format or render the output in the email. Is there any posibility?
      Thank you for your replies
    • By Kiwi Chris
      Forms are an essential part of most websites, and it's no surprise that there's an excellent premium module Form Builder but what if you're on a zero budget for whatever reason?
      It is possible to build forms quickly and easily by making use of a couple of free modules and the admin UI to give you a great deal of flexibility and speed of development, particularly if you need multiple forms on a website with different fields.
      1. First you're going to need to install a couple of modules:
      Form Template Processor
      Fieldtype Select External Option
      2. For each form that you want to display, create a template without a template file and add fields to it as you normally would. (eg I have formContact, formRegister etc)
      Tip: under the Advanced tab in the setup for each template, I add a tag Forms so that all my forms templates are nicely grouped together in admin.
      3. Create a new field of type Select External Option and call it formTemplate
      In the section Create options from any database table select
      templates as the source table id as the Option Value name as the Option Label 4. Create a new template file and call it renderForm.php (or whatever else you like)
      Add an email field to this form - This will be the email address that forms get submitted to. Add the formTemplate field you previously created to this form. This will allow you to select which of the templates you previously created such as formContact, formRegister etc you want to render. Add any other fields as usual that you want to render on the page. Add the following PHP code to the template file. $recipient = $page->email; $form = $modules->get('FormTemplateProcessor'); $form->template = $templates->get($page->formTemplate->label); // required $form->requiredFields = array('contactName', 'contactEmail', 'contactMesssage'); //Optional: This can be improved by having a field in the page template with a CSV list of required fields eg $form->requiredFields = explode(',', $page->requiredFields) $form->email = $recipient; // optional, sends form as email. FormTemplateProcessor can also save forms to the database. $content .= $form->render(); //generate the form to display. Note: this doesn't actually render the form at this point, but you have it in the $content variable ready to output wherever you want in your template.
      Add any template HTML or other PHP code and echo $content; wherever you want to render the form.
      5. Create a page using the renderForm template, and provide an email address, and select a form that you want to display.
      6. Use CSS to style the form as required.
      7. View your new page, and check that the form renders correctly.
      8. You can modify the templates you created at step 2 or create new ones as required if your requirements for what fields forms display changes.
      Note: The Form Template Processor module can also save form input as pages, and the FieldType Select External Option can be set up with filtering, so this solution can probably be refined further.
    • By henri
      Hi Guys,
      i am a newbe to processwire. Have to maintain a website, but never worked with processwire. I have got an form that is submitted ( i do not have the form thing), to two email addresses. The last week the mails to the second address aren't delivered so it seems. Where do i find the email addresses where the form is submitted to?? I cant find them, though i can find the include of the form. Who knows?????
×
×
  • Create New...