Skip to content
Snippets Groups Projects
test_email.py 4.96 KiB
Newer Older
Stéphane Diemer's avatar
Stéphane Diemer committed
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''
Check that emails can be sent.
Stéphane Diemer's avatar
Stéphane Diemer committed
'''
import os
import subprocess
import sys
Stéphane Diemer's avatar
Stéphane Diemer committed

Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
try:
    import spf
except ImportError:
    subprocess.check_call(['apt-get', '-qq', '-y', 'install', 'python3-spf'])
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
    import spf
if subprocess.call(['which', 'netstat']) != 0:
    subprocess.check_call(['apt-get', '-qq', '-y', 'install', 'net-tools'])
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed

YELLOW = '\033[93m'
GREEN = '\033[92m'
RED = '\033[91m'
DEF = '\033[0m'

Florent Thiery's avatar
Florent Thiery committed
os.chdir(os.path.dirname(__file__))
if not os.path.isfile('../utils.py'):
    print('The envsetup configuration was not found.')
Florent Thiery's avatar
Florent Thiery committed
    sys.exit(1)
else:
    es_utils = imp.load_source('es_utils', '../utils.py')
    conf = es_utils.load_conf()
Florent Thiery's avatar
Florent Thiery committed

Stéphane Diemer's avatar
Stéphane Diemer committed

def print_color(txt, col):
    print('%s%s%s' % (col, txt, DEF))

Stéphane Diemer's avatar
Stéphane Diemer committed

def print_yellow(txt):
    print_color(txt, YELLOW)


def print_red(txt):
    print_color(txt, RED)

Stéphane Diemer's avatar
Stéphane Diemer committed

def print_green(txt):
    print_color(txt, GREEN)

Stéphane Diemer's avatar
Stéphane Diemer committed

def check_listening_port():
    # check that postfix listens the port 25 correctly
    status, out = subprocess.getstatusoutput('netstat -pant | grep master | grep ":25"')
    if status != 0:
        print_red('The port 25 is not listened by postfix "master" process.')
    print_green('Postfix "master" process is listening port 25 correctly.')
    if '127.0.0.1:25' not in out:
        print_red('Postfix "master" process is not listening address 127.0.0.1, please check postfix configuration.')
        print('Postfix should listen address 127.0.0.1 to be sure that this server cannot be used as an SMTP relay by external services.')
        return 1
    print_green('Postfix "master" process is listening address 127.0.0.1 correctly.')
    return 0
Stéphane Diemer's avatar
Stéphane Diemer committed

Stéphane Diemer's avatar
Stéphane Diemer committed

def check_relay():
    print('Checking if SMTP relay conforms to conf.')
    status, out = subprocess.getstatusoutput('grep relayhost /etc/postfix/main.cf')
    if status == 0:
        configured_relay = out[len('relayhost'):].strip(' \t=').replace('[', '').replace(']', '')
        configured_relay = ''
    if not configured_relay:
        # no relay configured, check relayless situations
        ip = conf.get('NETWORK_IP_NAT')
        if not ip:
            ip = conf.get('NETWORK_IP')
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
        if not ip:
            print_yellow('Cannot determine public IP address')
            return 3
        with open('/etc/mailname', 'r') as f:
        if d not in ('ubicast.tv', 'ubicast.eu'):
            print_yellow('/etc/mailname does not contain ubicast.eu or ubicast.tv, mails will probably not be received on ubicast mailing lists')
            return 3
        # check spf
Nicolas KAROLAK's avatar
Nicolas KAROLAK committed
        result, explain = spf.check2(i=ip, s='support@ubicast.eu', h='')
        if result != 'pass':
            print_red('ip %s is not in ubicast.eu SPF and emails sent from support@ubicast.eu may be treated as spam' % ip)
            return 3
    conf_relay = conf.get('EMAIL_SMTP_SERVER', '').replace('[', '').replace(']', '')
Florent Thiery's avatar
Florent Thiery committed
    if conf_relay != configured_relay:
        print_red('Configured STMP relay (%s) does not match the expected value (%s).' % (configured_relay, conf_relay))
Florent Thiery's avatar
Florent Thiery committed
    else:
        print_green('STMP relay is properly set.')
Stéphane Diemer's avatar
Stéphane Diemer committed

    email = 'noreply+%s-%s@ubicast.eu' % (time.time(), random.randint(0, 1000))
    print('Sending test email to "%s".' % email)
    cmd = 'echo "This is a test email" | mail -s "Test email from `cat /etc/hostname`" %s' % email
    subprocess.getstatusoutput(cmd)
    waited = 1
    delay = 2
    print('Timeout to find email sending log is set to %s seconds.' % timeout)
    if os.path.isfile('/var/log/mail.log'):
        cmd = 'grep "%s" /var/log/mail.log' % email
    else:
        print('/var/log/mail.log not found, trying journalctl')
        cmd = 'journalctl -u postfix | grep %s' % email
        status, out = subprocess.getstatusoutput(cmd)
        if status == 0:
            out = out.strip().split('\n')[-1]
            if 'status=deferred' not in out:
                print('Log entry found after %s seconds.' % waited)
            print_red('Failed to send email.')
            print('No log entry found after %s seconds using command: %s' % (waited, cmd))
        print('No log entry found after %s seconds, waiting %s more seconds...' % (waited, delay))
        time.sleep(delay)
        waited += delay
        delay *= 2
    if 'bounced' not in out or 'The email account that you tried to reach does not exist.' in out:
        print_green('Email sent.')
        print_red('Failed to send email.')
        print('Sending log line:\n%s' % out)
Stéphane Diemer's avatar
Stéphane Diemer committed

Stéphane Diemer's avatar
Stéphane Diemer committed
if not os.path.exists('/etc/postfix'):
    print_red('Postfix dir does not exists, please install postfix.')
rc = check_listening_port()
if rc == 0:
    rc = check_relay()
    if send_test_email() == 1:
        rc = 1