Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python3
- import argparse
- import ssl
- import sys
- import socket
- #import os
- import re
- from base64 import b64encode, b64decode
- from getpass import getpass
- import time
- import quopri
- from random import randint
- SSL_PORT = 995
- PORT = 995
- ALT_PORT = 110
- BUF_SIZE = 2048
- pattern = re.compile(r"^(\d+)( (\d+))*?$")
- header_pattern = re.compile(r"([A-Z][A-Za-z\-]+):(.*)", re.DOTALL)
- headers = {"From", "To", "Subject", "Date"}
- end_file_pattern = re.compile(r"--.*?--")
- type_header = {"Content-Disposition"}
- attachment_pattern = re.compile(r"(attachment)(.*)")
- filename_pattern = re.compile(r"(filename)(.*)")
- filename_pattern2 = re.compile(r"(=)(.*)")
- coded_line_begin = re.compile(r"=(.*?)\?(.*?)\?(B|Q|b|q)\?(.*)")
- coded_line_end = re.compile(r"(.*?)\?=(.*)")
- #Content-Disposition:attachment;filename="test.png"
- #To: КН-201 <e@mail>
- #Subject: тема
- #Date: Fri, 5 Apr 2012 09:00:00 GMT+5
- def parse(choose_of_user, minv, maxv):
- #print(minv, maxv)
- result = pattern.search(choose_of_user)
- if result:
- begin = int(result.group(1))
- if result.group(2):
- end = int(result.group(3))
- else:
- end = int(result.group(1)) + 1
- #print(minv <= begin and begin <= end and end <= maxv + 1)
- if (minv <= begin and begin <= end and end <= maxv + 1):
- return range(begin, end)
- else:
- return None
- class MessageParser:
- def __init__(self):
- pass
- def parse_message(self, msg):
- lines = msg.split(b"\r\n")
- size = 0
- attachment_count = 0
- msg = {"filename":[]}
- current_header = ""
- read_token = False
- attach_read = False
- for line_bytes in lines:
- #print(line)
- try:
- line = line_bytes.decode()
- except UnicodeDecodeError:
- #print("unicode")
- continue
- size += len(line)
- res = header_pattern.search(line)
- if res:
- name_header = res.group(1)
- if name_header in headers:
- #print("header" + name_header)
- current_header = name_header
- read_token = True
- #print(res.group(1))
- msg[current_header] = res.group(2) + "\r\n"
- elif name_header in type_header:
- #print(line)
- res = attachment_pattern.search(res.group(2))
- if res:
- res = filename_pattern.search(res.group(2))
- if res:
- res = filename_pattern2.search(res.group(2))
- if res:
- attachment_count += 1
- msg["filename"].append(res.group(2))
- read_token = True
- msg[res.group(2)] = 0
- current_header = res.group(2)
- attach_read = True
- elif attach_read:
- pass
- #print(line)
- #print("true")
- #msg[current_header] += line + "\r\n"
- else:
- #print(line)
- #print("false")
- read_token = False
- attach_read = False
- elif read_token and not attach_read:
- #print(line)
- #print("true")
- msg[current_header] += line + "\r\n"
- elif attach_read and read_token:
- #print(line, len(line))
- #print("true")
- read_token = False
- elif attach_read:
- if (end_file_pattern.search(line)):
- #print("end", line)
- attach_read = False
- else:
- msg[current_header] += len(line)
- else:
- read_token = False
- attach_read = False
- msg["From"] = self.decode_header(msg.get("From"))
- msg["Subject"] = self.decode_header(msg.get("Subject"))
- msg["To"] = self.decode_header(msg.get("To"))
- msg["Date"] = msg.get("Date", "").strip()
- for key in headers:
- try:
- print("{}: {}".format(key, msg.get(key)))
- except UnicodeEncodeError:
- print("Header has a proplem with unicode {}".format(key))
- print("{} in bytes".format(msg.get(key).encode()))
- print("Amount attaches = {}".format(attachment_count))
- for filename in msg["filename"]:
- print("Filename: {}, size of file: {}".format(filename, msg.get(filename)))
- def decode_header(self, header):
- result = ""
- data = ""
- end = ""
- #print("header")
- #print(header)
- #print()
- if header:
- tokens = coded_line_begin.search(header)
- if tokens:
- while tokens:
- notcode = tokens.group(1)
- coding = tokens.group(2)
- alg = tokens.group(3)
- data = tokens.group(4)
- result += notcode
- #print(notcode, coding, alg, data)
- res = coded_line_end.search(data)
- result += self.get_original_string(coding, alg, res)
- if res:
- tokens = coded_line_begin.search(res.group(1))
- end = res.group(2)
- return result + end
- else:
- return header
- def get_original_string(self, coding, alg, res):
- if res:
- #print(res.group(1))
- coded_data = res.group(1)
- try:
- if alg == "Q" or alg == "q":
- string = quopri.decodestring(coded_data).decode(coding)
- else:
- string = b64decode(coded_data).decode(coding)
- except UnicodeEncodeError:
- return "unicode_troubles"
- return string
- return ""
- class POP3:
- def __init__(self, server_hostname, debug):
- self.server_hostname = server_hostname
- self.debug = debug
- self.timeout = 2
- self.parser = MessageParser()
- def _get_socket(self, host, port, timeout):
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.settimeout(timeout)
- if port == SSL_PORT:
- sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_SSLv23)
- sock.connect((host, port))
- greeting = sock.recv(1024)
- if self.debug:
- print(greeting, file=sys.stderr)
- return sock
- def connect(self, host, port):
- self.sock = self._get_socket(host, port, self.timeout)
- def send(self, msg):
- if (self.debug):
- print(msg, file=sys.stderr)
- self.sock.send(msg.encode() + b"\r\n")
- def recieve(self):
- result = b""
- data = b""
- try:
- data = self.sock.recv(BUF_SIZE)
- while data:
- result += data
- data = self.sock.recv(BUF_SIZE)
- except socket.timeout:
- # print("timeout")
- if result[:1] == b"-":
- print("Oparation failed")
- sys.exit(1)
- return result
- if result[:1] == b"-":
- print("Oparation failed")
- sys.exit(1)
- return result
- def authentication(self):
- mail = input("Enter your mail ")
- password = getpass("Enter your password ")
- self.send("USER {}".format(mail))
- ans = self.recieve()
- if (self.debug):
- print(ans, file=sys.stderr)
- self.send("PASS {}".format(password))
- ans = self.recieve()
- if (self.debug):
- print(ans, file=sys.stderr)
- def list_command(self):
- self.send("LIST")
- data = self.recieve()
- if (self.debug):
- print(data, file=sys.stderr)
- list_msgs = data.split(b"\r\n")[1:-2]
- #for letter_id in list_msgs[:-2]:
- # print(letter_id.decode())
- first = int(list_msgs[0].decode().split(" ")[0])
- last = int(list_msgs[-1].decode().split(" ")[0])
- print("First_number {}, last number - {}".format(first, last))
- res = None
- while not res:
- choose_of_user = input("сhoose one or range ")
- if (self.debug):
- print(choose_of_user, file=sys.stderr)
- res = parse(choose_of_user, first, last)
- #print(res)
- for i in res:
- msg_id = list_msgs[i - 1].decode().split(" ")[0]
- size_msg = list_msgs[i - 1].decode().split(" ")[1]
- print("ID {}".format(msg_id))
- try:
- self.retr_command("{}".format(list_msgs[i - 1].decode().split(" ")[0]))
- except UnicodeDecodeError as e:
- pass
- #print(e)
- print("Size message {} in octets".format(size_msg))
- def retr_command(self, msg_id):
- self.send("RETR {}".format(msg_id))
- ans = self.recieve()
- while ans[-5:] != b"\r\n.\r\n":
- #print(ans[-5:])
- ans += self.recieve()
- self.parser.parse_message(ans)
- if (self.debug):
- with open("retr.eml", "w") as f:
- print(ans, file=f)
- def top_command(self, msg_id):
- self.send("TOP {}".format(msg_id))
- ans = self.recieve()
- self.parser.parse_message(ans)
- if (self.debug):
- with open("top.eml", "w") as f:
- print(ans, file=f)
- def capa_command(self):
- self.send("CAPA")
- data = self.recieve().decode()
- if (self.debug):
- print(data, file=sys.stderr)
- def quit_command(self):
- self.send("QUIT")
- data = self.recieve()
- if (self.debug):
- print(data, file=sys.stderr)
- def is_valid_ip4_address(addr):
- parts = addr.split(".")
- if not len(parts) == 4:
- return False
- for part in parts:
- try:
- number = int(part)
- except ValueError:
- return False
- if number > 255:
- return False
- return True
- def to_ip(addr):
- if is_valid_ip4_address(addr):
- return addr
- return socket.gethostbyname(addr)
- def new_session(server, debug):
- connection = POP3(server, debug)
- ssl_connection = True
- try:
- connection.connect(server, PORT)
- if (debug):
- print("PORT = {}".format(PORT))
- except OSError as e:
- try:
- connection.connect(server, ALT_PORT)
- if (debug):
- ssl_connection = False
- print("PORT = {}".format(ALT_PORT))
- except OSError as e:
- print(e)
- sys.exit(1)
- connection.capa_command()
- connection.authentication()
- connection.list_command()
- connection.quit_command()
- def main():
- parser = argparse.ArgumentParser(description="POP3")
- parser.add_argument("server_pop3", help="Server POP3")
- parser.add_argument("-d", "--debug", action='store_true', help="debug_mode")
- args = parser.parse_args()
- try:
- new_session(args.server_pop3, args.debug)
- except Exception as e:
- print(e)
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement