Implement AUTH PLAIN authentication extensions in SMTP.
[mailpopbox.git] / smtp / server.go
1 package smtp
2
3 import (
4 "crypto/tls"
5 "fmt"
6 "io"
7 "net"
8 "net/mail"
9 "strings"
10 "time"
11 )
12
13 type ReplyLine struct {
14 Code int
15 Message string
16 }
17
18 func (l ReplyLine) String() string {
19 return fmt.Sprintf("%d %s", l.Code, l.Message)
20 }
21
22 var (
23 ReplyOK = ReplyLine{250, "OK"}
24 ReplyBadSyntax = ReplyLine{501, "syntax error"}
25 ReplyBadSequence = ReplyLine{503, "bad sequence of commands"}
26 ReplyBadMailbox = ReplyLine{550, "mailbox unavailable"}
27 )
28
29 func DomainForAddress(addr mail.Address) string {
30 domainIdx := strings.LastIndex(addr.Address, "@")
31 if domainIdx == -1 {
32 return ""
33 }
34 return addr.Address[domainIdx+1:]
35 }
36
37 type Envelope struct {
38 RemoteAddr net.Addr
39 EHLO string
40 MailFrom mail.Address
41 RcptTo []mail.Address
42 Data []byte
43 Received time.Time
44 ID string
45 }
46
47 func WriteEnvelopeForDelivery(w io.Writer, e Envelope) {
48 fmt.Fprintf(w, "Delivered-To: <%s>\r\n", e.RcptTo[0].Address)
49 fmt.Fprintf(w, "Return-Path: <%s>\r\n", e.MailFrom.Address)
50 w.Write(e.Data)
51 }
52
53 type Server interface {
54 Name() string
55 TLSConfig() *tls.Config
56 VerifyAddress(mail.Address) ReplyLine
57 // Verify that the authc+passwd identity can send mail as authz.
58 Authenticate(authz, authc, passwd string) bool
59 OnMessageDelivered(Envelope) *ReplyLine
60 }
61
62 type EmptyServerCallbacks struct{}
63
64 func (*EmptyServerCallbacks) TLSConfig() *tls.Config {
65 return nil
66 }
67
68 func (*EmptyServerCallbacks) VerifyAddress(mail.Address) ReplyLine {
69 return ReplyOK
70 }
71
72 func (*EmptyServerCallbacks) Authenticate(authz, authc, passwd string) bool {
73 return false
74 }
75
76 func (*EmptyServerCallbacks) OnMessageDelivered(Envelope) *ReplyLine {
77 return nil
78 }