~kolletzki/attachment-dl

9a6cee468c28902f027e57b2a4b5f0b1801e6f34 — Lukas Kolletzki 2 years ago 312e789 master
Fix download of inline attachments with filename
2 files changed, 63 insertions(+), 47 deletions(-)

M VERSION
M attachment-dl/imap.go
M VERSION => VERSION +1 -1
@@ 1,1 1,1 @@
0.2.0
\ No newline at end of file
0.2.2
\ No newline at end of file

M attachment-dl/imap.go => attachment-dl/imap.go +62 -46
@@ 33,6 33,26 @@ func GetClient(host, user, pass string) (*client.Client, error) {
	return c, nil
}

func GetMailboxes(c *client.Client) ([]*imap.MailboxInfo, error) {
	mboxes := make([]*imap.MailboxInfo, 0)

	mailboxes := make(chan *imap.MailboxInfo, 10)
	done := make(chan error, 1)
	go func() {
		done <- c.List("", "*", mailboxes)
	}()

	for m := range mailboxes {
		mboxes = append(mboxes, m)
	}

	if err := <-done; err != nil {
		return nil, err
	}

	return mboxes, nil
}

func SaveAttachments(c *client.Client, mboxName, dest string) (int, error) {
	mbox, err := c.Select(mboxName, true)
	if err != nil {


@@ 87,66 107,62 @@ func SaveAttachments(c *client.Client, mboxName, dest string) (int, error) {
				log.Fatal(err)
			}

			if h, ok := p.Header.(*mail.AttachmentHeader); ok {
				filename, _ := h.Filename()
				ext := filepath.Ext(filename)
			var filename string
			if ah, ok := p.Header.(*mail.AttachmentHeader); ok {
				filename, _ = ah.Filename()
			} else if ih, ok := p.Header.(*mail.InlineHeader); ok {
				// Workaround for Apple Mail which sets Content-Disposition to inline when attachments
				// are added via drag and drop to the mail

				// Prefix filename with from address
				if from != "" {
					filename = fmt.Sprintf("%s_%s", from, filename)
				_, params, err := ih.ContentDisposition()
				if err != nil {
					// TODO: Log
					continue
				}
				if v, ok := params["filename"]; ok {
					filename = v
				} else {
					continue
				}
			}

			ext := filepath.Ext(filename)

				// Find a suiting file name, even if the attachment was downloaded before
				for i := 1; i <= 50; i++ {
					if _, err := os.Stat(path.Join(dest, filename)); err != nil && os.IsNotExist(err) {
						if i == 50 {
							panic(fmt.Errorf("could not find a suiting file name for the attachment of message %d", m.Uid))
						}
			// Prefix filename with from address
			if from != "" {
				filename = fmt.Sprintf("%s_%s", from, filename)
			}

						break
			// Find a suiting file name, even if the attachment was downloaded before
			for i := 1; i <= 50; i++ {
				if _, err := os.Stat(path.Join(dest, filename)); err != nil && os.IsNotExist(err) {
					if i == 50 {
						panic(fmt.Errorf("could not find a suiting file name for the attachment of message %d", m.Uid))
					}

					// FIXME: This does not work properly, it just appends the counter instead of replacing it
					filename = fmt.Sprintf("%s (%d)%s", strings.TrimSuffix(filename, ext), i, ext)
					break
				}

				f, err := os.Create(path.Join(dest, filename))
				if err != nil {
					return 0, err
				}
				// FIXME: This does not work properly, it just appends the counter instead of replacing it
				filename = fmt.Sprintf("%s (%d)%s", strings.TrimSuffix(filename, ext), i, ext)
			}

				if _, err = io.Copy(f, p.Body); err != nil {
					return 0, err
				}
			f, err := os.Create(path.Join(dest, filename))
			if err != nil {
				return 0, err
			}

				if err = f.Close(); err != nil {
					return 0, err
				}
			if _, err = io.Copy(f, p.Body); err != nil {
				return 0, err
			}

				attCnt++
			if err = f.Close(); err != nil {
				return 0, err
			}

			attCnt++
		}
	}

	return attCnt, nil
}

func GetMailboxes(c *client.Client) ([]*imap.MailboxInfo, error) {
	mboxes := make([]*imap.MailboxInfo, 0)

	mailboxes := make(chan *imap.MailboxInfo, 10)
	done := make(chan error, 1)
	go func() {
		done <- c.List("", "*", mailboxes)
	}()

	for m := range mailboxes {
		mboxes = append(mboxes, m)
	}

	if err := <-done; err != nil {
		return nil, err
	}

	return mboxes, nil
}