1<?php
2
3class action_plugin_infomail extends DokuWiki_Action_Plugin
4{
5    /** @inheritdoc */
6    public function register(Doku_Event_Handler $controller)
7    {
8        // we handle AJAX and non AJAX requesat through the same handler
9        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleEvent');
10        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleEvent');
11        $controller->register_hook('TPL_ACT_UNKNOWN', 'BEFORE', $this, 'handleEvent');
12    }
13
14    /**
15     * @param Doku_Event $event
16     */
17    public function handleEvent(Doku_Event $event)
18    {
19        // the basic handling is the same for all events
20        // we either show the form or handle the post data
21
22        // FIXME change this into one string
23        if (!in_array($event->data, array('infomail', 'plugin_infomail'))) {
24            return;
25        }
26        $event->preventDefault();
27        // for this event we only signal, that we will handle this mode
28        if ($event->name === 'ACTION_ACT_PREPROCESS') {
29            return;
30        }
31        $event->stopPropagation();
32
33        global $INPUT;
34
35        // early output to trigger display msgs even via AJAX.
36        echo ' ';
37        tpl_flush();
38        if ($INPUT->server->str('REQUEST_METHOD') === 'POST') {
39            try {
40                $this->sendMail();
41                if ($event->name === 'AJAX_CALL_UNKNOWN') {
42                    $this->ajaxSuccess(); // To signal success to AJAX.
43                } else {
44                    msg($this->getLang('thanks'), 1);
45                }
46                return; // we're done here
47            } catch (\Exception $e) {
48                msg($e->getMessage(), -1);
49            }
50        }
51
52        echo $this->getForm();
53    }
54
55    /**
56     * Builds the Mail Form
57     */
58    protected function getForm()
59    {
60        global $INPUT;
61
62        /** @var helper_plugin_infomail $helper */
63        $helper = plugin_load('helper', 'infomail');
64
65        $id = getID(); // we may run in AJAX context
66        if ($id === '') throw new \RuntimeException('No ID given');
67
68        $form = new \dokuwiki\Form\Form([
69            'action' => wl($id, ['do' => 'infomail'], false, '&'),
70            'id' => 'infomail__plugin',
71        ]);
72        $form->setHiddenField('id', $id); // we need it for the ajax call
73
74        if ($INPUT->server->has('REMOTE_USER')) {
75            global $USERINFO;
76            $form->setHiddenField('s_name', $USERINFO['name']);
77            $form->setHiddenField('s_email', $USERINFO['mail']);
78        } else {
79            $form->addTextInput('s_name', $this->getLang('yourname'))->addClass('edit');
80            $form->addTextInput('s_email', $this->getLang('youremailaddress'))->addClass('edit');
81        }
82
83        //get default emails from config
84        $lists = explode('|', $this->getConf('default_recipient'));
85        $lists = array_filter($lists, 'mail_isvalid');
86        // get simple listfiles from pages and add them
87        $lists = array_merge($lists, $helper->getLists());
88
89        if ($lists) {
90            array_unshift($lists, ''); // add empty option
91            $form->addDropdown('r_predef', $lists, $this->getLang('bookmarks'));
92        }
93
94        $form->addTextInput('r_email', $this->getLang('recipients'))->addClass('edit');
95        $form->addTextInput('subject', $this->getLang('subject'))->addClass('edit');
96        $form->addTextarea('comment', $this->getLang('message'))->attr('rows', '8')->attr('cols', '10')->addClass('edit');
97
98        /** @var helper_plugin_captcha $captcha */
99        $captcha = plugin_load('helper', 'captcha');
100        if ($captcha) $form->addHTML($captcha->getHTML());
101
102        //$form->addCheckbox('archiveopt', $this->getLang('archive'))->addClass('edit');
103
104        $form->addTagOpen('div')->addClass('buttons');
105        $form->addButton('submit', $this->getLang('send_infomail'))->attr('type', 'submit');
106        $form->addButton('reset', $this->getLang('cancel_infomail'))->attr('type', 'reset');
107        $form->addTagClose('div');
108
109        return $form->toHTML();
110    }
111
112    /**
113     * Validate input and send mail if everything is ok
114     *
115     * @throws Exception when something went wrong
116     * @todo this method is still much too long
117     */
118    protected function sendMail()
119    {
120        global $conf;
121        global $INPUT;
122
123        /** @var helper_plugin_captcha $captcha */
124        $captcha = plugin_load('helper', 'captcha');
125        if ($captcha && !$captcha->check()) {
126            throw new \Exception('Wrong Captcha');
127        }
128
129        if (!checkSecurityToken()) {
130            throw new \Exception('Security token did not match');
131        }
132
133        /** @var helper_plugin_infomail $helper */
134        $helper = plugin_load('helper', 'infomail');
135
136        // Get recipients
137        $all_recipients = explode(' ', $INPUT->str('r_email'));
138        $bookmark = $INPUT->filter('trim')->str('r_predef');
139        if ($bookmark) {
140            // a bookmark may be a single address or a list
141            if (mail_isvalid($bookmark)) {
142                $all_recipients[] = $bookmark;
143            } else {
144                $all_recipients = array_merge($all_recipients, $helper->loadList($bookmark));
145            }
146        }
147        // clean up recipients
148        $all_recipients = array_map('trim', $all_recipients);
149        $all_recipients = array_map('strtolower', $all_recipients);
150        $all_recipients = array_filter($all_recipients, 'mail_isvalid');
151        $all_recipients = array_unique($all_recipients);
152        if (!$all_recipients) throw new \Exception($this->getLang('novalid_rec'));
153
154        // Sender name
155        $s_name = $INPUT->filter('trim')->str('s_name', $this->getConf('default_sender_displayname'));
156        if ($s_name === '') throw new \Exception($this->getLang('err_sendername'));
157
158        // Sender email
159        $s_email = $INPUT->filter('trim')->str('s_email', $this->getConf('default_sender'), true);
160        if (!mail_isvalid($s_email)) throw new \Exception($this->getLang('err_sendermail'));
161
162        // named Sender
163        $sender = "$s_name <$s_email>";
164
165        // the page ID
166        $id = $INPUT->filter('cleanID')->str('id');
167        if ($id === '' || !page_exists($id)) throw new \Exception($this->getLang('err_page'));
168
169        // comment
170        $comment = $INPUT->str('comment');
171
172        // shorturl hook
173        /** @var helper_plugin_shorturl $shorturl */
174        $shorturl = plugin_load('helper', 'shorturl');
175        if ($shorturl) {
176            $shortID = $shorturl->autoGenerateShortUrl($id);
177            $pageurl = wl($shortID, '', true, '&');
178        } else {
179            $pageurl = wl($id, '', true, '&');
180        }
181
182        // subject
183        $subject = $this->getConf('subjectprefix') . ' ' . $INPUT->str('subject');
184
185        // prepare replacements
186        $data = [
187            'NAME' => $INPUT->str('r_name'),
188            'PAGE' => $id,
189            'SITE' => $conf['title'],
190            'SUBJECT' => $subject,
191            'URL' => $pageurl,
192            'COMMENT' => $comment,
193            'AUTHOR' => $s_name,
194        ];
195
196        // get the text
197        $mailtext = $helper->loadTemplate();
198
199        // Send mail
200        $mailer = new Mailer();
201        $mailer->bcc($all_recipients);
202        $mailer->from($sender);
203        $mailer->subject($subject);
204        $mailer->setBody($mailtext, $data);
205        $mailer->send();
206
207        /* FIXME currently not implemented
208        if ($this->getConf('logmails')) {
209            $this->mail_log($recipient, $subject, $mailtext, $sender);
210        }
211
212        if ($archiveon) {
213            $this->mail_archive($all_recipients, $subject, $mailtext, $sender);
214        }
215        */
216    }
217
218    /**
219     * show success message in ajax mode
220     */
221    protected function ajaxSuccess()
222    {
223        echo '<form id="infomail_plugin" accept-charset="utf-8" method="post" action="?do=infomail">';
224        echo '<div class="no">';
225        echo '<span class="ui-icon ui-icon-circle-check" style="float: left; margin: 0 7px 50px 0;"></span>';
226        echo '<p>' . $this->getLang('thanks') . '</p>';
227        echo '<button type="reset" class="button">' . $this->getLang('close') . '</button>';
228        echo '</div>';
229        echo '</form>';
230    }
231
232    /*
233     * Logging infomails as Wikipages when configured so
234     *
235     * @todo currently not used, needs adjustment
236     */
237    protected function mail_archive($recipient, $subject, $mailtext, $sender)
238    {
239        global $conf;
240        $targetdir = $conf['cachedir'] . "/infomail-plugin/archive/";
241        if (!is_dir($targetdir)) {
242            mkdir($targetdir);
243        }
244
245        $t = time();
246        $date = strftime("%d.%m.%Y, %H:%M", $t);
247        $mailtext = "Von:   $sender\nAn:    $recipient\nDatum: $date\n\n" . $mailtext;
248
249        $filename = strftime("%Y%m%d%H%M%S", $t) . "_infomail.txt";
250        $archfile = $targetdir . $filename;
251        io_saveFile($archfile, "$mailtext\n", true);
252
253    }
254
255    /*
256     * Logging infomails as Wikipages when configured so
257     *
258     * @todo currently not used, needs adjustment
259     */
260    protected function mail_log($recipient, $subject, $mailtext, $sender)
261    {
262        global $conf;
263        $targetdir = $conf['cachedir'] . "/infomail-plugin/log/";
264        $logfile = $targetdir . "infomail.log";
265        if (!is_dir($targetdir)) {
266            mkdir($targetdir);
267        }
268
269        $t = time();
270        $log = $t . "\t" . strftime($conf['dformat'], $t) . "\t" . $_SERVER['REMOTE_ADDR'] . "\t" . $sender . "\t" . $recipient;
271        io_saveFile($logfile, "$log\n", true);
272
273    }
274
275}
276