store

package
v2.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 31, 2022 License: GPL-3.0 Imports: 36 Imported by: 0

Documentation

Overview

Package store communicates with API and caches metadata in a local database.

Index

Constants

View Source
const (
	// PathDelimiter for IMAP.
	PathDelimiter = "/"
	// UserLabelsMailboxName for IMAP.
	UserLabelsMailboxName = "Labels"
	// UserLabelsPrefix contains name with delimiter for IMAP.
	UserLabelsPrefix = UserLabelsMailboxName + PathDelimiter
	// UserFoldersMailboxName for IMAP.
	UserFoldersMailboxName = "Folders"
	// UserFoldersPrefix contains name with delimiter for IMAP.
	UserFoldersPrefix = UserFoldersMailboxName + PathDelimiter
)

Variables

View Source
var (

	// ErrNoSuchAPIID when mailbox does not have API ID.
	ErrNoSuchAPIID = errors.New("no such api id") //nolint:gochecknoglobals
	// ErrNoSuchUID when mailbox does not have IMAP UID.
	ErrNoSuchUID = errors.New("no such uid") //nolint:gochecknoglobals
	// ErrNoSuchSeqNum when mailbox does not have IMAP ID.
	ErrNoSuchSeqNum = errors.New("no such sequence number") //nolint:gochecknoglobals
)
View Source
var ErrAllMailOpNotAllowed = errors.New("operation not allowed for 'All Mail' folder")

ErrAllMailOpNotAllowed is error user when user tries to do unsupported operation on All Mail folder.

Functions

func RemoveStore

func RemoveStore(currentEvents *Events, path, userID string) error

RemoveStore removes the database file and clears the cache file.

func SetBuildAndCacheJobLimit

func SetBuildAndCacheJobLimit(maxJobs int)

Types

type Address

type Address struct {
	// contains filtered or unexported fields
}

Address holds mailboxes for IMAP user (login address). In combined mode there is only one address, in split mode there is one object per address.

func (*Address) APIAddress

func (storeAddress *Address) APIAddress() *pmapi.Address

APIAddress returns the `pmapi.Address` struct.

func (*Address) AddressID

func (storeAddress *Address) AddressID() string

AddressID returns the address ID.

func (*Address) AddressString

func (storeAddress *Address) AddressString() string

AddressString returns the address.

func (*Address) CreateMailbox

func (storeAddress *Address) CreateMailbox(name string) error

CreateMailbox creates the mailbox by calling an API. Mailbox is created in the structure by processing event.

func (*Address) GetMailbox

func (storeAddress *Address) GetMailbox(name string) (*Mailbox, error)

GetMailbox returns mailbox with the given IMAP name.

func (*Address) ListMailboxes

func (storeAddress *Address) ListMailboxes() []*Mailbox

ListMailboxes returns all mailboxes.

type AddressInfo

type AddressInfo struct {
	Address, AddressID string
}

AddressInfo is the format of the data held in the addresses bucket in the store. It allows us to easily keep an address and its ID together and serialisation/deserialisation to []byte.

type BridgeUser

type BridgeUser interface {
	ID() string
	GetAddressID(address string) (string, error)
	IsConnected() bool
	IsCombinedAddressMode() bool
	GetPrimaryAddress() string
	GetStoreAddresses() []string
	GetClient() pmapi.Client
	UpdateUser(context.Context) error
	UpdateSpace(*pmapi.User)
	CloseAllConnections()
	CloseConnection(string)
	Logout() error
}

BridgeUser is subset of bridge.User for use by the Store.

type ChangeNotifier

type ChangeNotifier interface {
	Notice(address, notice string)
	UpdateMessage(
		address, mailboxName string,
		uid, sequenceNumber uint32,
		msg *pmapi.Message, hasDeletedFlag bool)
	DeleteMessage(address, mailboxName string, sequenceNumber uint32)
	MailboxCreated(address, mailboxName string)
	MailboxStatus(address, mailboxName string, total, unread, unreadSeqNum uint32)

	CanDelete(mailboxID string) (bool, func())
}

type Events

type Events struct {
	// contains filtered or unexported fields
}

Events caches the last event IDs for all accounts (there should be only one instance).

func NewEvents

func NewEvents(path string) *Events

NewEvents constructs a new event cache at the given path.

type Mailbox

type Mailbox struct {
	// contains filtered or unexported fields
}

Mailbox is mailbox for specific address and mailbox.

func (*Mailbox) Color

func (storeMailbox *Mailbox) Color() string

Color returns the color of mailbox.

func (*Mailbox) Delete

func (storeMailbox *Mailbox) Delete() error

