Patch title: Release 94 bulk changes
Abstract:
File: /pliant/protocol/smtp/mail.page
Key:
    Removed line
    Added line
module "/pliant/language/unsafe.pli"
module "/pliant/language/stream.pli"
module "/pliant/language/context.pli"
module "/pliant/admin/md5.pli"
module "/pliant/admin/file.pli"
module "/pliant/fullpliant/this_computer.pli"
module "/pliant/fullpliant/password.pli"
module "mail.pli"

requires "browse_configuration"

title "Mailboxes administration"

para
  note "mail system global settings for this computer"
    read_only not allowed:"administrator"
    title "This computer mails settings"
    header "General settings"
      table columns 3 border 0
        cell [SMTP service:]
        cell
          var Str smtp := this_computer "pliant" "mail" "smtp_service"
          select "" smtp
            option "No" "false"
            option "Yes" "true"
        cell [Should we run the SMTP service on this server ?]
        cell [POP3 service:]
        cell
          var Str pop3 := this_computer "pliant" "mail" "pop3_service"
          select "" pop3
            option "No" "false"
            option "Yes" "true"
        cell [Should we run the POP3 service on this server ?]
        cell [Mailboxes redirect daemon:]
        cell
          var Str redirect := this_computer "pliant" "mail" "redirect_service"
          select "" redirect
            option "No" "false"
            option "Yes" "true"
        cell [Should we run the mailboxes redirection daemon on this server ?]
        cell [Mailboxes path:]
        cell
          var Str path := this_computer "pliant" "mail" "path"
          if path=""
            path := "data:/pliant/mail/"
          input "" path length 30 noeol
        cell
          [Where the mailboxes are stored on this computer.] ; eol
          [Keep in mind that a Pliant path starting with] ; fixed [ / ] ; [is specifying a directory within Pliant tree. If you want to specify a directory outside Pliant tree, it must start with] ; fixed [ file:/] ; eol
          [Futhermore, a Pliant path must end with a] ; fixed [ /]
    header "SMTP service"
      table columns 3 border 0
        cell [Name:]
        cell
          var Str name := this_computer "pliant" "mail" "smtp_name"
          input "" name length 20 noeol
        cell
          [The name this computer will give to others when they connect to it using SMTP protocol. ]
          [If blank,] ; fixed (text " "+computer_fullname+" ") ; [will be used.]
        cell [Log file:]
        cell
          var Str log := this_computer "pliant" "mail" "smtp_log"
          input "" log length 30 noeol
        cell [If not empty, all dialogs with SMTP clients connecting to this SMTP server will be logged in the specifyed file.]
    header "Forwarding messages"
      table columns 3 border 0
        cell [Next server:]
        cell
          var Str route := this_computer "pliant" "mail" "forward_route"
          input "" route length 20 noeol
        cell [If set, all mails will be forwarded to the specifyed SMTP server instead of querying the DNS.]
        cell [ISP SMTP server:]
        cell
          var Str isp := this_computer "pliant" "mail" "forward_isp"
          input "" isp length 20 noeol
        cell [If set, a web mail user will be abble to force a mail to be forwarded to this server if the target domain mail server refuses to receive directly.]
        cell [Threads:]
        cell
          var Str threads := this_computer "pliant" "mail" "forward_threads"
          input "" threads length 3 noeol
        cell [How many mails should we try to forward at once.]
        cell [Sleep:]
        cell
          var Str sleep := this_computer "pliant" "mail" "forward_sleep"
          input "" sleep length 4 noeol
        cell [When we tryed to forward all messages, how many time (in seconds) should we get asleep in order to free the processor for other tasks.]
    header "Redirecting mailboxes"
      table columns 3 border 0
        cell [Threads:]
        cell
          var Str r_threads := this_computer "pliant" "mail" "redirect_threads"
          input "" r_threads length 3 noeol
        cell [How many mailboxes should we try to redirect at once.]
        cell [Sleep:]
        cell
          var Str r_sleep := this_computer "pliant" "mail" "redirect_sleep"
          input "" r_sleep length 4 noeol
        cell [When we tryed to redirect all mailboxes, how many time (in seconds) should we get asleep in order to free the processor for other tasks.]
    if allowed:"administrator"
      button "Update"
        this_computer "pliant" "mail" "smtp_service" := smtp
        this_computer "pliant" "mail" "pop3_service" := pop3
        this_computer "pliant" "mail" "redirect_service" := redirect
        this_computer "pliant" "mail" "path" := path
        this_computer "pliant" "mail" "smtp_name" := name
        this_computer "pliant" "mail" "smtp_log" := log
        this_computer "pliant" "mail" "forward_route" := route
        this_computer "pliant" "mail" "forward_isp" := isp
        this_computer "pliant" "mail" "forward_threads" := threads
        this_computer "pliant" "mail" "forward_sleep" := sleep
        this_computer "pliant" "mail" "redirect_threads" := r_threads
        this_computer "pliant" "mail" "redirect_sleep" := r_sleep
        goto_backward
  eol
  if allowed:"administrator"
    page note "mails cleanup"
      var Int days := 365 ; var Int kb := 8192 ; var Bool spams := false
      title "Mails cleanup"
      [Remove mails that are] ; eol
      input "more than " days length 4 noeol ; [ days old] ; eol
      input "and more than " kb noeol length 5 ; [ KB big.] ; eol
      select "Also remove all spams that are older than selected date: " spams
        option "no" "false"
        option "yes" "true"
      var DateTime now := datetime
      page button "Run an intitial study"
        var Int drop_count := 0 ; var Intn drop_bytes := 0
        var Int keep_count := 0 ; var Intn keep_bytes := 0
        each m mailbox
          for (var Int lap) 0 1
            var Array:FileInfo files := file_list (shunt lap=0 m:in_path m:archive_path) standard+recursive
            for (var Int i) 0 files:size-1
              if now:seconds-files:i:datetime:seconds>days*86400 and (files:i:size>kb*1024n or spams and { (var Stream s) open files:i:name in+safe ; var CBool spam := s:readline="spam" ; s close ; spam })
                drop_count += 1 ; drop_bytes += files:i:size
              else
                keep_count += 1 ; keep_bytes += files:i:size
        title "Mails cleanup initial study"
        table columns 3
          cell void ; cell header [Count] ; cell header [Space]
          cell header [Drop] ; cell (text string:drop_count) ; cell (text (string drop_bytes\2^20)+" MB")
          cell header [Keep] ; cell (text string:keep_count) ; cell (text (string keep_bytes\2^20)+" MB")
        button "Do delete selected mails" noeol
          each m mailbox
            for (var Int lap2) 0 1
              var Array:FileInfo files2 := file_list (shunt lap2=0 m:in_path m:archive_path) standard+recursive
              for (var Int i) 0 files2:size-1
                if now:seconds-files2:i:datetime:seconds>days*86400 and (files2:i:size>kb*1024n or spams and { (var Stream s2) open files2:i:name in+safe ; var CBool spam2 := s2:readline="spam" ; s2 close ; spam2 })
                  file_delete files2:i:name       
          goto_backward 2
        button "Cancel"
          goto_backward 2


header "Mailboxes"
  table columns (shunt allowed:"administrator" 4 3)
    cell header
      [Mailbox ID]
    cell header
      [Description]
    if allowed:"administrator"
      cell header
        [Content]
    cell
      void
    each m mailbox
      cell
        fixed (text keyof:m) ; eol
        text m:name
      cell
        text m:abstract
      if allowed:"administrator"
        cell
          small
            var Array:FileInfo in_files := file_list m:in_path standard
            var Array:FileInfo out_files := file_list m:out_path standard
            if in_files:size>0
              var Int count := 0
              var DateTime now := datetime
              var DateTime older := now
              for (var Int i) 0 in_files:size-1
                if in_files:i:extension=".mail" and in_files:i:datetime<older
                  count += 1 ; older := in_files:i:datetime
              var Int days := now:date:days-older:date:days
              text string:count+" in mail"+(shunt count>1 "s" "")
              fixed [ ] ; text string:days+" day"+(shunt days>1 "s" "")
              if out_files:size>0 eol
            if out_files:size>0
              var Int count := 0 ; var Intn total := 0
              for (var Int i) 0 out_files:size-1
                if out_files:i:extension=".mail"
                  count += 1 ; total += out_files:i:size
              text string:count+" out mail"+(shunt count>1 "s" "")
              fixed [ ] ; text (string total\2^20)+" MB"
      cell
        button "Edit"
          read_only not allowed:"administrator"
          title "Mailbox '"+keyof:m+"'"
          header "Basic informations"
            table columns 3 border 0
              cell
                [Mailbox ID:]
              cell
                fixed (text keyof:m)
              cell
                []
              cell
                [User name:]
              cell
                input "" m:name
              cell
                [The usual name of the guy owning the mailbox.]
              cell
                [Computer:]
              cell
                input "" m:computer
              cell
                [The full name of the computer handling the mailbox.]
              cell
                [IP:]
              cell
                select "" m:check_ip
                  option "Must be correct" "true"
                  option "Not checked" "false"
              cell
                [You can ask to reject mails from domains or servers that have no IP address since they are usually spams.]
              cell
                [From:]
              cell
                select "" m:check_from
                  option "Must be correct" "true"
                  option "Not checked" "false"
              cell
                [You can ask to reject mails with an improper or missing 'From' field in the mail header since they are usually spams.]
              cell
                [To/Cc:]
              cell
                select "" m:check_to
                  option "Must be correct" "true"
                  option "Not checked" "false"
              cell
                [You can ask to reject mails with a missing 'To' or 'Cc' field in the mail header, usually called hidden copy.] ; eol
                [The problem here is that mails sent from mailing lists may also be rejected if the 'To' field is not set.]
              cell
                [Auto answer:]
              cell
                text_input "" m:auto_answer columns 40 rows 3
              cell
                [If this field is not empty, anybody sending a mail here will automatically receive the specified answer.]
              cell
                [Archive:]
              cell
                select "" m:archive
                  option "yes" "true"
                  option "no" "false"
              cell
                [Should the server keep a copy of the mails in the archives directory.]
            table columns 2 border 0
              cell [Description:]
              cell (text_input "" m:abstract rows 5 columns 60)
          header "Accessing mails using an external mailer (optional)"
            table columns 3 border 0
              cell
                [SMTP IP:]
              cell
                input "" m:smtp_ip
              cell
                [Only clients connecting from the specifyed IP areas will be abble to send mails using this mailbox.] ; eol
                [If empty, no client will be allowed to post out mails in this mailbox using an SMTP client such as Netscape.] ; eol
                note "extra details"
                  title "IP field"
                  [This is used to restrict the computers the user is allowed to connect from. ]
                  [As an example, you may want to specify that a use can connect from the intranet, but not from the Internet.]
                  para
                    [An axample can be:] ; fixed [ 127.0.0.1 10.30.144.0/255.255.255.0 ] ; eol
                    [and it means either 127.0.0.1 or 10.30.144.xxx IP address.]
              cell
                [POP3:]
              cell
                select "" m:pop3_level
                  option "Not allowed on this mailbox" "0"
                  option "Can be used only to detect new messages" "1"
                  option "Can read messages" "2"
                  option "Can read and remove messages" "3"
              cell
                []
              cell
                [POP3 IP:]
              cell
                input "" m:pop3_ip
              cell
                [If not empty, only clients connecting from the specifyed IP areas will be abble to use this mailbox.] ; eol
                note "extra details"
                  title "IP field"
                  [This is used to restrict the computers the user is allowed to connect from. ]
                  [As an example, you may want to specify that a use can connect from the intranet, but not from the Internet.]
                  para
                    [An axample can be:] ; fixed [ 127.0.0.1 10.30.144.0/255.255.255.0 ] ; eol
                    [and it means either 127.0.0.1 or 10.30.144.xxx IP address.]
              cell
                [POP3 password:]
              cell
                if allowed:"administrator"
                  input "" (var Str password) password
              cell
                [Type in the clear password that the POP3 client, such as Netscape, must provide to pick mails from this mailbox.] ; eol
                [In the mailboxes database, only the MD5 digest of the password is stored.]
          header "Relay computer (optional)"
            [You will use a relay computer when the server handling the mailbox is not permanently connected to the Internet.]
            table columns 3 border 0
              cell
                [Relay computer:]
              cell
                input "" m:relay_computer
              cell
                [You will use a relay computer if the computer handling the mailbox is not directly and permanently connected to the Internet. ]
                [In such a case, the MX field of the domain the box belongs to should point the relay computer. This one will accept mails and forward them to the computer handling the mailbox, and accept outgoing mails and forward them over the Internet.]
              cell
                [Archive:]
              cell
                select "" m:relay_archive
                  option "no" "false"
                  option "yes" "true"
              cell
                [Should the relay computer also keep a copy of the mails in the archives directory.]
          header "Mailing list (optional)"
            select "This is a mailing list: " m:list
              option "no" "false"
              option "yes" "true"
            [Subscribers:]
            table columns 2
              cell header [Line ID]
              cell header [Mailbox]
              each s m:subscriber
                cell
                  text keyof:s
                cell
                  input "" s length 30
            if allowed:"administrator"
              input "Line ID: " (var Str sid) length 10 noeol
              button "Add a line" noeol
                m:subscriber create sid
                reload_page
              button "Remove a line"
                m:subscriber delete sid
                reload_page
          header "Advanced settings (not recommended)"
            table columns 3 border 0
              cell
                [Mailbox path:]
              cell
                input "" m:path
              cell
                [Where mails related to this mailbox are stored and archived.] ; eol
                [You should leave this field blank most of the time since the global mailboxes path setting should be enough.]
              cell
                [Mailbox options:]
              cell
                input "" m:options length 40
              cell
                [Extra informations you can use in some of your custom plugins.]
          if allowed:"administrator"
            button "Update mailbox informations"
              if password<>""
                mail_secret_database:data:box create keyof:m
                mail_secret_database:data:box:(keyof m) pop3_password_md5 := string_md5_hexa_signature password
              goto_backward
  if allowed:"administrator"
    input "Mailbox ID: " (var Str mid) length 30 noeol
    button "Create the new mailbox" noeol
      mailbox create mid
      reload_page
    button "Delete the mailbox"
      mailbox delete mid
      mail_secret_database:data:box delete mid
      reload_page

