Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sending emails from PHP container to Mailpit running in another container does nothing #153

Closed
back-2-95 opened this issue Aug 14, 2023 · 11 comments

Comments

@back-2-95
Copy link

We are replacing MailHog with Mailpit in our tool Stohenge: druidfi/stonehenge#76

We have a problem getting email sent from PHP containers to host's port 1025. Noteworthy is that sending emails with curl from those same containers work just fine which I guess at least verifies that Mailpit is running just fine. When sending email through PHP (sendmail), we get no errors to logs or on terminal.

This is current setup & situation from the PR above ^^:

Mailpit is attached to localhost:1025 from a Docker container and is running with following flags:

mailpit --verbose --smtp=0.0.0.0:1025 --smtp-auth-accept-any --smtp-auth-allow-insecure

Contents of email.txt:

From: [email protected]
To: [email protected]
Subject: Email Subject

This is the body of the email.
It can contain multiple lines of text.

Works

Sending email from host (macOS) with Curl:

curl smtp://localhost:1025 --mail-from [email protected] --mail-rcpt [email protected] --upload-file email.txt

Sending email from another container with Curl:

curl smtp://host.docker.internal:1025 --mail-from [email protected] --mail-rcpt [email protected] --upload-file email.txt

Not working:

Sendmail configured for PHP as inside another container:

sendmail_path => /usr/sbin/sendmail -S host.docker.internal:1025 => /usr/sbin/sendmail -S host.docker.internal:1025

Sending email from another container with PHP mail() function:

php -r 'mail("[email protected]", "Test subject", "This is our test message", "From: [email protected]");'
@axllent
Copy link
Owner

axllent commented Aug 14, 2023

Considering you're running Mailpit in verbose mode, what output are you getting from the Mailpit container when you try connect/send from the PHP container?

I think it's one of a few things:

Firstly, is there are particular reason you're including --smtp-auth-accept-any or even --smtp-auth-allow-insecure? Please try with just mailpit --verbose --smtp=0.0.0.0:1025 as I'm pretty sure you're not proving any login details from sendmail, so adding --smtp-auth-accept-any means Mailpit tells the SMTP client it requires authentication ~ even if it accepts anything (curl just ignores this).

Secondly, what sendmail is your PHP container using? If it's the busybox implementation including in Alpine Linux, please note that it is extremely buggy, especially with PHP >=8. Based on #87 it turned out that this busybox's sendmail replaces all \n with \r\n - except that as from PHP8, all line breaks are already \r\n, so busybox's sendmail makes this \r\r\n. I'm no a C programmer, so my understanding may be off, but it definitely looked like the cause of the original issue to me.

You should be able to test PHP's mail() in verbose mode like this:

php -d "sendmail_path=/usr/sbin/sendmail -v -S host.docker.internal:1025 -t" -r 'mail("[email protected]", "Test subject", "This is our test message", "From: [email protected]");'

If you're getting errors similar to that bug report I linked to, then you will probably need to replace sendmail with a compliant sendmail version.

Lastly, I assume

sendmail_path => /usr/sbin/sendmail -S host.docker.internal:1025 => /usr/sbin/sendmail -S host.docker.internal:1025

is a typo? It should be just sendmail_path=/usr/sbin/sendmail -S host.docker.internal:1025

I hope this helps and that you're able to debug your issue.

@back-2-95
Copy link
Author

back-2-95 commented Aug 14, 2023

Sendmail is at least this container Alpine's BusyBox v1.36.1

php -d "sendmail_path=/usr/sbin/sendmail -v -S host.docker.internal:1025 -t" -r 'mail("[email protected]", "Test subject", "This is our test message", "From: [email protected]");'

gives failed at the end:

sendmail: recv:'220 497699dce1d7 Mailpit ESMTP Service ready'
sendmail: send:'EHLO druidfi.docker.so'
sendmail: recv:'250-497699dce1d7 greets druidfi.docker.so'
sendmail: recv:'250-SIZE 0'
sendmail: recv:'250-AUTH LOGIN PLAIN'
sendmail: recv:'250 ENHANCEDSTATUSCODES'
sendmail: send:'MAIL FROM:<[email protected]>'
sendmail: recv:'250 2.1.0 Ok'
sendmail: send:'RCPT TO:<[email protected]>'
sendmail: recv:'250 2.1.5 Ok'
sendmail: send:'DATA'
sendmail: recv:'354 Start mail input; end with <CR><LF>.<CR><LF>'
'endmail: send:'To: [email protected]
'endmail: send:'Subject: Test subject
'endmail: send:'From: [email protected]
'endmail: send:'
'endmail: send:'This is our test message
sendmail: send:'.'
sendmail: recv:'451 4.3.5 Unable to process mail'
sendmail: . failed

