-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
Missing email body when using sendmail #18024
Comments
It would be useful to see your configuration.
|
It isn't that simple. Can you check the original message of the email you received and post it here? If you run: func TestSendmail(t *testing.T) {
var mailService = setting.Mailer{
FromEmail: "test@gitea.com",
}
setting.MailService = &mailService
setting.Domain = "localhost"
m := NewMessage([]string{"test@localhost"}, "Gitea Test Email!", "Gitea Test Email!").ToMessage()
_, _ = m.WriteTo(os.Stdout)
} You will find the output, this is what you should see in your original message.
|
... or set "MAILER_TYPE=dummy" in app.ini |
@zeripath Here is my app.ini:
when I set
I'll need to google what Here's the header from the received email that I get (there's no mention of the Gitea Test Email! message body):
Not sure if this is the issue but it goes through a MS exchange server. I suspect the MS exchange is not the issue because when I try this manually using the |
What package is providing the /usr/sbin/sendmail command? As I said above I'm almost certain that this is not going to be sendmail but rather some other package that provides a sendmail command. |
I guess I thought gitea was the package that is providing the sendmail command. There are references to sendmail in the gitea code. from the logs that I have it looks like it is using sendmail:
|
$ docker exec -it <gitea_container> /bin/bash
bash-5.1# /usr/sbin/sendmail --help
BusyBox v1.32.1 () multi-call binary.
Usage: sendmail [-tv] [-f SENDER] [-amLOGIN 4<user_pass.txt | -auUSER -apPASS]
[-w SECS] [-H 'PROG ARGS' | -S HOST] [RECIPIENT_EMAIL]...
Read email from stdin and send it
Standard options:
-t Read additional recipients from message body
-f SENDER For use in MAIL FROM:<sender>. Can be empty string
Default: -auUSER, or username of current UID
-o OPTIONS Various options. -oi implied, others are ignored
-i -oi synonym, implied and ignored
Busybox specific options:
-v Verbose
-w SECS Network timeout
-H 'PROG ARGS' Run connection helper. Examples:
openssl s_client -quiet -tls1 -starttls smtp -connect smtp.gmail.com:25
openssl s_client -quiet -tls1 -connect smtp.gmail.com:465
$SMTP_ANTISPAM_DELAY: seconds to wait after helper connect
-S HOST[:PORT] Server (default $SMTPHOST or 127.0.0.1)
-amLOGIN Log in using AUTH LOGIN
-amPLAIN or AUTH PLAIN
(-amCRAM-MD5 not supported)
-auUSER Username for AUTH
-apPASS Password for AUTH
If no -a options are given, authentication is not done.
If -amLOGIN is given but no -au/-ap, user/password is read from fd #4.
Other options are silently ignored; -oi is implied.
Use makemime to create emails with attachments. So it's the sendmail provided by busybox |
The \01503d is \015. The 03d is simply due to a bug in the logger which I will fix imminently. \015 => \r so you can see that the blank line is being passed to "sendmail" |
In your testcase are you sending lines with \r\n? |
First of all, thank you for looking into this! And now I realize what you were asking regarding the package manager.
No, in my test case I was invoking sendmail from the command line, not piping any text to sendmail. I literally just type this:
What I think is happening is that \n should be used instead of \r, only reason why I say this is because on my linux terminal when I run |
The RFC disagrees with you. Lines have to be terminated with \r\n for SMTP. |
Why aren't you simply using the SMTP mailer directly? If you're just using the sendmail command on the docker AFAICS it's just using SMTP itself and it is not in itself a mailer daemon. |
I started off with SMTP but got autehntication failures. sendmail works for me from the command line and comes close to working |
Well it appears your chosen sendmail command doesn't appear to obey the standard. You could try catting a crlf'd message to it to prove that's the problem. If it is then you might have to write a script that will strip out the CRs or... Given your sendmail command is not doing anything different from what gitea can do I think you should work out why you were getting authentication problems with the SMTP backend or at least give us some more information as to what kind of authentication problems you were getting |
I'll check to see if I can install a different sendmail from the alpine linux repos.
My smtp authentication issues are just that I don't have the credentials to the smtp server and this particular server requires authentication if using Just to recap,
this does not work (sends the email but doesn't display message body): Thanks for your help today, I guess I'll try to chase down a different sendmail version that isn't packaged by busybox. |
busybox has sed and |
I don't understand why sendmail does not need to authenticate but gitea would - so I suspect that there is something else odd about your configuration here. |
Pretty much all the various Linux/Unix mail daemons internally store messages with just
So long-story short, even though the RFC specifies messages should use |
you could try the following patch and set SENDMAIL_CONVERT_CRLF to true in your app.ini to see if it solves the issue. diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index 1d19a3438..987e84a0d 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -1494,6 +1494,9 @@ PATH =
;;
;; Timeout for Sendmail
;SENDMAIL_TIMEOUT = 5m
+;;
+;; convert \r\n to \n for Sendmail
+;SENDMAIL_CONVERT_CRLF = false
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md
index 07655a181..00816964a 100644
--- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md
+++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md
@@ -667,6 +667,7 @@ Define allowed algorithms and their minimum key length (use -1 to disable a type
command or full path).
- `SENDMAIL_ARGS`: **_empty_**: Specify any extra sendmail arguments.
- `SENDMAIL_TIMEOUT`: **5m**: default timeout for sending email through sendmail
+- `SENDMAIL_CONVERT_CRLF`: **false**: some versions of sendmail require LF line endings rather than CRLF line endings. Set this to true if you require this.
- `SEND_BUFFER_LEN`: **100**: Buffer length of mailing queue. **DEPRECATED** use `LENGTH` in `[queue.mailer]`
## Cache (`cache`)
diff --git a/modules/setting/mailer.go b/modules/setting/mailer.go
index 1bcd63a91..19570ea97 100644
--- a/modules/setting/mailer.go
+++ b/modules/setting/mailer.go
@@ -37,9 +37,10 @@ type Mailer struct {
IsTLSEnabled bool
// Sendmail sender
- SendmailPath string
- SendmailArgs []string
- SendmailTimeout time.Duration
+ SendmailPath string
+ SendmailArgs []string
+ SendmailTimeout time.Duration
+ SendmailConvertCRLF bool
}
var (
@@ -71,8 +72,9 @@ func newMailService() {
IsTLSEnabled: sec.Key("IS_TLS_ENABLED").MustBool(),
SubjectPrefix: sec.Key("SUBJECT_PREFIX").MustString(""),
- SendmailPath: sec.Key("SENDMAIL_PATH").MustString("sendmail"),
- SendmailTimeout: sec.Key("SENDMAIL_TIMEOUT").MustDuration(5 * time.Minute),
+ SendmailPath: sec.Key("SENDMAIL_PATH").MustString("sendmail"),
+ SendmailTimeout: sec.Key("SENDMAIL_TIMEOUT").MustDuration(5 * time.Minute),
+ SendmailConvertCRLF: sec.Key("SENDMAIL_CONVERT_CRLF").MustBool(false),
}
MailService.From = sec.Key("FROM").MustString(MailService.User)
MailService.EnvelopeFrom = sec.Key("ENVELOPE_FROM").MustString("")
diff --git a/services/mailer/mailer.go b/services/mailer/mailer.go
index eac2b15c3..da810d380 100644
--- a/services/mailer/mailer.go
+++ b/services/mailer/mailer.go
@@ -253,6 +253,63 @@ func (s *smtpSender) Send(from string, to []string, msg io.WriterTo) error {
return client.Quit()
}
+type crlfConverter struct {
+ danglingCR bool
+ w io.Writer
+}
+
+func (c *crlfConverter) Write(bs []byte) (n int, err error) {
+ if len(bs) == 0 {
+ if c.danglingCR {
+ _, err := c.w.Write([]byte{'\r'})
+ if err != nil {
+ return 0, err
+ }
+ c.danglingCR = false
+ }
+ return c.w.Write(bs)
+ }
+ if c.danglingCR && bs[0] != '\n' {
+ _, err := c.w.Write([]byte{'\r'})
+ if err != nil {
+ return 0, err
+ }
+ c.danglingCR = false
+ }
+ if bs[len(bs)-1] == '\r' {
+ c.danglingCR = true
+ bs = bs[:len(bs)-1]
+ }
+ idx := bytes.Index(bs, []byte{'\r', '\n'})
+ for idx >= 0 {
+ count, err := c.w.Write(bs[:idx])
+ n += count
+ if err != nil {
+ return n, err
+ }
+ count, err = c.w.Write([]byte{'\n'})
+ if count == 1 {
+ n += 2
+ }
+ if err != nil {
+ return n, err
+ }
+ bs = bs[idx+2:]
+ idx = bytes.Index(bs, []byte{'\r', '\n'})
+ }
+ if len(bs) > 0 {
+ count, err := c.w.Write(bs)
+ n += count
+ if err != nil {
+ return n, err
+ }
+ }
+ if c.danglingCR {
+ n++
+ }
+ return
+}
+
// Sender sendmail mail sender
type sendmailSender struct {
}
@@ -290,13 +347,22 @@ func (s *sendmailSender) Send(from string, to []string, msg io.WriterTo) error {
return err
}
- _, err = msg.WriteTo(pipe)
+ if setting.MailService.SendmailConvertCRLF {
+ converter := &crlfConverter{
+ w: pipe,
+ }
+ _, err = msg.WriteTo(converter)
+ if converter.danglingCR && err == nil {
+ _, err = pipe.Write([]byte{'\r'})
+ }
+ } else {
+ _, err = msg.WriteTo(pipe)
+ }
// we MUST close the pipe or sendmail will hang waiting for more of the message
// Also we should wait on our sendmail command even if something fails
closeError = pipe.Close()
waitError = cmd.Wait()
-
if err != nil {
return err
} else if closeError != nil {
|
It appears that several versions of sendmail require that the mail is sent to them with LF line endings instead of CRLF endings - which of course they will then convert back to CRLF line endings to comply with the SMTP standard. This PR adds another setting SENDMAIL_CONVERT_CRLF which will pass the message writer through a filter. This will filter out and convert CRLFs to LFs before writing them out to sendmail. Fix go-gitea#18024 Signed-off-by: Andrew Thornton <art27@cantab.net>
@zeripath thanks again for all of your help. I was able to implement your suggestion and it worked. I pointed my sendmail_wrapper is just:
|
It appears that several versions of sendmail require that the mail is sent to them with LF line endings instead of CRLF endings - which of course they will then convert back to CRLF line endings to comply with the SMTP standard. This PR adds another setting SENDMAIL_CONVERT_CRLF which will pass the message writer through a filter. This will filter out and convert CRLFs to LFs before writing them out to sendmail. Fix #18024 Signed-off-by: Andrew Thornton <art27@cantab.net>
…18075) It appears that several versions of sendmail require that the mail is sent to them with LF line endings instead of CRLF endings - which of course they will then convert back to CRLF line endings to comply with the SMTP standard. This PR adds another setting SENDMAIL_CONVERT_CRLF which will pass the message writer through a filter. This will filter out and convert CRLFs to LFs before writing them out to sendmail. Fix go-gitea#18024 Signed-off-by: Andrew Thornton <art27@cantab.net>
Gitea Version
1.15.7
Git Version
No response
Operating System
alpine linux (using the official gitea docker image)
How are you running Gitea?
Through the official gitea docker image
Database
PostgreSQL
Can you reproduce the bug on the Gitea demo site?
No
Log Gist
https://gist.github.com/ben-kenney/8fc6715ffd2a6c5721469772957dba2e
Description
I've configured my gitea to use sendmail. I receive email notifications but they are all missing the message body and only contain the subject line.
When I log into my gitea docker container and manually check to see if sendmail is working, I can confirm that sendmail does work BUT it requires a blank line between the subject and the message body, like this:
The blank line before the message body appears to be important otherwise sendmail will not inlcude the message body, this is documented elsewhere (sorry I couldn't find anything more official than the linked response).
I'm curious to know if this could be the reason why I'm not able to see the email messages from gitea.
I think that emails such as this test email from gitea should likely need
\n\n
in front of the message body when using sendmail.Screenshots
Here's a screenshot of the email that I received from gitea after posting a test comment (note that the message body is blank).
The text was updated successfully, but these errors were encountered: