1 | <?php |
---|
2 | |
---|
3 | /** |
---|
4 | * New generic formmailer for technikum29 infrastructure |
---|
5 | **/ |
---|
6 | |
---|
7 | $maillib = dirname(__FILE__); |
---|
8 | require "$maillib/recaptchalib.php"; |
---|
9 | |
---|
10 | $key_file = "$maillib/recaptcha_keys.php"; |
---|
11 | $recaptcha_keys_loaded = null; |
---|
12 | if(file_exists($key_file)) { |
---|
13 | include $key_file; |
---|
14 | // now in global scope: |
---|
15 | // $publickey, recaptcha_get_answer, recaptcha_get_html etc. |
---|
16 | $recaptcha_keys_loaded = true; |
---|
17 | } else |
---|
18 | $recaptcha_keys_loaded = false; |
---|
19 | |
---|
20 | // This script can be used as standalone or libary. |
---|
21 | if(realpath($_SERVER['SCRIPT_FILENAME']) == __FILE__) { |
---|
22 | $mailer = new t29Mailer($_REQUEST); |
---|
23 | $mailer->run(); |
---|
24 | } |
---|
25 | |
---|
26 | class t29Mailer { |
---|
27 | function print_usage() { |
---|
28 | // problem: vars kriegt man nicht global, require include raum auch nicht global. |
---|
29 | // bad design. |
---|
30 | /*global $seiten_id, $version, $titel, $dynamischer_inhalt, $lib; |
---|
31 | $seiten_id = 'mailer'; |
---|
32 | $version = '$Id$'; |
---|
33 | $titel = "t29v6 form mailer usage"; |
---|
34 | $dynamischer_inhalt = true; |
---|
35 | |
---|
36 | $lib = "./"; |
---|
37 | require "$lib/technikum29.php";*/ |
---|
38 | ?> |
---|
39 | <html> |
---|
40 | <h2>Usage</h2> |
---|
41 | |
---|
42 | <p>This small mail system is capable of: |
---|
43 | |
---|
44 | <ul> |
---|
45 | <li>Mail to upstream and acknowledgement mail back to sender |
---|
46 | <li>Template based or individual output page with arguments |
---|
47 | </ul> |
---|
48 | |
---|
49 | |
---|
50 | <h3>Get or Post variables</h3> |
---|
51 | <table> |
---|
52 | <tr><th>name <th>default value <th>interpretation |
---|
53 | <tr><th>to <td>sven <td>one e-mail prefix, will be used with <tt>@technikum29.de</tt>, |
---|
54 | so mail goes to e.g. <tt>thevalue@technikum29.de</tt>. |
---|
55 | <tr><th>subject <td> <td>Subject of the mail. Can contain template variables like {foo}, where foo is some other |
---|
56 | variable. |
---|
57 | <tr><th>body<td> <td>Body of the mail. Can contain template variables. |
---|
58 | |
---|
59 | |
---|
60 | <tr><th>ack <td>false/no <td>Give true/yes for sending an ack mail. |
---|
61 | <tr><th>ack_to <td> <td>Target adress to send acknowledgement mail to. Can contain template variables like {data_sender_mail}. |
---|
62 | <tr><th>ack_subject <td> <td>Like subject, but for ack mail. |
---|
63 | <tr><th>ack_body <td> <td>Like body. |
---|
64 | |
---|
65 | |
---|
66 | </table> |
---|
67 | |
---|
68 | <?php } // end of method print_usage() |
---|
69 | |
---|
70 | // the small data holding architecture |
---|
71 | public $_values; |
---|
72 | // Security: Captcha checking not on $_values basis since that is regularily provided by |
---|
73 | // POST or REQUEST data which are directly given by user => spambots could disable captcha check |
---|
74 | public $enable_captcha_check = true; |
---|
75 | |
---|
76 | function __construct(Array $data=array()) { |
---|
77 | // default values |
---|
78 | $default_values = array( |
---|
79 | "to" => "sven", |
---|
80 | "subject" => "technikum29 form mailer", |
---|
81 | "body" => null, |
---|
82 | "ack" => false, |
---|
83 | |
---|
84 | 'header' => null, // has to be array |
---|
85 | |
---|
86 | "output_success_page" => '<html><h2>Mail successfully sent</h2><p>Thank you for your mail.</p>', |
---|
87 | "output_error_page" => function($mailer, $error) { |
---|
88 | ?><html> |
---|
89 | <h1>Errors in mail</h1> |
---|
90 | <form method="POST"> |
---|
91 | <p>Please fill out this captcha to send the mail. We don't like spam:</p> |
---|
92 | <?php $mailer->print_serialized_hidden_form(); ?> |
---|
93 | <?php echo $error; ?> |
---|
94 | <input type="submit" value="Yes I am human"> |
---|
95 | </form><?php |
---|
96 | }, |
---|
97 | |
---|
98 | "mail_info_append_text" => function($mailer) { |
---|
99 | $time = date('r'); |
---|
100 | $ret = <<<EOT |
---|
101 | |
---|
102 | Diese Mail wurde mit einem der technikum29 Web-Form-Mailer geschickt, |
---|
103 | und zwar dem t29v6-NG Formmailer. Ein Besucher hat also auf einer Webseite |
---|
104 | im technikum29.de-Angebot ein Formular ausgefüllt und daraufhin wurde |
---|
105 | diese Mail verschickt. |
---|
106 | |
---|
107 | Adresse wo Benutzer herkam: $_SERVER[HTTP_REFERER] |
---|
108 | Zeit, zu der der Besucher die Mail verschickte: $time |
---|
109 | Browser des Benutzers (User-Agent): $_SERVER[HTTP_USER_AGENT] |
---|
110 | IP-Adresse des Besuchers: $_SERVER[REMOTE_ADDR] |
---|
111 | |
---|
112 | EOT; |
---|
113 | |
---|
114 | if($mailer->ack) $ret .= <<<EOT1 |
---|
115 | |
---|
116 | Der Besucher bekam dafür eine Bestätigungsmail an die Adresse |
---|
117 | {$mailer->ack_to} . |
---|
118 | |
---|
119 | EOT1; |
---|
120 | return $ret; }, |
---|
121 | |
---|
122 | "recaptcha_challenge_field" => false, |
---|
123 | "recaptcha_response_field" => false |
---|
124 | ); // end of default values |
---|
125 | |
---|
126 | // merge given values |
---|
127 | $this->_values = array_merge($default_values, $data); |
---|
128 | } // end of constructor |
---|
129 | |
---|
130 | |
---|
131 | public function __set($property, $value){ |
---|
132 | return $this->_values[$property] = $value; |
---|
133 | } |
---|
134 | |
---|
135 | public function __get($property){ |
---|
136 | return array_key_exists($property, $this->_values) |
---|
137 | ? $this->_values[$property] |
---|
138 | #: #(array_key_exists($property, $this->default_values) |
---|
139 | # ? $this->default_values[$property] |
---|
140 | : null; |
---|
141 | } |
---|
142 | public function __isset($property) { |
---|
143 | return isset($this->$property) || isset($this->_values[$property]); # || isset($this->default_values[$property]); |
---|
144 | } |
---|
145 | |
---|
146 | // the system |
---|
147 | public function run() { |
---|
148 | global $recaptcha_keys_loaded; |
---|
149 | |
---|
150 | if(empty($this->_values)) { |
---|
151 | $this->print_usage(); |
---|
152 | return; |
---|
153 | } |
---|
154 | |
---|
155 | // check captcha and check presence of important field |
---|
156 | if(!$this->to || !$this->body) { |
---|
157 | // bubu |
---|
158 | } |
---|
159 | |
---|
160 | // show captcha validation, if neccessary |
---|
161 | if($recaptcha_keys_loaded && $this->enable_captcha_check && !$this->check_captcha()) { |
---|
162 | return false; |
---|
163 | } |
---|
164 | |
---|
165 | // send the ACK mail, if appropriate |
---|
166 | if($this->ack) { |
---|
167 | $this->ack_to = $this->call_or_return_callback('ack_to'); |
---|
168 | $this->ack_subject = $this->call_or_return_callback('ack_subject'); |
---|
169 | $this->ack_body = $this->call_or_return_callback('ack_body'); |
---|
170 | $this->send_mail($this->ack_to, $this->ack_subject, $this->ack_body); |
---|
171 | } |
---|
172 | |
---|
173 | // send the mail to t29 |
---|
174 | $this->to .= '@technikum29.de'; |
---|
175 | $this->body = $this->call_or_return_callback('body'); |
---|
176 | $this->body .= $this->call_or_return_callback('mail_info_append_text'); |
---|
177 | $this->subject = $this->call_or_return_callback('subject'); |
---|
178 | $this->send_mail($this->to, $this->subject, $this->body); |
---|
179 | |
---|
180 | // show output page |
---|
181 | $this->show_output_page('success'); |
---|
182 | |
---|
183 | return true; |
---|
184 | } |
---|
185 | |
---|
186 | public function send_mail($to, $subject, $message_body) { |
---|
187 | // compose the header |
---|
188 | $header = is_array($this->header) ? $this->header : array(); |
---|
189 | $testset = function($k, $v) use(&$header) { if(!isset($header[$k])) $header[$k] = $v; }; |
---|
190 | |
---|
191 | $testset('Content-Type', 'text/plain; charset=UTF-8'); // all t29v6 is utf-8 based! |
---|
192 | $testset('From', 'technikum29 Computer Musem Webmailer <www@technikum29.de>'); |
---|
193 | |
---|
194 | $additional_headers = join("\r\n", array_map(function($k) use(&$header) { return "$k: ".$header[$k]; }, array_keys($header))); |
---|
195 | |
---|
196 | // debug output |
---|
197 | $debug_mail = function($t, $s, $m, $a) { |
---|
198 | print "<div class='hidden'>"; |
---|
199 | print "<h2>Debug Mail Output</h2>"; |
---|
200 | print "<dl><dt>To<dd>$t <dt>Subject <dd>$s <dt>Message <dd><pre>$m</pre> <dt>Add. Headers <dd><pre>$a</pre></dl>"; |
---|
201 | print "</div>"; |
---|
202 | }; |
---|
203 | |
---|
204 | $debug_mail($to, $subject, $message_body, $additional_headers); |
---|
205 | mail($to, $subject, $message_body, $additional_headers); |
---|
206 | } |
---|
207 | |
---|
208 | |
---|
209 | public static function recaptcha_get_publickey() { |
---|
210 | global $publickey; |
---|
211 | return $publickey; |
---|
212 | } |
---|
213 | public static function recaptcha_get_html() { |
---|
214 | global $publickey; |
---|
215 | if ($publickey == null || $publickey == '') { |
---|
216 | // recaptcha_get_html wirft sonst ein die(). |
---|
217 | return '<b>t29Error: Recaptcha Publickey not loaded!</b>'; |
---|
218 | } |
---|
219 | return recaptcha_get_html($publickey); |
---|
220 | } |
---|
221 | |
---|
222 | public function print_serialized_hidden_form() { |
---|
223 | // serialize obect to hidden form elements |
---|
224 | foreach($this->_values as $k => $v) { |
---|
225 | if(!is_string($v)) continue; |
---|
226 | printf("\t<input type='hidden' name='%s' value='%s'>\n", $k, htmlentities($v, ENT_QUOTES | ENT_HTML401)); |
---|
227 | } |
---|
228 | } |
---|
229 | |
---|
230 | public function call_or_return_callback($property, $additional_argument=null) { |
---|
231 | if(!isset($this->_values[$property])) |
---|
232 | return null; |
---|
233 | if(is_callable($this->_values[$property])) { |
---|
234 | return call_user_func($this->_values[$property], $this, $additional_argument); |
---|
235 | } |
---|
236 | elseif(is_string($this->_values[$property])) { |
---|
237 | // make string replacements |
---|
238 | $mailer = $this; // PHP 5.3 convenience |
---|
239 | return preg_replace_callback("/\{([^}]+)\}/", function($match) use ($mailer) { |
---|
240 | $identifier = $match[1]; |
---|
241 | return isset($mailer->_values[$identifier]) |
---|
242 | ? $mailer->_values[$identifier] |
---|
243 | : "{?$identifier?}"; |
---|
244 | }, $this->_values[$property]); |
---|
245 | } |
---|
246 | |
---|
247 | } |
---|
248 | |
---|
249 | public function call_or_print_callback($property, $additional_argument=null) { |
---|
250 | $ret = $this->call_or_return_callback($property, $additional_argument); |
---|
251 | if($ret != null) print $ret; |
---|
252 | return true; |
---|
253 | } |
---|
254 | |
---|
255 | public function show_output_page($type, $additional_argument=null) { |
---|
256 | $id = "output_${type}_page"; |
---|
257 | $this->call_or_print_callback($id, $additional_argument); |
---|
258 | } |
---|
259 | |
---|
260 | |
---|
261 | /** |
---|
262 | * Check the Recaptcha challenge status and display an error page if |
---|
263 | * neccessary |
---|
264 | **/ |
---|
265 | public function check_captcha() { |
---|
266 | global $publickey; |
---|
267 | $resp = $this->check_captcha_answer(); |
---|
268 | |
---|
269 | if($resp === null) { |
---|
270 | $page = recaptcha_get_html($publickey); |
---|
271 | $this->show_output_page('error', $page); |
---|
272 | return false; |
---|
273 | } else if(!$resp->is_valid) { |
---|
274 | // display page |
---|
275 | $page = recaptcha_get_html($publickey, $resp->error); |
---|
276 | $this->show_output_page('error', $page); |
---|
277 | return false; |
---|
278 | } else { |
---|
279 | // valid answer |
---|
280 | return true; |
---|
281 | } |
---|
282 | } |
---|
283 | |
---|
284 | /** |
---|
285 | * Check the Captcha challenge field. |
---|
286 | * Return value is a Response object which basically allows to |
---|
287 | * differ three states: |
---|
288 | * $ret == null => no challenge answer present |
---|
289 | * $ret->is_valid == true => captcha answered valid (human detected) |
---|
290 | * $ret->is_valud == false => captcha answered false (no human detected) |
---|
291 | * |
---|
292 | * You can use $ret->error for a further call of |
---|
293 | * recaptcha_get_html($publickey, $ret->error); |
---|
294 | * |
---|
295 | * @returns librecaptcha Result object |
---|
296 | **/ |
---|
297 | public function check_captcha_answer() { |
---|
298 | global $publickey, $privatekey; |
---|
299 | |
---|
300 | # the response from reCAPTCHA |
---|
301 | $resp = null; |
---|
302 | # the error code from reCAPTCHA, if any |
---|
303 | $error = null; |
---|
304 | # display captcha? default: yes! |
---|
305 | $display_captcha = true; |
---|
306 | |
---|
307 | if(!$this->recaptcha_challenge_field || !$this->recaptcha_response_field) |
---|
308 | return null; |
---|
309 | |
---|
310 | $resp = recaptcha_check_answer ($privatekey, |
---|
311 | $_SERVER["REMOTE_ADDR"], |
---|
312 | $this->recaptcha_challenge_field, |
---|
313 | $this->recaptcha_response_field); |
---|
314 | return $resp; |
---|
315 | } |
---|
316 | } // end of class t29Mailer |
---|