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.
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.