2024-02-29 15:49:20 +00:00
|
|
|
#!/usr/bin/python3
|
|
|
|
#
|
|
|
|
# smtp.py
|
|
|
|
#
|
|
|
|
# Caterpillar - The simple and parasitic web proxy with spam filter
|
|
|
|
# Namyheon Go (Catswords Research) <gnh1201@gmail.com>
|
|
|
|
# https://github.com/gnh1201/caterpillar
|
|
|
|
# Created at: 2024-03-01
|
|
|
|
# Updated at: 2024-03-01
|
|
|
|
#
|
|
|
|
|
2024-02-29 15:44:59 +00:00
|
|
|
import asyncore
|
|
|
|
from smtpd import SMTPServer
|
2024-02-29 15:53:33 +00:00
|
|
|
import re
|
2024-02-29 15:44:59 +00:00
|
|
|
import json
|
|
|
|
import requests
|
2024-02-29 15:40:54 +00:00
|
|
|
|
2024-02-29 15:53:33 +00:00
|
|
|
from decouple import config
|
2024-02-29 15:54:08 +00:00
|
|
|
from requests.auth import HTTPBasicAuth
|
2024-02-29 15:53:33 +00:00
|
|
|
|
2024-03-02 08:36:30 +00:00
|
|
|
from server import extract_credentials, jsonrpc2_create_id, jsonrpc2_encode, jsonrpc2_decode
|
2024-02-29 15:53:33 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
smtp_host = config('SMTP_HOST', default='127.0.0.1')
|
|
|
|
smtp_port = config('SMTP_PORT', default=25, cast=int)
|
|
|
|
_username, _password, server_url = extract_credentials(config('SERVER_URL'))
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
print("\n[*] User has requested an interrupt")
|
|
|
|
print("[*] Application Exiting.....")
|
|
|
|
sys.exit()
|
|
|
|
|
|
|
|
auth = None
|
|
|
|
if _username:
|
|
|
|
auth = HTTPBasicAuth(_username, _password)
|
|
|
|
|
2024-02-29 15:40:54 +00:00
|
|
|
class CaterpillarSMTPServer(SMTPServer):
|
2024-02-29 19:09:45 +00:00
|
|
|
def __init__(self, localaddr, remoteaddr):
|
|
|
|
self.__class__.smtpd_hostname = "CaterpillarSMTPServer"
|
2024-03-02 10:49:48 +00:00
|
|
|
self.__class__.smtp_version = "0.1.6"
|
2024-02-29 19:09:45 +00:00
|
|
|
super().__init__(localaddr, remoteaddr)
|
|
|
|
|
2024-02-29 15:40:54 +00:00
|
|
|
def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
|
|
|
|
message_lines = data.decode('utf-8').split('\n')
|
|
|
|
subject = ''
|
|
|
|
to = ''
|
|
|
|
for line in message_lines:
|
|
|
|
pos = line.find(':')
|
|
|
|
if pos > -1:
|
|
|
|
k = line[0:pos]
|
|
|
|
v = line[pos+1:]
|
2024-03-02 10:49:48 +00:00
|
|
|
if k == 'Subject':
|
2024-02-29 15:40:54 +00:00
|
|
|
subject = v
|
2024-03-02 10:49:48 +00:00
|
|
|
elif k == 'To':
|
2024-02-29 15:44:59 +00:00
|
|
|
to = v
|
|
|
|
|
|
|
|
# build a data
|
2024-02-29 19:36:04 +00:00
|
|
|
proxy_data = {
|
|
|
|
'headers': {
|
2024-03-02 10:49:48 +00:00
|
|
|
"User-Agent": "php-httpproxy/0.1.6 (Client; Python " + python_version() + "; Caterpillar; abuse@catswords.net)",
|
2024-02-29 19:36:04 +00:00
|
|
|
},
|
|
|
|
'data': {
|
|
|
|
"to": to,
|
|
|
|
"from": mailfrom,
|
|
|
|
"subject": subject,
|
|
|
|
"message": data.decode('utf-8')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_, raw_data = jsonrpc2_encode('relay_sendmail', proxy_data['data'])
|
2024-02-29 15:44:59 +00:00
|
|
|
|
|
|
|
# send HTTP POST request
|
|
|
|
try:
|
2024-02-29 19:36:04 +00:00
|
|
|
response = requests.post(server_url, headers=proxy_data['headers'], data=raw_data, auth=auth)
|
2024-02-29 15:59:36 +00:00
|
|
|
if response.status_code == 200:
|
|
|
|
type, id, method, rpcdata = jsonrpc2_decode(response.text)
|
|
|
|
if rpcdata['success']:
|
|
|
|
print("[*] Email sent successfully.")
|
|
|
|
else:
|
2024-02-29 19:39:02 +00:00
|
|
|
raise Exception("(%s) %s" % (str(rpcdata['code']), rpcdata['message']))
|
2024-02-29 19:39:58 +00:00
|
|
|
else:
|
|
|
|
raise Exception("Status %s" % (str(response.status_code)))
|
2024-02-29 15:44:59 +00:00
|
|
|
except Exception as e:
|
2024-02-29 15:53:33 +00:00
|
|
|
print("[*] Failed to send email:", str(e))
|
2024-02-29 15:44:59 +00:00
|
|
|
|
|
|
|
# Start SMTP server
|
2024-02-29 15:53:33 +00:00
|
|
|
smtp_server = CaterpillarSMTPServer((smtp_host, smtp_port), None)
|
2024-02-29 15:40:54 +00:00
|
|
|
|
2024-02-29 15:44:59 +00:00
|
|
|
# Start asynchronous event loop
|
|
|
|
asyncore.loop()
|