Files
go-imap/imapclient/example_test.go

366 lines
8.8 KiB
Go

package imapclient_test
import (
"io"
"log"
"time"
"github.com/emersion/go-message/mail"
"github.com/emersion/go-sasl"
"github.com/emersion/go-imap/v2"
"github.com/emersion/go-imap/v2/imapclient"
)
func ExampleClient() {
c, err := imapclient.DialTLS("mail.example.org:993", nil)
if err != nil {
log.Fatalf("failed to dial IMAP server: %v", err)
}
defer c.Close()
if err := c.Login("root", "asdf").Wait(); err != nil {
log.Fatalf("failed to login: %v", err)
}
mailboxes, err := c.List("", "%", nil).Collect()
if err != nil {
log.Fatalf("failed to list mailboxes: %v", err)
}
log.Printf("Found %v mailboxes", len(mailboxes))
for _, mbox := range mailboxes {
log.Printf(" - %v", mbox.Mailbox)
}
selectedMbox, err := c.Select("INBOX", nil).Wait()
if err != nil {
log.Fatalf("failed to select INBOX: %v", err)
}
log.Printf("INBOX contains %v messages", selectedMbox.NumMessages)
if selectedMbox.NumMessages > 0 {
seqSet := imap.SeqSetNum(1)
fetchOptions := &imap.FetchOptions{Envelope: true}
messages, err := c.Fetch(seqSet, fetchOptions).Collect()
if err != nil {
log.Fatalf("failed to fetch first message in INBOX: %v", err)
}
log.Printf("subject of first message in INBOX: %v", messages[0].Envelope.Subject)
}
if err := c.Logout().Wait(); err != nil {
log.Fatalf("failed to logout: %v", err)
}
}
func ExampleClient_pipelining() {
var c *imapclient.Client
uid := imap.UID(42)
fetchOptions := &imap.FetchOptions{Envelope: true}
// Login, select and fetch a message in a single roundtrip
loginCmd := c.Login("root", "root")
selectCmd := c.Select("INBOX", nil)
fetchCmd := c.Fetch(imap.UIDSetNum(uid), fetchOptions)
if err := loginCmd.Wait(); err != nil {
log.Fatalf("failed to login: %v", err)
}
if _, err := selectCmd.Wait(); err != nil {
log.Fatalf("failed to select INBOX: %v", err)
}
if messages, err := fetchCmd.Collect(); err != nil {
log.Fatalf("failed to fetch message: %v", err)
} else {
log.Printf("Subject: %v", messages[0].Envelope.Subject)
}
}
func ExampleClient_Append() {
var c *imapclient.Client
buf := []byte("From: <root@nsa.gov>\r\n\r\nHi <3")
size := int64(len(buf))
appendCmd := c.Append("INBOX", size, nil)
if _, err := appendCmd.Write(buf); err != nil {
log.Fatalf("failed to write message: %v", err)
}
if err := appendCmd.Close(); err != nil {
log.Fatalf("failed to close message: %v", err)
}
if _, err := appendCmd.Wait(); err != nil {
log.Fatalf("APPEND command failed: %v", err)
}
}
func ExampleClient_Status() {
var c *imapclient.Client
options := imap.StatusOptions{NumMessages: true}
if data, err := c.Status("INBOX", &options).Wait(); err != nil {
log.Fatalf("STATUS command failed: %v", err)
} else {
log.Printf("INBOX contains %v messages", *data.NumMessages)
}
}
func ExampleClient_List_stream() {
var c *imapclient.Client
// ReturnStatus requires server support for IMAP4rev2 or LIST-STATUS
listCmd := c.List("", "%", &imap.ListOptions{
ReturnStatus: &imap.StatusOptions{
NumMessages: true,
NumUnseen: true,
},
})
for {
mbox := listCmd.Next()
if mbox == nil {
break
}
log.Printf("Mailbox %q contains %v messages (%v unseen)", mbox.Mailbox, mbox.Status.NumMessages, mbox.Status.NumUnseen)
}
if err := listCmd.Close(); err != nil {
log.Fatalf("LIST command failed: %v", err)
}
}
func ExampleClient_Store() {
var c *imapclient.Client
seqSet := imap.SeqSetNum(1)
storeFlags := imap.StoreFlags{
Op: imap.StoreFlagsAdd,
Flags: []imap.Flag{imap.FlagFlagged},
Silent: true,
}
if err := c.Store(seqSet, &storeFlags, nil).Close(); err != nil {
log.Fatalf("STORE command failed: %v", err)
}
}
func ExampleClient_Fetch() {
var c *imapclient.Client
seqSet := imap.SeqSetNum(1)
bodySection := &imap.FetchItemBodySection{Specifier: imap.PartSpecifierHeader}
fetchOptions := &imap.FetchOptions{
Flags: true,
Envelope: true,
BodySection: []*imap.FetchItemBodySection{bodySection},
}
messages, err := c.Fetch(seqSet, fetchOptions).Collect()
if err != nil {
log.Fatalf("FETCH command failed: %v", err)
}
msg := messages[0]
header := msg.FindBodySection(bodySection)
log.Printf("Flags: %v", msg.Flags)
log.Printf("Subject: %v", msg.Envelope.Subject)
log.Printf("Header:\n%v", string(header))
}
func ExampleClient_Fetch_streamBody() {
var c *imapclient.Client
seqSet := imap.SeqSetNum(1)
bodySection := &imap.FetchItemBodySection{}
fetchOptions := &imap.FetchOptions{
UID: true,
BodySection: []*imap.FetchItemBodySection{bodySection},
}
fetchCmd := c.Fetch(seqSet, fetchOptions)
defer fetchCmd.Close()
for {
msg := fetchCmd.Next()
if msg == nil {
break
}
for {
item := msg.Next()
if item == nil {
break
}
switch item := item.(type) {
case imapclient.FetchItemDataUID:
log.Printf("UID: %v", item.UID)
case imapclient.FetchItemDataBodySection:
b, err := io.ReadAll(item.Literal)
if err != nil {
log.Fatalf("failed to read body section: %v", err)
}
log.Printf("Body:\n%v", string(b))
}
}
}
if err := fetchCmd.Close(); err != nil {
log.Fatalf("FETCH command failed: %v", err)
}
}
func ExampleClient_Fetch_parseBody() {
var c *imapclient.Client
// Send a FETCH command to fetch the message body
seqSet := imap.SeqSetNum(1)
bodySection := &imap.FetchItemBodySection{}
fetchOptions := &imap.FetchOptions{
BodySection: []*imap.FetchItemBodySection{bodySection},
}
fetchCmd := c.Fetch(seqSet, fetchOptions)
defer fetchCmd.Close()
msg := fetchCmd.Next()
if msg == nil {
log.Fatalf("FETCH command did not return any message")
}
// Find the body section in the response
var bodySectionData imapclient.FetchItemDataBodySection
ok := false
for {
item := msg.Next()
if item == nil {
break
}
bodySectionData, ok = item.(imapclient.FetchItemDataBodySection)
if ok {
break
}
}
if !ok {
log.Fatalf("FETCH command did not return body section")
}
// Read the message via the go-message library
mr, err := mail.CreateReader(bodySectionData.Literal)
if err != nil {
log.Fatalf("failed to create mail reader: %v", err)
}
// Print a few header fields
h := mr.Header
if date, err := h.Date(); err != nil {
log.Printf("failed to parse Date header field: %v", err)
} else {
log.Printf("Date: %v", date)
}
if to, err := h.AddressList("To"); err != nil {
log.Printf("failed to parse To header field: %v", err)
} else {
log.Printf("To: %v", to)
}
if subject, err := h.Text("Subject"); err != nil {
log.Printf("failed to parse Subject header field: %v", err)
} else {
log.Printf("Subject: %v", subject)
}
// Process the message's parts
for {
p, err := mr.NextPart()
if err == io.EOF {
break
} else if err != nil {
log.Fatalf("failed to read message part: %v", err)
}
switch h := p.Header.(type) {
case *mail.InlineHeader:
// This is the message's text (can be plain-text or HTML)
b, _ := io.ReadAll(p.Body)
log.Printf("Inline text: %v", string(b))
case *mail.AttachmentHeader:
// This is an attachment
filename, _ := h.Filename()
log.Printf("Attachment: %v", filename)
}
}
if err := fetchCmd.Close(); err != nil {
log.Fatalf("FETCH command failed: %v", err)
}
}
func ExampleClient_Search() {
var c *imapclient.Client
data, err := c.UIDSearch(&imap.SearchCriteria{
Body: []string{"Hello world"},
}, nil).Wait()
if err != nil {
log.Fatalf("UID SEARCH command failed: %v", err)
}
log.Fatalf("UIDs matching the search criteria: %v", data.AllUIDs())
}
func ExampleClient_Idle() {
options := imapclient.Options{
UnilateralDataHandler: &imapclient.UnilateralDataHandler{
Expunge: func(seqNum uint32) {
log.Printf("message %v has been expunged", seqNum)
},
Mailbox: func(data *imapclient.UnilateralDataMailbox) {
if data.NumMessages != nil {
log.Printf("a new message has been received")
}
},
},
}
c, err := imapclient.DialTLS("mail.example.org:993", &options)
if err != nil {
log.Fatalf("failed to dial IMAP server: %v", err)
}
defer c.Close()
if err := c.Login("root", "asdf").Wait(); err != nil {
log.Fatalf("failed to login: %v", err)
}
if _, err := c.Select("INBOX", nil).Wait(); err != nil {
log.Fatalf("failed to select INBOX: %v", err)
}
// Start idling
idleCmd, err := c.Idle()
if err != nil {
log.Fatalf("IDLE command failed: %v", err)
}
// Wait for 30s to receive updates from the server
time.Sleep(30 * time.Second)
// Stop idling
if err := idleCmd.Close(); err != nil {
log.Fatalf("failed to stop idling: %v", err)
}
}
func ExampleClient_Authenticate_oauth() {
var (
c *imapclient.Client
username string
token string
)
if !c.Caps().Has(imap.AuthCap(sasl.OAuthBearer)) {
log.Fatal("OAUTHBEARER not supported by the server")
}
saslClient := sasl.NewOAuthBearerClient(&sasl.OAuthBearerOptions{
Username: username,
Token: token,
})
if err := c.Authenticate(saslClient); err != nil {
log.Fatalf("authentication failed: %v", err)
}
}