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 (sendmail-path
(string "/run/privileged/bin/sendmail") (string "/run/privileged/bin/sendmail")
"Path to a sendmail compatible mailing executable.") "Path to a sendmail compatible mailing executable.")
(webhook-port (port
(integer 3000) (integer 3000)
"Port to listen on for webhook notifications.") "Port to listen on for webhook notifications.")
(socket-path (socket-path
@ -54,36 +54,10 @@ the tiedote.md user on this system.")
(home-directory state-directory) (home-directory state-directory)
(shell (file-append bash-minimal "/bin/bash")))))) (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) (define (tiedote.md-shepherd-service config)
(match-record config <tiedote.md-configuration> (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 (list (shepherd-service
(documentation "A simple mass email system") (documentation "A simple mass email system")
(requirement '(networking user-processes)) (requirement '(networking user-processes))
@ -91,46 +65,48 @@ the tiedote.md user on this system.")
(start #~(let* ((user (getpw "tiedote.md")) (start #~(let* ((user (getpw "tiedote.md"))
(uid (passwd:uid user)) (uid (passwd:uid user))
(gid (passwd:gid user)) (gid (passwd:gid user))
(socket-directory (dirname #$socket-path))) (socket-directory (dirname #$socket-path))
(repo-path (string-append #$state-directory "/git-repo")))
(begin (begin
(mkdir-p socket-directory) (mkdir-p socket-directory)
(chown socket-directory uid gid) (chown socket-directory uid gid)
(make-forkexec-constructor (list #$(make-tiedote.md-server-script config)) (make-forkexec-constructor
#:user "tiedote.md" (list #$(file-append tiedote-md "/bin/tiedote.md")
#:group "tiedote.md" "--address" #$email-address
#:environment-variables "--sender-name" #$sender-name
(cons* "GIT_SSL_CAINFO=/etc/ssl/certs/ca-certificates.crt" "--sendmail" #$sendmail-path
(default-environment-variables)) "--socket" #$socket-path
#:directory #$state-directory)))) "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)))))) (stop #~(make-kill-destructor))))))
(define (tiedote.md-activation config) (define (tiedote.md-activation config)
(match-record config <tiedote.md-configuration> (match-record config <tiedote.md-configuration>
(state-directory email-address sender-name sendmail-path socket-path) (state-directory email-address sender-name sendmail-path socket-path)
(let* ((tiedote.md (file-append tiedote-md "/bin/tiedote.md")) (let* ((receive-exec (list (file-append tiedote-md "/bin/tiedote.md") ; file to exec
(receive-exec (list tiedote.md ; file to exec (file-append tiedote-md "/bin/tiedote.md") ; arg $0
tiedote.md ; arg $0
"--address" email-address "--address" email-address
"--sender-name" sender-name "--sender-name" sender-name
"--sendmail" sendmail-path "--sendmail" sendmail-path
"--socket" socket-path "--socket" socket-path))
"receive"))
(receive-script (program-file "tiedote.md-receive" (receive-script (program-file "tiedote.md-receive"
#~(begin #~(apply execl #$receive-exec)))
(setlocale LC_ALL "C.UTF-8")
(setenv "LANG" "C.UTF-8")
(apply execl '#$receive-exec))))
(forward-file (mixed-text-file "dot-forward" "|" receive-script))) (forward-file (mixed-text-file "dot-forward" "|" receive-script)))
#~(let* ((.forward (string-append #$state-directory "/.forward")) #~(let ((.forward (string-append #$state-directory "/.forward")))
(user (getpw "tiedote.md"))
(uid (passwd:uid user))
(gid (passwd:gid user)))
(if (file-exists? .forward) (if (file-exists? .forward)
(delete-file .forward)) (delete-file .forward))
; smtpd does not follow symbolic links and requires .forward files to (symlink #$forward-file .forward)))))
; be owned by the recipient
(copy-file #$forward-file .forward)
(chown .forward uid gid)))))
(define tiedote.md-service-type (define tiedote.md-service-type
(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). ilmoituksen HTTP POST -pyyntönä (esim. Git-palvelun webhookista).
Palvelimen voi käynnistää komennolla `tiedote.md server`. Mahdolliset asetukset 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 Sähköpostin lähettämiseen tarvitaan `sendmail`-yhteensopiva MTA (mail transfer
agent, sähköpostin välitysohjelma), jollaisen useimmat sähköpostipalvelimet agent, sähköpostin välitysohjelma), jollaisen useimmat sähköpostipalvelimet

View File

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