import os, errno, time, socket

def _mkdir(*a, **kw):
    try:
        os.mkdir(*a, **kw)
    except OSError, e:
        if e.errno == errno.EEXIST:
            pass
        else:
            raise

def create(path):
    _mkdir(path)
    _mkdir(os.path.join(path, 'cur'), 0700)
    _mkdir(os.path.join(path, 'new'), 0700)
    _mkdir(os.path.join(path, 'tmp'), 0700)

def process(path, callback):
    for subdir in [os.path.join(path, 'new'),
                   os.path.join(path, 'cur')]:
        for filename in os.listdir(subdir):
            callback(subdir, filename)


def getTimeFromFilename(filename):
    """
    Extract the delivery timestamp from a maildir message filename.

    See http://cr.yp.to/proto/maildir.html for more information.
    (Yes, I know DJB doesn't want people parsing the filenames.)

    Also parses microseconds when available. Return type is float when
    subsecond precision is possible, int otherwise.
    """

    # strip off potential info
    filename = filename.split(':', 1)[0]

    try:
        time, delivery, hostname = filename.split('.', 2)
    except ValueError:
        return None

    try:
        seconds = int(time)
    except ValueError:
        return None

    if delivery and delivery[0] not in '012345679':
        # looks like a new-style delivery identifier
        try:
            i = delivery.index('M')
        except ValueError:
            pass
        else:
            rest = delivery[i+1:]
            s = ''
            while rest and rest[0] in '0123456789':
                s = s + rest[0]
                rest = rest[1:]
            if s:
                try:
                    microseconds = int(s)
                except ValueError:
                    pass
                else:
                    return float(seconds + microseconds * 1e-6)

    return int(seconds)

def generateMaildirName():
    curtime = time.time()
    return '%s.M%sP%s.%s' % (
        int(curtime),
        int((curtime-int(curtime))*10e6),
        os.getpid(),
        socket.gethostname().replace('/', r'\057').replace(':', r'\072')
        )

def deliverToMaildir(path, source):
    create(path)
    filename = generateMaildirName()
    tmp = os.path.join(path, 'tmp', filename)
    f = file(tmp, 'w')

    while True:
        data = source.read(8192)
        if not data:
            break
        f.write(data)

    f.close()
    os.rename(tmp, os.path.join(path, 'new', filename))
