import io
import logging
import publicsuffix2
+import smtplib
+import socket
import sqlmodel
+import ssl
# Initialize logging as early as possible
from . import logger
def users(self):
return users.Users(self)
+ @functools.cached_property
+ def ssl_context(self):
+ # Create SSL context
+ context = ssl.create_default_context()
+
+ # Fetch the paths to the certificate & key
+ cert = self.config.get("ssl", "cert", fallback=None)
+ key = self.config.get("ssl", "key", fallback=None)
+
+ log.debug("Initializing SSL context")
+
+ # Load the certificate and key if they are set
+ if cert and key:
+ log.debug(" Certificate: %s" % cert)
+ log.debug(" Key: %s" % key)
+
+ # Load the credentials
+ context.load_cert_chain(cert, key)
+
+ return context
+
+ @property
+ def relay(self):
+ """
+ Connection to the local mail relay
+ """
+ hostname = socket.getfqdn()
+
+ # Open SMTP connection
+ conn = smtplib.SMTP(hostname)
+
+ # Start TLS connection
+ conn.starttls(context=self.ssl_context)
+
+ return conn
+
def search(self, name):
"""
Searches for a domain
import email.utils
import ldap
import logging
-import subprocess
+import smtplib
+
+from . import util
# Setup logging
log = logging.getLogger(__name__)
# Log the email
log.debug("Sending email:\n%s" % message.as_string())
- # Launch sendmail
- sendmail = subprocess.Popen(
- ["/usr/sbin/sendmail", "-t", "-oi"], stdin=subprocess.PIPE, text=True,
- )
+ # Make the address for bounce processing
+ return_path = util.make_verp_address(self.mail)
+
+ # Send the message to the local SMTP relay
+ try:
+ self.backend.relay.send_message(message, from_addr=return_path)
+
+ # Catch any exceptions
+ except smtplib.SMTPException as e:
+ log.error("Failed to send email: %s" % e)
- # Pipe the email into sendmail
- sendmail.communicate(message.as_string())
+ # Ignore the exception, because there is no way we can recover from this
+ return
class Group(LDAPObject):
# #
###############################################################################
+import email.utils
import idna
import ipaddress
import logging
Checks if something is a URL
"""
return "/" in s
+
+def make_verp_address(recipient):
+ """
+ Creates a VERP address which we will use for reliable bounce processing
+ """
+ # Parse the address
+ name, recipient = email.utils.parseaddr(recipient)
+
+ return "bounces+%s@ipfire.org" % recipient.replace("@", "=")