Delete deletes the mailbox by calling an API. Deletion has to be propagated to all the same mailboxes in all addresses. The propagation is processed by the event loop.

func (*Mailbox) FetchMessage

func (storeMailbox *Mailbox) FetchMessage(apiID string) (*Message, error)

FetchMessage fetches the message with the given `apiID`, stores it in the database, and returns a new store message wrapping it.

func (*Mailbox) GetAPIIDsFromSequenceRange

func (storeMailbox *Mailbox) GetAPIIDsFromSequenceRange(start, stop uint32) (apiIDs []string, err error)

GetAPIIDsFromSequenceRange returns API IDs by IMAP sequence number range.

func (*Mailbox) GetAPIIDsFromUIDRange

func (storeMailbox *Mailbox) GetAPIIDsFromUIDRange(start, stop uint32) (apiIDs []string, err error)

GetAPIIDsFromUIDRange returns API IDs by IMAP UID range.

API IDs are the long base64 strings that the API uses to identify messages. UIDs are unique increasing integers that must be unique within a mailbox.

func (*Mailbox) GetCounts

func (storeMailbox *Mailbox) GetCounts() (total, unread, unseenSeqNum uint, err error)

GetCounts returns numbers of total and unread messages in this mailbox bucket.

func (*Mailbox) GetDeletedAPIIDs

func (storeMailbox *Mailbox) GetDeletedAPIIDs() (apiIDs []string, err error)

GetDeletedAPIIDs returns API IDs in this mailbox for message ID.

func (*Mailbox) GetDelimiter

func (storeMailbox *Mailbox) GetDelimiter() string

GetDelimiter returns the path separator.

func (*Mailbox) GetLatestAPIID

func (storeMailbox *Mailbox) GetLatestAPIID() (apiID string, err error)

GetLatestAPIID returns the latest message API ID which still exists. Info: not the latest IMAP UID which can be already removed.

func (*Mailbox) GetMessage

func (storeMailbox *Mailbox) GetMessage(apiID string) (*Message, error)

GetMessage returns the `pmapi.Message` struct wrapped in `StoreMessage` tied to this mailbox.

func (*Mailbox) GetNextUID

func (storeMailbox *Mailbox) GetNextUID() (uid uint32, err error)

GetNextUID returns the next IMAP UID.

func (*Mailbox) GetUIDByHeader

func (storeMailbox *Mailbox) GetUIDByHeader(header *mail.Header) (foundUID uint32)

GetUIDByHeader returns UID of message existing in mailbox or zero if no match found.

func (*Mailbox) GetUIDList

func (storeMailbox *Mailbox) GetUIDList(apiIDs []string) *uidplus.OrderedSeq

GetUIDList returns UID list corresponding to messageIDs in a requested order.

func (*Mailbox) ImportMessage

func (storeMailbox *Mailbox) ImportMessage(enc []byte, seen bool, labelIDs []string, flags, time int64) (string, error)

func (*Mailbox) IsFolder

func (storeMailbox *Mailbox) IsFolder() bool

IsFolder returns whether the mailbox is a folder (has "Folders/" prefix).

func (*Mailbox) IsLabel

func (storeMailbox *Mailbox) IsLabel() bool

IsLabel returns whether the mailbox is a label (has "Labels/" prefix).

func (*Mailbox) IsSystem

func (storeMailbox *Mailbox) IsSystem() bool

IsSystem returns whether the mailbox is one of the specific system mailboxes (has no prefix).

func (*Mailbox) LabelID

func (storeMailbox *Mailbox) LabelID() string

LabelID returns ID of mailbox.

func (*Mailbox) LabelMessages

func (storeMailbox *Mailbox) LabelMessages(apiIDs []string) error

LabelMessages adds the label by calling an API. It has to be propagated to all the same messages in all mailboxes. The propagation is processed by the event loop.

func (*Mailbox) MarkMessagesDeleted

func (storeMailbox *Mailbox) MarkMessagesDeleted(apiIDs []string) error

MarkMessagesDeleted adds local flag \Deleted. This is not propagated to API until RemoveDeleted is called.

func (*Mailbox) MarkMessagesRead

func (storeMailbox *Mailbox) MarkMessagesRead(apiIDs []string) error

MarkMessagesRead marks the message read by calling an API. It has to be propagated to metadata mailbox which is done by the event loop.

func (*Mailbox) MarkMessagesStarred

func (storeMailbox *Mailbox) MarkMessagesStarred(apiIDs []string) error

MarkMessagesStarred adds the Starred label by calling an API. It has to be propagated to all the same messages in all mailboxes. The propagation is processed by the event loop.

func (*Mailbox) MarkMessagesUndeleted

func (storeMailbox *Mailbox) MarkMessagesUndeleted(apiIDs []string) error

