imap

package module
v0.1.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2024 License: MIT Imports: 20 Imported by: 9

README

# Simple IMAP Client Library

I wasn't able to find an IMAP client I liked (or found easy to use), so, now there's also this one. My goal here is to allow people to download emails quickly, and robustly, that's it.

Getting Started

go get github.com/BrianLeishman/go-imap

Usage

Below I've written a super basic demo function of what this library is capable of doing, and how one might use it.

package main

import (
	"fmt"

	"github.com/BrianLeishman/go-imap"
)

func check(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {

	// Defaults to false. This package level option turns on or off debugging output, essentially.
	// If verbose is set to true, then every command, and every response, is printed,
	// along with other things like error messages (before the retry limit is reached)
	imap.Verbose = true

	// Defaults to 10. Certain functions retry; like the login function, and the new connection function.
	// If a retried function fails, the connection will be closed, then the program sleeps for an increasing amount of time,
	// creates a new connection instance internally, selects the same folder, and retries the failed command(s).
	// You can check out github.com/StirlingMarketingGroup/go-retry for the retry implementation being used
	imap.RetryCount = 3

	// Create a new instance of the IMAP connection you want to use
	im, err := imap.New("username", "password", "mail.server.com", 993)
	check(err)
	defer im.Close()

	// Folders now contains a string slice of all the folder names on the connection
	folders, err := im.GetFolders()
	check(err)

	// folders = []string{
	// 	"INBOX",
	// 	"INBOX/My Folder"
	// 	"Sent Items",
	// 	"Deleted",
	// }

	// Now we can loop through those folders
	for _, f := range folders {

		// And select each folder, one at a time.
		// Whichever folder is selected last, is the current active folder.
		// All following commands will be executing inside of this folder
		err = im.SelectFolder(f)
		check(err)

		// This function implements the IMAP UID search, returning a slice of ints
		// Sending "ALL" runs the command "UID SEARCH ALL"
		// You can enter things like "*:1" to get the first UID, or "999999999:*"
		// to get the last (unless you actually have more than that many emails)
		// You can check out https://tools.ietf.org/html/rfc3501#section-6.4.4 for more
		uids, err := im.GetUIDs("ALL")
		check(err)

		// uids = []int{1, 2, 3}

		// GetEmails takes a list of ints as UIDs, and returns new Email objects.
		// If an email for a given UID cannot be found, there's an error parsing its body,
		// or the email addresses are malformed (like, missing parts of the address), then it is skipped
		// If an email is found, then an imap.Email struct slice is returned with the information from the email.
		// The Email struct looks like this:
		// type Email struct {
		// 	Flags     []string
		// 	Received  time.Time
		// 	Sent      time.Time
		// 	Size      uint64
		// 	Subject   string
		// 	UID       int
		// 	MessageID string
		// 	From      EmailAddresses
		// 	To        EmailAddresses
		// 	ReplyTo   EmailAddresses
		// 	CC        EmailAddresses
		// 	BCC       EmailAddresses
		// 	Text      string
		// 	HTML      string
		//	Attachments []Attachment
		// }
		// Where the address type fields are maps like [EmailAddress:Name EmailAddress2:Name2]
		// and an Attachment is a struct containing the Name, Content, and the MimeType (both as strings)
		emails, err := im.GetEmails(uids...)
		check(err)

		if len(emails) != 0 {
			// Should print a summary of one of the the emails
			// (yes, I said "one of", don't expect the emails to be returned in any particular order)
			fmt.Print(emails[0])

			im.MoveEmail(emails[0].UID, "INBOX/My Folder")
			// Subject: FW: FW:  FW:  New Order
			// To: Brian Leishman <brian@stumpyinc.com>
			// From: Customer Service <sales@totallylegitdomain.com>
			// Text: Hello, World!...(4.3 kB)
			// HTML: <html xmlns:v="urn:s... (35 kB)
			// 1 Attachment(s): [20180330174029.jpg (192 kB)]
		}

	}

}

Built With

Authors

Documentation

Index

Constants

View Source
const (
	IdleEventExists  = "EXISTS"
	IdleEventExpunge = "EXPUNGE"
	IdleEventFetch   = "FETCH"
)
View Source
const (
	EDate uint8 = iota
	ESubject
	EFrom
	ESender
	EReplyTo
	ETo
	ECC
	EBCC
	EInReplyTo
	EMessageID
)
View Source
const (
	EEName uint8 = iota
	// EESR is unused and should be ignored
	EESR
	EEMailbox
	EEHost
)
View Source
const TimeFormat = "_2-Jan-2006 15:04:05 -0700"

TimeFormat is the Go time version of the IMAP times

Variables

View Source
var AddSlashes = strings.NewReplacer(`"`, `\"`)

AddSlashes adds slashes to double quotes

View Source
var RemoveSlashes = strings.NewReplacer(`\"`, `"`)

RemoveSlashes removes slashes before double quotes

View Source
var RetryCount = 10

RetryCount is the number of times retired functions get retried

View Source
var SkipResponses = false

SkipResponses skips printing server responses in verbose mode

View Source
var Verbose = false

Verbose outputs every command and its response with the IMAP server

Functions

func GetTokenName

func GetTokenName(tokenType TType) string

GetTokenName returns the name of the given token type token

func IsLiteral

func IsLiteral(b rune) bool

IsLiteral returns if the given byte is an acceptable literal character

Types

type Attachment

type Attachment struct {
	Name     string
	MimeType string
	Content  []byte
}

Attachment is an Email attachment

func (Attachment) String

func (a Attachment) String() string

type Dialer

type Dialer struct {
	Folder   string
	Username string
	Password string
	Host     string
	Port     int

	Connected bool
	ConnNum   int
	// contains filtered or unexported fields
}

Dialer is basically an IMAP connection

func New

func New(username string, password string, host string, port int) (d *Dialer, err error)

New makes a new imap

func NewWithOAuth2 added in v0.1.7

func NewWithOAuth2(username string, accessToken string, host string, port int) (d *Dialer, err error)

NewWithOAuth2 makes a new imap with OAuth2

func (*Dialer) Authenticate added in v0.1.7

func (d *Dialer) Authenticate(user string, accessToken string) (err error)

func (*Dialer) CheckType

func (d *Dialer) CheckType(token *Token, acceptableTypes []TType, tks []*Token, loc string, v ...interface{}) (err error)

CheckType validates a type against a list of acceptable types, if the type of the token isn't in the list, an error is returned

func (*Dialer) Clone

func (d *Dialer) Clone() (d2 *Dialer, err error)

Clone returns a new connection with the same connection information as the one this is being called on

func (*Dialer) Close

func (d *Dialer) Close() (err error)

Close closes the imap connection

func (*Dialer) Exec

func (d *Dialer) Exec(command string, buildResponse bool, retryCount int, processLine func(line []byte) error) (response string, err error)

Exec executes the command on the imap connection

func (*Dialer) GetEmails

func (d *Dialer) GetEmails(uids ...int) (emails map[int]*Email, err error)

GetEmails returns email with their bodies for the given UIDs in the current folder. If no UIDs are given, they everything in the current folder is selected

func (*Dialer) GetFolders

func (d *Dialer) GetFolders() (folders []string, err error)

GetFolders returns all folders

func (*Dialer) GetOverviews

func (d *Dialer) GetOverviews(uids ...int) (emails map[int]*Email, err error)

GetOverviews returns emails without bodies for the given UIDs in the current folder. If no UIDs are given, they everything in the current folder is selected

func (*Dialer) GetStrtokI

func (d *Dialer) GetStrtokI() int

GetStrtokI returns the current position of the tokenizer

func (*Dialer) GetTotalEmailCount

func (d *Dialer) GetTotalEmailCount() (count int, err error)

GetTotalEmailCount returns the total number of emails in every folder

func (*Dialer) GetTotalEmailCountExcluding

func (d *Dialer) GetTotalEmailCountExcluding(excludedFolders []string) (count int, err error)

GetTotalEmailCountExcluding returns the total number of emails in every folder excluding the specified folders

func (*Dialer) GetTotalEmailCountStartingFrom

func (d *Dialer) GetTotalEmailCountStartingFrom(startFolder string) (count int, err error)

GetTotalEmailCountStartingFrom returns the total number of emails in every folder after the specified start folder

func (*Dialer) GetTotalEmailCountStartingFromExcluding

func (d *Dialer) GetTotalEmailCountStartingFromExcluding(startFolder string, excludedFolders []string) (count int, err error)

GetTotalEmailCountStartingFromExcluding returns the total number of emails in every folder after the specified start folder, excluding the specified folders

func (*Dialer) GetUIDs

func (d *Dialer) GetUIDs(search string) (uids []int, err error)

GetUIDs returns the UIDs in the current folder that match the search

func (*Dialer) Login

func (d *Dialer) Login(username string, password string) (err error)

Login attempts to login

func (*Dialer) MoveEmail added in v0.1.3

func (d *Dialer) MoveEmail(uid int, folder string) (err error)

Move a read email to a specified folder

func (*Dialer) ParseFetchResponse

func (d *Dialer) ParseFetchResponse(r string) (records [][]*Token, err error)

ParseFetchResponse parses a response from a FETCH command into tokens

func (*Dialer) Reconnect

func (d *Dialer) Reconnect() (err error)

Reconnect closes the current connection (if any) and establishes a new one

func (*Dialer) SelectFolder

func (d *Dialer) SelectFolder(folder string) (err error)

SelectFolder selects a folder

func (*Dialer) StartIdle added in v0.1.5

func (d *Dialer) StartIdle(handler *IdleHandler) error

func (*Dialer) Strtok

func (d *Dialer) Strtok(delims []byte) string

Strtok returns the next "token" in the sequence with the given delimeters

func (*Dialer) StrtokInit

func (d *Dialer) StrtokInit(b string, delims []byte) string

StrtokInit starts the strtok sequence

type Email

type Email struct {
	Flags       []string
	Received    time.Time
	Sent        time.Time
	Size        uint64
	Subject     string
	UID         int
	MessageID   string
	From        EmailAddresses
	To          EmailAddresses
	ReplyTo     EmailAddresses
	CC          EmailAddresses
	BCC         EmailAddresses
	Text        string
	HTML        string
	Attachments []Attachment
}

Email is an email message

func (Email) String

func (e Email) String() string

type EmailAddresses

type EmailAddresses map[string]string

EmailAddresses are a map of email address to names

func (EmailAddresses) String

func (e EmailAddresses) String() string

type ExistsEvent added in v0.1.5

type ExistsEvent struct {
	MessageIndex int
}

type ExpungeEvent added in v0.1.5

type ExpungeEvent struct {
	MessageIndex int
}

type FetchEvent added in v0.1.5

type FetchEvent struct {
	MessageIndex int
	UID          uint32
	Flags        []string
}

type IdleHandler added in v0.1.5

type IdleHandler struct {
	OnExists  func(event ExistsEvent)
	OnExpunge func(event ExpungeEvent)
	OnFetch   func(event FetchEvent)
}

type TType

type TType uint8

TType is the enum type for token values

const (
	// TUnset is an unset token; used by the parser
	TUnset TType = iota
	// TAtom is a string that's prefixed with `{n}`
	// where n is the number of bytes in the string
	TAtom
	// TNumber is a numeric literal
	TNumber
	// TLiteral is a literal (think string, ish, used mainly for field names, I hope)
	TLiteral
	// TQuoted is a quoted piece of text
	TQuoted
	// TNil is a nil value, nothing
	TNil
	// TContainer is a container of tokens
	TContainer
)

type Token

type Token struct {
	Type   TType
	Str    string
	Num    int
	Tokens []*Token
}

Token is a fetch response token (e.g. a number, or a quoted section, or a container, etc.)

func (Token) String

func (t Token) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL