PHP 8.1 deprecation obtained when using Send HTML e-mail Action in Rules

Created on 23 January 2023, almost 2 years ago
Updated 21 June 2024, 6 months ago

Problem/Motivation

The following PHP 8.1 deprecation is observed when sending an e-mail using the Send HTML e-mail Action in Rules:

Deprecated function: preg_match_all(): Passing null to parameter #2 ($subject) of type string is deprecated in token_scan() (line 124 of /home/techsoco/dev.techsoc.org.uk/includes/token.inc).

I'm not sure whether this is an issue for Mime Mail or Drupal core, but as I see the deprecation when using the Mime Mail plugin to Rules I'm reporting it here.

Steps to reproduce

I'm using Drupal core 7.94, Rules 7.x-2.13, Mime Mail 7.x-1.2, Mail System 7.x-2.35

Create a simple Rule Component, Action set, with a single Send HTML e-mail Action;
Complete only the Send HTML e-mail required fields and BODY;
Execute the Rule;
E-mail is sent but deprecation is reported in the log.

Repeat test with text additionally included in the PLAIN TEXT BODY field and there is no deprecation, so this field is the source of the error.
PLAIN TEXT BODY is not a required field and there is no deprecation if it is left blank when running with PHP 7.4.

Note: the e-mail sent is not correctly encoded when using PHP 8.1, but that is not (I believe) an issue for Mime Mail.

Proposed resolution

Sorry, I'm only a user.

Remaining tasks

User interface changes

API changes

Data model changes

🐛 Bug report
Status

Needs review

Version

1.2

Component

Code

Created by

