Uniform + Additional parameters ( -f noreply@emailaddress.com )

uniform

#1

I’m using Uniform for a static contact form on a client’s site. The form is sending perfectly but the emails are being flagged as spam by Gmail. I’m pretty sure this is happening because I can’t find a way to add the “-f noreply@clientname.com” flag to Uniform’s email actions.

In the past, I’ve used the following php mail function on the same server with no issue:

mail($to, $subject, $message, $headers, '-f noreply@clientname.com');

Anyone know how add the mail function’s 5th parameter to Uniform’s email actions?

$form->emailAction([
    'to' => $form->data('email'),
    'from' => 'hello@clientname.com',
    // Somehow add: -f noreply@clientname.com
]);

Thanks in advance!


#2

The Uniform email action uses the Email class of the toolkit, which doesn’t use the fifth parameter:

  $send = mail($email->to, str::utf8($email->subject), str::utf8($email->body), implode(PHP_EOL, $headers));

I think, the only way to achieve that would be by create a custom email action.


#3

Why not add the 5th parameter? Can you add this as a GitHub “wish”?
I run in the same issue multiple times and hacked the core to fix it.

Svnt


#4

Thanks @texnixe!

I was hoping that wouldn’t be the case…

Would you mind sharing your hack @Svnt?

Also I’m happy to make a feature request but I’m new to the forum so if anyone has any advice on how to go about it that’d be great!


#5

Instead of hacking the Email class, I’d extend it and then create a custom Uniform action that uses the new extended class. That way, your changes are safe when updating Kirby.

As regards the feature request, head over to GitHub and create a new issue in the toolkit repo: https://github.com/getkirby/toolkit/issues


#6

Ah yeah that makes sense.

What do you think the best way of extending the email class would be? Would it be a custom email driver https://getkirby.com/docs/developer-guide/toolkit/email-driver? Or is there a way of building a plugin that extends toolkit classes?

If it’s the email driver where should I put that code? There’s no mention of the correct place to make those changes…

Sorry if this stuff is obvious. Only just getting into extending Kirby and still finding it a little daunting haha


#7

Can’t (code is gone) and want (texnixes advice is much better).
Core hacking is always evil.


#8

You don’t have to write your own Uniform action. You can write your own email service and then use the service option of the default email action.


#9

Thanks @mzur

So in the end made a new email service here: site/plugins/email-services.php

It’s a just copy of the default mail driver form. Here’s the mail driver and contact form controller in case anyone is interested

Email Driver:

/**
 * Extend default mail driver
 */
email::$services['extended'] = function($email)
{

  $headers = array(
    'From: ' . $email->from,
    'Reply-To: ' . $email->replyTo,
    'Return-Path: ' . $email->replyTo,
    'Message-ID: <' . time() . '-' . $email->from . '>',
    'X-Mailer: PHP v' . phpversion(),
    'Content-Type: text/plain; charset=utf-8',
    'Content-Transfer-Encoding: 8bit',
  );

  $additional_parameters = $email->options['additional_parameters']; // the service-options parameter from the controller seems to be called options in the email driver

  ini_set('sendmail_from', $email->from);

  $send = mail($email->to, str::utf8($email->subject), str::utf8($email->body), implode(PHP_EOL, $headers), $additional_parameters);

  ini_restore('sendmail_from');

  if(!$send) {
    throw new Error('The email could not be sent');
  }

};

Controller:

use Uniform\Form;

return function ($site, $pages, $page) {
    $form = new Form([
        'name' => [
            'rules' => ['required'],
            'message' => 'Please enter a name',
        ],
        'email' => [
            'rules' => ['required', 'email'],
            'message' => 'Please enter a valid email address',
        ],
        'subject' => [
            'rules' => ['required'],
            'message' => 'Please enter a subject line',
        ],
        'message' => [
            'rules' => ['required'],
            'message' => 'Please enter a message',
        ],
    ]);

    if (r::is('POST')) {
        $form->emailAction([
            'to' => $page->email(),
            'from' => 'client@clientemail.com',
            'service' => 'extended',
            'service-options' => ['additional_parameters' => '-f noreply@clientemail.com'],
        ]);

    }

    return compact('form');
};

Unfortunately all emails are still being picked up by gmail’s spam filter. I’ve contacted the hosting provider. But anyone have any ideas?


#10

Does the site run at clientemail.com? Lots of email servers reject emails that come from a different domain than the email address.


#11

The site is currently in a subdomain of the clientemail.com hosted on the same server…


#12

So I’ve managed to resolve the issue.

In the end I created a new email service which allowed me to specify custom additional parameters

But in the end it was the Return-Path: header causing problems.
Seems like gmail needs Return-Path: to match From:
https://stackoverflow.com/questions/6201396/spf-issue-what-causes-softfail

Anyway here’s my email service an case anyone is interested:

/**
* Extend default mail driver
*/
email::$services['extended'] = function($email)
{

    $headers = array(
        'From: ' . $email->from,
        'Reply-To: ' . $email->replyTo,
        'Return-Path: ' . $email->from,
        'Message-ID: <' . time() . '-' . $email->from . '>',
        'X-Mailer: PHP/' . phpversion(),
        'MIME-Version: 1.0',
        'Content-Type: text/plain; charset=utf-8',
        'Content-Transfer-Encoding: 8bit',
    );

    $additional_parameters = $email->options['additional_parameters'];

    ini_set('sendmail_from', $email->from);
    $send = mail($email->to, str::utf8($email->subject), str::utf8($email->body), implode(PHP_EOL, $headers), $additional_parameters);
    ini_restore('sendmail_from');

    if(!$send) {
         throw new Error('The email could not be sent');
    }
};

Thanks again for everyone’s advice


#13

Also, @mzur, the documentation on where to put a custom snippet for the email body is very vague. I keep getting a “Snippet name does not exist” exception. Where should it be placed and how should the filename be formatted in the snippet option?

Thanks again for putting up with all my questions!


#14

If your email snippet is in/snippets/form and called email-table.php, the snippet option would look like this

$form->emailAction([
  'to' => 'name@example.com',
  'from' => 'from@example.com',
  'snippet' => 'form/email-table' 
])