func (d Dir) Create() error {
	err := os.Mkdir(string(d), os.ModeDir|CreateMode)
	if err != nil && !os.IsExist(err) {
		return err
	}
	err = os.Mkdir(filepath.Join(string(d), "tmp"), os.ModeDir|CreateMode)
	if err != nil && !os.IsExist(err) {
		return err
	}
	err = os.Mkdir(filepath.Join(string(d), "new"), os.ModeDir|CreateMode)
	if err != nil && !os.IsExist(err) {
		return err
	}
	err = os.Mkdir(filepath.Join(string(d), "cur"), os.ModeDir|CreateMode)
	if err != nil && !os.IsExist(err) {
		return err
	}
	return nil
}
Create creates the directory structure for a Maildir.
If the main directory already exists, it tries to create the subdirectories
in there. If an error occurs while creating one of the subdirectories, this
function may leave a partially created directory structure.
package maildir
import (
	"bufio"
	"bytes"
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io"
	"net/mail"
	"net/textproto"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"sync/atomic"
	"time"
)
var Separator rune = ':'
var id int64 = 10000
const CreateMode = 0700
type KeyError struct {
	Key string  
	N   int     
}
func (e *KeyError) Error() string {
	return "maildir: key " + e.Key + " matches " + strconv.Itoa(e.N) + " files."
}
type FlagError struct {
	Info         string  
	Experimental bool    
}
func (e *FlagError) Error() string {
	if e.Experimental {
		return "maildir: experimental info section encountered: " + e.Info[2:]
	}
	return "maildir: bad info section encountered: " + e.Info
}
type Dir string
func (d Dir) Unseen() ([]string, error) {
	f, err := os.Open(filepath.Join(string(d), "new"))
	if err != nil {
		return nil, err
	}
	defer f.Close()
	names, err := f.Readdirnames(0)
	if err != nil {
		return nil, err
	}
	var keys []string
	for _, n := range names {
		if n[0] != '.' {
			split := strings.FieldsFunc(n, func(r rune) bool {
				return r == Separator
			})
			key := split[0]
			info := "2,"
			if len(split) > 1 {
				info = split[1]
			}
			keys = append(keys, key)
			err = os.Rename(filepath.Join(string(d), "new", n),
				filepath.Join(string(d), "cur", key+string(Separator)+info))
		}
	}
	return keys, err
}
func (d Dir) UnseenCount() (int, error) {
	f, err := os.Open(filepath.Join(string(d), "new"))
	if err != nil {
		return 0, err
	}
	defer f.Close()
	names, err := f.Readdirnames(0)
	if err != nil {
		return 0, err
	}
	c := 0
	for _, n := range names {
		if n[0] != '.' {
			c += 1
		}
	}
	return c, nil
}
func (d Dir) Keys() ([]string, error) {
	f, err := os.Open(filepath.Join(string(d), "cur"))
	if err != nil {
		return nil, err
	}
	defer f.Close()
	names, err := f.Readdirnames(0)
	if err != nil {
		return nil, err
	}
	var keys []string
	for _, n := range names {
		if n[0] != '.' {
			split := strings.FieldsFunc(n, func(r rune) bool {
				return r == Separator
			})
			keys = append(keys, split[0])
		}
	}
	return keys, nil
}
func fileExists(filename string) bool {
	finfo, err := os.Stat(filename)
	return err == nil && finfo.Mode().IsRegular()
}
var suffices []string = []string{
	"",
	"S",
	"D",
	"F",
	"P",
	"R",
	"T",
	"DF",
	"DP",
	"DR",
	"DS",
	"DT",
	"FP",
	"FR",
	"FS",
	"FT",
	"PR",
	"PS",
	"PT",
	"RS",
	"RT",
	"ST",
	"DFP",
	"DFR",
	"DFS",
	"DFT",
	"DPR",
	"DPS",
	"DPT",
	"DRS",
	"DRT",
	"DST",
	"FPR",
	"FPS",
	"FPT",
	"FRS",
	"FRT",
	"FST",
	"PRS",
	"PRT",
	"PST",
	"RST",
	"DFPR",
	"DFPS",
	"DFPT",
	"DFRS",
	"DFRT",
	"DFST",
	"DPRS",
	"DPRT",
	"DPST",
	"DRST",
	"FPRS",
	"FPRT",
	"FPST",
	"FRST",
	"PRST",
	"DFPRS",
	"DFPRT",
	"DFPST",
	"DFRST",
	"DPRST",
	"FPRST",
	"DFPRST"}
