Added files.
This commit is contained in:
411
imapclient/example_test.go
Normal file
411
imapclient/example_test.go
Normal file
@@ -0,0 +1,411 @@
|
||||
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)
|
||||
}
|
||||
defer idleCmd.Close()
|
||||
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
done <- idleCmd.Wait()
|
||||
}()
|
||||
|
||||
// Wait for 30s to receive updates from the server, then stop idling
|
||||
t := time.NewTimer(30 * time.Second)
|
||||
defer t.Stop()
|
||||
select {
|
||||
case <-t.C:
|
||||
if err := idleCmd.Close(); err != nil {
|
||||
log.Fatalf("failed to stop idling: %v", err)
|
||||
}
|
||||
if err := <-done; err != nil {
|
||||
log.Fatalf("IDLE command failed: %v", err)
|
||||
}
|
||||
case err := <-done:
|
||||
if err != nil {
|
||||
log.Fatalf("IDLE command failed: %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)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleClient_Closed() {
|
||||
c, err := imapclient.DialTLS("mail.example.org:993", nil)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to dial IMAP server: %v", err)
|
||||
}
|
||||
|
||||
selected := false
|
||||
|
||||
go func(c *imapclient.Client) {
|
||||
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)
|
||||
}
|
||||
|
||||
selected = true
|
||||
|
||||
c.Close()
|
||||
}(c)
|
||||
|
||||
// This channel shall be closed when the connection is closed.
|
||||
<-c.Closed()
|
||||
log.Println("Connection has been closed")
|
||||
|
||||
if !selected {
|
||||
log.Fatalf("Connection was closed before selecting mailbox")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user