MarkMessagesUndeleted removes local flag \Deleted. This is not propagated to API.

func (*Mailbox) MarkMessagesUnread

func (storeMailbox *Mailbox) MarkMessagesUnread(apiIDs []string) error

MarkMessagesUnread marks the message unread by calling an API. It has to be propagated to metadata mailbox which is done by the event loop.

func (*Mailbox) MarkMessagesUnstarred

func (storeMailbox *Mailbox) MarkMessagesUnstarred(apiIDs []string) error

MarkMessagesUnstarred removes the Starred label by calling an API. It has to be propagated to all the same messages in all mailboxes. The propagation is processed by the event loop.

func (*Mailbox) Name

func (storeMailbox *Mailbox) Name() string

Name returns the name of mailbox.

func (*Mailbox) RemoveDeleted

func (storeMailbox *Mailbox) RemoveDeleted(apiIDs []string) error

RemoveDeleted sends request to API to remove message from mailbox. If the mailbox is All Mail or All Sent, it does nothing. If the mailbox is Trash or Spam and message is not in any other mailbox, messages is deleted. In all other cases the message is only removed from the mailbox. If nil is passed, all messages with \Deleted flag are removed. In other cases only messages with \Deleted flag and included in the passed list.

func (*Mailbox) Rename

func (storeMailbox *Mailbox) Rename(newName string) error

Rename updates the mailbox by calling an API. Change has to be propagated to all the same mailboxes in all addresses. The propagation is processed by the event loop.

func (*Mailbox) UIDValidity

func (storeMailbox *Mailbox) UIDValidity() uint32

UIDValidity returns the current value of structure version.

func (*Mailbox) UnlabelMessages

func (storeMailbox *Mailbox) UnlabelMessages(apiIDs []string) error

UnlabelMessages removes the label by calling an API. It has to be propagated to all the same messages in all mailboxes. The propagation is processed by the event loop.

type Message

type Message struct {
	// contains filtered or unexported fields
}

Message is wrapper around `pmapi.Message` with connection to a specific mailbox with helper functions to get IMAP UID, sequence numbers and similar.

func (*Message) GetBodyStructure

func (message *Message) GetBodyStructure() (*pkgMsg.BodyStructure, error)

GetBodyStructure returns the message's body structure. It checks first if it's in the store. If it is, it returns it from store, otherwise it computes it from the message cache (and saves the result to the store).

func (*Message) GetHeader

func (message *Message) GetHeader() ([]byte, error)

GetHeader will return cached header from DB.

func (*Message) GetMIMEHeader

func (message *Message) GetMIMEHeader() (textproto.MIMEHeader, error)

GetMIMEHeader will return cached header from DB, parsed as a textproto.MIMEHeader.

func (*Message) GetMIMEHeaderFast

func (message *Message) GetMIMEHeaderFast() (header textproto.MIMEHeader)

GetMIMEHeaderFast returns full header if message was cached. If full header is not available it will return header from metadata. NOTE: Returned header may not contain all fields.

func (*Message) GetRFC822

func (message *Message) GetRFC822() ([]byte, error)

GetRFC822 returns the raw message literal.

func (*Message) GetRFC822Size

func (message *Message) GetRFC822Size() (uint32, error)

GetRFC822Size returns the size of the raw message literal.

func (*Message) ID

func (message *Message) ID() string

ID returns message ID on our API (always the same ID for all mailboxes).

func (*Message) IsFullHeaderCached

func (message *Message) IsFullHeaderCached() bool

IsFullHeaderCached will check that valid full header is stored in DB.

func (*Message) IsMarkedDeleted

func (message *Message) IsMarkedDeleted() bool

IsMarkedDeleted returns true if message is marked as deleted for specific mailbox.

func (*Message) Message

func (message *Message) Message() *pmapi.Message

Message returns message struct from pmapi.

func (*Message) SequenceNumber

func (message *Message) SequenceNumber() (uint32, error)

SequenceNumber returns index of message in used mailbox.

func (*Message) UID

func (message *Message) UID() (uint32, error)

UID returns message UID for IMAP, specific for mailbox used to get the message.

type MsgCachePool

type MsgCachePool struct {
	// contains filtered or unexported fields
}

type PanicHandler

type PanicHandler interface {
	HandlePanic()
}

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is local user storage, which handles the synchronization between IMAP and PM API.

func New

func New(
	sentryReporter *sentry.Reporter,
	panicHandler PanicHandler,
	user BridgeUser,
	listener listener.Listener,
	cache cache.Cache,
	builder *message.Builder,
	path string,
	currentEvents *Events,
) (store *Store, err error)

New creates or opens a store for the given `user`.

