Fill out Message class, get streaming from stdin working.

FossilOrigin-Name: 8f3589d9d53f730c498e99104318e0ac41f3ef3c59945eab57986fbd386e6f61
This commit is contained in:
Mahlon E. Smith 2023-06-18 17:04:02 +00:00
parent 33a5553e31
commit 312de83456
2 changed files with 90 additions and 20 deletions

View file

@ -1,6 +1,7 @@
# vim: set et nosta sw=4 ts=4 : # vim: set et nosta sw=4 ts=4 :
# #
# A class that represents an individual Maildir. # A class that represents an individual Maildir, and a Nessage class to nanage
# files underneath them.
# #
############################################################# #############################################################
@ -9,6 +10,8 @@
import import
std/os, std/os,
std/osproc,
std/posix,
std/streams, std/streams,
std/strformat, std/strformat,
std/times std/times
@ -17,6 +20,16 @@ import
util util
#############################################################
# C O N S T A N T S
#############################################################
const
OWNERDIRPERMS = { fpUserExec, fpUserWrite, fpUserRead }
OWNERFILEPERMS = { fpUserWrite, fpUserRead }
BUFSIZE = 8192 # reading and writing buffer size
############################################################# #############################################################
# T Y P E S # T Y P E S
############################################################# #############################################################
@ -32,9 +45,11 @@ type Maildir* = ref object
# An email message, under a specific Maildir. # An email message, under a specific Maildir.
# #
type Message* = ref object type Message* = ref object
dir: Maildir basename: string
path: string dir: Maildir
stream: FileStream headers: seq[ tuple[ header: string, value: seq[string] ] ]
path: string
stream: FileStream
############################################################# #############################################################
@ -50,28 +65,88 @@ proc newMaildir*( path: string ): Maildir =
result.tmp = path & "/tmp" result.tmp = path & "/tmp"
if not dirExists( path ): if not dirExists( path ):
let perms = { fpUserExec, fpUserWrite, fpUserRead }
debug "Creating new maildir at {path}.".fmt debug "Creating new maildir at {path}.".fmt
try: try:
for p in [ result.path, result.cur, result.new, result.tmp ]: for p in [ result.path, result.cur, result.new, result.tmp ]:
p.createDir p.createDir
p.setFilePermissions( perms ) p.setFilePermissions( OWNERDIRPERMS )
except CatchableError as err: except CatchableError as err:
deferral "Unable to create Maildir: ({err.msg}), deferring delivery.".fmt deferral "Unable to create Maildir: ({err.msg}), deferring delivery.".fmt
proc subDir*( dir: Maildir, path: string ): Maildir =
## Creates a new Maildir relative to an existing one.
result = newMaildir( dir.path & "/" & path )
proc newMessage*( dir: Maildir ): Message = proc newMessage*( dir: Maildir ): Message =
## Create and return a Message - an open FileStream under a specific Maildir ## Create and return a Message - an open FileStream under a specific Maildir
## (in tmp) ## (in tmp)
result = new Message result = new Message
let now = getTime() let now = getTime()
var hostname = newString(256)
discard getHostname( cstring(hostname), cint(256) )
result.dir = dir result.dir = dir
result.path = dir.path & dir.tmp & '/' & $now.toUnixFloat() result.basename = $now.toUnixFloat() & '.' & $getCurrentProcessID() & '.' & $hostname
result.path = result.dir.tmp & "/" & result.basename
result.headers = @[]
try:
debug "Opening new message at {result.path}.".fmt
result.stream = openFileStream( result.path, fmWrite )
result.path.setFilePermissions( OWNERFILEPERMS )
except CatchableError as err:
deferral "Unable to write file {result.path}: {err.msg}".fmt
proc save*( msg: Message, dir=msg.dir ) =
## Move the message from tmp to new. Defaults to its current
## maildir, but can be provided a different one.
msg.stream.close()
let newpath = dir.new & "/" & msg.basename
debug "Moving message to {newpath}.".fmt
msg.path.moveFile( newpath )
msg.dir = dir
msg.path = newpath
# make new message (tmp)
# save message (move from tmp to new) proc delete*( msg: Message ) =
## Remove a message from disk.
msg.stream.close()
debug "Removing message at {msg.path}.".fmt
msg.path.removeFile
msg.path = ""
proc writeStdin*( msg: Message ) =
## Streams stdin to the message file, returning how
## many bytes were written.
let input = stdin.newFileStream()
var buf = input.readStr( BUFSIZE )
var total = buf.len
msg.stream.write( buf )
while buf != "" and buf.len == BUFSIZE:
buf = input.readStr( BUFSIZE )
total = total + buf.len
msg.stream.write( buf )
msg.stream.flush()
msg.stream.close()
debug "Wrote {total} bytes from stdin".fmt
# FIXME: filter through external program
# - open new message
# - stream current message to new
# - remove current
# - return new
#
# FIXME: header parsing to tuples
# - open file
# - skip lines that don't match headers
# - unwrap multiline headers
# - store header, add value to seq of strings

View file

@ -1,8 +1,7 @@
# vim: set et nosta sw=4 ts=4 : # vim: set et nosta sw=4 ts=4 :
import import
std/os, std/os
std/streams
import import
lib/config, lib/config,
@ -19,15 +18,11 @@ let
conf = get_config( opts.config ) conf = get_config( opts.config )
default = newMaildir( home & "Maildir" ) default = newMaildir( home & "Maildir" )
let dest = default.subDir( ".wooo" )
echo repr default.newMessage let msg = default.newMessage
msg.writeStdin()
# msg.filter()
msg.save( dest )
# let input = stdin.newFileStream()
# var buf = input.readStr( 8192 )
# var message = buf
# while buf != "":
# buf = input.readStr( 8192 )
# message = message & buf
# echo message