All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.anrisoftware.sscontrol.mail.postfix.script.linux.BasePostfixScript.groovy Maven / Gradle / Ivy

There is a newer version: 1.0-alpha-4
Show newest version
/*
 * Copyright 2013-2014 Erwin Müller 
 *
 * This file is part of sscontrol-mail-postfix.
 *
 * sscontrol-mail-postfix is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * sscontrol-mail-postfix is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with sscontrol-mail-postfix. If not, see .
 */
package com.anrisoftware.sscontrol.mail.postfix.script.linux

import static org.apache.commons.io.FileUtils.*
import groovy.util.logging.Slf4j

import javax.inject.Inject

import org.apache.commons.io.FileUtils
import org.apache.commons.io.FilenameUtils
import org.joda.time.Duration
import org.stringtemplate.v4.ST

import com.anrisoftware.globalpom.textmatch.tokentemplate.TokenTemplate
import com.anrisoftware.resources.templates.api.TemplateResource
import com.anrisoftware.resources.templates.api.Templates
import com.anrisoftware.resources.templates.api.TemplatesFactory
import com.anrisoftware.sscontrol.core.debuglogging.DebugLogging
import com.anrisoftware.sscontrol.core.debuglogging.DebugLoggingProperty
import com.anrisoftware.sscontrol.core.service.LinuxScript
import com.anrisoftware.sscontrol.mail.api.MailService
import com.anrisoftware.sscontrol.mail.certificate.Certificate
import com.anrisoftware.sscontrol.mail.postfix.linux.AuthConfig
import com.anrisoftware.sscontrol.mail.postfix.linux.BasePostfixScriptLogger
import com.anrisoftware.sscontrol.mail.postfix.linux.BindAddressesRenderer
import com.anrisoftware.sscontrol.mail.postfix.linux.DeliveryConfig
import com.anrisoftware.sscontrol.mail.postfix.linux.DurationRenderer
import com.anrisoftware.sscontrol.mail.postfix.linux.PostfixPropertiesProvider
import com.anrisoftware.sscontrol.mail.postfix.linux.StorageConfig
import com.anrisoftware.sscontrol.mail.statements.User
import com.anrisoftware.sscontrol.scripts.changefilemod.ChangeFileModFactory
import com.anrisoftware.sscontrol.scripts.changefileowner.ChangeFileOwnerFactory
import com.anrisoftware.sscontrol.scripts.unix.ScriptExecFactory
import com.google.inject.Provider

/**
 * Postfix/base configuration.
 *
 * @author Erwin Mueller, [email protected]
 * @since 1.0
 */
@Slf4j
abstract class BasePostfixScript extends LinuxScript {

    @Inject
    BasePostfixScriptLogger logg

    @Inject
    private DebugLoggingProperty debugLoggingProperty

    @Inject
    TemplatesFactory templatesFactory

    @Inject
    ScriptExecFactory scriptExecFactory

    @Inject
    ChangeFileModFactory changeFileModFactory

    @Inject
    ChangeFileOwnerFactory changeFileOwnerFactory

    /**
     * The {@link Templates} for the Postfix/base script.
     */
    Templates basePostfixTemplates

    /**
     * {@code main.cf} configuration templates.
     */
    TemplateResource mainConfigurationTemplate

    /**
     * {@code master.cf} configuration templates.
     */
    TemplateResource masterConfigurationTemplate

    /**
     * {@code /etc/mailname} configuration templates.
     */
    TemplateResource mailnameConfigurationTemplate

    /**
     * {@code postalias} command templates.
     */
    TemplateResource postaliasCommandTemplate

    /**
     * {@code postmap} command templates.
     */
    TemplateResource postmapCommandTemplate

    /**
     * Renderer for {@code inet_interfaces}.
     */
    @Inject
    BindAddressesRenderer bindAddressesRenderer

    /**
     * Renderer for time duration.
     */
    @Inject
    DurationRenderer durationRenderer

    @Inject
    PostfixPropertiesProvider postfixPropertiesProvider

    /**
     * Storages configuration.
     */
    @Inject
    Map> storages

    /**
     * Storages configuration.
     */
    @Inject
    Map> deliveries

    /**
     * Authentication configurations.
     */
    @Inject
    Map> authentications

    /**
     * Returns the profile name of the script.
     */
    abstract String getProfileName()

    @Override
    def run() {
        basePostfixTemplates = templatesFactory.create "BasePostfixScript", templatesAttributes
        mainConfigurationTemplate = basePostfixTemplates.getResource "main_configuration"
        masterConfigurationTemplate = basePostfixTemplates.getResource "master_configuration"
        mailnameConfigurationTemplate = basePostfixTemplates.getResource("mailname_configuration")
        postaliasCommandTemplate = basePostfixTemplates.getResource "postalias_command"
        postmapCommandTemplate = basePostfixTemplates.getResource "postmap_command"
        setupDefaultDebug()
        runDistributionSpecific()
        appendDefaultDestinations()
        deployMailname()
        deployMain()
        deployMaster()
        reconfigureFiles()
        deployStorage()
        deployDelivery()
        deployAuth()
    }

