1 <?php
2 /*!
3 \brief mail plugin
4 \author Fabian Hicker <Fabian.Hickert@GONICUS.de>
5 \version 2.6.2
6 \date 03.12.2007
8 This class provides the functionality to read and write all attributes
9 relevant for gosaMailAccounts from/to the LDAP.
10 It does syntax checking and displays the formulars required.
11 Special handling like sieve or imap actions will be implemented
12 by the mailMethods.
15 Functions :
17 - mailAccount (&$config, $dn= NULL)
18 - execute()
19 - save_object()
20 - get_vacation_templates()
21 - addForwarder($address)
22 - delForwarder($addresses)
23 - addAlternate($address)
24 - delAlternate($addresses)
25 - prepare_vacation_template($contents)
26 - display_forward_dialog()
27 - remove_from_parent()
28 - save()
29 - check()
30 - adapt_from_template($dn, $skip= array())
31 - getCopyDialog()
32 - saveCopyDialog()
33 - PrepareForCopyPaste($source)
34 - get_multi_edit_values()
35 - multiple_check()
36 - set_multi_edit_values($values)
37 - init_multiple_support($attrs,$all)
38 - get_multi_init_values()
39 - multiple_execute()
40 - multiple_save_object()
41 - make_name($attrs)
42 - plInfo()
45 */
47 class mailAccount extends plugin
48 {
49 /* Definitions */
50 var $plHeadline = "Mail";
51 var $plDescription = "This does something";
52 var $view_logged = FALSE;
53 var $is_account = FALSE;
54 var $initially_was_account = FALSE;
56 /* GOsa mail attributes */
57 var $mail = "";
58 var $gosaVacationStart = 0;
59 var $gosaVacationStop = 0;
60 var $gosaMailAlternateAddress = array();
61 var $gosaMailForwardingAddress = array();
62 var $gosaMailDeliveryMode = "[L ]";
63 var $gosaMailServer = "";
64 var $gosaMailQuota = "";
65 var $gosaMailMaxSize = "";
66 var $gosaVacationMessage = "";
67 var $gosaSpamSortLevel = "";
68 var $gosaSpamMailbox = "";
70 /* The methods defaults */
71 var $mailMethod = NULL;
72 var $MailDomain = "";
73 var $sieveManagementUsed = FALSE;
74 var $multiple_support = FALSE;
75 var $vacationTemplates = array();
76 var $sieve_management = NULL;
77 var $forward_dialog = FALSE;
78 var $initial_uid = "";
79 var $mailDomainPart = "";
80 var $mailDomainParts = array();
81 var $MailBoxes = array("INBOX");
83 /* Used LDAP attributes && classes */
84 var $attributes= array(
85 "mail", "gosaMailServer","gosaMailQuota", "gosaMailMaxSize","gosaMailForwardingAddress",
86 "gosaMailDeliveryMode", "gosaSpamSortLevel", "gosaSpamMailbox","gosaMailAlternateAddress",
87 "gosaVacationStart","gosaVacationStop", "gosaVacationMessage", "gosaMailAlternateAddress",
88 "gosaMailForwardingAddress");
89 var $objectclasses= array("gosaMailAccount");
92 /*! \brief Initialize the mailAccount
93 */
94 function __construct (&$config, $dn= NULL)
95 {
96 plugin::plugin($config,$dn);
98 /* Intialize the used mailMethod
99 */
100 $tmp = new mailMethod($config,$this);
101 $this->mailMethod = $tmp->get_method();
102 $this->mailMethod->fixAttributesOnLoad();
103 $this->mailDomainParts = $this->mailMethod->getMailDomains();
104 $this->SpamLevels = $this->mailMethod->getSpamLevels();
106 /* Remember account status
107 */
108 $this->initially_was_account = $this->is_account;
110 /* Initialize vacation settings
111 */
112 if(empty($this->gosaVacationStart)){
113 $this->gosaVacationStart = time();
114 $this->gosaVacationStop = time();
115 }
117 /* Read vacation templates
118 */
119 $this->vacationTemplates = $this->get_vacation_templates();
121 /* Initialize configured values
122 */
123 if($this->is_account){
125 if($this->mailMethod->connect() && $this->mailMethod->account_exists()){
127 /* Read quota */
128 $this->gosaMailQuota = $this->mailMethod->getQuota($this->gosaMailQuota);
129 if($this->mailMethod->is_error()){
130 msg_dialog::display(_("Mail error"), sprintf(_("Cannot read quota settings! Error was: %s."),
131 $this->mailMethod->get_error()), ERROR_DIALOG);
132 }
134 /* Read mailboxes */
135 $this->MailBoxes = $this->mailMethod->getMailboxList($this->MailBoxes);
136 if($this->mailMethod->is_error()){
137 msg_dialog::display(_("Mail error"), sprintf(_("Cannot get list of mailboxes! Error was: %s."),
138 $this->mailMethod->get_error()), ERROR_DIALOG);
139 }
141 }elseif(!$this->mailMethod->is_connected()){
142 msg_dialog::display(_("Mail error"), sprintf(_("Cannot connect mail method! Error was: %s."),
143 $this->mailMethod->get_error()), ERROR_DIALOG);
144 }elseif(!$this->mailMethod->account_exists()){
145 msg_dialog::display(_("Mail error"), sprintf(_("Mailbox '%s' doesn't exists on mail server: %s."),
146 $this->mailMethod->get_account_id(),$this->gosaMailServer), ERROR_DIALOG);
147 }
149 /* If the doamin part is selectable, we have to split the mail address
150 */
151 if($this->mailMethod->domainSelectionEnabled()){
152 $this->mailDomainPart = preg_replace("/^[^@]*+@/","",$this->mail);
153 $this->mail = preg_replace("/@.*$/","\\1",$this->mail);
154 if(!in_array($this->mailDomainPart,$this->mailDomainParts)){
155 $this->mailDomainParts[] = $this->mailDomainPart;
156 }
157 }
159 /* Load attributes containing arrays */
160 foreach (array("gosaMailAlternateAddress", "gosaMailForwardingAddress") as $val){
161 $this->$val= array();
162 if (isset($this->attrs["$val"]["count"])){
163 for ($i= 0; $i<$this->attrs["$val"]["count"]; $i++){
164 array_push($this->$val, $this->attrs["$val"][$i]);
165 }
166 }
167 }
168 }
170 /* Intialize sieveManagement if necessary */
171 if($this->mailMethod->allowSieveManagement()){
172 $this->mailboxList = &$this->MailBoxes;
173 $this->sieve_management = new sieveManagement($this->config,$this->dn,$this,$this->mailMethod->getUAttrib());
174 }
176 /* Get global filter config used in add local forward
177 */
178 if (!session::is_set("mailfilter")){
179 $ui= get_userinfo();
180 $base= get_base_from_people($ui->dn);
181 $mailfilter= array( "depselect" => $base,
182 "muser" => "",
183 "regex" => "*");
184 session::set("mailfilter", $mailfilter);
185 }
187 /* Disconnect mailMethod. Connect on demand later.
188 */
189 $this->mailMethod->disconnect();
190 }
193 function execute()
194 {
195 /* Call parent execute */
196 $display = plugin::execute();
198 /* Log view */
199 if($this->is_account && !$this->view_logged){
200 $this->view_logged = TRUE;
201 new log("view","users/".get_class($this),$this->dn);
202 }
205 /****************
206 Account status
207 ****************/
209 if(isset($_POST['modify_state'])){
210 if($this->is_account && $this->acl_is_removeable() && $this->mailMethod->accountRemoveAble()){
211 $this->is_account= FALSE;
212 }elseif(!$this->is_account && $this->acl_is_createable() && $this->mailMethod->accountCreateable()){
213 $this->is_account= TRUE;
214 }
215 }
216 if(!$this->multiple_support_active){
217 if (!$this->is_account && $this->parent === NULL){
218 $display= "<img alt=\"\" src=\"images/small-error.png\" align=\"middle\"> <b>".
219 msgPool::noValidExtension(_("Mail"))."</b>";
220 $display.= back_to_main();
221 return ($display);
222 }
223 if ($this->parent !== NULL){
224 if ($this->is_account){
225 $reason = "";
226 if(!$this->mailMethod->accountRemoveable($reason)){
227 $display= $this->show_disable_header(msgPool::removeFeaturesButton(_("Mail")),$reason ,TRUE,TRUE);
228 }else{
229 $display= $this->show_disable_header(msgPool::removeFeaturesButton(_("Mail")),msgPool::featuresEnabled(_("Mail")));
230 }
231 } else {
232 $reason = "";
233 if(!$this->mailMethod->accountCreateable($reason)){
234 $display= $this->show_disable_header(msgPool::addFeaturesButton(_("Mail")),$reason ,TRUE,TRUE);
235 }else{
236 $display= $this->show_disable_header(msgPool::addFeaturesButton(_("Mail")),msgPool::featuresDisabled(_("Mail")));
237 }
238 return ($display);
239 }
240 }
241 }
243 /****************
244 Sieve Management Dialog
245 ****************/
246 if($this->mailMethod->allowSieveManagement()){
247 if(isset($_POST['sieveManagement'])
248 && preg_match("/C/",$this->gosaMailDeliveryMode)
249 && $this->acl_is_writeable("sieveManagement")
250 && $this->mailMethod->allowSieveManagement()) {
251 $this->dialog = $this->sieve_management;
252 }
253 if(isset($_POST['sieve_cancel'])){
254 $this->dialog = FALSE;
255 }
256 if(isset($_POST['sieve_finish'])){
257 $this->sieve_management = $this->dialog;
258 $this->dialog = FALSE;
259 }
260 if(is_object($this->dialog)){
261 $this->dialog->save_object();
262 return($this->dialog->execute());
263 }
264 }
266 /****************
267 Forward addresses
268 ****************/
269 if (isset($_POST['add_local_forwarder'])){
270 $this->forward_dialog= TRUE;
271 $this->dialog= TRUE;
272 }
273 if (isset($_POST['add_locals_cancel'])){
274 $this->forward_dialog= FALSE;
275 $this->dialog= FALSE;
276 }
277 if (isset($_POST['add_locals_finish'])){
278 if (isset($_POST['local_list'])){
279 if($this->acl_is_writeable("gosaMailForwardingAddress")){
280 foreach ($_POST['local_list'] as $val){
281 if (!in_array ($val, $this->gosaMailAlternateAddress) &&
282 $val != $this->mail){
283 $this->addForwarder($val);
284 $this->is_modified= TRUE;
285 }
286 }
287 }
288 $this->forward_dialog= FALSE;
289 $this->dialog= FALSE;
290 } else {
291 msg_dialog::display(_("Error"), _("Please select an entry!"), ERROR_DIALOG);
292 }
293 }
294 if (isset($_POST['add_forwarder'])){
295 if ($_POST['forward_address'] != ""){
296 $address= $_POST['forward_address'];
297 $valid= FALSE;
298 if (!tests::is_email($address)){
299 if (!tests::is_email($address, TRUE)){
300 if ($this->is_template){
301 $valid= TRUE;
302 } else {
303 msg_dialog::display(_("Error"), msgPool::invalid(_("Mail address"),
304 "","","your-address@your-domain.com"),ERROR_DIALOG);
305 }
306 }
307 } elseif ($address == $this->mail
308 || in_array($address, $this->gosaMailAlternateAddress)) {
309 msg_dialog::display(_("Error"),_("Cannot add primary address to the list of forwarders!") , ERROR_DIALOG);
310 } else {
311 $valid= TRUE;
312 }
313 if ($valid){
314 if($this->acl_is_writeable("gosaMailForwardingAddress")){
315 $this->addForwarder ($address);
316 $this->is_modified= TRUE;
317 }
318 }
319 }
320 }
321 if (isset($_POST['delete_forwarder'])){
322 $this->delForwarder ($_POST['forwarder_list']);
323 }
324 if ($this->forward_dialog){
325 return($this->display_forward_dialog());
326 }
329 /****************
330 Alternate addresses
331 ****************/
333 if (isset($_POST['add_alternate'])){
334 $valid= FALSE;
335 if (!tests::is_email($_POST['alternate_address'])){
336 if ($this->is_template){
337 if (!(tests::is_email($_POST['alternate_address'], TRUE))){
338 msg_dialog::display(_("Error"),msgPool::invalid(_("Mail address"),"","","your-domain@your-domain.com"),ERROR_DIALOG);
339 } else {
340 $valid= TRUE;
341 }
342 } else {
343 msg_dialog::display(_("Error"),msgPool::invalid(_("Mail address"),"","","your-domain@your-domain.com"),ERROR_DIALOG);
344 }
345 } else {
346 $valid= TRUE;
347 }
348 if ($valid && ($user= $this->addAlternate ($_POST['alternate_address'])) != ""){
349 $ui= get_userinfo();
350 if ($user != $ui->username){
351 msg_dialog::display(_("Error"), msgPool::duplicated(_("Mail address"))." ".
352 sprintf(_("Address is already in use by user '%s'."), $user), ERROR_DIALOG);
353 }
354 }
355 }
356 if (isset($_POST['delete_alternate']) && isset($_POST['alternates_list'])){
357 $this->delAlternate ($_POST['alternates_list']);
358 }
360 /****************
361 SMARTY- Assign smarty variables
362 ****************/
363 $smarty = get_smarty();
364 $SkipWrite = (!isset($this->parent) || !$this->parent) && !session::is_set('edit');
365 $tmp = $this->plInfo();
366 foreach($tmp['plProvidedAcls'] as $name => $transl){
367 $smarty->assign("$name"."ACL", $this->getacl($name,$SkipWrite));
368 }
369 foreach($this->attributes as $attr){
370 $smarty->assign($attr,$this->$attr);
371 }
372 $smarty->assign("quotaEnabled", $this->mailMethod->quotaEnabled());
373 if($this->mailMethod->is_connected()){
374 $smarty->assign("quotaUsage", $this->mailMethod->getQuotaUsage());
375 }else{
376 $smarty->assign("quotaUsage", _("Unknown"));
377 }
378 $smarty->assign("gosaMailQuota",$this->gosaMailQuota);
379 $smarty->assign("domainSelectionEnabled", $this->mailMethod->domainSelectionEnabled());
380 $smarty->assign("MailDomains", $this->mailDomainParts);
381 $smarty->assign("MailDomain" , $this->mailDomainPart);
382 $smarty->assign("MailServers", $this->mailMethod->getMailServers());
383 $smarty->assign("allowSieveManagement", $this->mailMethod->allowSieveManagement());
384 $smarty->assign("own_script", $this->sieveManagementUsed);
386 /* _Multiple users vars_ */
387 foreach($this->attributes as $attr){
388 $u_attr = "use_".$attr;
389 $smarty->assign($u_attr,in_array($attr,$this->multi_boxes));
390 }
391 foreach(array("only_local","gosaMailForwardingAddress","use_mailsize_limit","drop_own_mails","use_vacation","use_spam_filter") as $attr){
392 $u_attr = "use_".$attr;
393 $smarty->assign($u_attr,in_array($attr,$this->multi_boxes));
394 }
397 /****************
398 SMARTY- Assign flags
399 ****************/
401 $types = array(
402 "V"=>"use_vacation",
403 "S"=>"use_spam_filter",
404 "R"=>"use_mailsize_limit",
405 "I"=>"drop_own_mails",
406 "C"=>"own_script");
407 foreach($types as $option => $varname){
408 if (preg_match("/".$option."/", $this->gosaMailDeliveryMode)) {
409 $smarty->assign($varname, "checked");
410 } else {
411 $smarty->assign($varname, "");
412 }
413 }
414 if (!preg_match("/L/", $this->gosaMailDeliveryMode)) {
415 $smarty->assign("only_local", "checked");
416 } else {
417 $smarty->assign("only_local", "");
418 }
421 /****************
422 Smarty- Vacation settings
423 ****************/
424 $smarty->assign("rangeEnabled", FALSE);
425 $smarty->assign("template", "");
426 if (count($this->vacationTemplates)){
427 $smarty->assign("show_templates", "true");
428 $smarty->assign("vacationtemplates", $this->vacationTemplates);
429 if (isset($_POST['vacation_template'])){
430 $smarty->assign("template", $_POST['vacation_template']);
431 }
432 } else {
433 $smarty->assign("show_templates", "false");
434 }
436 /* Vacation range assigments
437 */
438 if($this->mailMethod->vacationRangeEnabled()){
439 $smarty->assign("rangeEnabled", TRUE);
440 if($this->gosaVacationStop ==0){
441 $date= getdate(time());
442 $date["mday"]++;
443 }else{
444 $date= getdate($this->gosaVacationStop);
445 }
446 $smarty->assign("end_day", $date["mday"]);
447 $smarty->assign("end_month", $date["mon"]-1);
448 $smarty->assign("end_year", $date["year"]);
450 if($this->gosaVacationStart == 0){
451 $date= getdate(time());
452 }else{
453 $date= getdate($this->gosaVacationStart);
454 }
455 $smarty->assign("start_day", $date["mday"]);
456 $smarty->assign("start_month", $date["mon"]-1);
457 $smarty->assign("start_year", $date["year"]);
458 $days= array();
459 for($d= 1; $d<32; $d++){
460 $days[$d]= $d;
461 }
462 $years= array();
463 for($y= $date['year']-10; $y<$date['year']+10; $y++){
464 $years[]= $y;
465 }
466 $months= msgPool::months();
467 $smarty->assign("months", $months);
468 $smarty->assign("years", $years);
469 $smarty->assign("days", $days);
471 }
473 /* fill filter settings
474 */
475 $smarty->assign("spamlevel", $this->SpamLevels);
476 $smarty->assign("spambox" , $this->MailBoxes);
478 $smarty->assign("multiple_support",$this->multiple_support_active);
479 return($display.$smarty->fetch(get_template_path("generic.tpl",TRUE,dirname(__FILE__))));
480 }
484 /* Save data to object */
485 function save_object()
486 {
487 if (isset($_POST['mailTab'])){
489 /* Save ldap attributes */
490 plugin::save_object();
492 /* Get posted mail domain part, if necessary
493 */
494 if($this->mailMethod->domainSelectionEnabled() && isset($_POST['MailDomain'])){
495 if(in_array(get_post('MailDomain'), $this->mailDomainParts)){
496 $this->mailDomainPart = get_post('MailDomain');
497 }
498 }
500 /* Import vacation message?
501 */
502 if (isset($_POST["import_vacation"]) && isset($this->vacationTemplates[$_POST["vacation_template"]])){
503 if($this->multiple_support_active){
504 $contents = file_get_contents($_POST["vacation_template"]);
505 }else{
506 $contents = $this->prepare_vacation_template(file_get_contents($_POST["vacation_template"]));
507 }
508 $this->gosaVacationMessage= htmlspecialchars($contents);
509 }
511 /* Handle flags
512 */
513 if(isset($_POST['own_script'])){
514 if(!preg_match("/C/",$this->gosaMailDeliveryMode)){
515 $str= preg_replace("/[\[\]]/","",$this->gosaMailDeliveryMode);
516 $this->gosaMailDeliveryMode = "[".$str."C]";
517 }
518 }else{
520 /* Assemble mail delivery mode
521 The mode field in ldap consists of values between braces, this must
522 be called when 'mail' is set, because checkboxes may not be set when
523 we're in some other dialog.
525 Example for gosaMailDeliveryMode [LR ]
526 L - Local delivery
527 R - Reject when exceeding mailsize limit
528 S - Use spam filter
529 V - Use vacation message
530 C - Use custm sieve script
531 I - Only insider delivery */
533 $tmp= preg_replace("/[^a-z]/i","",$this->gosaMailDeliveryMode);
536 /* Handle delivery flags */
537 if($this->acl_is_writeable("gosaMailDeliveryModeL")){
538 if(!preg_match("/L/",$tmp) && !isset($_POST['only_local'])){
539 $tmp.="L";
540 }elseif(preg_match("/L/",$tmp) && isset($_POST['only_local'])){
541 $tmp = preg_replace("/L/","",$tmp);
542 }
543 }
544 $opts = array(
545 "R" => "use_mailsize_limit",
546 "S" => "use_spam_filter",
547 "V" => "use_vacation",
548 "C" => "own_script",
549 "I" => "drop_own_mails");
551 foreach($opts as $flag => $post){
552 if($this->acl_is_writeable("gosaMailDeliveryMode".$flag)){
553 if(!preg_match("/".$flag."/",$tmp) && isset($_POST[$post])){
554 $tmp.= $flag;
555 }elseif(preg_match("/".$flag."/",$tmp) && !isset($_POST[$post])){
556 $tmp = preg_replace("/".$flag."/","",$tmp);
557 }
558 }
559 }
561 $tmp= "[$tmp]";
562 if ($this->gosaMailDeliveryMode != $tmp){
563 $this->is_modified= TRUE;
564 }
565 $this->gosaMailDeliveryMode= $tmp;
566 if($this->mailMethod->vacationRangeEnabled()){
567 if($this->acl_is_writeable("gosaVacationMessage") && preg_match("/V/",$this->gosaMailDeliveryMode)){
568 if(isset($_POST['gosaVacationStart'])){
569 $this->gosaVacationStart = $_POST['gosaVacationStart'];
570 }
571 if(isset($_POST['gosaVacationStop'])){
572 $this->gosaVacationStop = $_POST['gosaVacationStop'];
573 }
574 }
575 }
576 }
577 }
578 }
581 /*! \brief Parse vacation templates and build up an array
582 containing 'filename' => 'description'.
583 Used to fill vacation dropdown box.
584 @return Array All useable vacation templates.
585 */
586 function get_vacation_templates()
587 {
588 $vct = array();
589 if ($this->config->get_cfg_value("vacationTemplateDirectory") != ""){
590 $dir= $this->config->get_cfg_value("vacationTemplateDirectory");
591 if (is_dir($dir) && is_readable($dir)){
592 $dh = opendir($dir);
593 while($file = readdir($dh)){
594 $description= "";
595 if (is_file($dir."/".$file)){
596 $fh = fopen($dir."/".$file, "r");
597 $line= fgets($fh, 256);
598 if (!preg_match('/^DESC:/', $line)){
599 msg_dialog::display(_("Configuration error"), sprintf(_("No DESC tag in vacation template '%s'!"), $file), ERROR_DIALOG);
600 }else{
601 $description= trim(preg_replace('/^DESC:\s*/', '', $line));
602 }
603 fclose ($fh);
604 }
605 if ($description != ""){
606 $vct["$dir/$file"]= $description;
607 }
608 }
609 closedir($dh);
610 }
611 }
612 return($vct);
613 }
616 /*! \brief Adds the given mail address to the list of mail forwarders
617 */
618 function addForwarder($address)
619 {
620 if(empty($address)) return;
621 if($this->acl_is_writeable("gosaMailForwardingAddress")){
622 $this->gosaMailForwardingAddress[]= $address;
623 $this->gosaMailForwardingAddress= array_unique ($this->gosaMailForwardingAddress);
624 sort ($this->gosaMailForwardingAddress);
625 reset ($this->gosaMailForwardingAddress);
626 $this->is_modified= TRUE;
627 }else{
628 msg_dialog::display(_("Permission error"), _("You have no permission to modify these addresses!"), ERROR_DIALOG);
629 }
630 }
633 /*! \brief Removes the given mail address from the list of mail forwarders
634 */
635 function delForwarder($addresses)
636 {
637 if($this->acl_is_writeable("gosaMailForwardingAddress")){
638 $this->gosaMailForwardingAddress= array_remove_entries ($addresses, $this->gosaMailForwardingAddress);
639 $this->is_modified= TRUE;
640 }else{
641 msg_dialog::display(_("Permission error"), _("You have no permission to modify these addresses!"), ERROR_DIALOG);
642 }
643 }
646 /*! \brief Add given mail address to the list of alternate adresses ,
647 . check if this mal address is used, skip adding in this case
648 */
649 function addAlternate($address)
650 {
651 if(empty($address)) return;
652 if($this->acl_is_writeable("gosaMailAlternateAddress")){
653 $ldap= $this->config->get_ldap_link();
654 $address= strtolower($address);
656 /* Is this address already assigned in LDAP? */
657 $ldap->cd ($this->config->current['BASE']);
658 $ldap->search ("(&(!(objectClass=gosaUserTemplate))(objectClass=gosaMailAccount)(|(mail=$address)".
659 "(alias=$address)(gosaMailAlternateAddress=$address)))", array("uid"));
660 if ($ldap->count() > 0){
661 $attrs= $ldap->fetch ();
662 return ($attrs["uid"][0]);
663 }
664 if (!in_array($address, $this->gosaMailAlternateAddress)){
665 $this->gosaMailAlternateAddress[]= $address;
666 $this->is_modified= TRUE;
667 }
668 sort ($this->gosaMailAlternateAddress);
669 reset ($this->gosaMailAlternateAddress);
670 return ("");
671 }else{
672 msg_dialog::display(_("Permission error"), _("You have no permission to modify these addresses!"), ERROR_DIALOG);
673 }
674 }
677 /*! \brief Removes the given mail address from the alternate addresses list
678 */
679 function delAlternate($addresses)
680 {
681 if($this->acl_is_writeable("gosaMailAlternateAddress")){
682 $this->gosaMailAlternateAddress= array_remove_entries ($addresses,$this->gosaMailAlternateAddress);
683 $this->is_modified= TRUE;
684 }else{
685 msg_dialog::display(_("Permission error"), _("You have no permission to modify these addresses!"), ERROR_DIALOG);
686 }
687 }
690 /*! \brief Prepare importet vacation string. \
691 . Replace placeholder like %givenName a.s.o.
692 @param string Vacation string
693 @return string Completed vacation string
694 */
695 private function prepare_vacation_template($contents)
696 {
697 /* Replace attributes */
698 $attrs = array();
699 $obj = NULL;
700 if(isset($this->parent->by_object['user'])){
701 $attrs = $this->parent->by_object['user']->attributes;
702 $obj = $this->parent->by_object['user'];
703 }else{
704 $obj = new user($this->config,$this->dn);
705 $attrs = $obj->attributes;
706 }
707 if($obj){
708 foreach ($attrs as $val){
709 if(preg_match("/dateOfBirth/",$val)){
710 if($obj->use_dob){
711 $contents= preg_replace("/%$val/",date("Y-d-m",$obj->dateOfBirth),$contents);
712 }
713 }else {
714 $contents= preg_replace("/%$val/",
715 $obj->$val, $contents);
716 }
718 /* Replace vacation start and end time */
719 if(preg_match("/%start/",$contents)){
720 $contents = preg_replace("/%start/",date("d.m.Y",$this->gosaVacationStart),$contents);
721 }
722 if(preg_match("/%end/",$contents)){
723 $contents = preg_replace("/%end/",date("d.m.Y",$this->gosaVacationStop),$contents);
724 }
725 }
726 }
727 $contents = ltrim(preg_replace("/^DESC:.*$/m","",$contents),"\n ");
728 return($contents);
729 }
732 /*! \brief Displays a dialog that allows mail address selection.
733 */
734 function display_forward_dialog()
735 {
736 restore_error_handler();
738 $smarty = get_smarty();
739 $ldap= $this->config->get_ldap_link();
741 /* Save data */
742 $mailfilter= session::get("mailfilter");
743 foreach( array("depselect", "muser", "regex") as $type){
744 if (isset($_POST[$type])){
745 $mailfilter[$type]= $_POST[$type];
746 }
747 }
748 if (isset($_GET['search'])){
749 $s= mb_substr($_GET['search'], 0, 1, "UTF8")."*";
750 if ($s == "**"){
751 $s= "*";
752 }
753 $mailfilter['regex']= $s;
754 }
755 session::set("mailfilter", $mailfilter);
757 /* Get actual list */
758 $mailusers= array ();
759 if ($mailfilter['regex'] != '*' && $mailfilter['regex'] != ""){
760 $regex= $mailfilter['regex'];
761 $filter= "(|(mail=$regex)(gosaMailAlternateAddress=$regex))";
762 } else {
763 $filter= "";
764 }
765 if ($mailfilter['muser'] != ""){
766 $user= $mailfilter['muser'];
767 $filter= "$filter(|(uid=$user)(cn=$user)(givenName=$user)(sn=$user))";
768 }
770 /* Add already present people to the filter */
771 $exclude= "";
772 foreach ($this->gosaMailForwardingAddress as $mail){
773 $exclude.= "(mail=$mail)";
774 }
775 if ($exclude != ""){
776 $filter.= "(!(|$exclude))";
777 }
778 $res= get_list("(&(objectClass=gosaMailAccount)$filter)", "users", $mailfilter['depselect'],
779 array("sn", "mail", "givenName"), GL_SIZELIMIT | GL_SUBSEARCH);
780 $ldap->cd($mailfilter['depselect']);
781 $ldap->search ("(&(objectClass=gosaMailAccount)$filter)", array("sn", "mail", "givenName"));
782 while ($attrs= $ldap->fetch()){
783 if(preg_match('/%/', $attrs['mail'][0])){
784 continue;
785 }
786 $name= $this->make_name($attrs);
787 $mailusers[$attrs['mail'][0]]= $name."<".
788 $attrs['mail'][0].">";
789 }
790 natcasesort ($mailusers);
791 reset ($mailusers);
793 /* Show dialog */
794 $smarty->assign("search_image", get_template_path('images/lists/search.png'));
795 $smarty->assign("usearch_image", get_template_path('images/lists/search-user.png'));
796 $smarty->assign("tree_image", get_template_path('images/lists/search-subtree.png'));
797 $smarty->assign("infoimage", get_template_path('images/info.png'));
798 $smarty->assign("launchimage", get_template_path('images/lists/action.png'));
799 $smarty->assign("mailusers", $mailusers);
800 if (isset($_POST['depselect'])){
801 $smarty->assign("depselect", $_POST['depselect']);
802 }
803 $smarty->assign("deplist", $this->config->idepartments);
804 $smarty->assign("apply", apply_filter());
805 $smarty->assign("alphabet", generate_alphabet());
806 $smarty->assign("hint", print_sizelimit_warning());
807 foreach( array("depselect", "muser", "regex") as $type){
808 $smarty->assign("$type", $mailfilter[$type]);
809 }
810 $smarty->assign("hint", print_sizelimit_warning());
811 $display= $smarty->fetch (get_template_path('mail_locals.tpl', TRUE, dirname(__FILE__)));
812 return ($display);
813 }
816 /*! \brief Removes the mailAccount extension from ldap
817 */
818 function remove_from_parent()
819 {
820 /* Cancel if there's nothing to do here */
821 if (!$this->initially_was_account){
822 return;
823 }
825 /* If domain part was selectable, contruct mail address */
826 if($this->mailMethod->domainSelectionEnabled()){
827 $this->mail = $this->mail."@".$this->mailDomainPart;
828 }
830 /* Remove GOsa attributes */
831 plugin::remove_from_parent();
833 /* Zero arrays */
834 $this->attrs['gosaMailAlternateAddress'] = array();
835 $this->attrs['gosaMailForwardingAddress']= array();
838 $this->mailMethod->fixAttributesOnRemove();
839 $this->cleanup();
841 @DEBUG (DEBUG_LDAP, __LINE__, __FUNCTION__, __FILE__,$this->attributes, "Save");
842 $ldap= $this->config->get_ldap_link();
843 $ldap->cd($this->dn);
844 $ldap->modify ($this->attrs);
846 /* Add "view" to logging class */
847 new log("remove","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
848 if (!$ldap->success()){
849 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
850 }
852 /* Let the mailMethod remove this mailbox, e.g. from imap and
853 update shared folder membership, ACL may need to be updated.
854 */
855 if (!$this->is_template){
857 if(!$this->mailMethod->connect()){
858 msg_dialog::display(_("Mail error"), sprintf(_("Cannot connect mail method! Error was: %s."),
859 $this->mailMethod->get_error()), ERROR_DIALOG);
860 }else{
861 if(!$this->mailMethod->deleteMailbox()){
862 msg_dialog::display(_("Mail error"), sprintf(_("Cannot remove mailbox! Error was: %s."),
863 $this->mailMethod->get_error()), ERROR_DIALOG);
864 }
865 if(!$this->mailMethod->updateSharedFolder()){
866 msg_dialog::display(_("Mail error"), sprintf(_("Cannot update shared folder permissions! Error was: %s."),
867 $this->mailMethod->get_error()), ERROR_DIALOG);
868 }
869 }
870 }
871 $this->mailMethod->disconnect();
873 /* Optionally execute a command after we're done */
874 $this->handle_post_events("remove",array("uid" => $this->uid));
875 }
878 /*! \brief Save the mailAccount settings to the ldap database.
879 */
880 function save()
881 {
882 $ldap= $this->config->get_ldap_link();
884 /* If domain part was selectable, contruct mail address */
885 if($this->mailMethod->domainSelectionEnabled()){
886 $this->mail = $this->mail."@".$this->mailDomainPart;
887 }
889 /* Enforce lowercase mail address and trim whitespaces
890 */
891 $this->mail = trim(strtolower($this->mail));
893 /* Call parents save to prepare $this->attrs */
894 plugin::save();
896 /* Save arrays */
897 $this->attrs['gosaMailAlternateAddress'] = $this->gosaMailAlternateAddress;
898 $this->attrs['gosaMailForwardingAddress']= $this->gosaMailForwardingAddress;
900 if(!$this->mailMethod->vacationRangeEnabled()){
901 $this->attrs['gosaVacationStart'] = $this->attrs['gosaVacationStop'] = array();
902 }elseif (!preg_match('/V/', $this->gosaMailDeliveryMode)){
903 unset($this->attrs['gosaVacationStart']);
904 unset($this->attrs['gosaVacationStop']);
905 }
907 /* Map method attributes */
908 $this->mailMethod->fixAttributesOnStore();
910 /* Save data to LDAP */
911 $ldap->cd($this->dn);
912 $this->cleanup();
913 $ldap->modify ($this->attrs);
915 if (!$ldap->success()){
916 msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
917 }
919 /* Log last action */
920 if($this->initially_was_account){
921 new log("modify","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
922 }else{
923 new log("create","users/".get_class($this),$this->dn,array_keys($this->attrs),$ldap->get_error());
924 }
926 /* Only do IMAP actions if we are not a template */
927 if (!$this->is_template){
928 $this->mailMethod->connect();
929 if(!$this->mailMethod->is_connected()){
930 msg_dialog::display(_("Mail error"), sprintf(_("Cannot connect mail method! Error was: %s."),
931 $this->mailMethod->get_error()), ERROR_DIALOG);
932 }else{
933 if(!$this->mailMethod->updateMailbox()){
934 msg_dialog::display(_("Mail error"), sprintf(_("Cannot update mailbox! Error was: %s."),
935 $this->mailMethod->get_error()), ERROR_DIALOG);
936 }
937 if(!$this->mailMethod->setQuota($this->gosaMailQuota)){
938 msg_dialog::display(_("Mail error"), sprintf(_("Cannot write quota settings! Error was: %s."),
939 $this->mailMethod->get_error()), ERROR_DIALOG);
940 }
942 if (!is_integer(strpos($this->gosaMailDeliveryMode, "C"))){
943 if(!$this->mailMethod->saveSieveSettings()){
944 msg_dialog::display(_("Mail error"), $this->mailMethod->get_error(), ERROR_DIALOG);
945 }
946 }else{
948 echo "Check sieve management here";
950 @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,
951 "User uses an own sieve script, skipping sieve update.".$str."</b>","");
952 }
954 if(!$this->mailMethod->updateSharedFolder()){
955 msg_dialog::display(_("Mail error"), sprintf(_("Cannot update shared folder permissions! Error was: %s."),
956 $this->mailMethod->get_error()), ERROR_DIALOG);
957 }
958 }
959 }
960 $this->mailMethod->disconnect();
962 /* Optionally execute a command after we're done */
963 if ($this->initially_was_account == $this->is_account){
964 if ($this->is_modified){
965 $this->handle_post_events("modify", array("uid" => $this->uid));
966 }
967 } else {
968 $this->handle_post_events("add", array("uid" => $this->uid));
969 }
970 }
973 /*! \brief Check given values
974 */
975 function check()
976 {
977 if(!$this->is_account){
978 return(array());
979 }
981 $ldap= $this->config->get_ldap_link();
983 /* Call common method to give check the hook */
984 $message= plugin::check();
986 if(empty($this->gosaMailServer)){
987 $message[]= msgPool::noserver(_("Mail"));
988 }
990 /* Mail address checks */
991 $mail = $this->mail;
992 if($this->mailMethod->domainSelectionEnabled()){
993 $mail.= "@".$this->mailDomainPart;
994 }
996 if (empty($mail)){
997 $message[]= msgPool::required(_("Primary address"));
998 }
999 if ($this->is_template){
1000 if (!tests::is_email($mail, TRUE)){
1001 $message[]= msgPool::invalid(_("Mail address"),"","","%givenName.%sn@your-domain.com");
1002 }
1003 } else {
1004 if (!tests::is_email($mail)){
1005 $message[]= msgPool::invalid(_("Mail address"),"","","your-address@your-domain.com");
1006 }
1007 }
1009 /* Check if this mail address is already in use */
1010 $ldap->cd($this->config->current['BASE']);
1011 $filter = "(&(!(objectClass=gosaUserTemplate))(!(uid=".$this->uid."))".
1012 "(objectClass=gosaMailAccount)".
1013 "(|(mail=".$mail.")(alias=".$mail.")(gosaMailAlternateAddress=".$mail.")))";
1014 $ldap->search($filter,array("uid"));
1015 if ($ldap->count() != 0){
1016 $message[]= msgPool::duplicated(_("Mail address"));
1017 }
1020 /* Check quota */
1021 if ($this->gosaMailQuota != '' && $this->acl_is_writeable("gosaMailQuota")){
1022 if (!is_numeric($this->gosaMailQuota)) {
1023 $message[]= msgPool::invalid(_("Quota size"),$this->gosaMailQuota,"/^[0-9]*/");
1024 } else {
1025 $this->gosaMailQuota= (int) $this->gosaMailQuota;
1026 }
1027 }
1029 /* Check rejectsize for integer */
1030 if ($this->gosaMailMaxSize != '' && $this->acl_is_writeable("gosaMailMaxSize")){
1031 if (!is_numeric($this->gosaMailMaxSize)){
1032 $message[]= msgPool::invalid(_("Mail reject size"),$this->gosaMailMaxSize,"/^[0-9]*/");
1033 } else {
1034 $this->gosaMailMaxSize= (int) $this->gosaMailMaxSize;
1035 }
1036 }
1038 /* Need gosaMailMaxSize if use_mailsize_limit is checked */
1039 if (is_integer(strpos($this->gosaMailDeliveryMode, "R")) && $this->gosaMailMaxSize == ""){
1040 $message[]= msgPool::required(_("Mail reject size"));
1041 }
1043 if((preg_match("/S/", $this->gosaMailDeliveryMode))&&(empty($this->gosaSpamMailbox))) {
1044 $message[]= msgPool::required(_("Spam folder"));
1045 }
1047 if ($this->mailMethod->vacationRangeEnabled()
1048 && preg_match('/V/', $this->gosaMailDeliveryMode)
1049 && $this->gosaVacationStart > $this->gosaVacationStop){
1050 $message[]= msgPool::invalid(_("Vacation interval"));
1051 }
1052 return($message);
1053 }
1056 /*! \brief Adapt from template, using 'dn'
1057 */
1058 function adapt_from_template($dn, $skip= array())
1059 {
1060 plugin::adapt_from_template($dn, $skip);
1062 foreach (array("gosaMailAlternateAddress", "gosaMailForwardingAddress") as $val){
1064 if (in_array($val, $skip)){
1065 continue;
1066 }
1068 $this->$val= array();
1069 if (isset($this->attrs["$val"]["count"])){
1070 for ($i= 0; $i<$this->attrs["$val"]["count"]; $i++){
1071 $value= $this->attrs["$val"][$i];
1072 foreach (array("sn", "givenName", "uid") as $repl){
1073 if (preg_match("/%$repl/i", $value)){
1074 $value= preg_replace ("/%$repl/i", $this->parent->$repl, $value);
1075 }
1076 }
1077 array_push($this->$val, strtolower(rewrite($value)));
1078 }
1079 }
1080 }
1081 $this->mail= strtolower(rewrite($this->mail));
1082 }
1085 /*! \brief Creates the mail part for the copy & paste dialog
1086 */
1087 function getCopyDialog()
1088 {
1089 if(!$this->is_account) return("");
1090 $smarty = get_smarty();
1091 $smarty->assign("mail",$this->mail);
1092 $smarty->assign("gosaMailAlternateAddress",$this->gosaMailAlternateAddress);
1093 $smarty->assign("gosaMailForwardingAddress",$this->gosaMailForwardingAddress);
1094 $str = $smarty->fetch(get_template_path("copypaste.tpl",TRUE, dirname(__FILE__)));
1096 $ret = array();
1097 $ret['status'] = "";
1098 $ret['string'] = $str;
1099 return($ret);
1100 }
1103 /*! \brief save_object for copy&paste vars
1104 */
1105 function saveCopyDialog()
1106 {
1107 if(!$this->is_account) return;
1109 /* Execute to save mailAlternateAddress && gosaMailForwardingAddress */
1110 $this->execute();
1111 if(isset($_POST['mail'])){
1112 $this->mail = $_POST['mail'];
1113 }
1114 }
1117 /*! \brief Prepare this account to be copied
1118 */
1119 function PrepareForCopyPaste($source)
1120 {
1121 plugin::PrepareForCopyPaste($source);
1123 /* Reset alternate mail addresses */
1124 $this->gosaMailAlternateAddress = array();
1125 }
1128 /*! \brief Prepare this class the be useable when editing multiple users at once
1129 */
1130 function get_multi_edit_values()
1131 {
1132 $ret = plugin::get_multi_edit_values();
1133 if(in_array("gosaMailQuota",$this->multi_boxes)){
1134 $ret['gosaMailQuota'] = $this->gosaMailQuota;
1135 }
1136 $flag_add = $flag_remove = array();
1137 $tmp= preg_replace("/[^a-z]/i","",$this->gosaMailDeliveryMode);
1138 $opts = array(
1139 "R" => "use_mailsize_limit",
1140 "S" => "use_spam_filter",
1141 "L" => "only_local",
1142 "V" => "use_vacation",
1143 "C" => "own_script",
1144 "I" => "drop_own_mails");
1145 foreach($opts as $flag => $post){
1146 if(in_array($post, $this->multi_boxes)){
1147 if(preg_match("/".$flag."/",$tmp)){
1148 $flag_add[] = $flag;
1149 }else{
1150 $flag_remove[] = $flag;
1151 }
1152 }
1153 }
1154 $ret['flag_add'] = $flag_add;
1155 $ret['flag_remove'] = $flag_remove;
1156 return($ret);
1157 }
1160 /*! \brief Check given input for multiple user edit
1161 */
1162 function multiple_check()
1163 {
1164 $message = plugin::multiple_check();
1166 if(empty($this->gosaMailServer) && in_array("gosaMailServer",$this->multi_boxes)){
1167 $message[]= msgPool::noserver(_("Mail"));
1168 }
1170 /* Check quota */
1171 if ($this->gosaMailQuota != '' && in_array("gosaMailQuota",$this->multi_boxes)){
1172 if (!is_numeric($this->gosaMailQuota)) {
1173 $message[]= msgPool::invalid(_("Quota size"),$this->gosaMailQuota,"/^[0-9]*/");
1174 } else {
1175 $this->gosaMailQuota= (int) $this->gosaMailQuota;
1176 }
1177 }
1179 /* Check rejectsize for integer */
1180 if ($this->gosaMailMaxSize != '' && in_array("gosaMailMaxSize",$this->multi_boxes)){
1181 if (!is_numeric($this->gosaMailMaxSize)){
1182 $message[]= msgPool::invalid(_("Mail reject size"),$this->gosaMailMaxSize,"/^[0-9]*/");
1183 } else {
1184 $this->gosaMailMaxSize= (int) $this->gosaMailMaxSize;
1185 }
1186 }
1188 if(empty($this->gosaSpamMailbox) && in_array("gosaSpamMailbox",$this->multi_boxes)){
1189 $message[]= msgPool::required(_("Spam folder"));
1190 }
1192 if ( in_array("use_vacation",$this->multi_boxes) &&
1193 preg_match('/V/', $this->gosaMailDeliveryMode) && $this->gosaVacationStart > $this->gosaVacationStop){
1194 $message[]= msgPool::invalid(_("Vacation interval"));
1195 }
1196 return($message);
1197 }
1200 /*! \brief ...
1201 */
1202 function set_multi_edit_values($values)
1203 {
1204 plugin::set_multi_edit_values($values);
1205 $tmp= preg_replace("/[^a-z]/i","",$this->gosaMailDeliveryMode);
1206 if(isset($values['flag_add'])){
1207 foreach($values['flag_add'] as $flag){
1208 if(!preg_match("/".$flag."/",$tmp)){
1209 $tmp .= $flag;
1210 }
1211 }
1212 }
1213 if(isset($values['flag_remove'])){
1214 foreach($values['flag_remove'] as $flag){
1215 if(preg_match("/".$flag."/",$tmp)){
1216 $tmp = preg_replace("/".$flag."/","",$tmp);
1217 }
1218 }
1219 }
1220 $this->gosaMailDeliveryMode = "[".$tmp."]";
1222 /* Set vacation message and replace placeholder like %givenName
1223 */
1224 if(isset($values['gosaVacationMessage'])){
1225 $this->gosaVacationMessage = $this->prepare_vacation_template($values['gosaVacationMessage']);
1226 }
1227 }
1230 /*! \brief Initialize plugin to be used as multiple edit class.
1231 */
1232 function init_multiple_support($attrs,$all)
1233 {
1234 plugin::init_multiple_support($attrs,$all);
1235 if(isset($this->multi_attrs['gosaMailQuota'])){
1236 $this->gosaMailQuota = $this->multi_attrs['gosaMailQuota'];
1237 }
1238 }
1241 /*! \brief
1242 */
1243 function get_multi_init_values()
1244 {
1245 $attrs = plugin::get_multi_init_values();
1246 $attrs['gosaMailQuota'] = $this->gosaMailQuota;
1247 return($attrs);
1248 }
1251 /*! \brief Display multiple edit dialog
1252 */
1253 function multiple_execute()
1254 {
1255 return($this->execute());
1256 }
1259 /*! \brief Save posts from multiple edit dialog
1260 */
1261 function multiple_save_object()
1262 {
1263 plugin::multiple_save_object();
1265 $this->save_object();
1266 foreach(array("only_local","gosaMailForwardingAddress","use_mailsize_limit","drop_own_mails","use_vacation","use_spam_filter") as $attr){
1267 if(isset($_POST["use_".$attr])){
1268 $this->multi_boxes[] = $attr;
1269 }
1270 }
1271 }
1274 /*! \brief Creates the user names for the add_local_forward dialog
1275 */
1276 function make_name($attrs)
1277 {
1278 $name= "";
1279 if (isset($attrs['sn'][0])){
1280 $name= $attrs['sn'][0];
1281 }
1282 if (isset($attrs['givenName'][0])){
1283 if ($name != ""){
1284 $name.= ", ".$attrs['givenName'][0];
1285 } else {
1286 $name.= $attrs['givenName'][0];
1287 }
1288 }
1289 if ($name != ""){
1290 $name.= " ";
1291 }
1293 return ($name);
1294 }
1297 /*! \brief ACL settings
1298 */
1299 static function plInfo()
1300 {
1301 return (array(
1302 "plShortName" => _("Mail"),
1303 "plDescription" => _("Mail settings"),
1304 "plSelfModify" => TRUE,
1305 "plDepends" => array("user"), // This plugin depends on
1306 "plPriority" => 4, // Position in tabs
1307 "plSection" => array("personal" => _("My account")),
1308 "plCategory" => array("users"),
1309 "plOptions" => array(),
1311 "plProvidedAcls" => array(
1312 "mail" => _("Mail address"),
1313 "gosaMailServer" => _("Mail server"),
1314 "gosaMailQuota" => _("Quota size"),
1316 "gosaMailDeliveryModeV" => _("Add vacation information"), // This is flag of gosaMailDeliveryMode
1317 "gosaVacationMessage" => _("Vacation message"),
1319 "gosaMailDeliveryModeS" => _("Use spam filter"), // This is flag of gosaMailDeliveryMode
1320 "gosaSpamSortLevel" => _("Spam level"),
1321 "gosaSpamMailbox" => _("Spam mail box"),
1323 "sieveManagement" => _("Sieve management"),
1325 "gosaMailDeliveryModeR" => _("Reject due to mailsize"), // This is flag of gosaMailDeliveryMode
1326 "gosaMailMaxSize" => _("Mail max size"),
1328 "gosaMailForwardingAddress" => _("Forwarding address"),
1329 "gosaMailDeliveryModeL" => _("Local delivery"), // This is flag of gosaMailDeliveryMode
1330 "gosaMailDeliveryModeI" => _("No delivery to own mailbox "), // This is flag of gosaMailDeliveryMode
1331 "gosaMailAlternateAddress" => _("Mail alternative addresses"),
1333 "gosaMailForwardingAddress" => _("Forwarding address"),
1334 "gosaMailDeliveryModeC" => _("Use custom sieve script")) // This is flag of gosaMailDeliveryMode
1335 ));
1336 }
1339 }
1341 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
1342 ?>