1 <?php
3 class goMailServer extends goService{
5 var $cli_summary = "This pluign is used within the ServerService Pluign \nand indicates that this server supports mailqueue listings and so on.";
6 var $cli_description = "Some longer text\nfor help";
7 var $cli_parameters = array("eins" => "Eins ist toll", "zwei" => "Zwei ist noch besser");
9 /* This plugin only writes its objectClass */
10 var $objectclasses = array("goMailServer");
12 /* This class can't be assigned twice so it conflicts with itsself */
13 var $DisplayName = "";
14 var $dn = NULL;
15 var $StatusFlag = "goMailServerStatus";
16 var $attributes = array("description","postfixHeaderSizeLimit",
17 "postfixMailboxSizeLimit","postfixMessageSizeLimit",
18 "postfixMyDestinations","postfixMyDomain","postfixMyhostname",
19 "postfixMyNetworks","postfixRelayhost","postfixTransportTable",
20 "postfixSenderRestrictions","postfixRecipientRestrictions");
22 var $goMailServerStatus ;
23 var $postfixHeaderSizeLimit = 0;
24 var $postfixMailboxSizeLimit = 0;
25 var $postfixMessageSizeLimit = 0;
26 var $postfixMyDestinations = array();
27 var $postfixMyDomain = "";
28 var $postfixMyhostname = "";
29 var $postfixMyNetworks = array();
30 var $postfixRelayhost = "";
31 var $postfixTransportTable = array();
32 var $postfixSenderRestrictions = array();
33 var $postfixRecipientRestrictions = array();
34 var $description = "";
35 var $RestrictionFilters = array();
36 var $TransportProtocols = array();
37 var $Actions = array();
38 var $cn = "";
39 var $conflicts = array("goMailServer","kolab");
40 var $view_logged =FALSE;
42 function goMailServer(&$config,$dn)
43 {
44 goService::goService($config,$dn);
45 $this->DisplayName = _("Mail smtp service (Postfix)");
47 $this->Actions = array( SERVICE_STOPPED=>SERVICE_STOPPED,
48 SERVICE_STARTED => SERVICE_STARTED,
49 SERVICE_RESTARTED=>SERVICE_RESTARTED);
51 /* Fill RestrictionFilters TransportProtocols from external hooks */
52 $str = $this->config->data['TABS']['SERVERSERVICE'];
53 $this->TransportProtocols =array("smtp"=>"SMTP");
54 $this->RestrictionFilters = array("FILTER"=>"FILTER");
55 foreach(
56 array(
57 "postfixRestrictionFilters"=>"RestrictionFilters",
58 "postfixProtocols" =>"TransportProtocols")
59 as $file => $var){
60 if($this->config->get_cfg_value("goMailServer",$file) != ""){
61 $file = $this->config->get_cfg_value("goMailServer",$file);
62 if((isset($file)) && is_readable($file)){
63 $tmp = file_get_contents($file);
64 $tmp2= preg_split("/\n/",$tmp);
65 foreach($tmp2 as $entry){
66 if(empty($entry)) continue;
67 if(preg_match("/:/",$entry)){
68 $tmp3 = explode(":",$entry);
69 $r = $this->$var;
70 $r[$tmp3[0]]=$tmp3[1];
71 $this->$var = $r;
72 }else{
73 $r = $this->$var;
74 $r[$entry] =$entry;
75 $this->$var = $r;
76 }
77 }
78 }
79 }
80 }
83 /* Get postfix my networks */
84 $this->postfixMyNetworks = array();
85 $tmp = array();
86 if(isset($this->attrs['postfixMyNetworks'][0])){
87 $tmp = explode(",",$this->attrs['postfixMyNetworks'][0]);
88 foreach($tmp as $str){
89 if(!empty($str)){
90 $this->postfixMyNetworks[base64_encode($str)] = $str;
91 }
92 }
93 }
96 /* Create full name */
97 if(isset($this->attrs['postfixMyDomain'][0])){
98 $this->postfixMyhostname .= ".".$this->attrs['postfixMyDomain'][0];
99 }
102 /* Get postfix my domains */
103 $this->postfixMyDestinations = array();
104 if(isset($this->attrs['postfixMyDestinations'][0])){
105 unset($this->attrs['postfixMyDestinations']['count']);
106 foreach($this->attrs['postfixMyDestinations'] as $str){
107 $this->postfixMyDestinations[base64_encode($str)] = $str;
108 }
109 }
112 /* Get transport tables */
113 $tmp = array();
114 $this->postfixTransportTable = array();
115 if(isset($this->attrs['postfixTransportTable'])){
116 $tmp = array();
117 unset($this->attrs['postfixTransportTable']['count']);
118 foreach($this->attrs['postfixTransportTable'] as $entry){
120 //0: offshore.vip.ms-europa.lhsystems.com smtp:172.28.0.2
122 $Number = preg_replace('/^([^:]+):.*$/', '\\1', $entry);
123 $Rest = trim(preg_replace("/^[0-9]*:/","",$entry));
125 $Protocol_Destination = preg_replace("/^.*\ /","",$Rest);
126 $Source = preg_replace("/\ .*$/","",$Rest);
128 $Protocol = preg_replace ('/^([^:]+):.*$/', '\\1' ,trim($Protocol_Destination));
129 $Destination = preg_replace ('/^[^:]+:(.*)$/', '\\1' ,trim($Protocol_Destination));
131 $Destination = preg_replace ("/[\[\]]/","",$Destination);
133 $tmp[$Number]['src'] = $Source;
134 $tmp[$Number]['dst'] = $Destination;
135 $tmp[$Number]['prt'] = $Protocol;
136 }
137 ksort($tmp);
138 foreach($tmp as $entry){
139 $this->postfixTransportTable[] = $entry;
140 }
141 }
144 /* Get sender restrictions */
145 $tmp = array();
146 $this->postfixSenderRestrictions = array();
147 if(isset($this->attrs['postfixSenderRestrictions'])){
148 unset($this->attrs['postfixSenderRestrictions']['count']);
149 foreach($this->attrs['postfixSenderRestrictions'] as $entry){
150 $nr = preg_replace("/:.*$/","",$entry);
151 $rest= trim(preg_replace("/^[^:]+:/","",$entry));
152 $src = preg_replace("/ .*$/","",$rest);
153 $rest= preg_replace("/^[^ ]+ /","",$rest);
154 $dst = preg_replace("/^.* /","",$rest);
155 $prt = preg_replace("/ .*$/","",$rest);
157 $tmp[$nr]['src'] = $src;
158 $tmp[$nr]['dst'] = $dst;
159 $tmp[$nr]['filter'] = $prt;
160 }
161 ksort($tmp);
162 foreach($tmp as $entry){
163 $this->postfixSenderRestrictions[] = $entry;
164 }
165 }
168 /* Get sender restrictions */
169 $tmp = array();
170 $this->postfixRecipientRestrictions = array();
171 if(isset($this->attrs['postfixRecipientRestrictions'])){
172 unset($this->attrs['postfixRecipientRestrictions']['count']);
173 foreach($this->attrs['postfixRecipientRestrictions'] as $entry){
174 $nr = preg_replace("/:.*$/","",$entry);
175 $rest= trim(preg_replace("/^[^:]+:/","",$entry));
176 $src = preg_replace("/ .*$/","",$rest);
177 $rest= preg_replace("/^[^ ]+ /","",$rest);
178 $dst = preg_replace("/^.* /","",$rest);
179 $prt = preg_replace("/ .*$/","",$rest);
181 $tmp[$nr]['src'] = $src;
182 $tmp[$nr]['dst'] = $dst;
183 $tmp[$nr]['filter'] = $prt;
184 }
185 ksort($tmp);
186 foreach($tmp as $entry){
187 $this->postfixRecipientRestrictions[] = $entry;
188 }
189 }
191 // Prepare lists
192 $this->recipientRestrictionList = new sortableListing(array(),array(), TRUE);
193 $this->recipientRestrictionList->setDeleteable(true);
194 $this->recipientRestrictionList->setEditable(false);
195 $this->recipientRestrictionList->setWidth("100%");
196 $this->recipientRestrictionList->setHeight("100px");
197 $this->recipientRestrictionList->setDefaultSortColumn(0);
198 $this->recipientRestrictionList->setColspecs(array('*','*','*','20px'));
199 $this->recipientRestrictionList->setHeader(array(_("Source"),_("Destination"),_("Filter")));
201 $this->senderRestrictionList = new sortableListing(array(),array(), TRUE);
202 $this->senderRestrictionList->setDeleteable(true);
203 $this->senderRestrictionList->setEditable(false);
204 $this->senderRestrictionList->setWidth("100%");
205 $this->senderRestrictionList->setHeight("100px");
206 $this->senderRestrictionList->setDefaultSortColumn(0);
207 $this->senderRestrictionList->setColspecs(array('*','*','*','20px'));
208 $this->senderRestrictionList->setHeader(array(_("Source"),_("Destination"),_("Filter")));
210 $this->protocolsList = new sortableListing(array(),array(), TRUE);
211 $this->protocolsList->setDeleteable(true);
212 $this->protocolsList->setEditable(false);
213 $this->protocolsList->setWidth("100%");
214 $this->protocolsList->setHeight("100px");
215 $this->protocolsList->setColspecs(array('*','*','*','20px'));
216 $this->protocolsList->setHeader(array(_("Source"),_("Destination"),_("Protocol")));
217 $this->protocolsList->setDefaultSortColumn(0);
219 }
221 function execute()
222 {
223 $smarty = get_smarty();
226 if($this->is_account && !$this->view_logged){
227 $this->view_logged = TRUE;
228 new log("view","server/".get_class($this),$this->dn);
229 }
231 $tmp = $this->plInfo();
232 foreach($tmp['plProvidedAcls'] as $name => $translation){
233 $smarty->assign($name."ACL",$this->getacl($name));
234 }
237 /* Add delete my network entry */
238 if($this->acl_is_writeable("postfixMyNetworks")){
239 if((isset($_POST['AddpostfixMyNetworks'])) && (!empty($_POST['NewString_postfixMyNetworks']))){
240 $str = get_post('NewString_postfixMyNetworks');
241 $this->postfixMyNetworks[base64_encode($str)] = $str;
242 }
243 if((isset($_POST['DelpostfixMyNetworks'])) &&
244 isset($_POST['Select_postfixMyNetworks']) &&
245 (count($_POST['Select_postfixMyNetworks']))){
246 foreach(get_post('Select_postfixMyNetworks') as $str ){
247 unset($this->postfixMyNetworks[$str]);
248 }
249 }
250 }
253 /* Add delete my domain entry */
254 if($this->acl_is_writeable("postfixMyDestinations")){
255 if((isset($_POST['AddpostfixMyDestinations'])) && (!empty($_POST['NewString_postfixMyDestinations']))){
256 $str = get_post('NewString_postfixMyDestinations');
257 $this->postfixMyDestinations[base64_encode($str)] = $str;
258 }
260 if((isset($_POST['DelpostfixMyDestinations'])) && isset($_POST['Select_postfixMyDestinations']) &&(count($_POST['Select_postfixMyDestinations']))){
261 foreach(get_post('Select_postfixMyDestinations') as $str ){
262 unset($this->postfixMyDestinations[$str]);
263 }
264 }
265 }
268 $this->senderRestrictionList->save_object();
269 $this->recipientRestrictionList->save_object();
270 $this->protocolsList->save_object();
272 $action = $this->senderRestrictionList->getAction();
273 if($action['action'] == 'reorder'){
274 $this->postfixSenderRestrictions = $this->senderRestrictionList->getMaintainedData();
275 }
276 if($action['action'] == 'delete'){
277 $id = $this->senderRestrictionList->getKey($action['targets'][0]);
278 unset($this->postfixSenderRestrictions[$id]);
279 }
281 $action = $this->recipientRestrictionList->getAction();
282 if($action['action'] == 'reorder'){
283 $this->postfixRecipientRestrictions = $this->recipientRestrictionList->getMaintainedData();
284 }
285 if($action['action'] == 'delete'){
286 $id = $this->recipientRestrictionList->getKey($action['targets'][0]);
287 unset($this->postfixRecipientRestrictions[$id]);
288 }
290 $action = $this->protocolsList->getAction();
291 if($action['action'] == 'reorder'){
292 $this->postfixTransportTable = $this->protocolsList->getMaintainedData();
293 }
294 if($action['action'] == 'delete'){
295 $id = $this->protocolsList->getKey($action['targets'][0]);
296 unset($this->postfixTransportTable[$id]);
297 }
299 /* Add sender restriction */
300 if($this->acl_is_writeable("postfixSenderRestrictions")){
301 if(isset($_POST['AddpostfixSenderRestrictions'])){
302 $src = get_post('Source_postfixSenderRestrictions');
303 $dst = get_post('Destination_postfixSenderRestrictions');
304 $Filter = get_post('SenderRestrictionFilter');
305 $tmp = array();
306 $tmp['src'] = $src;
307 $tmp['dst'] = $dst;
308 $tmp['filter'] = $Filter;
309 $this->postfixSenderRestrictions[] = $tmp;
310 }
311 }
314 /* Add sender restriction */
315 if($this->acl_is_writeable("postfixRecipientRestrictions")){
316 if(isset($_POST['AddpostfixRecipientRestrictions'])){
317 $src = get_post('Source_postfixRecipientRestrictions');
318 $dst = get_post('Destination_postfixRecipientRestrictions');
319 $Filter = get_post('RecipientRestrictionFilter');
320 $tmp = array();
321 $tmp['src'] = $src;
322 $tmp['dst'] = $dst;
323 $tmp['filter'] = $Filter;
324 $this->postfixRecipientRestrictions[] = $tmp;
325 }
326 }
328 /* Handle transports */
329 if($this->acl_is_writeable("postfixTransportTable")){
330 if(isset($_POST['AddpostfixTransportTable'])){
331 $src = trim(get_post('Source_postfixTransportTable'));
332 $dst = trim(get_post('Destination_postfixTransportTable'));
333 $prt = trim(get_post('TransportProtocol'));
335 $tmp2 = array();
336 if((!empty($src)) && (!empty($dst))){
337 if(preg_match("/:/",$dst)){
338 $tmp = explode(":",$dst);
339 $port = trim($tmp[1]);
340 $ip = trim($tmp[0]);
342 if((tests::is_ip($ip)) && (is_numeric($port))){
343 $dst = "[".$ip."]:".$port;
344 }
345 }
346 if(tests::is_ip($dst)){
347 $dst = "[".$dst."]";
348 }
349 $tmp2 ['src'] = $src;
350 $tmp2 ['dst'] = $dst;
351 $tmp2 ['prt'] = $prt;
353 $this->postfixTransportTable[] = $tmp2;
354 }
355 }
356 }
358 /* Set attributes */
359 foreach($this->attributes as $attr){
360 $smarty->assign($attr,set_post($this->$attr));
361 }
364 /* Create list for translation tables */
365 $this->protocolsList->setAcl($this->getacl('postfixTransportTable'));
366 $lData = array();
367 foreach($this->postfixTransportTable as $key => $entry){
368 $lData[$key]=array('data' => array($entry['src'],$entry['dst'],$entry['prt']));
369 }
370 $this->protocolsList->setListData($this->postfixTransportTable, $lData);
371 $this->protocolsList->update();
372 $smarty->assign("postfixTransportTableList" ,$this->protocolsList->render());
375 /* Create list for sender restrictions */
376 $this->senderRestrictionList->setAcl($this->getacl('postfixSenderRestrictions'));
377 $lData = array();
378 foreach($this->postfixSenderRestrictions as $key => $entry){
379 $lData[$key]=array('data' => array($entry['src'],$entry['dst'],$entry['filter']));
380 }
381 $this->senderRestrictionList->setListData($this->postfixSenderRestrictions, $lData);
382 $this->senderRestrictionList->update();
383 $smarty->assign("postfixSenderRestrictionsList" ,$this->senderRestrictionList->render());
386 /* Create list for translation tables */
387 $this->recipientRestrictionList->setAcl($this->getacl('postfixRecipientRestrictions'));
388 $lData = array();
389 foreach($this->postfixRecipientRestrictions as $key => $entry){
390 $lData[$key]=array('data' => array($entry['src'],$entry['dst'],$entry['filter']));
391 }
392 $this->recipientRestrictionList->setListData($this->postfixRecipientRestrictions, $lData);
393 $this->recipientRestrictionList->update();
394 $smarty->assign("postfixRecipientRestrictionsList" ,$this->recipientRestrictionList->render());
397 /* set new status */
398 if(isset($_POST['ExecAction'])){
399 if(isset($this->Actions[$_POST['action']])){
400 $this->setStatus(get_post('action'));
401 }
402 }
405 $smarty->assign("is_new", set_post($this->dn));
406 $smarty->assign("is_acc", set_post($this->initially_was_account));
407 $smarty->assign("TransportProtocols", set_post($this->TransportProtocols));
408 $smarty->assign("Actions", set_post($this->Actions));
409 $smarty->assign("RestrictionFilters", set_post($this->RestrictionFilters));
410 $smarty->assign("postfixTransportTable" , set_post($this->getTransports()));
411 $smarty->assign("postfixSenderRestrictions" , set_post($this->getSenderRestrictions()));
412 $smarty->assign("postfixRecipientRestrictions",set_post($this->getRecipientRestrictions()));
414 return($smarty->fetch(get_template_path("goMailServer.tpl",TRUE,dirname(__FILE__))));
415 }
418 /* return transports formated for select box */
419 function getTransports()
420 {
421 $ret = array();
422 foreach($this->postfixTransportTable as $key => $vals){
423 $ret[$key] = $vals['src']." -> ".$vals['prt'].":".$vals['dst'];
424 }
425 return($ret);
426 }
429 /* return sender restriction formated for select box */
430 function getSenderRestrictions()
431 {
432 $ret = array();
433 foreach($this->postfixSenderRestrictions as $key => $vals){
434 $ret[$key] = $vals['src']." ".$vals['filter']." ".$vals['dst'];
435 }
436 return($ret);
437 }
440 /* return recipient restriction formated for select box */
441 function getRecipientRestrictions()
442 {
443 $ret = array();
444 foreach($this->postfixRecipientRestrictions as $key => $vals){
445 $ret[$key] = $vals['src']." ".$vals['filter']." ".$vals['dst'];
446 }
447 return($ret);
448 }
451 /* Return list entry */
452 function getListEntry()
453 {
454 $fields = goService::getListEntry();
455 $fields['Message'] = _("Mail smtp service (Postfix)");
456 #$fields['AllowEdit'] = true;
457 return($fields);
458 }
461 function save()
462 {
463 $this->postfixMyDomain = preg_replace("/^[^\.]+\./","",$this->postfixMyhostname);
464 $this->postfixMyhostname = preg_replace("/\..*$/","",$this->postfixMyhostname);
466 plugin::save();
468 /* Fix transport table*/
469 $i = 0 ;
470 $this->attrs['postfixTransportTable'] = array();
471 foreach($this->postfixTransportTable as $key => $entry){
472 $this->attrs['postfixTransportTable'][] = $i.": ".$entry['src']." ".$entry['prt'].":".$entry['dst'];
473 $i ++;
474 }
477 /* Fix sender restrictions */
478 $i = 0;
479 $this->attrs['postfixSenderRestrictions'] =array();
480 foreach($this->postfixSenderRestrictions as $key => $entry){
481 $this->attrs['postfixSenderRestrictions'][] = $i.": ".$entry['src']." ".$entry['filter']." ".$entry['dst'];
482 $i ++;
483 }
486 /* Fix recipient restrictions */
487 $i = 0;
488 $this->attrs['postfixRecipientRestrictions'] =array();
489 foreach($this->postfixRecipientRestrictions as $key => $entry){
490 $this->attrs['postfixRecipientRestrictions'][] = $i.": ".$entry['src']." ".$entry['filter']." ".$entry['dst'];
491 $i ++;
492 }
495 /* Fix mydomains */
496 $this->attrs['postfixMyDestinations'] = array();
497 foreach($this->postfixMyDestinations as $entry){
498 $this->attrs['postfixMyDestinations'][] =$entry;
499 }
502 /* Fix mydomains */
503 if(count($this->postfixMyNetworks)){
504 $this->attrs['postfixMyNetworks'] = "";
505 foreach($this->postfixMyNetworks as $entry){
506 $this->attrs['postfixMyNetworks'] .=$entry.",";
507 }
508 $this->attrs['postfixMyNetworks'] = preg_replace("/,$/","",$this->attrs['postfixMyNetworks']);
509 }else{
510 $this->attrs['postfixMyNetworks'] = array();
511 }
514 /* Check if this is a new entry ... add/modify */
515 $ldap = $this->config->get_ldap_link();
516 $ldap->cat($this->dn,array("objectClass"));
517 if($ldap->count()){
518 $ldap->cd($this->dn);
519 $ldap->modify($this->attrs);
520 }else{
521 $ldap->cd($this->dn);
522 $ldap->add($this->attrs);
523 }
524 if (!$ldap->success()){
525 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, 0, get_class()));
526 }
528 if($this->initially_was_account){
529 $this->handle_post_events("modify");
530 new log("modify","server/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
531 }else{
532 $this->handle_post_events("add");
533 new log("create","server/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
534 }
536 }
539 function check()
540 {
541 $message =plugin::check();
542 if(!is_numeric($this->postfixHeaderSizeLimit)){
543 $message[] = msgPool::invalid(_("Header size limit"),$this->postfixHeaderSizeLimit,"/[0-9]/");
544 }
545 if(!is_numeric($this->postfixMailboxSizeLimit)){
546 $message[] = msgPool::invalid(_("Mailbox size limit"),$this->postfixMailboxSizeLimit,"/[0-9]/");
547 }
548 if(!is_numeric($this->postfixMessageSizeLimit)){
549 $message[] = msgPool::invalid(_("Message size limit"),$this->postfixMessageSizeLimit,"/[0-9]/");
550 }
551 return $message;
552 }
555 function save_object()
556 {
557 plugin::save_object();
558 }
561 function PrepareForCopyPaste($source)
562 {
563 plugin::PrepareForCopyPaste($source);
565 $source_o = new goMailServer($this->config,$source['dn']);
566 foreach(array("postfixMyDomain","postfixMyhostname","postfixMyNetworks","postfixTransportTable","postfixSenderRestrictions","postfixRecipientRestrictions","postfixMyDestinations") as $attr){
567 $this->$attr = $source_o->$attr;
568 }
569 }
572 /* Return plugin informations for acl handling */
573 static function plInfo()
574 {
575 return (array(
576 "plShortName" => _("Mail smtp (Postfix)"),
577 "plDescription" => _("Mail smtp - Postfix")." ("._("Services").")",
578 "plSelfModify" => FALSE,
579 "plDepends" => array(),
580 "plPriority" => 98,
581 "plSection" => array("administration"),
582 "plCategory" => array("server"),
583 "plRequirements"=> array(
584 'ldapSchema' => array('goMailServer' => '>=2.7'),
585 'onFailureDisablePlugin' => array(get_class())
586 ),
588 "plProperties" => array(
589 array(
590 "name" => "postfixProtocols",
591 "type" => "file",
592 "default" => "",
593 "description" => _("The 'postfixProtocols' statement defines a file to include for the postfix module in order to display user defined protocols.")."
595 File syntax:
596 name1:Description1
597 name2:Description2",
599 "check" => "gosaProperty::isReadableFile",
600 "migrate" => "",
601 "group" => "mail",
602 "mandatory" => FALSE),
603 array(
604 "name" => "postfixRestrictionFilters",
605 "type" => "file",
606 "default" => "",
607 "description" => _("The 'postfixRestrictionFilters' statement defines a file to include for the postfix module in order to display user defined restriction filters.")."
609 File syntax:
610 name1:Description1
611 name2:Description2",
612 "check" => "gosaProperty::isReadableFile",
613 "migrate" => "",
614 "group" => "mail",
615 "mandatory" => FALSE),
616 ),
618 "plProvidedAcls"=> array(
620 "start" => _("Start"),
621 "stop" => _("Stop"),
622 "restart" => _("Restart"),
623 "postfixMyhostname" => _("Visible full qualified hostname"),
624 "description" => _("Description"),
625 "postfixHeaderSizeLimit" => _("Header size limit"),
626 "postfixMailboxSizeLimit" => _("Max mailbox size"),
627 "postfixMessageSizeLimit" => _("Max message size"),
628 "postfixMyDestinations" => _("Domains to accept mail for"),
629 "postfixMyNetworks" => _("Local networks"),
630 "postfixRelayhost" => _("Relay host"),
631 "postfixTransportTable" => _("Transport table"),
632 "postfixSenderRestrictions" => _("Restrictions for sender"),
633 "postfixRecipientRestrictions"=> _("Restrictions for recipient"))
634 ));
635 }
636 }
637 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
638 ?>