func (d Dir) quickFilename(key string) string {
	filePrefix := filepath.Join(string(d), "cur", key+string(Separator)+"2,")
	for _, suffix := range suffices {
		if filename := filePrefix + suffix; fileExists(filename) {
			return filename
		}
	}
	return ""
}
func (d Dir) Filename(key string) (string, error) {
	if matchedFile := d.quickFilename(key); matchedFile != "" {
		return matchedFile, nil
	}
	dirPath := filepath.Join(string(d), "cur")
	f, err := os.Open(dirPath)
	if err != nil {
		return "", err
	}
	defer f.Close()
	names, err := f.Readdirnames(-1)
	if err != nil {
		return "", err
	}
	for _, name := range names {
		if strings.HasPrefix(name, key) {
			return filepath.Join(dirPath, name), nil
		}
	}
	return "", &KeyError{key, 0}
}
func (d Dir) Header(key string) (header mail.Header, err error) {
	filename, err := d.Filename(key)
	if err != nil {
		return
	}
	file, err := os.Open(filename)
	if err != nil {
		return
	}
	defer file.Close()
	tp := textproto.NewReader(bufio.NewReader(file))
	hdr, err := tp.ReadMIMEHeader()
	if err != nil {
		return
	}
	header = mail.Header(hdr)
	return
}
func (d Dir) Message(key string) (*mail.Message, error) {
	filename, err := d.Filename(key)
	if err != nil {
		return &mail.Message{}, err
	}
	r, err := os.Open(filename)
	if err != nil {
		return &mail.Message{}, err
	}
	defer r.Close()
	buf := new(bytes.Buffer)
	_, err = io.Copy(buf, r)
	if err != nil {
		return &mail.Message{}, err
	}
	msg, err := mail.ReadMessage(buf)
	if err != nil {
		return msg, err
	}
	return msg, nil
}
type runeSlice []rune
func (s runeSlice) Len() int           { return len(s) }
func (s runeSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s runeSlice) Less(i, j int) bool { return s[i] < s[j] }
func (d Dir) Flags(key string) (string, error) {
	filename, err := d.Filename(key)
	if err != nil {
		return "", err
	}
	split := strings.FieldsFunc(filename, func(r rune) bool {
		return r == Separator
	})
	switch {
	case len(split[1]) < 2,
		split[1][1] != ',':
		return "", &FlagError{split[1], false}
	case split[1][0] == '1':
		return "", &FlagError{split[1], true}
	case split[1][0] != '2':
		return "", &FlagError{split[1], false}
	}
	rs := runeSlice(split[1][2:])
	sort.Sort(rs)
	return string(rs), nil
}
func (d Dir) SetFlags(key string, flags string) error {
	info := "2,"
	rs := runeSlice(flags)
	sort.Sort(rs)
	for _, r := range rs {
		if []rune(info)[len(info)-1] != r {
			info += string(r)
		}
	}
	return d.SetInfo(key, info)
}
func (d Dir) SetInfo(key, info string) error {
	filename, err := d.Filename(key)
	if err != nil {
		return err
	}
	err = os.Rename(filename, filepath.Join(string(d), "cur", key+
		string(Separator)+info))
	return err
}
func Key() (string, error) {
	fmt.Println("maildir: Key() is deprecated without replacement. See https://github.com/luksen/maildir/issues/5 for details.")
	return generateKey()
}
func generateKey() (string, error) {
	var key string
	key += strconv.FormatInt(time.Now().Unix(), 10)
	key += "."
	host, err := os.Hostname()
	if err != err {
		return "", err
	}
	host = strings.Replace(host, "/", "\057", -1)
	host = strings.Replace(host, string(Separator), "\072", -1)
	key += host
	key += "."
	key += strconv.FormatInt(int64(os.Getpid()), 10)
	key += strconv.FormatInt(id, 10)
	atomic.AddInt64(&id, 1)
	bs := make([]byte, 10)
	_, err = io.ReadFull(rand.Reader, bs)
	if err != nil {
		return "", err
	}
	key += hex.EncodeToString(bs)
	return key, nil
}