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