phpsmtpssmtpopensmtpd

PHP's mail relay via OpenSMTPD returns error Message is not RFC 2822 compliant


I have the following setting in my php.ini

[mail function]
sendmail_path = /usr/sbin/sendmail -t -i

Binary /usr/sbin/sendmail comes from the installed ssmtp package on Alpine Linux. I want to relay all emails to the opensmtpd container from the private network, so my /etc/ssmtp.conf looks like this:

mailhub=opensmtpd

This is how I send the email:

$ php -r 'mail("valid@address.com", "Test subject", "This is our test message", "From: my@email.com");'

and I get the following error:

sendmail: 550 5.7.1 Delivery not authorized, message refused: Message is not RFC 2822 compliant


UPDATE

Added more verbosity to the sendmail command and adjusted a bit the /etc/ssmtp.conf as follows:

mailhub=opensmtpd:25
FromLineOverride=Yes
UseTLS=No

This is how I call it

$ php -r '$headers = ["Date" => date("r", time()), "From" => "my@email.com", "Reply-To" => "my@email.com", "X-Mailer" => "PHP/" .
 phpversion()]; mail("valid@email.com", "Test subject", "This is our test masdlkfjaslkdfjaslkdfjaskldjfeproiqweessage\r\n", $headers);'

And this is the output:

[<-] 220 opensmtpd-2298774033-mq2hl ESMTP OpenSMTPD
[->] HELO php-3107772150-7jj96
[<-] 250 opensmtpd-2298774033-mq2hl Hello php-3107772150-7jj96 [172.17.0.60], pleased to meet you
[->] MAIL FROM:<my@email.com>
[<-] 250 2.0.0: Ok
[->] RCPT TO:<opensmtpd:25@php-3107772150-7jj96>
[<-] 250 2.1.5 Destination address valid: Recipient ok
[->] DATA
[<-] 354 Enter mail, end with "." on a line by itself
[->] Received: by php-3107772150-7jj96 (sSMTP sendmail emulation); Fri, 01 Apr 2022 14:13:35 +0000
[->] To: valid@email.com
[->] Subject: Test subject
[->] Date: Fri, 01 Apr 2022 14:13:35 +0000
[->] From: my@email.com
[->] Reply-To: my@email.com
[->] X-Mailer: PHP/8.0.17
[->]
[->] This is our test masdlkfjaslkdfjaslkdfjaskldjfeproiqweessage
[->]
[->]
[->] .
[<-] 550 5.7.1 Delivery not authorized, message refused: Message is not RFC 2822 compliant

I don't get it


UPDATE 2

As you can see from the output above the recipient was incorrect, that's because ssmtp's sendmail from Alpine package doesn't support -t flag. You can of course change sendmail_path in php config to /usr/sbin/ssmtp -t -f which will set correct recipients but ssmtp unfortunately doesn't support -v flag which is crucial for me to debug.

I actually made it work for a short time. I've removed ssmtp package so /usr/sbin/sendmail now used from busybox. That's what I used in the first place, the problem is it can't override FROM email from the message, so you have to hardcode the sender:

sendmail_path = /usr/sbin/sendmail -t -i -f my@email.com -v -S opensmtpd:25

Once I did that and prepended my body message with Body: it started working and I actually received the email. However, it also included "Body:" in the actual email message which I found weird. I thought perhaps this is a bug in OpenSMTPD, so I updated it from 6.0.3 to 6.7.1. And after that it stopped working again:

sendmail: recv:'220 opensmtpd-839025387-f4d7n ESMTP OpenSMTPD'
sendmail: send:'EHLO php-4163283461-9fd2b'
sendmail: recv:'250-opensmtpd-839025387-f4d7n Hello php-4163283461-9fd2b [172.17.0.50], pleased to meet you'
sendmail: recv:'250-8BITMIME'
sendmail: recv:'250-ENHANCEDSTATUSCODES'
sendmail: recv:'250-SIZE 36700160'
sendmail: recv:'250-DSN'
sendmail: recv:'250 HELP'
sendmail: send:'MAIL FROM:<my@email.com>'
sendmail: recv:'250 2.0.0 Ok'
sendmail: send:'RCPT TO:<valid@email.com>'
sendmail: recv:'250 2.1.5 Destination address valid: Recipient ok'
sendmail: send:'DATA'
sendmail: recv:'354 Enter mail, end with "." on a line by itself'
'endmail: send:'To: valid@email.com
'endmail: send:'Subject: Test subject
'endmail: send:'From: my@email.com
'endmail: send:'
'endmail: send:'Body: This is our test message
sendmail: send:''
sendmail: send:'.'
sendmail: recv:'550 5.7.1 Delivery not authorized, message refused: Message is not RFC 2822 compliant'
sendmail: . failed

And this is opensmtpd config:

listen on 0.0.0.0

table aliases file:/etc/smtpd/aliases

queue ttl 4d

bounce warn-interval 1h, 6h, 2d

smtp max-message-size 35M

table authinfo db:/etc/smtpd/authinfo.db
action act01 relay host "smtp+tls://user@host:587" auth <authinfo>
match from any for any action act01

Sending emails directly from OpenSMTPD works like a charm.


Solution

  • As @tripleee noted in the comment it seems this is a known bug in OpenSMTPD. I tried adding a CR (\r) before the body:

    $ php -r 'mail("<valid@email.com>", "Test subject", "\rThis is our test message", "From: my@email.com");'
    

    And it worked but only for OpenSMTPD 6.0, not 6.7:

    sendmail: recv:'220 opensmtpd-401834694-0hz0r ESMTP OpenSMTPD'
    sendmail: send:'EHLO php-4163283461-9fd2b'
    sendmail: recv:'250-opensmtpd-401834694-0hz0r Hello php-4163283461-9fd2b [172.17.0.50], pleased to meet you'
    sendmail: recv:'250-8BITMIME'
    sendmail: recv:'250-ENHANCEDSTATUSCODES'
    sendmail: recv:'250-SIZE 36700160'
    sendmail: recv:'250-DSN'
    sendmail: recv:'250 HELP'
    sendmail: send:'MAIL FROM:<my@email.com>'
    sendmail: recv:'250 2.0.0: Ok'
    sendmail: send:'RCPT TO:<valid@email.com>'
    sendmail: recv:'250 2.1.5 Destination address valid: Recipient ok'
    sendmail: send:'DATA'
    sendmail: recv:'354 Enter mail, end with "." on a line by itself'
    'endmail: send:'To: <valid@email.com>
    'endmail: send:'Subject: Test subject
    'endmail: send:'From: my@email.com
    'endmail: send:'
    'his is our test message
    sendmail: send:''
    sendmail: send:'.'
    sendmail: recv:'250 2.0.0: 9b837971 Message accepted for delivery'
    sendmail: send:'QUIT'
    sendmail: recv:'221 2.0.0: Bye'
    

    UPDATED

    I found this issue in php repository discussing the same problem with CRLF and the suggestion how to fix it that works for all versions of OpenSMTPD:

    sendmail_path = '/usr/bin/dos2unix -u | /usr/sbin/sendmail -t -i -f my@email.com -v -S opensmtpd:25'
    

    I'm still not sure what's exactly causing the issues by not following the RFC, it's either php, sendmail (both busybox's and ssmtp's) or OpenSMTPD. But for now I consider the workaround with dos2unix as the solution to my issue.


    Addition

    This is the issue reported in php repository saying that headers are not delimited with CRLF as it should according to the RFC. And this is the commit that fixes it (from what I can tell since 8.1.3 and 8.0.16). So, PHP now uses a correct delimiter \r\n but sendmail expects \n so looks like it's a sendmail bug after all.