#[Copyright 2024 ITwrx. This file is part of GoAccessReporter. GoAccessReporter is released under the GNU Affero General Public License 3.0. See COPYING or for details.]# import parsetoml, smtp, mime, std/[logging, times, dirs, paths, os, osproc] let dt = now() let nowDT = dt.format("M-d-YYYY h:mm:ss tt") let nowDTNoSpaces = dt.format("M-d-YYYY-h-mm-ss-tt") discard existsOrCreateDir(Path expandTilde("~/.goaccess-reporter")) discard existsOrCreateDir(Path expandTilde("~/.goaccess-reporter/reports")) var logger = newFileLogger(expandTilde("~/.goaccess-reporter/goaccess-reporter.log")) var logMsg: string proc logKeyParseError(key: string, tableName: string, tomlFile: string) = logMsg = nowDT & ": unable to parse '" & key & "' key from table: " & tableName & " in " & tomlFile & ".toml." logger.log(lvlError, logMsg) var tomlErrors = false var tomlSitesTable, tomlEmailTable: TomlTableRef try: let tomlSitesData = parsetoml.parseFile("/etc/goaccess-reporter/sites.toml") tomlSitesTable = tomlSitesData.getTable() except TomlError: logMsg = nowDT & ": Unable to parse '/etc/goaccess-reporter/sites.toml'" logger.log(lvlError, logMsg) echo "Error: unable to parse toml sites config file" quit() try: let tomlEmailData = parsetoml.parseFile("/etc/goaccess-reporter/email.toml") tomlEmailTable = tomlEmailData.getTable() except TomlError: logMsg = nowDT & ": Unable to parse '/etc/goaccess-reporter/email.toml'" logger.log(lvlError, logMsg) echo "Error: unable to parse toml email config file" quit() type Site = object name, logFile, output: string appendDate, deleteAfter: bool emailAddresses: seq[string] type Email = object hostname, senderAddress, senderPassword: string starttlsPort: int var sites: seq[Site] var site: Site var email: Email var emailAddresses: seq[string] var logFile, output, outputPath, origOutputLocation, outputLocation, outputFilename: string var appendDate, deleteAfter: bool var emails: seq[TomlValueRef] var goaccessRun, tarRun: tuple[output: string, exitCode: int] for key, val in tomlEmailTable.pairs: if val.kind == TomlValueKind.Table: let tableName = key let table = val.getTable() try: email.hostname = table["hostname"].getStr() except KeyError: tomlErrors = true logKeyParseError("hostname", tableName, "email") try: email.starttlsPort = table["starttls-port"].getInt() except KeyError: tomlErrors = true logKeyParseError("starttls-port", tableName, "email") try: email.senderAddress = table["sender-address"].getStr() except KeyError: tomlErrors = true logKeyParseError("sender-address", tableName, "email") try: email.senderPassword = table["sender-password"].getStr() except KeyError: tomlErrors = true logKeyParseError("sender-password", tableName, "email") for key, val in tomlSitesTable.pairs: if val.kind == TomlValueKind.Table: let tableName = key site.name = tableName let table = val.getTable() try: logFile = table["log-file"].getStr() site.logFile = logFile except KeyError: tomlErrors = true logKeyParseError("log-file", tableName, "sites") try: output = table["output"].getStr() site.output = output except KeyError: tomlErrors = true logKeyParseError("output", tableName, "sites") try: appendDate = table["append-date"].getBool() site.appendDate = appendDate except KeyError: tomlErrors = true logKeyParseError("append-date", tableName, "sites") try: deleteAfter = table["delete-after"].getBool() site.deleteAfter = deleteAfter except KeyError: tomlErrors = true logKeyParseError("delete-after", tableName, "sites") try: emails = table["email-addresses"].getElems() for email in emails: emailAddresses.add($email) site.emailAddresses = emailAddresses except KeyError: tomlErrors = true logKeyParseError("email-addresses", tableName, "sites") sites.add(site) emailAddresses = @[] if not tomlErrors: outputPath = expandTilde("~/.goaccess-reporter/reports") for site in sites: if site.appendDate: origOutputLocation = expandTilde("~/.goaccess-reporter/reports/" & site.name & "-report-" & nowDTNoSpaces & ".html") outputFilename = site.name & "-report-" & nowDTNoSpaces & ".html" else: origOutputLocation = expandTilde("~/.goaccess-reporter/reports/" & site.name & "-report.html") outputFilename = site.name & "-report.html" goaccessRun = execCmdEx( "goaccess " & site.logFile & " -o " & origOutputLocation & " --geoip-database=/var/www/goaccess-geolite2-city.mmdb") if goaccessRun.exitCode == 1: echo goaccessRun.output logMsg = goaccessRun.output logger.log(lvlError, logMsg) quit() tarRun = execCmdEx("tar -zcf " & outputPath & "/" & outputFilename.changeFileExt("tar.gz") & " -C " & outputPath & " " & outputFilename) if tarRun.exitCode == 1: echo tarRun.output logMsg = tarRun.output logger.log(lvlError, logMsg) quit() else: outputLocation = origOutputLocation.changeFileExt("tar.gz") outputFilename = outputFilename.changeFileExt("tar.gz") #send the reports via email. Using the mime module for sending with attachment, so some things are different from using smtp only. var tarFile = newAttachment(readFile(outputLocation), filename = outputFilename) tarFile.encodeBase64() var multi = newMimeMessage() # Main email data multi.body = "I have no idea what goes here. a message that their client is not compat?" multi.header["bcc"] = site.emailAddresses.mimeList multi.header["from"] = email.senderAddress multi.header["subject"] = "GoAccess/SEO Report for " & site.name # Add text to email body var first = newMimeMessage() first.header["Content-Type"] = "text/plain" first.body = "Please see attached SEO/GoAccess report." multi.parts.add first multi.parts.add tarFile let smtpConn = newSmtp(debug=false) smtpConn.connect(email.hostname, Port email.starttlsPort) smtpConn.startTls() smtpConn.auth(email.senderAddress, email.senderPassword) smtpConn.sendmail(email.hostname, site.emailAddresses, $multi.finalize()) smtpConn.close() if site.deleteAfter: removeFile(origOutputLocation) removeFile(outputLocation) else: echo "Errors in toml config file. Please see '~/.goaccess-reporter/goaccess-reporter.log'" quit()