An IMAP4rev1 library written in Go. It can be used to build a client and/or a server and supports UTF-7.
go get github.com/emersion/go-imap
Other IMAP implementations in Go:
- Require to make many type assertions or conversions
- Are not idiomatic or are ugly
- Are not pleasant to use
- Implement a server xor a client, not both
- Don't implement unilateral updates (i.e. the server can't notify clients for new messages)
This package implements all commands specified in the RFC.
Command | Client | Client tests | Server | Server tests |
---|---|---|---|---|
CAPABILITY | ✓ | ✓ | ✓ | ✓ |
NOOP | ✓ | ✓ | ✓ | ✓ |
LOGOUT | ✓ | ✓ | ✓ | ✓ |
AUTHENTICATE | ✓ | ✓ | ✓ | ✓ |
LOGIN | ✓ | ✓ | ✓ | ✓ |
STARTTLS | ✓ | ✓ | ✓ | ✗ |
SELECT | ✓ | ✓ | ✓ | ✓ |
EXAMINE | ✓ | ✓ | ✓ | ✗ |
CREATE | ✓ | ✓ | ✓ | ✓ |
DELETE | ✓ | ✓ | ✓ | ✓ |
RENAME | ✓ | ✓ | ✓ | ✓ |
SUBSCRIBE | ✓ | ✓ | ✓ | ✓ |
UNSUBSCRIBE | ✓ | ✓ | ✓ | ✓ |
LIST | ✓ | ✓ | ✓ | ✓ |
LSUB | ✓ | ✓ | ✓ | ✗ |
STATUS | ✓ | ✓ | ✓ | ✓ |
APPEND | ✓ | ✓ | ✓ | ✗ |
CHECK | ✓ | ✓ | ✓ | ✗ |
CLOSE | ✓ | ✓ | ✓ | ✗ |
EXPUNGE | ✓ | ✓ | ✓ | ✗ |
SEARCH | ✓ | ✓ | ✓ | ✗ |
FETCH | ✓ | ✓ | ✓ | ✗ |
STORE | ✓ | ✓ | ✓ | ✗ |
COPY | ✓ | ✓ | ✓ | ✗ |
UID | ✓ | ✗ | ✓ | ✗ |
Commands defined in IMAP extensions are available in other packages.
package main
import (
"log"
"github.com/emersion/go-imap/client"
imap "github.com/emersion/go-imap/common"
)
func main() {
log.Println("Connecting to server...")
// Connect to server
c, err := client.DialTLS("mail.example.org:993", nil)
if err != nil {
log.Fatal(err)
}
log.Println("Connected")
// Don't forget to logout
defer c.Logout()
// Login
if err := c.Login("username", "password"); err != nil {
log.Fatal(err)
}
log.Println("Logged in")
// List mailboxes
mailboxes := make(chan *imap.MailboxInfo)
go (func () {
err = c.List("", "%", mailboxes)
})()
log.Println("Mailboxes:")
for m := range mailboxes {
log.Println("* " + m.Name)
}
if err != nil {
log.Fatal(err)
}
// Select INBOX
mbox, err := c.Select("INBOX", false)
if err != nil {
log.Fatal(err)
}
log.Println("Flags for INBOX:", mbox.Flags)
// Get the last 4 messages
seqset, _ := imap.NewSeqSet("")
seqset.AddRange(mbox.Messages - 3, mbox.Messages)
messages := make(chan *imap.Message, 4)
err = c.Fetch(seqset, []string{"ENVELOPE"}, messages)
if err != nil {
log.Fatal(err)
}
for msg := range messages {
log.Println(msg.Envelope.Subject)
}
log.Println("Done!")
}
package main
import (
"log"
"github.com/emersion/go-imap/server"
"github.com/emersion/go-imap/backend/memory"
)
func main() {
// Create a memory backend
bkd := memory.New()
// Create a new server
s, err := server.Listen(":3000", bkd)
if err != nil {
log.Fatal(err)
}
// Since we will use this server for testing only, we can allow plain text
// authentication over unencrypted connections
s.AllowInsecureAuth = true
log.Println("Server listening at", s.Addr())
// Do something else to keep the server alive
select {}
}
You can now use telnet localhost 3000
to manually connect to the server.
MIT