Check-in [b484b5bc12]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add script for sending emails
Timelines: family | ancestors | trunk
Files: files | file ages | folders
SHA1: b484b5bc12d6ab2220063bf57155776914b3bda7
User & Date: rkeene 2024-12-12 01:23:27
Context
2024-12-12
01:23
Add script for sending emails Leaf check-in: b484b5bc12 user: rkeene tags: trunk
2024-10-14
14:06
Upgrade to latest version of Fossil check-in: 897ed7c4b4 user: rkeene tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added scripts/fossil-send-email.































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/env tclsh
#
# Monitor the database file named by the DBFILE variable
# looking for email messages sent by Fossil.  Forward each
# to /usr/sbin/sendmail.
#

set PIPE "sendmail -ti"
set MAINDB "/home/chiselapp/mail.db"

package require sqlite3

proc uuid {} {
	return [exec uuidgen -r]
}

proc log {level message} {
	catch {
		set fd [open /var/log/fossil-send-mail.log a+]
		puts $fd "[clock format [clock seconds]] $level $message"
	}
	catch {
		close $fd
	}
}

proc debug_log {msg} {
	log debug $msg
}

proc error_log {msg} {
	log error $msg
}

proc process_user_file {dbfile user maindb} {
	sqlite3 db $dbfile

	set added_rows [list]
	try {
		db timeout 60000
		catch {
			db eval {PRAGMA journal_mode=WAL}
		}

		db transaction immediate {
			set to_delete [list]
			db eval {SELECT emailid, msg FROM email} row {
				set emailid [uuid]
				set msg $row(msg)

				debug_log "Copying $user:$row(emailid) -> maindb:$emailid"
				$maindb eval {INSERT INTO email (emailid, user, msg, sent) VALUES ($emailid, $user, $msg, 0);}

				lappend to_delete $row(emailid)
				lappend added_rows $emailid
			}

			foreach emailid $to_delete {
				db eval {DELETE FROM email WHERE emailid = $emailid}
			}
		}
	} on error {} {
		foreach emailid $added_rows {
			$maindb eval {DELETE FROM email WHERE emailid = $emailid}
		}
	} finally {
		db close
	}
}

proc sanitize_message {msg} {
	set msg [regsub -all -line {^From: .*$} $msg "From: ChiselApp.com <noreply@chiselapp.com>"]
	return $msg
}

proc process_file {maindb} {
	set to_mark_error [list]
	set to_delete [list]

	try {
		$maindb transaction immediate {
			$maindb eval {SELECT emailid, user, msg FROM email WHERE sent = 0} row {
				debug_log "Processing $row(emailid):$row(user)..."

				set msg [sanitize_message $row(msg)]

				lappend to_delete $row(emailid)

				if {[catch {
					set out [open |$::PIPE w]
					puts -nonewline $out $msg
					close $out
				} err]} {
					error_log "Error: $err $row(user):$row(emailid)"

					lappend to_mark_error $row(emailid) $err
				}
			}
		}
	} finally {
		$maindb transaction immediate {
			foreach {emailid err} $to_mark_error {
				$maindb eval {UPDATE email SET send_error = $err WHERE emailid = $emailid}
			}

			foreach {emailid} $to_delete {
				$maindb eval {UPDATE email SET sent = 1 WHERE emailid = $emailid}
			}
		}
	}
}

proc main {} {
	sqlite3 maindb $::MAINDB
	maindb timeout 60000
	maindb eval {CREATE TABLE IF NOT EXISTS email (emailid PRIMARY KEY, user NOT NULL, msg NOT NULL, send_error, sent BOOLEAN NOT NULL)}
	maindb eval {CREATE INDEX IF NOT EXISTS emailBySent ON email (sent)}
	catch {
		maindb eval {PRAGMA journal_mode=WAL}
	}

	while 1 {
		maindb transaction {
			foreach dbfile [glob -nocomplain /home/chiselapp/www/repos/*/data/mail.sql] {
				set user [lindex [split $dbfile /] end-2]

				if {[catch {
					process_user_file $dbfile $user maindb
				} err]} {
					error_Log "Error processing $dbfile: $err"
				}
			}
		}

		catch {
			process_file maindb
		}

		after 10000
	}
}

main