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