    /**
     * Setups the default debug logging.
     */
    void setupDefaultDebug() {
        if (service.debug == null) {
            service.debug = debugLoggingProperty.defaultDebug this
        }
        if (service.debug.level == null) {
            service.debug.level = 0
        }
    }

    /**
     * Runs distribution-specific configuration before
     * the Postfix/configuration.
     */
    abstract runDistributionSpecific()

    /**
     * Deploy storage configuration.
     */
    def deployStorage() {
        def provider = storages["${storageName}.${profileName}"]
        logg.checkStorageConfig provider, this, storageName, profileName
        def config = provider.get()
        config.script = this
        config.deployStorage()
    }

    /**
     * Deploy delivery configuration.
     */
    def deployDelivery() {
        if (deliveryName == null) {
            return
        }
        def provider = deliveries["${deliveryName}.${storageName}.${profileName}"]
        logg.checkDeliveryConfig provider, this, deliveryName, storageName, profileName
        def config = provider.get()
        config.script = this
        config.deployDelivery()
    }

    /**
     * Deploy authentication configuration.
     */
    def deployAuth() {
        if (authName == null) {
            return
        }
        def provider = authentications["${authName}.${storageName}.${profileName}"]
        logg.checkAuthConfig provider, this, authName, storageName, profileName
        def config = provider.get()
        config.script = this
        config.deployAuth()
    }

    /**
     * Rehash and re-alias files.
     */
    def reconfigureFiles() {
        aliasesDatabaseFile.isFile() ? null : FileUtils.touch(aliasesDatabaseFile)
        realiasFile aliasesDatabaseFile
    }

    /**
     * Append the default destinations.
     */
    void appendDefaultDestinations() {
        service.destinations defaultDestinations
    }

    /**
     * Sets the domain name of the mail server. This is done usually in
     * the {@code /etc/mailname} file.
     *
     * @see #getMailnameFile()
     * @see #getCurrentMailnameConfiguration()
     * @see #getMailnameConfiguration()
     */
    void deployMailname() {
        deployConfiguration configurationTokens(), currentMailnameConfiguration, mailnameConfiguration, mailnameFile
    }

    /**
     * Returns the mail name configuration.
     */
    List getMailnameConfiguration() {
        def template = new TokenTemplate(".*\n", mailnameConfigurationTemplate.getText(true, "name", service.domainName))
        template.enclose = false
        [template]
    }

    /**
     * Sets the main configuration of the mail server. This is done usually in
     * the {@code /etc/postfix/main.cf} file.
     *
     * @see #getMainFile()
     * @see #getAliasMapsFile()
     */
    void deployMain() {
        def configuration = [
            myHostnameConf(),
            myOriginConf(),
            smtpdBannerConf(),
            relayhostConf(),
            inetInterfacesConf(),
            myDestinationConf(),
            masqueradeDomainsConf(),
            aliasMapsConf(),
            aliasDatabaseConf(),
            smtpTlsSecurityLevelConf(),
            smtpdTlsSecurityLevelConf(),
            smtpTlsNoteStarttlsOfferConf(),
            smtpdTlsLoglevelConf(),
            smtpdTlsReceivedHeaderConf(),
            smtpdTlsSessionCacheTimeoutConf(),
            randomSourceConf(),
            certFileConf(),
            keyFileConf(),
            caFileConf(),
            unknownLocalRecipientRejectCodeConf(),
            delayWarningTimeConf(),
            maximalQueueLifetimeConf(),
            minimalRetriesDelayConf(),
            maximumRetriesDelayConf(),
            heloTimeoutConf(),
            recipientLimitConf(),
            backOffErrorLimitConf(),
            blockingErrorLimitConf(),
            heloRestrictionsConf(),
            senderRestrictionsConf(),
            clientRestrictionsConf(),
            recipientRestrictionsConf(),
            dataRestrictionsConf(),
            heloRequiredConf(),
            delayRejectConf(),
            disableVrfyCommandConf(),
        ]
        deployConfiguration configurationTokens(), currentMainConfiguration, configuration, mainFile
    }

    def myHostnameConf() {
        def replace = mainConfigurationTemplate.getText(true, "hostnameConfig", "mail", service)
        def search = mainConfigurationTemplate.getText(true, "hostnameConfig_search")
        new TokenTemplate(search, replace, escape: false)
    }

    def myOriginConf() {
        def replace = mainConfigurationTemplate.getText(true, "originConfig", "mail", service)
        def search = mainConfigurationTemplate.getText(true, "originConfig_search")
        new TokenTemplate(search, replace, escape: false)
    }

    def smtpdBannerConf() {
        def replace = mainConfigurationTemplate.getText(true, "bannerConfig", "banner", banner)
        def search = mainConfigurationTemplate.getText(true, "bannerConfig_search")
        new TokenTemplate(search, replace, escape: false)
    }