@axllent
Copy link
Owner

axllent commented Aug 14, 2023

Your output looks identical to #87 - this is not a Mailpit bug, it looks like the same busybox sendmail bug likely caused by \r\r\n (which is not valid/compliant).

As a work-around for the buggy sendmail, you could set your existing sendmail as such:

sendmail_path=sh -c 'dos2unix | /usr/sbin/sendmail -S host.docker.internal:1025 -t'

The dos2unix command replaces all \r\n with just \n, which busybox's sendmail then turns back into \r\n - and everything is compliant again.

You can test this with:

php -d "sendmail_path=sh -c 'dos2unix | /usr/sbin/sendmail -S host.docker.internal:1025 -t'" -r 'mail("[email protected]", "Test subject", "This is our test message", "From: [email protected]");'

@back-2-95
Copy link
Author

Workaround seems to work, I tested it on a few projects. Problem still persists on projects where we are not the authors of the PHP Docker images used and if they don't support changing sendmail configuration with PHP_SENDMAIL_PATH env variable.

@axllent
Copy link
Owner

axllent commented Aug 15, 2023

Whilst I understand your issue (not always having control over the docker images used), this is appears to still be an issue with this sendmail implementation, which is sending non-RFC-compliant headers to Mailpit (or any SMTP server for that matter). In my view, Mailpit is doing exactly what is was mean to - it is (among other things) an SMTP testing tool too, and so it isn't accepting a non-compliant SMTP connection.

The problem should be fixed upstream, ie: in busybox's sendmail, which would then resolve the issue everywhere once fixed and rolled out. I have just reported the issue in their bug tracker, so we'll see what happens there and what their response is.

I will still look in the meantime whether there is a work-around for Mailpit (to accept the non-compliant headers), however last time I looked it didn't seem possible, and as I just said, it defeats the point of testing SMTP if it allows non-compliant headers.

@back-2-95
Copy link
Author

You mention in #87 alternative sendmail available for Alpine being msmtp? Is it somewhat drop-in replacement? If so, I could use that in out internal images.

@axllent
Copy link
Owner

axllent commented Aug 15, 2023

That was (from memory) a replacement, but not sure about it being "drop-in". But ... before you continue - I have been looking into a working solution. The workaround (I haven't released this yet) will resolve the issue for you, with an option to turn it off. I'm not 100% happy about "fixing" messages by default, but with careful consideration I think that this is the better approach as it's clear that this is a blocker for many developers who use busybox's sendmail implementation in testing.

Most users, like yourself, will just get an error and not understand what the actual problem is, and some major mailservers like postfix already auto-correct this anyway. I expect to have this "feature" released in the next couple of days.

axllent added a commit that referenced this issue Aug 16, 2023
…<CR><CR><LF>

Due to a bug in some common sendmail implementations and PHP >=8.0, message headers sometimes contain `\r\r\n` which is not RFC compliant.

Mailpit will now fix these non-compliant headers. This can be disabled via `--smtp-strict-rfc-headers`

See #87 / #153
@axllent
Copy link
Owner

axllent commented Aug 16, 2023

I have just released this "fix" in v1.8.2. Please let me know if it resolves your sending error?

@back-2-95
Copy link
Author

back-2-95 commented Aug 16, 2023

Just tried it:

It works IF I change the php.ini sendmail setting from PHP_SENDMAIL_PATH=/usr/sbin/sendmail -S host.docker.internal:1025 to PHP_SENDMAIL_PATH=/usr/sbin/sendmail -S host.docker.internal:1025 -t

@axllent
Copy link
Owner

axllent commented Aug 16, 2023

Ahh yes, the -t is required IF your mailer (PHP) doesn't provide the recipients on the commandline when using that sendmail. This is expected behaviour and the default in the php.ini.

Glad it's working!

@axllent axllent closed this as completed Aug 16, 2023
@back-2-95
Copy link
Author

Yes! Thank you for the support, I can now add Mailpit as Mailhog replacement in our tooling and projects just need to add that -t flag to PHP_SENDMAIL_PATH.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants