initial code push
This commit is contained in:
328
mailrelay.py
Executable file
328
mailrelay.py
Executable file
@@ -0,0 +1,328 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# quick and dirty test script for smtp relay
|
||||||
|
# 250 2.0.0 0BHI16hQ021841-0BHI16hR021841 Message accepted for delivery
|
||||||
|
# fortinet session
|
||||||
|
#
|
||||||
|
# Done
|
||||||
|
# ----
|
||||||
|
# add cc, bcc and lists
|
||||||
|
# add colors
|
||||||
|
# add list of receivers
|
||||||
|
#
|
||||||
|
# Todo
|
||||||
|
# ----
|
||||||
|
# add response check
|
||||||
|
# add custom attachment
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import base64
|
||||||
|
import socket
|
||||||
|
import random
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
__tool_name__ = 'mailrelay.py'
|
||||||
|
__tool_version__ = '0.3.1'
|
||||||
|
__tool_author__ = 'dash'
|
||||||
|
__tool_desc__ = 'not so quick but dirty\'n\'dirty tool for smtp relay checks, nothing fancy here.'
|
||||||
|
|
||||||
|
globTimeout=0
|
||||||
|
|
||||||
|
#https://stackoverflow.com/questions/2330245/python-change-text-color-in-shell
|
||||||
|
def liteUp(string, status, bold):
|
||||||
|
attr = []
|
||||||
|
if status == 'green':
|
||||||
|
attr.append('32')
|
||||||
|
elif status == 'red':
|
||||||
|
attr.append('31')
|
||||||
|
elif status == 'orange':
|
||||||
|
attr.append('33')
|
||||||
|
elif status == 'purple':
|
||||||
|
attr.append('35')
|
||||||
|
elif status == 'cyan':
|
||||||
|
attr.append('36')
|
||||||
|
elif status == 'yellow':
|
||||||
|
attr.append('93')
|
||||||
|
elif status == 'lightblue':
|
||||||
|
attr.append('94')
|
||||||
|
elif status == 'pink':
|
||||||
|
attr.append('95')
|
||||||
|
else:
|
||||||
|
# red
|
||||||
|
attr.append('90')
|
||||||
|
if bold:
|
||||||
|
attr.append('1')
|
||||||
|
return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), string)
|
||||||
|
|
||||||
|
def buildSocket(host,port):
|
||||||
|
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
|
||||||
|
try:
|
||||||
|
sock.connect((host,int(port)))
|
||||||
|
|
||||||
|
except socket.gaierror as e:
|
||||||
|
errMsg = '{0}:{1}: {2}'.format(host,port,e)
|
||||||
|
print(liteUp(errMsg, 'red', 0))
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
return sock
|
||||||
|
|
||||||
|
def parseVariable(var):
|
||||||
|
if var.find(':')>0:
|
||||||
|
out = var.split(':')
|
||||||
|
return out[0],out[1]
|
||||||
|
else:
|
||||||
|
print('Sorry, unexpected variable.')
|
||||||
|
return False, False
|
||||||
|
|
||||||
|
def parseResponse(respData):
|
||||||
|
# response types
|
||||||
|
# 250 OK
|
||||||
|
# 550 Error
|
||||||
|
# 503 Need RCPT (recipient)
|
||||||
|
if respData[:3]==(b'250'):
|
||||||
|
#print('yay')
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def recvSmtpData(sock):
|
||||||
|
# basic recv function should do the trick for now
|
||||||
|
try:
|
||||||
|
data = sock.recv(1024)
|
||||||
|
except socket.timeout as e:
|
||||||
|
errMsg = e
|
||||||
|
print(liteUp(errMsg, 'red', 0))
|
||||||
|
sys.exit()
|
||||||
|
except BrokenPipeError as e:
|
||||||
|
errMsg = e
|
||||||
|
print(liteUp(errMsg, 'red', 0))
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def sendSmtpData(sock, data):
|
||||||
|
|
||||||
|
# lets send the data over the wire
|
||||||
|
try:
|
||||||
|
sock.send(data)
|
||||||
|
except socket.timeout as e:
|
||||||
|
# errMsg = '{0}:{1}: {2}'.format(host,port,e)
|
||||||
|
errMsg = e
|
||||||
|
print(liteUp(errMsg, 'red', 0))
|
||||||
|
sys.exit()
|
||||||
|
except BrokenPipeError as e:
|
||||||
|
# errMsg = '{0}:{1}: {2}'.format(host,port,e)
|
||||||
|
errMsg = e
|
||||||
|
print(liteUp(errMsg, 'red', 0))
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
# add artifical timeout here
|
||||||
|
time.sleep(globTimeout)
|
||||||
|
|
||||||
|
|
||||||
|
return True, data
|
||||||
|
|
||||||
|
def sendEhlo(sock):
|
||||||
|
hihello = ['localhost','127.0.0.2','10.10.10.45']
|
||||||
|
ehloMe = random.choice(hihello)
|
||||||
|
ehloNow = ('ehlo {0}\r\n'.format(ehloMe)).encode()
|
||||||
|
sendSmtpData(sock, ehloNow)
|
||||||
|
print(liteUp(ehloNow.decode().rstrip('\n'), 'pink', 0))
|
||||||
|
recvData = recvSmtpData(sock)
|
||||||
|
print(liteUp(recvData.decode().rstrip('\n'), 'orange', 0))
|
||||||
|
result = parseResponse(recvData)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def sendMailFrom(sock, senderMail):
|
||||||
|
# prepare smtp mail from
|
||||||
|
mf = 'MAIL FROM: <{0}>\r\n'.format(senderMail)
|
||||||
|
mf = mf.encode()
|
||||||
|
sendSmtpData(sock, mf)
|
||||||
|
print(liteUp(mf.decode().rstrip('\n'), 'pink', 0))
|
||||||
|
recvData = recvSmtpData(sock)
|
||||||
|
print(liteUp(recvData.decode().rstrip('\n'), 'orange', 0))
|
||||||
|
result = parseResponse(recvData)
|
||||||
|
|
||||||
|
def sendMailTo(sock, targetMail):
|
||||||
|
# prepare smtp rcpt to
|
||||||
|
rt = 'RCPT TO: <{0}>\r\n'.format(targetMail)
|
||||||
|
# rt = 'RCPT TO: <{0}>,<{0}>\r\n'.format(targetMail)
|
||||||
|
rt = rt.encode()
|
||||||
|
sendSmtpData(sock, rt)
|
||||||
|
print(liteUp(rt.decode().rstrip('\n'), 'pink', 0))
|
||||||
|
recvData = recvSmtpData(sock)
|
||||||
|
print(liteUp(recvData.decode().rstrip('\n'), 'orange', 0))
|
||||||
|
result = parseResponse(recvData)
|
||||||
|
|
||||||
|
def sendCustom(sock, cmd, recvOn):
|
||||||
|
|
||||||
|
# prepare smtp rcpt to
|
||||||
|
cmd = cmd.encode()
|
||||||
|
sendSmtpData(sock, cmd)
|
||||||
|
print(liteUp(cmd.decode().rstrip('\n'), 'pink', 0))
|
||||||
|
|
||||||
|
if recvOn:
|
||||||
|
recvData = recvSmtpData(sock)
|
||||||
|
print(liteUp(recvData.decode().rstrip('\n'), 'orange', 0))
|
||||||
|
result = parseResponse(recvData)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def openFile(targetList):
|
||||||
|
fr = open(targetList, 'r')
|
||||||
|
buf = fr.readlines()
|
||||||
|
return buf
|
||||||
|
|
||||||
|
def openFileRead(filename):
|
||||||
|
fr = open(filename, 'rb')
|
||||||
|
buf = fr.read()
|
||||||
|
return buf
|
||||||
|
|
||||||
|
def run(args):
|
||||||
|
|
||||||
|
targetMail = args.targetMail
|
||||||
|
targetCcMail = args.targetCcMail
|
||||||
|
targetBccMail = args.targetBccMail
|
||||||
|
|
||||||
|
targetList = args.targetList
|
||||||
|
targetCcList = args.targetCcList
|
||||||
|
targetBccList = args.targetBccList
|
||||||
|
|
||||||
|
senderMail = args.senderMail
|
||||||
|
subject = args.subject
|
||||||
|
body = args.body
|
||||||
|
|
||||||
|
attachment = args.attachment
|
||||||
|
attachmentName = args.attachmentName
|
||||||
|
|
||||||
|
mailHost = args.mtaAddr
|
||||||
|
mailHost, mailHostPort = parseVariable(mailHost)
|
||||||
|
conn = '[+] Connected: {0}:{1}'.format(mailHost, mailHostPort)
|
||||||
|
|
||||||
|
sock = buildSocket(mailHost,mailHostPort)
|
||||||
|
print(liteUp(conn, 'ppppink', 0))
|
||||||
|
|
||||||
|
# ehlo at system
|
||||||
|
sendEhlo(sock)
|
||||||
|
|
||||||
|
# send mail from
|
||||||
|
sendMailFrom(sock, senderMail)
|
||||||
|
|
||||||
|
if targetList:
|
||||||
|
mails = openFile(targetList)
|
||||||
|
for targetMail in mails:
|
||||||
|
targetMail = targetMail.rstrip('\r')
|
||||||
|
targetMail = targetMail.rstrip('\n')
|
||||||
|
# send Mail To
|
||||||
|
sendMailTo(sock, targetMail)
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
# send Mail To
|
||||||
|
sendMailTo(sock, targetMail)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# initiate DATA block for mailcontent
|
||||||
|
sendCustom(sock,'DATA\r\n',True)
|
||||||
|
|
||||||
|
# send subject
|
||||||
|
sub = 'SUBJECT: {0}\r\n'.format(subject)
|
||||||
|
sendCustom(sock,sub,False)
|
||||||
|
|
||||||
|
# cc list or not
|
||||||
|
if targetCcList:
|
||||||
|
mails = openFile(targetCcList)
|
||||||
|
for targetCcMail in mails:
|
||||||
|
targetCcMail = targetCcMail.rstrip('\r')
|
||||||
|
targetCcMail = targetCcMail.rstrip('\n')
|
||||||
|
# send CC Mail
|
||||||
|
custData = 'CC: <{0}>\r\n'.format(targetCcMail)
|
||||||
|
sendCustom(sock,custData,False)
|
||||||
|
else:
|
||||||
|
# initiate DATA block for mailcontent
|
||||||
|
custData = 'CC: <{0}>\r\n'.format(targetCcMail)
|
||||||
|
sendCustom(sock,custData,False)
|
||||||
|
|
||||||
|
# bcc list or not
|
||||||
|
if targetBccList:
|
||||||
|
mails = openFile(targetBccList)
|
||||||
|
for targetBccMail in mails:
|
||||||
|
targetBccMail = targetBccMail.rstrip('\r')
|
||||||
|
targetBccMail = targetBccMail.rstrip('\n')
|
||||||
|
# send CC Mail
|
||||||
|
custData = 'CC: <{0}>\r\n'.format(targetBccMail)
|
||||||
|
sendCustom(sock,custData,False)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# initiate DATA block for mailcontent
|
||||||
|
custData = 'BCC: <{0}>\r\n'.format(targetBccMail)
|
||||||
|
sendCustom(sock,custData,False)
|
||||||
|
|
||||||
|
# so you want to send an attachment??
|
||||||
|
if not attachmentName:
|
||||||
|
attachmentName = attachment
|
||||||
|
|
||||||
|
if attachment:
|
||||||
|
buf=openFileRead(attachment)
|
||||||
|
attachmentB64 = base64.b64encode(buf)
|
||||||
|
# i should patent that crap
|
||||||
|
rndBoundary = int((str(random.random()+1)).replace('.',''))
|
||||||
|
bndry = '==============={0}=='.format(rndBoundary)
|
||||||
|
ct = 'Content-Type: multipart/mixed; boundary="{0}"'.format(bndry)
|
||||||
|
ct2 = 'MIME-Version: 1.0'
|
||||||
|
sendCustom(sock,ct,False)
|
||||||
|
sendCustom(sock,ct2,False)
|
||||||
|
|
||||||
|
ctbody = '--{0}\r\nContent-Type: text/plain; charset="us-ascii"\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: 7bit\r\n\r\n{1}\r\n'.format(bndry,body)
|
||||||
|
sendCustom(sock,ctbody,False)
|
||||||
|
|
||||||
|
ctattach = '--{0}\r\nContent-Type: application/octet-stream\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename={1}\r\n\r\n{2}\r\n\r\n--{0}\r\n'.format(bndry,attachmentName, attachmentB64)
|
||||||
|
sendCustom(sock,ctattach,False)
|
||||||
|
else:
|
||||||
|
body = '{0}\r\n'.format(body)
|
||||||
|
sendCustom(sock,body,False)
|
||||||
|
|
||||||
|
done = '.\r\n'
|
||||||
|
sendCustom(sock,done,True)
|
||||||
|
|
||||||
|
quit = 'quit\r\n'
|
||||||
|
sendCustom(sock,quit,True)
|
||||||
|
|
||||||
|
conn = '[+] Finished'
|
||||||
|
print(liteUp(conn, 'ppppink', 0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
parser_desc = '{0} {1} by {2}'.format(__tool_name__, __tool_version__,__tool_author__)
|
||||||
|
prog_desc = __tool_desc__
|
||||||
|
parser = argparse.ArgumentParser(prog = prog_desc, description=parser_desc)
|
||||||
|
parser.add_argument("-z","--socket-timeout",action="store",required=False,type=int,help='time to wait for socket (defaut:5)',dest='sockTimeout',default=5)
|
||||||
|
parser.add_argument("-Z","--manual-timeout",action="store",required=False,type=int,help='time to wait for socket (defat:5)',dest='sockTimeout',default=5)
|
||||||
|
parser.add_argument("-t","--target-email",action="store",required=False,help='single e-mail address the mails to sent to',dest='targetMail')
|
||||||
|
parser.add_argument("-cc","--target-cc-email",action="store",required=False,help='single CC e-mail address the mails to sent to',dest='targetCcMail', default=False)
|
||||||
|
parser.add_argument("-bcc","--target-bcc-email",action="store",required=False,help='single BCC e-mail address the mails to sent to',dest='targetBccMail', default=False)
|
||||||
|
parser.add_argument("-CC","--target-cc-list",action="store",required=False,help='single CC e-mail address the mails to sent to',dest='targetCcList', default=False)
|
||||||
|
parser.add_argument("-BCC","--target-bcc-list",action="store",required=False,help='single BCC e-mail address the mails to sent to',dest='targetBccList', default=False)
|
||||||
|
parser.add_argument("-T","--target-list",action="store",required=False,help='list with email addresses mail sent to',dest='targetList',default= False)
|
||||||
|
parser.add_argument("-e","--sender-email",action="store",required=False,help='single sender e-mail addr, FORMAT:<email>password>',dest='senderMail')
|
||||||
|
parser.add_argument("-s","--email-subject",action="store",required=False,help='the subject',dest='subject',default='Imptant Notice about your paypal account')
|
||||||
|
parser.add_argument("-b","--email-body",action="store",required=False,help='the body, e.g. \'hi there, this is a massivtest. please ignore.\'',dest='body',default='Sorry, you have been hacked.')
|
||||||
|
parser.add_argument("-a","--attachment",action="store",required=False,help='send attachment',dest='attachment',default=False)
|
||||||
|
parser.add_argument("-A","--attachment-name",action="store",required=False,help='send attachment',dest='attachmentName',default="ls.file")
|
||||||
|
parser.add_argument("-m","--mta",action="store",required=False,help='the mta, FORMAT:<smtp>:<port>, e.g. smtp.provider.m:25',dest='mtaAddr',default='smtp.gmail.com:25')
|
||||||
|
|
||||||
|
if len(sys.argv)==1:
|
||||||
|
parser.print_help()
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
run(args)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
146
massmail.py
Executable file
146
massmail.py
Executable file
@@ -0,0 +1,146 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# basic script by samlopezf
|
||||||
|
# tuned and combat ready by dash
|
||||||
|
# in the year of the covid outbreak, december
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import smtplib
|
||||||
|
import argparse
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from email.mime.base import MIMEBase
|
||||||
|
from email import encoders
|
||||||
|
|
||||||
|
from IPython import embed
|
||||||
|
__tool_name__ = 'massmails.py'
|
||||||
|
__tool_version__ = '0.3'
|
||||||
|
__tool_author__ = 'dash'
|
||||||
|
__tool_fork__ = 'https://github.com/samlopezf/Python-Email/'
|
||||||
|
__tool_desc__ = 'simple tool to test mail servers for robustnes, it will send one email per account to the target email address'
|
||||||
|
|
||||||
|
|
||||||
|
def parseVariable(var):
|
||||||
|
if var.find(':')>0:
|
||||||
|
out = var.split(':')
|
||||||
|
return out[0],out[1]
|
||||||
|
|
||||||
|
else:
|
||||||
|
print('Sorry, unexpected variable.')
|
||||||
|
return False, False
|
||||||
|
|
||||||
|
def buildEmail(emailSender, emailTarget, emailSubject, emailBody, emailAttachment):
|
||||||
|
msg = MIMEMultipart()
|
||||||
|
msg['From'] = emailSender
|
||||||
|
msg['To'] = emailTarget
|
||||||
|
msg['Subject'] = emailSubject
|
||||||
|
|
||||||
|
body = emailBody
|
||||||
|
msg.attach(MIMEText(body,'plain'))
|
||||||
|
|
||||||
|
|
||||||
|
# is there an attachment specified
|
||||||
|
if emailAttachment:
|
||||||
|
filename=emailAttachment
|
||||||
|
attachment =open(filename,'rb')
|
||||||
|
|
||||||
|
part = MIMEBase('application','octet-stream')
|
||||||
|
part.set_payload((attachment).read())
|
||||||
|
encoders.encode_base64(part)
|
||||||
|
part.add_header('Content-Disposition',"attachment; filename= "+filename)
|
||||||
|
|
||||||
|
msg.attach(part)
|
||||||
|
|
||||||
|
text = msg.as_string()
|
||||||
|
return text
|
||||||
|
|
||||||
|
def openFile(filename):
|
||||||
|
fr = open(filename,'rb')
|
||||||
|
buf = fr.readlines()
|
||||||
|
return buf
|
||||||
|
|
||||||
|
def run(args):
|
||||||
|
# parser.add_argument("-T","--target-list",action="store",required=False,help='list of emails to send to',dest='targetList')
|
||||||
|
# parser.add_argument("-E","--sender-list",action="store",required=False,help='sender email list, FORMAT:<email>:<password><CR><LF>',dest='senderList')
|
||||||
|
|
||||||
|
emailSender = args.senderMail
|
||||||
|
emailTarget = args.targetMail
|
||||||
|
|
||||||
|
emailTargetList = args.targetList
|
||||||
|
emailSenderList = args.senderList
|
||||||
|
|
||||||
|
emailSubject = args.subject
|
||||||
|
emailBody = args.body
|
||||||
|
emailAttachment = args.attachment
|
||||||
|
|
||||||
|
mtaAddr = args.mtaAddr
|
||||||
|
|
||||||
|
# lets build up vars for mta
|
||||||
|
emailMta, emailMtaPort = parseVariable(mtaAddr)
|
||||||
|
print('{0}:{1}'.format(emailMta, emailMtaPort))
|
||||||
|
|
||||||
|
if emailSenderList:
|
||||||
|
senders = openFile(emailSenderList)
|
||||||
|
for emailSender in senders:
|
||||||
|
emailSender = emailSender.decode()
|
||||||
|
emailSender = emailSender.rstrip('\r')
|
||||||
|
emailSender = emailSender.rstrip('\n')
|
||||||
|
#print(emailSender)
|
||||||
|
emailSender, emailPassword = parseVariable(emailSender)
|
||||||
|
print('{0}/{1}'.format(emailSender, emailPassword))
|
||||||
|
|
||||||
|
# build up the mail
|
||||||
|
text = buildEmail(emailSender, emailTarget, emailSubject, emailBody, emailAttachment)
|
||||||
|
print(text)
|
||||||
|
|
||||||
|
# lets send the mail
|
||||||
|
server = smtplib.SMTP(emailMta,emailMtaPort)
|
||||||
|
server.starttls()
|
||||||
|
#embed()
|
||||||
|
server.login(emailSender,emailPassword)
|
||||||
|
|
||||||
|
|
||||||
|
server.sendmail(emailSender,emailTarget,text)
|
||||||
|
server.quit()
|
||||||
|
|
||||||
|
else:
|
||||||
|
print('Single Mail Test')
|
||||||
|
emailSender, emailPassword = parseVariable(emailSender)
|
||||||
|
print('{0}/{1}'.format(emailSender, emailPassword))
|
||||||
|
text = buildEmail(emailSender, emailTarget, emailSubject, emailBody, emailAttachment)
|
||||||
|
|
||||||
|
server = smtplib.SMTP(emailMta,emailMtaPort)
|
||||||
|
server.starttls()
|
||||||
|
server.login(emailSender,emailPassword)
|
||||||
|
|
||||||
|
|
||||||
|
server.sendmail(emailSender,emailTarget,text)
|
||||||
|
server.quit()
|
||||||
|
|
||||||
|
print('The end my friend')
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
parser_desc = '{0} {1} by {2}'.format(__tool_name__, __tool_version__,__tool_author__)
|
||||||
|
prog_desc = __tool_desc__
|
||||||
|
parser = argparse.ArgumentParser(prog = prog_desc, description=parser_desc)
|
||||||
|
# parser.add_argument("-z","--socket-timeout",action="store",required=False,type=int,help='time to wait for socket (default:5)',dest='sockTimeout',default=5)
|
||||||
|
parser.add_argument("-t","--target-email",action="store",required=False,help='single e-mail address the mails to sent to',dest='targetMail')
|
||||||
|
parser.add_argument("-T","--target-list",action="store",required=False,help='list of emails to send to',dest='targetList')
|
||||||
|
parser.add_argument("-e","--sender-email",action="store",required=False,help='single sender e-mail addr, FORMAT:<email>:<password>',dest='senderMail')
|
||||||
|
parser.add_argument("-E","--sender-list",action="store",required=False,help='sender email list, FORMAT:<email>:<password><CR><LF>',dest='senderList')
|
||||||
|
parser.add_argument("-s","--email-subject",action="store",required=False,help='the subject',dest='subject',default='Important Notice about your paypal account')
|
||||||
|
parser.add_argument("-b","--email-body",action="store",required=False,help='the body, e.g. \'hi there, this is a massive test. please ignore.\'',dest='body',default='Sorry, you have been hacked.')
|
||||||
|
parser.add_argument("-a","--email-attachment",action="store",required=False,help='the attachment',dest='attachment',default=None)
|
||||||
|
parser.add_argument("-M","--mta",action="store",required=False,help='the mta, FORMAT:<smtp>:<port>, e.g. smtp.provider.com:25',dest='mtaAddr',default='smtp.gmail.com:25')
|
||||||
|
|
||||||
|
if len(sys.argv)==1:
|
||||||
|
parser.print_help()
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
run(args)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
Reference in New Issue
Block a user