#!/usr/bin/env python # # Copyright (C) 2003,2004 Jason R. Mastaler # # This file is part of TMDA. # # TMDA is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. A copy of this license should # be included in the file COPYING. # # TMDA 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 General Public License # for more details. # # You should have received a copy of the GNU General Public License # along with TMDA; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ Description =========== smtp-check-sender verifies the validity of an e-mail address by probing the SMTP port of its primary mail exchanger without actually sending mail to it (SMTP interruptus). This feature, often called 'sender address verification' is available for Postfix and Exim (and possibly others) at the MTA level. That is preferred if possible because it covers all users on the system and saves TMDA work. This script is made available for users who want this functionality, but can't or don't want to implement it at the MTA level. Requirements ============ Python, and also the PyDNS module, available at http://pydns.sourceforge.net/ Usage ===== smtp-check-sender is meant to be run from your TMDA FILTER_INCOMING file with a 'pipe' entry similar to the following: # drop mail from verified bogus addresses which can't be replied to pipe '~/bin/smtp-check-sender $SENDER' drop $SENDER is expanded to the envelope sender address of the incoming message. If you want to experiment on the command line, you'd do so with something like this: $ echo | smtp-check-sender user@domain.tld Uncomment the 'server.set_debuglevel(1)' line in the program for more verbose output. Limitations =========== This technique will not work with MTAs (e.g, qmail) where you cannot verify the validity of an address via SMTP. Luckily, most MTAs do not have this limitation. """ import DNS # http://pydns.sourceforge.net/ import smtplib import socket import sys # we read stdin, but don't actually use it data = sys.stdin.read() # bail out here if no address is specified if len(sys.argv) < 2: sys.exit(1) # Make sure you either take the default of '' (meaning probe with an # empty envelope sender <>), or use a valid address for this variable, # otherwise you risk losing mail. mail_from_address = '' address_to_verify = sys.argv[1] verify_hostname = address_to_verify.split('@', 1)[1] DNS.DiscoverNameServers() mxlist = DNS.mxlookup(verify_hostname) if mxlist: primx = mxlist[0][1] else: primx = verify_hostname # SMTP conversation server = smtplib.SMTP(primx) #server.set_debuglevel(1) server.docmd('helo', socket.getfqdn()) server.docmd('mail from:', '<%s>' % mail_from_address) code, msg = server.docmd('rcpt to:', '<%s>' % address_to_verify) server.quit() # RFC 2821 is quite clear in stating that all codes starting # with 5 are always `permanent negative completion replies. if str(code).startswith('5'): print 'BAD sender' sys.exit(0) else: print 'GOOD sender' sys.exit(1)