Compare commits

..

8 Commits

3 changed files with 39 additions and 66 deletions

View File

@ -30,7 +30,7 @@ the tiedote.md user on this system.")
(sendmail-path
(string "/run/privileged/bin/sendmail")
"Path to a sendmail compatible mailing executable.")
(webhook-port
(port
(integer 3000)
"Port to listen on for webhook notifications.")
(socket-path
@ -54,36 +54,10 @@ the tiedote.md user on this system.")
(home-directory state-directory)
(shell (file-append bash-minimal "/bin/bash"))))))
(define (make-tiedote.md-server-script config)
(match-record config <tiedote.md-configuration>
(socket-path email-address sender-name webhook-port sendmail-path
remote-branch remote-url state-directory)
(program-file "tiedote.md-server"
#~(begin
; use utf8 before starting tiedote.md to be able to pass utf characters as arguments
(setlocale LC_ALL "C.UTF-8")
; use utf8 after exec so that ghc text library doesn't crash from IO
(setenv "LANG" "C.UTF-8")
(let ((tiedote.md #$(file-append tiedote-md "/bin/tiedote.md"))
(repo-path (string-append #$state-directory "/git-repo")))
(apply execl
`(,tiedote.md
,tiedote.md
"--address" #$email-address
"--sender-name" #$sender-name
"--sendmail" #$sendmail-path
"--socket" #$socket-path
"server"
"--repository" ,repo-path
"--port" #$(number->string webhook-port)
"--remote-url" #$remote-url
,@(if #$(maybe-value-set? remote-branch)
(list "--remote-branch" #$remote-branch)
'()))))))))
(define (tiedote.md-shepherd-service config)
(match-record config <tiedote.md-configuration>
(state-directory socket-path)
(state-directory socket-path email-address sender-name port sendmail-path
remote-branch remote-url)
(list (shepherd-service
(documentation "A simple mass email system")
(requirement '(networking user-processes))
@ -91,46 +65,48 @@ the tiedote.md user on this system.")
(start #~(let* ((user (getpw "tiedote.md"))
(uid (passwd:uid user))
(gid (passwd:gid user))
(socket-directory (dirname #$socket-path)))
(socket-directory (dirname #$socket-path))
(repo-path (string-append #$state-directory "/git-repo")))
(begin
(mkdir-p socket-directory)
(chown socket-directory uid gid)
(make-forkexec-constructor (list #$(make-tiedote.md-server-script config))
#:user "tiedote.md"
#:group "tiedote.md"
#:environment-variables
(cons* "GIT_SSL_CAINFO=/etc/ssl/certs/ca-certificates.crt"
(default-environment-variables))
#:directory #$state-directory))))
(make-forkexec-constructor
(list #$(file-append tiedote-md "/bin/tiedote.md")
"--address" #$email-address
"--sender-name" #$sender-name
"--sendmail" #$sendmail-path
"--socket" #$socket-path
"server"
"--repository" repo-path
"--port" #$(number->string port)
"--remote-url" #$remote-url
;,@(if #$(maybe-value-set? remote-branch)
; (list "--remote-branch" #$remote-branch)
; '())
)
#:user "tiedote.md"
#:group "tiedote.md"
#:environment (cons "GIT_SSL_CAINFO=/etc/ssl/certs/ca-certificates.crt"
(default-environment-variable))
#:directory #$state-directory))))
(stop #~(make-kill-destructor))))))
(define (tiedote.md-activation config)
(match-record config <tiedote.md-configuration>
(state-directory email-address sender-name sendmail-path socket-path)
(let* ((tiedote.md (file-append tiedote-md "/bin/tiedote.md"))
(receive-exec (list tiedote.md ; file to exec
tiedote.md ; arg $0
(let* ((receive-exec (list (file-append tiedote-md "/bin/tiedote.md") ; file to exec
(file-append tiedote-md "/bin/tiedote.md") ; arg $0
"--address" email-address
"--sender-name" sender-name
"--sendmail" sendmail-path
"--socket" socket-path
"receive"))
"--socket" socket-path))
(receive-script (program-file "tiedote.md-receive"
#~(begin
(setlocale LC_ALL "C.UTF-8")
(setenv "LANG" "C.UTF-8")
(apply execl '#$receive-exec))))
#~(apply execl #$receive-exec)))
(forward-file (mixed-text-file "dot-forward" "|" receive-script)))
#~(let* ((.forward (string-append #$state-directory "/.forward"))
(user (getpw "tiedote.md"))
(uid (passwd:uid user))
(gid (passwd:gid user)))
#~(let ((.forward (string-append #$state-directory "/.forward")))
(if (file-exists? .forward)
(delete-file .forward))
; smtpd does not follow symbolic links and requires .forward files to
; be owned by the recipient
(copy-file #$forward-file .forward)
(chown .forward uid gid)))))
(symlink #$forward-file .forward)))))
(define tiedote.md-service-type
(service-type

View File

@ -41,7 +41,9 @@ lähettämisestä ja Git-tietovaraston päivittämisestä, kun se saa muutoksist
ilmoituksen HTTP POST -pyyntönä (esim. Git-palvelun webhookista).
Palvelimen voi käynnistää komennolla `tiedote.md server`. Mahdolliset asetukset
saa listattua lisäämällä komentoon `--help` valitsimen.
saa listattua lisäämällä komentoon `--help` valitsimen. `--address`
valitsimesta tulee huomata, että osoitteessa voi käyttää vain ASCII-merkkejä
(ks. [#15](https://git.olarinmaensamoojat.fi/OMS/tiedote.md/issues/15)).
Sähköpostin lähettämiseen tarvitaan `sendmail`-yhteensopiva MTA (mail transfer
agent, sähköpostin välitysohjelma), jollaisen useimmat sähköpostipalvelimet

View File

@ -4,6 +4,7 @@
module TiedoteMD.Send where
import Control.Concurrent (threadDelay)
import Control.Exception (throwIO)
import Control.Lens (set, _Just)
import Control.Monad (forever, unless)
import Data.Acid (AcidState, query, update)
@ -14,7 +15,8 @@ import Data.MIME.Charset (defaultCharsets)
import Data.Set (Set)
import Data.Time (getCurrentTime)
import System.Exit (ExitCode(..))
import System.IO (hClose, stdout, stderr)
import System.Exit.Codes (codeTempFail)
import System.IO (hClose, stdout)
import System.Process (CreateProcess(..), StdStream(..), waitForProcess, createProcess, proc)
import System.Random (getStdRandom, uniform)
@ -23,25 +25,18 @@ import qualified Data.IMF as IMF
import qualified Data.List.NonEmpty as NE
import qualified Data.Set as Set
import qualified Data.Text as T
import qualified Data.Text.IO as T
import TiedoteMD.State
import TiedoteMD.Types
sendmail :: FilePath -> LBS.ByteString -> IO ()
sendmail path bs = do
(Just stdin, _, Just stderr, processHandle) <- createProcess
(proc path ["-t"]) {std_in = CreatePipe, std_err = CreatePipe}
(Just stdin, _, _, processHandle) <- createProcess (proc path ["-t"]) {std_in = CreatePipe}
LBS.hPut stdin bs
hClose stdin
errors <- T.hGetContents stderr
exitCode <- waitForProcess processHandle
-- TODO: handle System.Exit.Codes.codeTempFail differently from other failures
unless (exitCode == ExitSuccess) $ do
T.hPutStr System.IO.stderr $
"Sending mail with " <> (T.pack path) <> " failed with " <> (T.pack $ show exitCode)
unless (T.null errors) $ T.hPutStrLn System.IO.stderr $ ":\n" <> errors
T.hPutStrLn System.IO.stderr ""
unless (exitCode `elem` [ExitSuccess, codeTempFail]) $
throwIO $ ProcessError (T.pack path) exitCode
manageQueue :: AcidState State -> Mailbox -> FilePath -> IO ()
manageQueue acid sender sendmailPath = forever $ do