🇬🇧United Kingdom stevewilson

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @stevewilson
  • Status changed to Postponed: needs info almost 2 years ago
  • 🇺🇸United States tr Cascadia

    Can you please export your Rule and post it here so we can try to reproduce the error?

  • 🇬🇧United Kingdom stevewilson

    I've created a very simple Rule Component that exhibits the reported characteristic. I uploaded it as a text file but can't see how to reference it (sorry - more learning required) but, as it's small, I'm pasting it here:

    { "rules_html_e_mail_test" : {
        "LABEL" : "HTML e-mail test",
        "PLUGIN" : "action set",
        "OWNER" : "rules",
        "REQUIRES" : [ "rules", "mimemail" ],
        "ACTION SET" : [
          { "mimemail" : {
              "USING" : {
                "key" : "html_email_test",
                "to" : "[site:mail]",
                "subject" : "Send HTML e-mail test",
                "body" : "Testing for preg_match_all() deprecation.",
                "language" : [ "" ]
              },
              "PROVIDE" : { "send_status" : { "send_status" : "Send status" } }
            }
          }
        ]
      }
    }
    

    As you can see, it's an Action set with a single "Send HTML e-mail" Action, to send an e-mail to the administrative e-mail address for the site.

    When I execute the Component from the Administration » Configuration » Workflow » Rules » Components page with PHP 8.1 set, I get the reported deprecation in the log. With PHP 7.4 set, there is no deprecation. If, via the user interface form, I add some text to the Plain text body field, the 8.1 deprecation is no longer reported.

  • Status changed to Active almost 2 years ago
  • 🇺🇸United States tr Cascadia

    Thanks. I'll see if I can reproduce the problem. This is clearly due to changes in PHP in PHP 8.1. In short, somewhere some module is trying to do token replacement on a string but that string is set to NULL. In PHP 8.1 variable types are enforced more strictly.

    This may or may not be a problem with Mime Mail. Or with Rules, or even with core or the contributed Token module if you're using that.

  • 🇺🇸United States rclemings

    I'm seeing the same thing with a rules component. I've pasted the relevant part below. When any of the tokens is null, I get the error. In one example I'm looking at, [node:field-funding-duration] is null. In mimemail.rules.inc, it looks as if the body field is just passed through without checking the tokens. Since there are multiple tokens in that field (among others), I can't see an easy fix, short of editing the rule and changing all null tokens to empty before building the body field. Suggestions welcome as to the best way to do that, if mimemail can't be patched.

    "DO" : [
      { "mimemail" : {
          "USING" : {
            "key" : "funding_source_update",
            "to" : "[node:field-funding-contact-email]",
            "subject" : "Update request for \u0022[node:title]\u0022 listing",
            "body" : "TITLE: [node:title]\u003Cbr\u003E\u003Cbr\u003E\r\nTYPE: [node:field-funding-type]\u003Cbr\u003E\u003Cbr\u003E\r\nSUMMARY: [node:summary]\u003Cbr\u003E\u003Cbr\u003E\r\nDESCRIPTION: [node:body]\u003Cbr\u003E\u003Cbr\u003E\r\nFUNDER(S):\u003Cbr\u003E\r\n[node:field-funding-organization:0:title]: [node:field-funding-organization:0:url]\u003Cbr\u003E\r\n[node:field-funding-organization:1:title]: [node:field-funding-organization:1:url]\u003Cbr\u003E\r\n[node:field-funding-organization:2:title]: [node:field-funding-organization:2:url]\u003Cbr\u003E\r\n[node:field-funding-organization:3:title]: [node:field-funding-organization:3:url]\u003Cbr\u003E\u003Cbr\u003E\r\nAMOUNT: [node:field-funding-amount]\u003Cbr\u003E\u003Cbr\u003E\r\nDEADLINE: [node:field-funding-deadline]\u003Cbr\u003E\u003Cbr\u003E\r\nQUALIFICATIONS: [node:field-funding-qualifications:value]\u003Cbr\u003E\u003Cbr\u003E\r\nDURATION: [node:field-funding-duration]\u003Cbr\u003E\u003Cbr\u003E\r\nTYPES OF SUPPORT: [node:field-funding-support-types]\u003Cbr\u003E\u003Cbr\u003E\r\nSUBJECTS: [node:field-funding-subjects]\u003Cbr\u003E\u003Cbr\u003E\r\nOTHER SUBJECTS: [node:field-funding-other-subjects]\u003Cbr\u003E\u003Cbr\u003E\r\nGEOGRAPHIC FOCUS OR RESTRICTIONS: [node:field_funding_geographic]\u003Cbr\u003E\u003Cbr\u003E\r\nTIPS: [node:field-funding-tips:value]\u003Cbr\u003E\u003Cbr\u003E\r\nPAST PROJECTS: [node:field-funding-pastprojects:value]\u003Cbr\u003E\u003Cbr\u003E\r\nPAST AWARDEES: [node:field-funding-past-awardees:value]\u003Cbr\u003E\u003Cbr\u003E\r\nAPPLICATION LINK: [node:field-funding-applink:url]\u003Cbr\u003E\u003Cbr\u003E\r\nMORE INFORMATION LINK: [node:field-funding-moreinfo:url]\u003Cbr\u003E\u003Cbr\u003E\r\nCONTACT NAME: [node:field-funding-contact-name]\u003Cbr\u003E\u003Cbr\u003E\r\nCONTACT EMAIL: [node:field-funding-contact-email]\u003Cbr\u003E\u003Cbr\u003E\r\nCONTACT PHONE: [node:field-funding-contact-phone]\u003C\/p\u003E\r\n\u003Cp\u003E(Please leave this link intact in your reply: [node:url])\u003C\/p\u003E",
            "language" : [ "" ]
          },
          "PROVIDE" : { "send_status" : { "send_status" : "Send status" } }
        }
      }
    ]
    
  • 🇺🇸United States tr Cascadia

    In PHP 8.1, many modules that implement token replacement have a problem with tokens that default to NULL instead of defaulting to a value with the proper data type (like an empty string or an empty array instead of NULL). With your [node:field-funding-duration], usually what needs to be done is to ensure all your fields have default values and that the code providing the tokens doesn't use NULL values.

    I haven't looked much into the original issue yet - the instructions to reproduce in #3 are good, but D7 is very low on my priority list.

  • 🇬🇧United Kingdom stevewilson

    The source of the issue for me appears to be line 205 in mimemail.module. My knowledge of PHP and Dupal module constructs is minimal but the following change removed the deprecation I was seeing:

    - 205  $message['params']['plaintext'] = token_replace($params['plaintext'], $context, $options);
    + 205  $message['params']['plaintext'] = !empty($params['plaintext']) ? token_replace($params['plaintext'], $context, $options) : ($params['plaintext']);
    

    I'm not going to be so bold as to suggest that this is an appropriate fix for the issue, but it does seem to confirm this line as it's source.

    It's also clear that line 204, which performs the same token replacement on the Body field will, if no Body text is entered, give rise to the same deprecation as seen with an empty Plain text body field. (In my test Rule above, I cleared the Body field and entered the text instead in the Plain text body field to prove this.) A similar change to that made in line 205 once again removed the deprecation.

    I'm presuming that token replacement on the To and Subject fields (lines 202 and 203 respectively) will not not give rise to the deprecation as these fields are designated on the form as Required fields and hence will never be empty?
    But what about lines 51 and 57 in mimemail_action.module? Are they a concern?

    A limited contribution I'm afraid, but hopefully it might help move things along.

  • 🇺🇸United States rclemings

    What if there are multiple tokens in the field? In my case the body field is not empty but some of the tokens within it can be empty (or null, rather). I was thinking I'd have to go through the tokens one at a time and changes the nulls to empties.

  • 🇧🇷Brazil dungahk Balneário Camboriú

    I had the same issue and I ended up just setting a value to the plaintext parameter.

    I agree the module should handle that better though, either validating the rule to make sure the value is not empty or as #7 suggested, add a check on the value.

  • Status changed to Needs review 6 months ago
  • Open in Jenkins → Open on Drupal.org →
    Core: 7.x + Environment: PHP 5.3 & MySQL 5.5
    last update 6 months ago
    9 pass
  • 🇫🇷France anrikun

    This simple patch fixes this issue.

Production build 0.71.5 2024