Skip to content

[BUG] Fix PHP 8.x incompatibility in SMTP5 library (each() removed in PHP 8.0) #257

@dexkuz

Description

@dexkuz

Problem
When using multiOTP 5.10.x with the embedded PHP 8.4.x, sending emails via SMTP fails with a fatal PHP error:
PHP Fatal error: Uncaught Error: Call to undefined function each()
in /usr/local/bin/multiotp/multiotp.proxy.php on line 65732
The same error occurs in index.php (used by the web service / XmlServer):
PHP Fatal error: Uncaught Error: Call to undefined function each()
in /usr/local/bin/multiotp/index.php on line 65732
The each() function was deprecated in PHP 7.2 and completely removed in PHP 8.0. The embedded SMTP5 library still uses it in the SMTP authentication handshake.

Root Cause
In the SMTP5 class, the SMTP authentication method detection uses each():
php// Before fix (broken on PHP 8.x):
list($code, $arr) = each($_RESULT);

Fix
Replace each() with its PHP 8.x compatible equivalent:
php// After fix (compatible with PHP 8.x):
$code = key($_RESULT); $arr = current($_RESULT); next($_RESULT);
This fix needs to be applied in two files:

multiotp.proxy.php
index.php

One-liner to apply:
bashsed -i 's/list($code, $arr) = each($_RESULT);/$code = key($_RESULT); $arr = current($_RESULT); next($_RESULT);/' multiotp.proxy.php

sed -i 's/list($code, $arr) = each($_RESULT);/$code = key($_RESULT); $arr = current($_RESULT); next($_RESULT);/' index.php

Additional findings during investigation

  1. SMTP password config key corruption
    When setting SMTP password via CLI (multiotp -config smtp-password=...), the key is sometimes written as smtp_password:= instead of smtp_password= in multiotp.ini, causing silent authentication failure. Setting it directly in the ini file avoids this.
  2. SMTP SSL mode logic
    The $ssl_mode detection in SendEmail() only checks smtp_ssl=1 for SSL mode but does not handle STARTTLS (port 587). Port 465 with smtp_ssl=1 works correctly. Port 587 with STARTTLS causes a TLS handshake error because the library connects with TLS directly instead of upgrading via STARTTLS.
    Recommendation: Use port 465 with smtp_ssl=1 for Gmail and other providers that support it.
  3. email_code_allowed disabled by default
    The email_code_allowed config is 0 by default, which causes error 66 when trying to send OTP by email. This should be documented more prominently.

Environment

multiOTP version: 5.10.1.5
PHP version: 8.4.16
Deployment: Docker (multiotp/multiotp-open-source)
SMTP provider tested: Gmail (smtp.gmail.com:465, SSL)

Dockerfile workaround (for Docker users until fix is merged)
dockerfileFROM multiotp/multiotp-open-source

RUN sed -i 's/list($code, $arr) = each($_RESULT);/$code = key($_RESULT); $arr = current($_RESULT); next($_RESULT);/'
/usr/local/bin/multiotp/multiotp.proxy.php &&
sed -i 's/list($code, $arr) = each($_RESULT);/$code = key($_RESULT); $arr = current($_RESULT); next($_RESULT);/'
/usr/local/bin/multiotp/index.php

I hope it will be usefull for someone who also wants to add their smtp.
And hope dev's will fix it

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions