]> sipb.mit.edu Git - ikiwiki.git/blob - IkiWiki/Plugin/notifyemail.pm
c345e4365dc0155446885b57d2dd4b896878ac34
[ikiwiki.git] / IkiWiki / Plugin / notifyemail.pm
1 #!/usr/bin/perl
2 package IkiWiki::Plugin::notifyemail;
3
4 use warnings;
5 use strict;
6 use IkiWiki 3.00;
7
8 sub import {
9         hook(type => "formbuilder_setup", id => "notifyemail", call => \&formbuilder_setup);
10         hook(type => "formbuilder", id => "notifyemail", call => \&formbuilder);
11         hook(type => "getsetup", id => "notifyemail",  call => \&getsetup);
12         hook(type => "changes", id => "notifyemail", call => \&notify);
13 }
14
15 sub getsetup () {
16         return
17                 plugin => {
18                         safe => 1,
19                         rebuild => 0,
20                 },
21 }
22
23 sub formbuilder_setup (@) {
24         my %params=@_;
25
26         my $form=$params{form};
27         return unless $form->title eq "preferences";
28         my $session=$params{session};
29         $form->field(name => "subscriptions", size => 50,
30                 fieldset => "preferences",
31                 comment => "(".htmllink("", "", "ikiwiki/PageSpec", noimageinline => 1).")",
32                 value => getsubscriptions($session->param("name")));
33 }
34
35 sub formbuilder (@) {
36         my %params=@_;
37         my $form=$params{form};
38         return unless $form->title eq "preferences" &&
39                 $form->submitted eq "Save Preferences" && $form->validate &&
40                 defined $form->field("subscriptions");
41         setsubscriptions($form->field('name'), $form->field('subscriptions'));
42 }
43
44 sub getsubscriptions ($) {
45         my $user=shift;
46         eval q{use IkiWiki::UserInfo};
47         error $@ if $@;
48         IkiWiki::userinfo_get($user, "subscriptions");
49 }
50
51 sub setsubscriptions ($$) {
52         my $user=shift;
53         my $subscriptions=shift;
54         eval q{use IkiWiki::UserInfo};
55         error $@ if $@;
56         IkiWiki::userinfo_set($user, "subscriptions", $subscriptions);
57 }
58
59 # Called by other plugins to subscribe the user to a pagespec.
60 sub subscribe ($$) {
61         my $user=shift;
62         my $addpagespec=shift;
63         my $pagespec=getsubscriptions($user);
64         setsubscriptions($user, $pagespec." or ".$addpagespec);
65 }
66
67 sub notify (@) {
68         my @files=@_;
69         return unless @files;
70
71         eval q{use Mail::Sendmail};
72         error $@ if $@;
73         eval q{use IkiWiki::UserInfo};
74         error $@ if $@;
75         eval q{use URI};
76         error($@) if $@;
77
78         # Daemonize, in case the mail sending takes a while.
79         defined(my $pid = fork) or error("Can't fork: $!");
80         return if $pid; # parent
81         chdir '/';
82         open STDIN, '/dev/null';
83         open STDOUT, '>/dev/null';
84         POSIX::setsid() or error("Can't start a new session: $!");
85         open STDERR, '>&STDOUT' or error("Can't dup stdout: $!");
86
87         # Don't need to keep a lock on the wiki as a daemon.
88         IkiWiki::unlockwiki();
89
90         my $userinfo=IkiWiki::userinfo_retrieve();
91         exit 0 unless defined $userinfo;
92
93         foreach my $user (keys %$userinfo) {
94                 my $pagespec=$userinfo->{$user}->{"subscriptions"};
95                 next unless defined $pagespec && length $pagespec;
96                 my $email=$userinfo->{$user}->{email};
97                 next unless defined $email && length $email;
98
99                 foreach my $file (@files) {
100                         my $page=pagename($file);
101                         next unless pagespec_match($page, $pagespec);
102                         my $content="";
103                         my $showcontent=defined pagetype($file);
104                         if ($showcontent) {
105                                 $content=eval { readfile(srcfile($file)) };
106                                 $showcontent=0 if $@;
107                         }
108                         my $url;
109                         if (! IkiWiki::isinternal($page)) {
110                                 $url=urlto($page, undef, 1);
111                         }
112                         elsif (defined $pagestate{$page}{meta}{permalink}) {
113                                 # need to use permalink for an internal page
114                                 $url=URI->new_abs($pagestate{$page}{meta}{permalink}, $config{url});
115                         }
116                         else {
117                                 $url=$config{url}; # crummy fallback url
118                         }
119                         my $pagedesc=$page;
120                         if (defined $pagestate{$page}{meta}{title} &&
121                             length $pagestate{$page}{meta}{title}) {
122                                 $pagedesc=qq{"$pagestate{$page}{meta}{title}"};
123                         }
124                         my $subject=gettext("change notification:")." ".$pagedesc;
125                         if (pagetype($file) eq '_comment') {
126                                 $subject=gettext("comment notification:")." ".$pagedesc;
127                         }
128                         my $template=template("notifyemail.tmpl");
129                         $template->param(
130                                 wikiname => $config{wikiname},
131                                 url => $url,
132                                 prefsurl => $config{cgiurl}."?do=prefs",
133                                 showcontent => $showcontent,
134                                 content => $content,
135                         );
136                         sendmail(
137                                 To => $email,
138                                 From => "$config{wikiname} <$config{adminemail}>",
139                                 Subject => $subject,
140                                 Message => $template->output,
141                         );
142                 }
143         }
144
145         exit 0; # daemon child
146 }
147
148 1