这是我最终用来解决这个问题的 Python 代码。您必须对其进行调整才能在与我的配置不同的服务器上工作。
import os
import re
import subprocess
def find_recipients(usernames):
recipients = {'local': set(), 'external': set(), 'missing_local': set(),
'file': set(), 'program': set(), 'error_messages': set()}
visited_lists = set()
sendmail = subprocess.Popen(('sendmail', '-bt'), stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
def handle_local_user(username):
username = username.lower()
list_path = '/shared/aliases/' + username
if os.path.isfile(list_path):
visit_list(list_path)
elif os.path.isdir('/home/' + username):
recipients['local'].add(username)
else:
recipients['missing_local'].add(username)
def visit_list(list_path):
if list_path not in visited_lists:
visited_lists.add(list_path)
with open(list_path, 'r') as ml_file:
for ml_line in ml_file:
if not re.match(r'^\s*(#.*)?$', ml_line):
if not ml_line.endswith('\n'):
ml_line += '\n'
sendmail.stdin.write('/parse ' + ml_line)
sendmail.stdin.flush()
match = None
while match is None:
match = re.match(r'^mailer ([^,]*), (.*)\n$',
sendmail.stdout.readline())
mailer, recipient_info = match.groups()
if mailer == 'local':
handle_local_user(
re.match(r'^user (.+)$',
recipient_info).group(1))
elif mailer == 'relay':
user, at, domain = re.match(
r'^host smtp\.mydomain\.org, user (.*)$',
recipient_info).group(1).partition('@')
domain = domain.lower()
if domain == 'mydomain.org':
handle_local_user(user)
else:
recipients['external'].add(user + at + domain)
elif mailer == '*file*':
recipients['file'].add(
re.match(r'^user (.+)$',
recipient_info).group(1))
elif mailer == 'prog':
recipients['program'].add(
re.match(r'^user (.+)$',
recipient_info).group(1))
elif mailer == '*include*':
visit_list(re.match(r'^user (.+)$',
recipient_info).group(1))
elif mailer == '*error*':
raise RuntimeError('address parsing error: ' +
recipient_info)
else:
raise RuntimeError('unrecognized mailer: ' +
mailer)
for un in usernames:
handle_local_user(un)
sendmail.communicate('/quit')
return recipients