12 "src.bluestatic.org/mailpopbox/pop3"
15 func runPOP3Server(config Config) <-chan error {
24 type pop3Server struct {
29 func (server *pop3Server) run() {
30 for _, s := range server.config.Servers {
31 if err := os.Mkdir(s.MaildropPath, 0700); err != nil && !os.IsExist(err) {
36 l, err := net.Listen("tcp", fmt.Sprintf(":%d", server.config.POP3Port))
43 conn, err := l.Accept()
49 go pop3.AcceptConnection(conn, server)
53 func (server *pop3Server) Name() string {
54 return server.config.Hostname
57 func (server *pop3Server) OpenMailbox(user, pass string) (pop3.Mailbox, error) {
58 for _, s := range server.config.Servers {
59 if user == "mailbox@"+s.Domain && pass == s.MailboxPassword {
60 return server.openMailbox(s.MaildropPath)
63 return nil, errors.New("permission denied")
66 func (server *pop3Server) openMailbox(maildrop string) (*mailbox, error) {
67 files, err := ioutil.ReadDir(maildrop)
69 // TODO: hide error, log instead
74 messages: make([]message, 0, len(files)),
78 for _, file := range files {
84 filename: path.Join(maildrop, file.Name()),
88 mb.messages = append(mb.messages, msg)
106 func (m message) ID() int {
110 func (m message) Size() int {
114 func (m message) Deleted() bool {
118 func (mb *mailbox) ListMessages() ([]pop3.Message, error) {
119 msgs := make([]pop3.Message, len(mb.messages))
120 for i := 0; i < len(mb.messages); i++ {
121 msgs[i] = &mb.messages[i]
126 func (mb *mailbox) GetMessage(id int) pop3.Message {
127 if id > len(mb.messages) {
130 return &mb.messages[id-1]
133 func (mb *mailbox) Retrieve(msg pop3.Message) (io.ReadCloser, error) {
134 filename := msg.(*message).filename
135 return os.Open(filename)
138 func (mb *mailbox) Delete(msg pop3.Message) error {
139 msg.(*message).deleted = true
143 func (mb *mailbox) Close() error {
144 for _, message := range mb.messages {
146 os.Remove(message.filename)
152 func (mb *mailbox) Reset() {
153 for _, message := range mb.messages {
154 message.deleted = false