func (*Store) BuildAndCacheMessage

func (store *Store) BuildAndCacheMessage(ctx context.Context, messageID string) error

BuildAndCacheMessage builds the given message (with background priority) and puts it in the cache. It builds with background priority.

func (*Store) Close

func (store *Store) Close() error

Close stops the event loop and closes the database to free the file.

func (*Store) CloseEventLoopAndCacher

func (store *Store) CloseEventLoopAndCacher()

CloseEventLoopAndCacher stops the eventloop (if it is present).

func (*Store) CreateDraft

func (store *Store) CreateDraft(
	kr *crypto.KeyRing,
	message *pmapi.Message,
	attachmentReaders []io.Reader,
	attachedPublicKey,
	attachedPublicKeyName string,
	parentID string,
) (*pmapi.Message, []*pmapi.Attachment, error)

CreateDraft creates draft with attachments. If `attachedPublicKey` is passed, it's added to attachments. Both draft and attachments are encrypted with passed `kr` key.

func (*Store) GetAddress

func (store *Store) GetAddress(addressID string) (*Address, error)

GetAddress returns the store address by given ID.

func (*Store) GetAddressID

func (store *Store) GetAddressID(addr string) (id string, err error)

GetAddressID returns the ID of the given address.

func (*Store) GetAddressInfo

func (store *Store) GetAddressInfo() (addrs []AddressInfo, err error)

GetAddressInfo returns information about all addresses owned by the user. The first element is the user's primary address and the rest (if present) are aliases. It tries to source the information from the store but if the store doesn't yet have it, it fetches it from the API and caches it for later.

func (*Store) GetMaxUpload

func (store *Store) GetMaxUpload() (int64, error)

GetMaxUpload returns max size of message + all attachments in bytes.

func (*Store) GetSpaceKB

func (store *Store) GetSpaceKB() (usedSpace, maxSpace uint32, err error)

GetSpaceKB returns used and total space in kilo bytes (needed for IMAP Quota. Quota is "in units of 1024 octets" (or KB) and PM returns bytes.

func (*Store) IsCached

func (store *Store) IsCached(messageID string) (has bool)

IsCached returns whether the given message already exists in the cache.

func (*Store) IsCombinedMode

func (store *Store) IsCombinedMode() bool

IsCombinedMode returns whether the store is set to combined mode.

func (*Store) RebuildMailboxes

func (store *Store) RebuildMailboxes() (err error)

RebuildMailboxes truncates all mailbox buckets and recreates them from the metadata bucket again.

func (*Store) Remove

func (store *Store) Remove() error

Remove closes and removes the database file and clears the cache file.

func (*Store) RemoveCache

func (store *Store) RemoveCache() error

func (*Store) SendMessage

func (store *Store) SendMessage(messageID string, req *pmapi.SendMessageReq) error

SendMessage sends the message.

func (*Store) SetChangeNotifier

func (store *Store) SetChangeNotifier(notifier ChangeNotifier)

SetChangeNotifier sets notifier to be called once mailbox or message changes.

func (*Store) StartWatcher

func (store *Store) StartWatcher()

func (*Store) TestDumpDB

func (store *Store) TestDumpDB(tb assert.TestingT)

TestDumpDB will dump store database content.

func (*Store) TestGetEventLoop

func (store *Store) TestGetEventLoop() *eventLoop

TestGetEventLoop returns the store's event loop.

func (*Store) TestGetLastEvent

func (store *Store) TestGetLastEvent() *pmapi.Event

TestGetLastEvent returns last event processed by the store's event loop.

func (*Store) TestGetStoreFilePath

func (store *Store) TestGetStoreFilePath() string

TestGetStoreFilePath returns the filepath of the store's database file.

func (*Store) TestIsSyncRunning

func (store *Store) TestIsSyncRunning() bool

TestIsSyncRunning returns whether the sync is currently ongoing.

func (*Store) TestPollNow

func (store *Store) TestPollNow()

TestPollNow triggers a loop of the event loop.

func (*Store) TestSync

func (store *Store) TestSync()

TestSync triggers a sync of the store.

func (*Store) UnlockCache

func (store *Store) UnlockCache(kr *crypto.KeyRing) error

UnlockCache unlocks the cache for the user with the given keyring.

func (*Store) UseCombinedMode

func (store *Store) UseCombinedMode(useCombined bool) (err error)

UseCombinedMode sets whether the store should be set to combined mode.

func (*Store) UserID

func (store *Store) UserID() string

UserID returns user ID.

type Storer

type Storer interface {
	IsCached(messageID string) bool
	BuildAndCacheMessage(ctx context.Context, messageID string) error
}

Directories

Path Synopsis
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

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