com.anrisoftware.sscontrol.mail.postfix.script.linux.BasePostfixScript.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sscontrol-mail-postfix Show documentation
Show all versions of sscontrol-mail-postfix Show documentation
Installs Postfix mail server. - http://www.postfix.org/
/*
* 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
}
}