    def relayhostConf() {
        def replace = mainConfigurationTemplate.getText(true, "relayhostConfig", "mail", service)
        def search = mainConfigurationTemplate.getText(true, "relayhostConfig_search")
        new TokenTemplate(search, replace, escape: false)
    }

    def inetInterfacesConf() {
        def replace = mainConfigurationTemplate.getText(true, "interfacesConfig", "mail", service)
        def search = mainConfigurationTemplate.getText(true, "interfacesConfig_search")
        new TokenTemplate(search, replace, escape: false)
    }

    def myDestinationConf() {
        def replace = mainConfigurationTemplate.getText(true, "destinationsConfig", "mail", service)
        def search = mainConfigurationTemplate.getText(true, "destinationsConfig_search")
        new TokenTemplate(search, replace, escape: false)
    }

    def masqueradeDomainsConf() {
        def replace = mainConfigurationTemplate.getText(true, "masqueradeDomainsConfig", "mail", service)
        def search = mainConfigurationTemplate.getText(true, "masqueradeDomainsConfig_search")
        new TokenTemplate(search, replace, escape: false)
    }

    def aliasMapsConf() {
        def replace = mainConfigurationTemplate.getText(true, "aliasMapsConfig", "file", aliasesMapsFile)
        def search = mainConfigurationTemplate.getText(true, "aliasMapsConfig_search")
        new TokenTemplate(search, replace, escape: false)
    }

    def aliasDatabaseConf() {
        def replace = mainConfigurationTemplate.getText(true, "aliasDatabaseConfig", "file", aliasesDatabaseFile)
        def search = mainConfigurationTemplate.getText(true, "aliasDatabaseConfig_search")
        new TokenTemplate(search, replace, escape: false)
    }

    def smtpTlsSecurityLevelConf() {
        if (service.certificate == null) {
            return []
        }
        def replace = mainConfigurationTemplate.getText(true, "smtpTlsSecurityLevelConfig", "level", smtpTlsSecurityLevel)
        def search = mainConfigurationTemplate.getText(true, "smtpTlsSecurityLevelConfig_search")
        new TokenTemplate(search, replace, escape: false)
    }

