diff options
author | Holger Weiss <holger@zedat.fu-berlin.de> | 2016-11-29 17:27:11 (GMT) |
---|---|---|
committer | Holger Weiss <holger@zedat.fu-berlin.de> | 2016-11-29 17:27:11 (GMT) |
commit | b92a28a5fe38436fecd20b32b2ba1e68521f6430 (patch) | |
tree | ed4ef1ad7125b31c8a3bfd8fbdb1656bc6c4e286 /libexec/filter-github-emails | |
parent | a0e978dc078a72b1224a011defd0d905e5062dc8 (diff) | |
download | site-b92a28a5fe38436fecd20b32b2ba1e68521f6430.tar.gz |
Remove Procmail filter for plugins@ address
We no longer forward GitHub notifications to the mailing list.
Diffstat (limited to 'libexec/filter-github-emails')
-rwxr-xr-x | libexec/filter-github-emails | 300 |
1 files changed, 0 insertions, 300 deletions
diff --git a/libexec/filter-github-emails b/libexec/filter-github-emails deleted file mode 100755 index 85ec1a3..0000000 --- a/libexec/filter-github-emails +++ /dev/null | |||
@@ -1,300 +0,0 @@ | |||
1 | #!/usr/bin/perl -T | ||
2 | # | ||
3 | # Copyright (c) 2014 Monitoring Plugins Development Team | ||
4 | # | ||
5 | # Originally written by Holger Weiss <holger@zedat.fu-berlin.de>. | ||
6 | # | ||
7 | # This program is free software; you may redistribute it and/or modify it under | ||
8 | # the same terms as Perl itself. | ||
9 | # | ||
10 | |||
11 | # | ||
12 | # This script receives GitHub email notifications and tries to distinguish | ||
13 | # actual user comments from mere status change reports, so that they can be | ||
14 | # filtered in different ways. While at it, the messages are also modified to | ||
15 | # make them suitable for being forwarded to a mailing list. | ||
16 | # | ||
17 | # Note: If you edit this script, make sure to never use die() or exit(). | ||
18 | # Instead, call the following subroutine: | ||
19 | # | ||
20 | # - panic($format, @args); | ||
21 | # Log an error message, print original message to standard output, exit | ||
22 | # non-zero. Note that panic() expects printf(3)-style arguments. Don't | ||
23 | # use variables within the format string (unless you're sure they will | ||
24 | # never contain format specifications). Add them to the @args instead. | ||
25 | # | ||
26 | # Exceptions raised by imported modules should be cought by our $SIG{__DIE__} | ||
27 | # handler. | ||
28 | # | ||
29 | # Also, never write output to STDERR. Instead, use one of the following | ||
30 | # subroutines in order to write messages to syslog: | ||
31 | # | ||
32 | # - debug($format, @args); | ||
33 | # Write a debug message to syslog, printf(3)-style. | ||
34 | # - info($format, @args); | ||
35 | # Write an informational message to syslog, printf(3)-style. | ||
36 | # - notice($format, @args); | ||
37 | # Write a notice to syslog, printf(3)-style. | ||
38 | # - warning($format, @args); | ||
39 | # Write a warning to syslog, printf(3)-style. | ||
40 | # - error($format, @args); | ||
41 | # Write an error to syslog, printf(3)-style. | ||
42 | # - critical($format, @args); | ||
43 | # Write a critical error to syslog, printf(3)-style. | ||
44 | # | ||
45 | |||
46 | use warnings; | ||
47 | use strict; | ||
48 | use Email::MIME; | ||
49 | use File::Basename; | ||
50 | use Sys::Syslog qw(:standard :macros); | ||
51 | use Text::Wrap; | ||
52 | |||
53 | use constant COMMENTS_TO => | ||
54 | 'Monitoring Plugins Development <devel@monitoring-plugins.org>'; | ||
55 | use constant STATUS_CHANGES_TO => | ||
56 | 'Monitoring Plugins Development <devel@monitoring-plugins.org>'; | ||
57 | use constant TIMEOUT => 15; | ||
58 | |||
59 | $ENV{PATH} = '/usr/bin:/bin'; | ||
60 | $" = ''; | ||
61 | |||
62 | # Lines will have a length of no more than $columns - 1. | ||
63 | $Text::Wrap::columns = 77; | ||
64 | $Text::Wrap::huge = 'overflow'; | ||
65 | |||
66 | setlogmask(LOG_UPTO(LOG_INFO)); | ||
67 | openlog(basename($0), 'pid', 'mail'); | ||
68 | |||
69 | $SIG{__WARN__} = sub { panic('Caught warning: %s', $_[0] || '(null)') }; | ||
70 | $SIG{__DIE__} = sub { panic('Caught exception: %s', $_[0] || '(null)') }; | ||
71 | $SIG{ALRM} = sub { panic('Timeout after %d seconds', TIMEOUT) }; | ||
72 | $SIG{HUP} = sub { panic('Caught SIGHUP') }; | ||
73 | $SIG{INT} = sub { panic('Caught SIGINT') }; | ||
74 | $SIG{PIPE} = sub { panic('Caught SIGPIPE') }; | ||
75 | $SIG{TERM} = sub { panic('Caught SIGTERM') }; | ||
76 | $SIG{USR1} = sub { panic('Caught SIGUSR1') }; | ||
77 | $SIG{USR2} = sub { panic('Caught SIGUSR2') }; | ||
78 | |||
79 | alarm(TIMEOUT); | ||
80 | |||
81 | my $MESSAGE_ID; | ||
82 | my @MESSAGE = <>; # The complete email message. | ||
83 | |||
84 | # | ||
85 | # Log and exit. | ||
86 | # | ||
87 | |||
88 | sub _report { | ||
89 | my ($level, $format, @args) = @_; | ||
90 | |||
91 | chomp(@args); | ||
92 | syslog($level, "$format (%s)", @args, $MESSAGE_ID || 'null'); | ||
93 | } | ||
94 | |||
95 | sub debug { _report(LOG_DEBUG, @_) } | ||
96 | sub info { _report(LOG_INFO, @_) } | ||
97 | sub notice { _report(LOG_NOTICE, @_) } | ||
98 | sub warning { _report(LOG_WARNING, @_) } | ||
99 | sub error { _report(LOG_ERR, @_) } | ||
100 | sub critical { _report(LOG_CRIT, @_) } | ||
101 | |||
102 | sub panic { | ||
103 | $SIG{$_} = 'DEFAULT' for keys %SIG; | ||
104 | critical(@_); | ||
105 | print @MESSAGE; | ||
106 | bye(1); | ||
107 | } | ||
108 | |||
109 | sub bye { | ||
110 | my $status = shift; | ||
111 | |||
112 | debug('Exiting with status %d', $status); | ||
113 | closelog; | ||
114 | exit($status); | ||
115 | } | ||
116 | |||
117 | # | ||
118 | # Wrap overlong lines. | ||
119 | # | ||
120 | |||
121 | sub rewrap { | ||
122 | my $wrap = sub { | ||
123 | my $line = shift; | ||
124 | my $indent; | ||
125 | |||
126 | if ($line =~ /^(?: {4}|\t)/) { | ||
127 | return $line; | ||
128 | } elsif (/^([> ]+)/) { | ||
129 | $indent = $1; | ||
130 | } else { | ||
131 | $indent = ''; | ||
132 | } | ||
133 | return wrap('', $indent, $line); | ||
134 | }; | ||
135 | my @lines = split(/\n/, shift); | ||
136 | my @wrapped = map { $wrap->($_) } @lines; | ||
137 | |||
138 | debug('Rewrapping text'); | ||
139 | return join("\n", @wrapped); | ||
140 | } | ||
141 | |||
142 | # | ||
143 | # Write the email to STDOUT. | ||
144 | # | ||
145 | sub print_email { | ||
146 | my $email = shift; | ||
147 | my $text = $email->as_string; | ||
148 | |||
149 | # Email::MIME sometimes prepends an empty line :-/ | ||
150 | $text =~ s/^[\r\n]+//; | ||
151 | print $email->as_string; | ||
152 | } | ||
153 | |||
154 | # | ||
155 | # Look up MIME parts. | ||
156 | # | ||
157 | |||
158 | sub get_part { | ||
159 | my ($email, $type) = @_; | ||
160 | |||
161 | debug('Searching for %s part in email', $type); | ||
162 | |||
163 | foreach my $part ($email->subparts) { | ||
164 | next if $part->subparts; | ||
165 | return $part if $part->content_type =~ /\Q$type\E/i; | ||
166 | } | ||
167 | panic('Cannot find %s part in email', $type); | ||
168 | } | ||
169 | |||
170 | # | ||
171 | # Edit a message. | ||
172 | # | ||
173 | |||
174 | sub edit_header { | ||
175 | my ($header, $recipient, $description) = @_; | ||
176 | |||
177 | debug('Editing header'); | ||
178 | |||
179 | $header->header_set('Lines'); | ||
180 | $header->header_set('Content-Length'); | ||
181 | $header->header_set('Reply-To'); # Remove GitHub's reply address. | ||
182 | $header->header_set('To' => $recipient); | ||
183 | $header->header_set('X-MP-Content' => $description); | ||
184 | |||
185 | # Strip the [monitoring-plugins] tag. | ||
186 | my $subject = $header->header('Subject'); | ||
187 | $subject =~ s/^\[monitoring-plugins\] (.+)/$1/; | ||
188 | $subject =~ s/^Re: \[monitoring-plugins\] (.+)/Re: $1/; | ||
189 | $header->header_set('Subject' => $subject); | ||
190 | |||
191 | return $header; | ||
192 | } | ||
193 | |||
194 | sub edit_text_body { | ||
195 | my $body = shift; | ||
196 | my ($s, $r); | ||
197 | |||
198 | debug('Editing text/plain body'); | ||
199 | |||
200 | $body = rewrap($body); # While at it, wrap overlong lines. | ||
201 | |||
202 | $s = "\n---\nReply to this email directly or view it on GitHub:"; | ||
203 | $r = "\n-- \nReply to this email on GitHub:"; | ||
204 | $body =~ s/$s/$r/; | ||
205 | |||
206 | return $body; | ||
207 | } | ||
208 | |||
209 | sub edit_html_body { | ||
210 | my $body = shift; | ||
211 | my ($s, $r); | ||
212 | |||
213 | debug('Editing text/html body'); | ||
214 | |||
215 | $s = 'Reply to this email directly or '; | ||
216 | $r = ''; | ||
217 | $body =~ s/$s/$r/; | ||
218 | |||
219 | $s = 'view it on GitHub'; | ||
220 | $r = 'Reply to this email on GitHub'; | ||
221 | $body =~ s/$s/$r/; | ||
222 | |||
223 | return $body; | ||
224 | } | ||
225 | |||
226 | # | ||
227 | # Check message type. | ||
228 | # | ||
229 | |||
230 | sub is_github_mail { | ||
231 | my $email = shift; | ||
232 | |||
233 | return $email->subparts == 2 | ||
234 | and defined($email->header('From')) | ||
235 | and defined($email->header('X-GitHub-Recipient')) | ||
236 | and index($email->header('From'), 'notifications@github.com') != -1 | ||
237 | and $email->header('X-GitHub-Recipient') eq 'monitoring-user'; | ||
238 | } | ||
239 | |||
240 | sub is_github_status_change { | ||
241 | my $email = shift; | ||
242 | my $body = get_part($email, 'text/plain')->body_str; | ||
243 | |||
244 | if ($body =~ tr/\n// == 5) { | ||
245 | return 1 if $body =~ /^(?:Closed|Reopened) #\d+\.$/m; | ||
246 | return 1 if $body =~ /^Closed #\d+ via [0-9a-f]{40}\.$/m; | ||
247 | } | ||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | # | ||
252 | # Handle message type. | ||
253 | # | ||
254 | |||
255 | sub handle_github_mail { | ||
256 | my $email = shift; | ||
257 | my $text = get_part($email, 'text/plain'); | ||
258 | my $html = get_part($email, 'text/html'); | ||
259 | my $text_body = $text->body_str; | ||
260 | my $html_body = $html->body_str; | ||
261 | |||
262 | $text->body_str_set(edit_text_body($text_body)); | ||
263 | $html->body_str_set(edit_html_body($html_body)); | ||
264 | $email->parts_set([$text, $html]); | ||
265 | |||
266 | if (is_github_status_change($email)) { | ||
267 | info('Received a GitHub status change'); | ||
268 | $email->header_obj_set(edit_header($email->header_obj, | ||
269 | STATUS_CHANGES_TO, 'GitHub status change')); | ||
270 | } else { | ||
271 | info('Received a GitHub comment'); | ||
272 | $email->header_obj_set(edit_header($email->header_obj, | ||
273 | COMMENTS_TO, 'GitHub comment')); | ||
274 | } | ||
275 | print_email($email); | ||
276 | } | ||
277 | |||
278 | sub handle_non_github_mail { | ||
279 | my $email = shift; | ||
280 | |||
281 | notice('Received a non-GitHub message'); | ||
282 | # Just spit out the email as-is. | ||
283 | print_email($email); | ||
284 | } | ||
285 | |||
286 | # | ||
287 | # Action! | ||
288 | # | ||
289 | |||
290 | my $email = Email::MIME->new("@MESSAGE"); | ||
291 | |||
292 | $MESSAGE_ID = $email->header('Message-ID') || '(null)'; | ||
293 | $email->header_set('X-MP-Filter' => basename($0)); | ||
294 | |||
295 | if (is_github_mail($email)) { | ||
296 | handle_github_mail($email); | ||
297 | } else { | ||
298 | handle_non_github_mail($email); | ||
299 | } | ||
300 | bye(0); | ||