header "Redirections"
  table columns 4
    cell header
      [Line ID]
    cell header
      [User / Server]
    cell header
      [Status]
    cell void
    each r mail_database:data:redirect
      cell
        text keyof:r
      cell
        text r:user+" / "+r:pop3_server
      cell
        text (shunt r:error="" "ok" "trouble")
      cell
        button "edit"
          read_only not allowed:"administrator"
          title "Mail redirect definition"
          table columns 3 border 0
            cell header [pick mails from] ; cell void ; cell void
            cell
              [POP3 server:]
            cell
              input "" r:pop3_server
            cell
              []
            cell
              [POP3 user:]
            cell
              input "" r:user
            cell
              []
            cell
              [POP3 password:]
            cell
              var Str pwd := password r:pop3_server r:user
              input "" (var Str pwd) password
            cell
              []
            cell header [put mails on] ; cell void ; cell void
            cell
              [SMTP server:]
            cell
              input "" r:smtp_server
            cell
              []
            cell
              [Mailbox:]
            cell
              input "" r:mailbox length 30
            cell
              []
            cell header [status] ; cell void ; cell void
            cell
              [Status:]
            cell
              text (shunt r:error="" "ok" r:error)
            cell
              []
          if allowed:"administrator"
            button "Update redirect informations"
              if pwd<>""
                password create r:pop3_server
                password:(r:pop3_server) create r:user
                password:(r:pop3_server):(r:user) password := pwd
              goto_backward
  if allowed:"administrator"
    input "Redirect ID: " (var Str rid) length 3 noeol
    button "Create the new redirection" noeol
      mail_database:data:redirect create rid
      reload_page
    button "Delete the redirection"
      mail_database:data:redirect delete rid
      reload_page

header "Blacklist"

  header "DNS"
    para
      [A DNS specified here will be queried for spammers.] ; eol
      [An example could be: ] ; fixed [spam.dnsrbl.net]
    table columns 1
      cell header
        [DNS]
      each b mail_database:data:black_dns
        cell
          text keyof:b
    if allowed:"administrator"
      input "DNS: " (var Str bdns) noeol
      button "Record this DNS" noeol
        mail_database:data:black_dns create bdns
        reload_page
      button "Remove this DNS"
        mail_database:data:black_dns delete bdns
        reload_page

  header "Mail boxes"
    para
      [A mail from a mailbox or domain listed here will always be rejected.]
    table columns 1
      cell header
        [Mailbox or domain]
      each b mail_database:data:black_from
        cell
          text keyof:b
    if allowed:"administrator"
      input "Mailbox or domain: " (var Str bfrom) noeol
      button "Blacklist it" noeol
        mail_database:data:black_from create bfrom
        reload_page
      button "Remove from blacklist"
        mail_database:data:black_from delete bfrom
        reload_page

  header "SMTP server IP"
    para
      [A mail from a computer which IP address is listed here will always be rejected.]
    table columns 1
      cell header
        [IP]
      each b mail_database:data:black_ip
        cell
          text keyof:b
    if allowed:"administrator"
      input "Serve IP: " (var Str bip) length 12 noeol
      button "Blacklist it" noeol
        mail_database:data:black_ip create bip
        reload_page
      button "Remove from blacklist"
        mail_database:data:black_ip delete bip
        reload_page

  header "SMTP server name"
    para
      [A mail from a computer which name is listed here will always be rejected.] ; eol
      [The name of the server is provided within the 'HELO' SMTP command.]
    table columns 1
      cell header
        [Name]
      each b mail_database:data:black_name
        cell
          text keyof:b
    if allowed:"administrator"
      input "Server name: " (var Str bname) length 12 noeol
      button "Blacklist it" noeol
        mail_database:data:black_name create bname
        reload_page
      button "Remove from blacklist"
        mail_database:data:black_name delete bname
        reload_page

header "Magic list"

  header "Mail boxes"
    para
      [A mail from a mailbox or domain listed here will always be accepted.]
    table columns 1
      cell header
        [Mailbox or domain]
      each w mail_database:data:magic_from
        cell
          text keyof:w
    if allowed:"administrator"
      input "Mailbox or domain: " (var Str mfrom) noeol
      button "Allow it" noeol
        mail_database:data:magic_from create mfrom
        reload_page
      button "Remove it"
        mail_database:data:magic_from delete mfrom
        reload_page

  header "SMTP server IP"
    para
      [A mail from a computer which IP address is listed here will always be accepted.]
    table columns 1
      cell header
        [IP]
      each w mail_database:data:magic_ip
        cell
          text keyof:w
    if allowed:"administrator"
      input "Server IP: " (var Str mip) length 12 noeol
      button "Allow it" noeol
        mail_database:data:magic_ip create mip
        reload_page
      button "Remove it"
        mail_database:data:magic_ip delete mip
        reload_page

  header "SMTP server name"
    para
      [A mail from a computer which name is listed here will always be accepted.] ; eol
      [The name of the server is provided within the 'HELO' SMTP command.]
    table columns 1
      cell header
        [Name]
      each w mail_database:data:magic_name
        cell
          text keyof:w
    if allowed:"administrator"
      input "Server name: " (var Str mname) length 12 noeol
      button "Allow it" noeol
        mail_database:data:magic_name create mname
        reload_page
      button "Remove it"
        mail_database:data:magic_name delete mname
        reload_page