    /**
     * Returns the SMTP TLS security level, for example {@code "may"}, see
     * smtp_tls_security_level [postfix.org].
     *
     * 
    *
  • profile property {@code "smtp_tls_security_level"}
  • *
* * @see #getPostfixProperties() */ String getSmtpTlsSecurityLevel() { profileProperty "smtp_tls_security_level", defaultProperties } def smtpdTlsSecurityLevelConf() { if (service.certificate == null) { return [] } def replace = mainConfigurationTemplate.getText(true, "smtpdTlsSecurityLevelConfig", "level", smtpdTlsSecurityLevel) def search = mainConfigurationTemplate.getText(true, "smtpdTlsSecurityLevelConfig_search") new TokenTemplate(search, replace, escape: false) } /** * Returns the SMTPD TLS security level, for example {@code "may"}, see * smtpd_tls_security_level [postfix.org]. * *
    *
  • profile property {@code "smtpd_tls_security_level"}
  • *
* * @see #getPostfixProperties() */ String getSmtpdTlsSecurityLevel() { profileProperty "smtpd_tls_security_level", defaultProperties } def smtpTlsNoteStarttlsOfferConf() { if (service.certificate == null) { return [] } def replace = mainConfigurationTemplate.getText(true, "smtpTlsNoteStarttlsOfferConfig", "enabled", smtpTlsNoteStarttlsOffer) def search = mainConfigurationTemplate.getText(true, "smtpTlsNoteStarttlsOfferConfig_search") new TokenTemplate(search, replace, escape: false) } /** * Returns to log the hostname of a remote SMTP server that offers STARTTLS, for example {@code "true"}, see * smtp_tls_note_starttls_offer [postfix.org]. * *
    *
  • profile property {@code "tls_note_starttls_offer"}
  • *
* * @see #getPostfixProperties() */ boolean getSmtpTlsNoteStarttlsOffer() { profileBooleanProperty "tls_note_starttls_offer", defaultProperties } def smtpdTlsLoglevelConf() { if (service.certificate == null) { return [] } DebugLogging debug = service.debug def tlslevel = debug.args.tlslevel == null ? defaultTlsLevel : debug.args.tlslevel def replace = mainConfigurationTemplate.getText(true, "smtpdTlsLoglevelConfig", "level", tlslevel) def search = mainConfigurationTemplate.getText(true, "smtpdTlsLoglevelConfig_search") new TokenTemplate(search, replace, escape: false) } /** * Returns default TLS logging level, for example {@code "0"}, see * smtpd_tls_loglevel [postfix.org]. * *
    *
  • profile property {@code "default_tls_loglevel"}
  • *
* * @see #getPostfixProperties() */ int getDefaultTlsLevel() { profileNumberProperty "default_tls_loglevel", defaultProperties } def smtpdTlsReceivedHeaderConf() { if (service.certificate == null) { return [] } def replace = mainConfigurationTemplate.getText(true, "smtpdTlsReceivedHeaderConfig", "enabled", smtpdTlsReceivedHeader) def search = mainConfigurationTemplate.getText(true, "smtpdTlsReceivedHeaderConfig_search") new TokenTemplate(search, replace, escape: false) } /** * Returns that the Postfix SMTP server produces Received: message headers, for example {@code "true"}, see * smtpd_tls_received_header [postfix.org]. * *
    *
  • profile property {@code "tls_received_header"}
  • *
* * @see #getPostfixProperties() */ boolean getSmtpdTlsReceivedHeader() { profileBooleanProperty "tls_received_header", defaultProperties } def smtpdTlsSessionCacheTimeoutConf() { if (service.certificate == null) { return [] } def replace = mainConfigurationTemplate.getText(true, "smtpdTlsSessionCacheTimeoutConfig", "time", smtpdTlsSessionCacheTimeout.standardSeconds) def search = mainConfigurationTemplate.getText(true, "smtpdTlsSessionCacheTimeoutConfig_search") new TokenTemplate(search, replace, escape: false) } /** * Returns the expiration time of Postfix SMTP server TLS session cache information, for example {@code "PT1H"}, see * smtpd_tls_session_cache_timeout [postfix.org]. * *
    *
  • profile property {@code "tls_session_cache_timeout"}
  • *
* * @see #getPostfixProperties() */ Duration getSmtpdTlsSessionCacheTimeout() { profileDurationProperty "tls_session_cache_timeout", defaultProperties } def randomSourceConf() { if (service.certificate == null) { return [] } def replace = mainConfigurationTemplate.getText(true, "randomSourceConfig", "source", randomSource) def search = mainConfigurationTemplate.getText(true, "randomSourceConfig_search") new TokenTemplate(search, replace, escape: false) } /** * Returns the external entropy source for the pseudo random number generator pool, for example {@code "dev:/dev/urandom"}, see * tls_random_source [postfix.org]. * *
    *
  • profile property {@code "random_source"}
  • *
* * @see #getPostfixProperties() */ String getRandomSource() { profileProperty "random_source", defaultProperties } def certFileConf() { def file = deployCertFile(service) if (!file) { return [] } def replace = mainConfigurationTemplate.getText(true, "certFileConfig", "file", file) def search = mainConfigurationTemplate.getText(true, "certFileConfig_search") new TokenTemplate(search, replace, escape: false) } /** * Deploys the certificate file to the server. * * @param service * the {@link MailService} service. * * @return the certificate {@code File} or {@code null}. */ File deployCertFile(MailService service) { Certificate cert = service.certificate File file = null if (cert == null) { return file } def name = FilenameUtils.getName cert.cert.path file = new File(certsDir, name) FileUtils.copyURLToFile cert.cert.toURL(), file changeFileOwnerFactory.create( log: log, owner: rootUser, ownerGroup: rootGroup, files: [file], command: chownCommand, this, threads)() changeFileModFactory.create( log: log, mod: "o-rw", files: [file], command: chmodCommand, this, threads)() return file } def keyFileConf() { def file = deployCertKeyFile(service) if (!file) { return [] } def replace = mainConfigurationTemplate.getText(true, "keyFileConfig", "file", file) def search = mainConfigurationTemplate.getText(true, "keyFileConfig_search") new TokenTemplate(search, replace, escape: false) } /** * Deploys the certificate key file to the server. * * @param service * the {@link MailService} service. * * @return the certificate {@code File} or {@code null}. */ File deployCertKeyFile(MailService service) { Certificate cert = service.certificate File file = null if (cert == null) { return file } def name = FilenameUtils.getName cert.key.path file = new File(certKeysDir, name) FileUtils.copyURLToFile cert.key.toURL(), file changeFileOwnerFactory.create( log: log, owner: rootUser, ownerGroup: rootGroup, files: [file], command: chownCommand, this, threads)() changeFileModFactory.create( log: log, mod: "o-rw", files: [file], command: chmodCommand, this, threads)() return file } def caFileConf() { def file = deployCertCaFile(service) if (!file) { return [] } def replace = mainConfigurationTemplate.getText(true, "caFileConfig", "file", file) def search = mainConfigurationTemplate.getText(true, "caFileConfig_search") new TokenTemplate(search, replace, escape: false) } /** * Deploys the certificate CA file to the server. * * @param service * the {@link MailService} service. * * @return the certificate {@code File} or {@code null}. */ File deployCertCaFile(MailService service) { Certificate cert = service.certificate File file = null if (cert == null || cert.ca == null) { return file } def name = FilenameUtils.getName cert.ca.path file = new File(certsDir, name) FileUtils.copyURLToFile cert.ca.toURL(), file changeFileOwnerFactory.create( log: log, owner: rootUser, ownerGroup: rootGroup, files: [file], command: chownCommand, this, threads)() changeFileModFactory.create( log: log, mod: "o-rw", files: [file], command: chmodCommand, this, threads)() return file } /** * Deploys the certificate PEM file to the server. * * @param service * the {@link MailService} service. * * @return the certificate {@code File} or {@code null}. */ File deployCertPemFile(MailService service) { Certificate cert = service.certificate File file = null if (cert == null || cert.pem == null) { return file } def name = FilenameUtils.getName cert.pem.path file = new File(certsDir, name) FileUtils.copyURLToFile cert.pem.toURL(), file changeFileOwnerFactory.create( log: log, owner: rootUser, ownerGroup: rootGroup, files: [file], command: chownCommand, this, threads)() changeFileModFactory.create( log: log, mod: "o-rw", files: [file], command: chmodCommand, this, threads)() return file } /** * Returns the certification files directory, for * example {@code "/etc/ssl/certs".} * *
    *
  • profile property {@code "certificates_directory"}
  • *
* * @see #getPostfixProperties() */ File getCertsDir() { profileDirProperty "certificates_directory", defaultProperties } /** * Returns the certification keys files directory, for * example {@code "/etc/ssl/private".} * *
    *
  • profile property {@code "certificates_keys_directory"}
  • *
* * @see #getPostfixProperties() */ File getCertKeysDir() { profileDirProperty "certificates_keys_directory", defaultProperties } def unknownLocalRecipientRejectCodeConf() { def replace = mainConfigurationTemplate.getText(true, "unknownLocalRecipientRejectCodeConfig", "code", unknownLocalRecipientRejectCode) def search = mainConfigurationTemplate.getText(true, "unknownLocalRecipientRejectCodeConfig_search") new TokenTemplate(search, replace, escape: false) } def delayWarningTimeConf() { def replace = mainConfigurationTemplate.getText(true, "delayWarningTimeConfig", "time", delayWarningTime) def search = mainConfigurationTemplate.getText(true, "delayWarningTimeConfig_search") new TokenTemplate(search, replace, escape: false) } def maximalQueueLifetimeConf() { def replace = mainConfigurationTemplate.getText(true, "maximalQueueLifetimeConfig", "time", maximalQueueLifetime) def search = mainConfigurationTemplate.getText(true, "maximalQueueLifetimeConfig_search") new TokenTemplate(search, replace, escape: false) } def minimalRetriesDelayConf() { def replace = mainConfigurationTemplate.getText(true, "minimalRetriesDelayConfig", "time", minimalRetriesDelay) def search = mainConfigurationTemplate.getText(true, "minimalRetriesDelayConfig_search") new TokenTemplate(search, replace, escape: false) } def maximumRetriesDelayConf() { def replace = mainConfigurationTemplate.getText(true, "maximumRetriesDelayConfig", "time", maximalRetriesDelay) def search = mainConfigurationTemplate.getText(true, "maximumRetriesDelayConfig_search") new TokenTemplate(search, replace, escape: false) } def heloTimeoutConf() { def replace = mainConfigurationTemplate.getText(true, "heloTimeoutConfig", "time", heloTimeout) def search = mainConfigurationTemplate.getText(true, "heloTimeoutConfig_search") new TokenTemplate(search, replace, escape: false) } def recipientLimitConf() { def replace = mainConfigurationTemplate.getText(true, "recipientLimitConfig", "limit", recipientLimit) def search = mainConfigurationTemplate.getText(true, "recipientLimitConfig_search") new TokenTemplate(search, replace, escape: false) } def backOffErrorLimitConf() { def replace = mainConfigurationTemplate.getText(true, "backOffErrorLimitConfig", "limit", backOffErrorLimit) def search = mainConfigurationTemplate.getText(true, "backOffErrorLimitConfig_search") new TokenTemplate(search, replace, escape: false) } def blockingErrorLimitConf() { def replace = mainConfigurationTemplate.getText(true, "blockingErrorLimitConfig", "limit", blockingErrorLimit) def search = mainConfigurationTemplate.getText(true, "blockingErrorLimitConfig_search") new TokenTemplate(search, replace, escape: false) } def heloRestrictionsConf() { def replace = mainConfigurationTemplate.getText(true, "heloRestrictionsConfig", "restrictions", heloRestrictions) def search = mainConfigurationTemplate.getText(true, "heloRestrictionsConfig_search") new TokenTemplate(search, replace, escape: false) } def senderRestrictionsConf() { def replace = mainConfigurationTemplate.getText(true, "senderRestrictionsConfig", "restrictions", senderRestrictions) def search = mainConfigurationTemplate.getText(true, "senderRestrictionsConfig_search") new TokenTemplate(search, replace, escape: false) } def clientRestrictionsConf() { def replace = mainConfigurationTemplate.getText(true, "clientRestrictionsConfig", "restrictions", clientRestrictions) def search = mainConfigurationTemplate.getText(true, "clientRestrictionsConfig_search") new TokenTemplate(search, replace, escape: false) } def recipientRestrictionsConf() { def replace = mainConfigurationTemplate.getText(true, "recipientRestrictionsConfig", "restrictions", recipientRestrictions) def search = mainConfigurationTemplate.getText(true, "recipientRestrictionsConfig_search") new TokenTemplate(search, replace, escape: false) } def dataRestrictionsConf() { def replace = mainConfigurationTemplate.getText(true, "dataRestrictionsConfig", "restrictions", dataRestrictions) def search = mainConfigurationTemplate.getText(true, "dataRestrictionsConfig_search") new TokenTemplate(search, replace, escape: false) } def heloRequiredConf() { def replace = mainConfigurationTemplate.getText(true, "heloRequiredConfig", "flag", heloRequired) def search = mainConfigurationTemplate.getText(true, "heloRequiredConfig_search") new TokenTemplate(search, replace, escape: false) } def delayRejectConf() { def replace = mainConfigurationTemplate.getText(true, "delayRejectConfig", "flag", delayReject) def search = mainConfigurationTemplate.getText(true, "delayRejectConfig_search") new TokenTemplate(search, replace, escape: false) } def disableVrfyCommandConf() { def replace = mainConfigurationTemplate.getText(true, "disableVrfyCommandConfig", "flag", disableVrfyCommand) def search = mainConfigurationTemplate.getText(true, "disableVrfyCommandConfig_search") new TokenTemplate(search, replace, escape: false) } /** * Sets the main configuration of the mail server. This is done usually in * the {@code /etc/postfix/main.cf} file. * * @see #getMasterFile() */ void deployMaster() { def configuration = [ submissionConf(), smtpsConf(), ] deployConfiguration configurationTokens(), currentMasterConfiguration, configuration, masterFile } /** * Returns the current {@code master.cf} configuration. This is usually the * configuration file {@code /etc/postfix/master.cf}. * * @see #getMasterFile() */ String getCurrentMasterConfiguration() { currentConfiguration masterFile } def submissionConf() { boolean enabled = service.certificate != null && submissionEnabled def replace = masterConfigurationTemplate.getText(true, "submissionConfig", "enabled", enabled) def search = masterConfigurationTemplate.getText(true, "submissionConfig_search") new TokenTemplate(search, replace, enclose: false, escape: false) } /** * Returns to enable submission port, for * example {@code "true".} * *
    *
  • profile property {@code "submission_enabled"}
  • *
* * @see #getPostfixProperties() */ boolean getSubmissionEnabled() { profileBooleanProperty "submission_enabled", defaultProperties } def smtpsConf() { boolean enabled = service.certificate != null def replace = masterConfigurationTemplate.getText(true, "smtpsConfig", "enabled", enabled) def search = masterConfigurationTemplate.getText(true, "smtpsConfig_search") new TokenTemplate(search, replace, enclose: false, escape: false) } /** * Returns the storage method for domains and users. * *
    *
  • profile property {@code "storage"}
  • *
*/ String getStorageName() { profileProperty "storage" } /** * Returns the delivery method. * *
    *
  • profile property {@code "delivery"}
  • *
*/ String getDeliveryName() { containsKey("delivery") ? profileProperty("delivery") : null } /** * Returns the delivery method. * *
    *
  • profile property {@code "auth"}
  • *
*/ String getAuthName() { containsKey("auth") ? profileProperty("auth") : null } /** * Returns a list of the default destination domains. * *
    *
  • profile property {@code "default_destinations"}
  • *
* * @see #getPostfixProperties() */ List getDefaultDestinations() { profileListProperty "default_destinations", postfixProperties } /** * Returns the banner text that follows the 220 status code in the SMTP * greeting banner. * *
    *
  • profile property {@code "banner"}
  • *
* * @see #getPostfixProperties() */ String getBanner() { profileProperty "banner", postfixProperties } /** * Returns the absolute path of the mail name configuration file. * If the path is not absolute then it is assume to be under * the configuration directory. * *
    *
  • property {@code "mailname_file"}
  • *
* * @see #getMailnameConfigurationDir() * @see #getDefaultProperties() */ File getMailnameFile() { profileFileProperty "mailname_file", mailnameConfigurationDir, defaultProperties } /** * Returns the absolute path of the mail name configuration directory. * *
    *
  • property {@code "mailname_configuration_directory"}
  • *
* * @see #getDefaultProperties() */ File getMailnameConfigurationDir() { profileDirProperty "mailname_configuration_directory", defaultProperties } /** * Returns the {@code main.cf} file. If the path is not absolute then it * is assume to be under the configuration directory. * *
    *
  • property {@code "main_file"}
  • *
* * @see #getConfigurationDir() * @see #getDefaultProperties() */ File getMainFile() { profileFileProperty "main_file", configurationDir, defaultProperties } /** * Returns the {@code master.cf} file. If the path is not absolute then it * is assume to be under the configuration directory. * *
    *
  • property {@code "master_file"}
  • *
* * @see #getConfigurationDir() * @see #getDefaultProperties() */ File getMasterFile() { profileFileProperty "master_file", configurationDir, defaultProperties } /** * Returns the absolute path of the aliases maps file. * If the path is not absolute then it is assume to be under * the configuration directory. For example {@code "aliases"}. * *
    *
  • profile property {@code "aliases_maps_file"}
  • *
* * @see #getConfigurationDir() * @see #getDefaultProperties() */ File getAliasesMapsFile() { profileFileProperty "aliases_maps_file", configurationDir, defaultProperties } /** * Returns the absolute path of the aliases database file. * If the path is not absolute then it is assume to be under * the configuration directory. For example {@code "aliases"}. * *
    *
  • profile property {@code "aliases_database_file"}
  • *
* * @see #getConfigurationDir() * @see #getDefaultProperties() */ File getAliasesDatabaseFile() { profileFileProperty "aliases_database_file", configurationDir, defaultProperties } /** * Returns the command for the {@code postmap} command. Can be a full * path or just the command name that can be found in the current * search path. * *
    *
  • profile property {@code "postmap_command"}
  • *
* * @see #getDefaultProperties() */ String getPostmapCommand() { profileProperty "postmap_command", defaultProperties } /** * Returns the command for the {@code postalias} command. Can be a full * path or just the command name that can be found in the current * search path. * *
    *
  • profile property {@code "postalias_command"}
  • *
* * @see #getDefaultProperties() */ String getPostaliasCommand() { profileProperty "postalias_command", defaultProperties } /** * Returns the path of the base directory for virtual users. * *
    *
  • profile property {@code "mailbox_base_directory"}
  • *
* * @see #getDefaultProperties() */ File getMailboxBaseDir() { profileDirProperty "mailbox_base_directory", defaultProperties } /** * Returns the pattern for the directories that are created for each virtual * domain and virtual user under the mailbox base directory. * *
    *
  • profile property {@code "mailbox_pattern"}
  • *
* * @see #postfixProperties */ String getMailboxPattern() { profileProperty "mailbox_pattern", postfixProperties } /** * Returns the numerical Postfix/SMTP server response code when a * local recipient address is unknown. Example {@code 550}. * *
    *
  • profile property {@code "unknown_local_recipient_reject_code"}
  • *
* * @see #postfixProperties */ int getUnknownLocalRecipientRejectCode() { profileNumberProperty "unknown_local_recipient_reject_code", postfixProperties } /** * Returns the time after which the sender receives a copy of the message * headers of mail that is still queued. Example {@code PT4H}. * *
    *
  • profile property {@code "delay_warning_time"}
  • *
* * @see Duration#parse(String) * @see #postfixProperties */ Duration getDelayWarningTime() { profileDurationProperty "delay_warning_time", postfixProperties } /** * Returns the time after which the message is consider as not possible * to deliver. Example {@code P7D}. * *
    *
  • profile property {@code "maximal_queue_lifetime"}
  • *
* * @see Duration#parse(String) * @see #postfixProperties */ Duration getMaximalQueueLifetime() { profileDurationProperty "maximal_queue_lifetime", postfixProperties } /** * Returns the minimal time between attempts to deliver a deferred message. * Example {@code PT15M}. * *
    *
  • profile property {@code "minimal_retries_delay"}
  • *
* * @see Duration#parse(String) * @see #postfixProperties */ Duration getMinimalRetriesDelay() { profileDurationProperty "minimal_retries_delay", postfixProperties } /** * Returns the maximal time between attempts to deliver a deferred message. * Example {@code PT2H}. * *
    *
  • profile property {@code "maximal_retries_delay"}
  • *
* * @see Duration#parse(String) * @see #postfixProperties */ Duration getMaximalRetriesDelay() { profileDurationProperty "maximal_retries_delay", postfixProperties } /** * Returns the Postfix/SMTP client time limit for sending the HELO or * EHLO command, and for receiving the initial remote SMTP server response. * Example {@code PT60S}. * *
    *
  • profile property {@code "helo_timeout"}
  • *
* * @see Duration#parse(String) * @see #postfixProperties */ Duration getHeloTimeout() { profileDurationProperty "helo_timeout", postfixProperties } /** * Returns the maximal number of recipients that the Postfix/SMTP server * accepts per message delivery request. * Example {@code 16}. * *
    *
  • profile property {@code "recipient_limit"}
  • *
* * @see #postfixProperties */ int getRecipientLimit() { profileNumberProperty "recipient_limit", postfixProperties } /** * Returns the number of errors before the Postfix/SMTP server slows * down all its responses. Example {@code 3}. * *
    *
  • profile property {@code "back_off_error_limit"}
  • *
* * @see #postfixProperties */ int getBackOffErrorLimit() { profileNumberProperty "back_off_error_limit", postfixProperties } /** * Returns the maximal number of errors a remote SMTP client is allowed * to make without delivering mail. Example {@code 12}. * *
    *
  • profile property {@code "blocking_error_limit"}
  • *
* * @see #postfixProperties */ int getBlockingErrorLimit() { profileNumberProperty "blocking_error_limit", postfixProperties } /** * Returns the restrictions that the Postfix/SMTP server applies in the * context of a client HELO command. * *
    *
  • profile property {@code "helo_restrictions"}
  • *
* * @see #postfixProperties */ String getHeloRestrictions() { profileProperty "helo_restrictions", postfixProperties } /** * Returns the restrictions that the Postfix/SMTP server applies in the * context of a client MAIL FROM command. * *
    *
  • profile property {@code "sender_restrictions"}
  • *
* * @see #postfixProperties */ String getSenderRestrictions() { profileProperty "sender_restrictions", postfixProperties } /** * Returns the restrictions that the Postfix/SMTP server applies in the * context of a client connection request. * *
    *
  • profile property {@code "client_restrictions"}
  • *
* * @see #postfixProperties */ String getClientRestrictions() { profileProperty "client_restrictions", postfixProperties } /** * Returns the restrictions that the Postfix/SMTP server applies in the * context of a client RCPT TO command * *
    *
  • profile property {@code "recipient_restrictions"}
  • *
* * @see #postfixProperties */ String getRecipientRestrictions() { profileProperty "recipient_restrictions", postfixProperties } /** * Returns the restrictions that the Postfix/SMTP server applies in the * context of the SMTP DATA command. * *
    *
  • profile property {@code "data_restrictions"}
  • *
* * @see #postfixProperties */ String getDataRestrictions() { profileProperty "data_restrictions", postfixProperties } /** * Require that a remote SMTP client introduces itself with the HELO/EHLO * command. * *
    *
  • profile property {@code "helo_required"}
  • *
* * @see #postfixProperties */ boolean isHeloRequired() { profileProperty "helo_required", postfixProperties } /** * Wait until the RCPT TO/ETRN command. * *
    *
  • profile property {@code "delay_reject"}
  • *
* * @see #postfixProperties */ boolean isDelayReject() { profileProperty "delay_reject", postfixProperties } /** * Disable the SMTP VRFY command. * *
    *
  • profile property {@code "disable_vrfy_command"}
  • *
* * @see #postfixProperties */ boolean isDisableVrfyCommand() { profileProperty "disable_vrfy_command", postfixProperties } /** * Returns the group name of the virtual user accounts. * *
    *
  • profile property {@code "virtual_group_name"}
  • *
* * @see #getDefaultProperties() */ String getVirtualGroupName() { profileProperty "virtual_group_name", defaultProperties } /** * Returns the user name of the virtual user accounts. * *
    *
  • profile property {@code "virtual_name_name"}
  • *
* * @see #getDefaultProperties() */ String getVirtualUserName() { profileProperty "virtual_name_name", defaultProperties } /** * Returns the minimum identification number for virtual users. * *
    *
  • profile property {@code "minimum_uid"}
  • *
* * @see #getDefaultProperties() */ int getMinimumUid() { profileNumberProperty "minimum_uid", defaultProperties } /** * Returns the user identification number for virtual users. * *
    *
  • profile property {@code "virtual_uid"}
  • *
* * @see #getDefaultProperties() */ int getVirtualUid() { profileNumberProperty "virtual_uid", defaultProperties } /** * Returns the group identification number for virtual users. * *
    *
  • profile property {@code "virtual_gid"}
  • *
* * @see #getDefaultProperties() */ int getVirtualGid() { profileNumberProperty "virtual_gid", defaultProperties } /** * Returns the Postfix/properties. */ def getPostfixProperties() { postfixPropertiesProvider.get() } /** * Returns additional template attributes. */ Map getTemplatesAttributes() { ["renderers": [ bindAddressesRenderer, durationRenderer ]] } /** * Returns the current mail name configuration. This is usually the * configuration file {@code /etc/mailname}. * * @see #getMailnameFile() */ String getCurrentMailnameConfiguration() { currentConfiguration mailnameFile } /** * Returns the current {@code main.cf} configuration. This is usually the * configuration file {@code /etc/postfix/main.cf}. * * @see #getMainFile() */ String getCurrentMainConfiguration() { currentConfiguration mainFile } /** * Execute the {@code postmap} command on the specified file. * * @see #getPostmapCommand() */ void rehashFile(File file) { def task = scriptExecFactory.create( log: log, command: postmapCommand, file: file, this, threads, postmapCommandTemplate, "postmap")() logg.rehashFileDone this, file, task } /** * Execute the {@code postalias} command on the specified file. * * @see #getPostmapCommand() */ void realiasFile(File file) { def task = scriptExecFactory.create( log: log, command: postaliasCommand, file: file, this, threads, postaliasCommandTemplate, "postalias")() logg.realiasFileDone this, file, task } /** * Replace the variables of the mailbox path pattern. *
    *
  • {@code } is replaced with the user domain; *
  • {@code } is replaced with the user name; *
* * @param user * the {@link User}. */ String createMailboxPath(User user) { ST st = new ST(mailboxPattern).add("domain", user.domain.name).add("user", user.name) st.render() } /** * Returns the Postfix user, for example {@code "postfix"}. * *
    *
  • profile property {@code "postfix_user"}
  • *
* * @see #getDefaultProperties() */ String getPostfixUser() { profileProperty "postfix_user", defaultProperties } /** * Returns the Postfix group, for example {@code "postfix"}. * *
    *
  • profile property {@code "postfix_group"}
  • *
* * @see #getDefaultProperties() */ String getPostfixGroup() { profileProperty "postfix_group", defaultProperties } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy