Skip to content

Commit

Permalink
added support for having imap inboxes by prefix
Browse files Browse the repository at this point in the history
with inboxPrefix you can create nested labels in your gmail and have all those
downloaded and sorted within a folder using that label.
  • Loading branch information
rwese committed Aug 14, 2021
1 parent 1c7263d commit 536c1df
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 15 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ Gatherers:
Gatherers:
<gatherer_name>:
Type: imap
Inbox: INBOX // is the default
InboxPrefix: gmail_label // every gmail label starting with
Config:
Server: server:993
Username:
Expand Down
87 changes: 75 additions & 12 deletions archivar/archiver/archivers/imap/client/imap.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,22 @@ type Imap struct {
username string
password string
inbox string
inboxPrefix string
processingInbox string
allowInsecureSSL bool
client *client.Client
section *imap.BodySectionName
items []imap.FetchItem
logger *logrus.Logger
}

func New(server, username, password, inbox string, allowInsecureSSL bool, logger *logrus.Logger) *Imap {
func New(server, username, password, inbox, inboxPrefix string, allowInsecureSSL bool, logger *logrus.Logger) *Imap {
i := &Imap{
server: server,
username: username,
password: password,
inbox: inbox,
inboxPrefix: inboxPrefix,
allowInsecureSSL: allowInsecureSSL,
logger: logger,
}
Expand Down Expand Up @@ -96,7 +99,7 @@ func (i Imap) ProcessMessage(msg *imap.Message, upload archivers.UploadFunc) err
mailData.subject = subject
}

filePrefixPath := mailData.getFilePath()
filePrefixPath := mailData.getFilePath(i.processingInbox, true, true)

if err != nil {
log.Fatal(err)
Expand Down Expand Up @@ -166,7 +169,7 @@ var subjectCleanup = regexp.MustCompile(`[^a-zA-Z0-9\-_ ]+`)

const SUBJECT_LENGTH = 30

func (m mailData) getFilePath() string {
func (m mailData) getFilePath(inbox string, addPlusStringToPath, addInboxToPath bool) string {
// TODO add variant options
timestamp := fmt.Sprintf(
"%04d%02d%02d_%02d%02d%02d",
Expand All @@ -178,15 +181,19 @@ func (m mailData) getFilePath() string {
m.date.Second(),
)

rootDirectory := m.to.Address
foundPlusString := emailPlusPart.FindSubmatch([]byte(m.to.String()))
if len(foundPlusString) > 1 {
rootDirectory = string(foundPlusString[1])
pathParts := []string{}
pathParts = append(pathParts, inbox)
pathParts = append(pathParts, m.to.Address)
if addPlusStringToPath {
foundPlusString := emailPlusPart.FindSubmatch([]byte(m.to.String()))
if len(foundPlusString) > 1 {
pathParts = append(pathParts, string(foundPlusString[1]))
}
}

subjectCleanupPath := subjectCleanup.ReplaceAllString(m.subject, "")
pathParts = append(pathParts, subjectCleanup.ReplaceAllString(timestamp+"-"+m.subject, ""))

return path.Join(rootDirectory, timestamp+"_"+subjectCleanupPath)
return path.Join(pathParts...)
}

func (i Imap) FlagAndDeleteMessages(readMsgSeq *imap.SeqSet) (err error) {
Expand All @@ -202,20 +209,76 @@ func (i Imap) FlagAndDeleteMessages(readMsgSeq *imap.SeqSet) (err error) {

return
}
func (i *Imap) getInboxesByPrefix(prefix string) []string {
i.Connect()
mailboxes := make(chan *imap.MailboxInfo, 10)
done := make(chan error, 1)
go func() {
done <- i.client.List("", prefix+"*", mailboxes)
}()

inboxes := []string{}
for m := range mailboxes {
inboxes = append(inboxes, m.Name)
}

return inboxes
}
func (i *Imap) ListInboxes() {
i.Connect()
mailboxes := make(chan *imap.MailboxInfo, 10)
done := make(chan error, 1)
go func() {
done <- i.client.List("", "*", mailboxes)
}()

log.Println("Mailboxes:")
for m := range mailboxes {
log.Println("* " + m.Name)
}
}

func (i *Imap) GetMessages(messageChan chan *imap.Message, deleteDownloaded bool) (err error) {
i.Connect()

mbox, err := i.client.Select(i.inbox, false)
inboxes := []string{}
if i.inbox != "" {
inboxes = append(inboxes, i.inbox)
}

if i.inboxPrefix != "" {
inboxes = append(inboxes, i.getInboxesByPrefix(i.inboxPrefix)...)
}

for _, inbox := range inboxes {
i.processingInbox = inbox

err := i.processInboxMessages(inbox, messageChan, deleteDownloaded)
if err != nil {
return nil
}
}

return nil
}

func (i *Imap) processInboxMessages(inbox string, messageChan chan *imap.Message, deleteDownloaded bool) (err error) {
mbox, err := i.client.Select(inbox, false)
if err != nil {
return
i.ListInboxes()
return err
}

i.logger.Debugf("selected '%s'", i.inbox)
i.logger.Debugf("selected '%s'", inbox)

criteria := imap.NewSearchCriteria()
criteria.WithoutFlags = []string{imap.DeletedFlag}

foundMsgs, err := i.client.Search(criteria)
if err != nil {
return err
}

if mbox.Messages == 0 {
i.logger.Debug("no messages")
return nil
Expand Down
10 changes: 7 additions & 3 deletions archivar/archiver/archivers/imap/gatherer.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type ImapGathererConfig struct {
Username string
Password string
Inbox string
InboxPrefix string
AllowInsecureSSL bool
DeleteDownloaded bool
}
Expand All @@ -26,12 +27,14 @@ type ImapGatherer struct {
}

func NewGatherer(c interface{}, storage archivers.Archiver, logger *logrus.Logger) (i archivers.Gatherer) {
igc := ImapGathererConfig{
Inbox: "Inbox",
}
igc := ImapGathererConfig{}

config.ConfigFromStruct(c, &igc)

if igc.Inbox == "" && igc.InboxPrefix == "" {
igc.Inbox = "Inbox"
}

return &ImapGatherer{
deleteDownloaded: igc.DeleteDownloaded,
storage: storage,
Expand All @@ -41,6 +44,7 @@ func NewGatherer(c interface{}, storage archivers.Archiver, logger *logrus.Logge
igc.Username,
igc.Password,
igc.Inbox,
igc.InboxPrefix,
igc.AllowInsecureSSL,
logger,
),
Expand Down
10 changes: 10 additions & 0 deletions etc/archivar.yaml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ Gatherers:
Password:
Server: https://server/remote.php/dav/files/username/
UploadDirectory: /input_directory/
imap_gmail_with_prefix_labels:
Type: imap
InboxPrefix: archivar
Config:
Server: server:993
Username:
Password:
# DeleteDownloaded: False
# AllowInsecureSSL: False
imap_mail_account:
Type: imap
Config:
Expand All @@ -57,6 +66,7 @@ Gatherers:
Password:
# DeleteDownloaded: False
# AllowInsecureSSL: False
InboxPrefix: archivar
Processors:
superSecretDataEncrypter:
Type: encrypter
Expand Down

0 comments on commit 536c1df

Please sign in to comment.