1
0
mirror of https://blitiri.com.ar/repos/chasquid synced 2026-01-27 20:45:56 +00:00

smtp: Distinguish permanent errors

This patch makes the SMTP courier distinguish permanent errors, so the queue
can decide whether to retry or not.

It's based on the SMTP replies: 5xy is considerent permanent, anything else is
transient (including errors other than protocol issues).
This commit is contained in:
Alberto Bertogli
2016-10-02 01:16:39 +01:00
parent 7cbe6a5076
commit 0e41821779
3 changed files with 41 additions and 4 deletions

View File

@@ -107,21 +107,21 @@ retry:
from = "" from = ""
} }
if err = c.MailAndRcpt(from, to); err != nil { if err = c.MailAndRcpt(from, to); err != nil {
return tr.Errorf("MAIL+RCPT %v", err), false return tr.Errorf("MAIL+RCPT %v", err), smtp.IsPermanent(err)
} }
w, err := c.Data() w, err := c.Data()
if err != nil { if err != nil {
return tr.Errorf("DATA %v", err), false return tr.Errorf("DATA %v", err), smtp.IsPermanent(err)
} }
_, err = w.Write(data) _, err = w.Write(data)
if err != nil { if err != nil {
return tr.Errorf("DATA writing: %v", err), false return tr.Errorf("DATA writing: %v", err), smtp.IsPermanent(err)
} }
err = w.Close() err = w.Close()
if err != nil { if err != nil {
return tr.Errorf("DATA closing %v", err), false return tr.Errorf("DATA closing %v", err), smtp.IsPermanent(err)
} }
c.Quit() c.Quit()

View File

@@ -2,6 +2,7 @@
// 5321. It extends net/smtp as follows: // 5321. It extends net/smtp as follows:
// //
// - Supports SMTPUTF8, via MailAndRcpt. // - Supports SMTPUTF8, via MailAndRcpt.
// - Adds IsPermanent.
// //
package smtp package smtp
@@ -127,3 +128,20 @@ func isASCII(s string) bool {
} }
return true return true
} }
// ErrIsPermanent returns true if the error is permanent, and false otherwise.
// If it can't tell, it returns false.
func IsPermanent(err error) bool {
terr, ok := err.(*textproto.Error)
if !ok {
return false
}
// Error codes 5yz are permanent.
// https://tools.ietf.org/html/rfc5321#section-4.2.1
if terr.Code >= 500 && terr.Code < 600 {
return true
}
return false
}

View File

@@ -3,6 +3,7 @@ package smtp
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"fmt"
"net" "net"
"net/smtp" "net/smtp"
"net/textproto" "net/textproto"
@@ -11,6 +12,24 @@ import (
"time" "time"
) )
func TestIsPermanent(t *testing.T) {
cases := []struct {
err error
permanent bool
}{
{&textproto.Error{499, ""}, false},
{&textproto.Error{500, ""}, true},
{&textproto.Error{599, ""}, true},
{&textproto.Error{600, ""}, false},
{fmt.Errorf("something"), false},
}
for _, c := range cases {
if p := IsPermanent(c.err); p != c.permanent {
t.Errorf("%v: expected %v, got %v", c.err, c.permanent, p)
}
}
}
func TestIsASCII(t *testing.T) { func TestIsASCII(t *testing.T) {
cases := []struct { cases := []struct {
str string str string