Created
June 7, 2017 04:58
-
-
Save arthurafarias/b4b5feda467530514a4c6500c4800968 to your computer and use it in GitHub Desktop.
Atividade de Redes de Computadores - Questão 02
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
"""Google SMTP Client. | |
Usage: | |
gsmtpc (-l=<email>|--login=<email>) | |
gsmtpc (-l=<email>|--login=<email>) [-p=<plain> | --password=<plain>] [-r=<email> | --recipient=<email>] [-s=<text> | --subject=<text>] [-m=<text> | --message=<text>] | |
gsmtpc (-h | --help) | |
Options: | |
-h --help Show this screen. | |
-l --login=<email> User's account used to login in smtp server. | |
-p --password=<plain> User's account plain password to login in gmail smtp server. | |
-r --recipient=<email> Recipient e-mail account. | |
-s --subject=<text> Subject of the message. | |
-m --message=<text> Message. | |
""" | |
from docopt import docopt | |
from types import * | |
import base64 | |
import socket | |
import ssl | |
import re | |
import sys | |
DEBUGGING = True | |
from getpass import getpass | |
import readline | |
def rlinput(prompt, prefill=''): | |
try: | |
return raw_input(prompt) | |
finally: | |
readline.set_startup_hook() | |
# Classe que, por interface em linha de comando oferece toda a autenticação e | |
# arcabouço facilitado para envio de e-mails pelo gmail. | |
class GoogleSMTPClient(object): | |
# Cada propriedade, quando chamada, mas não definida é interativamente | |
# solicitada ao usuário. | |
@property | |
def args(self): | |
return self._args | |
@args.setter | |
def args(self, value): | |
self._args = value | |
self.user = self._args.get("--login") | |
self.password = self._args.get("--password") | |
self.recipient = self._args.get("--recipient") | |
self.subject = self._args.get("--subject") | |
self.message = self._args.get("--message") | |
@property | |
def user(self): | |
try: | |
if not self._user: | |
self._user = raw_input("type your username (ex. [email protected]): ") | |
return self._user | |
else: | |
return self._user | |
except AttributeError: | |
self._user = None | |
return self.user | |
@user.setter | |
def user(self, value): | |
self._user = value | |
@property | |
def password(self): | |
try: | |
if not self._password: | |
self._password = getpass("Type your password: ") | |
return self._password | |
else: | |
return self._password | |
except AttributeError: | |
self._password = None | |
return self.password | |
@password.setter | |
def password(self, value): | |
self._password = value | |
@property | |
def recipient(self): | |
try: | |
if not self._recipient: | |
self._recipient = raw_input("type the recipient (ex. [email protected]): ") | |
return self._recipient | |
else: | |
return self._recipient | |
except AttributeError: | |
self._recipient = None | |
return self.recipient | |
@recipient.setter | |
def recipient(self, value): | |
self._recipient = value | |
@property | |
def subject(self): | |
try: | |
if not self._subject: | |
self._subject = raw_input("type the subject of the message: ") | |
return self._subject | |
else: | |
return self._subject | |
except AttributeError: | |
self._subject = None | |
return self.subject | |
@subject.setter | |
def subject(self, value): | |
self._subject = value | |
@property | |
def message(self): | |
try: | |
if not self._message: | |
print("type the message (exit: cntrl + c): ") | |
self._message = "" | |
while True: | |
try: | |
input_str = raw_input("> ") | |
self._message += input_str + "\r\n" | |
except KeyboardInterrupt: | |
print ("Is message correct?") | |
print ("\n===text===") | |
print (self.message) | |
print ("===text===\n") | |
while True: | |
confirm = raw_input("Discard? (y/n):") | |
if ( (confirm == "Y") | (confirm == "y") ): | |
self.message = "" | |
break | |
elif( (confirm == "N") | (confirm == "n") ): | |
return self._message | |
else: | |
print("Invalid Input") | |
else: | |
return self._message | |
except AttributeError: | |
self._message = None | |
return self.message | |
@message.setter | |
def message(self, value): | |
self._message = value | |
@property | |
def authcode(self): | |
return base64.b64encode("\000" + self.user + "\000" + self.password ) | |
def gsmtp_create_context(self): | |
# Inicia um contexto SSL | |
self.ssl_context = ssl.create_default_context() | |
# Cria-se uma conexxão SSL | |
self.ssl_connection = self.ssl_context.wrap_socket(socket.socket( socket.AF_INET, socket.SOCK_STREAM ), server_hostname="smtp.gmail.com") | |
pass | |
def gsmtp_send_command(self, command): | |
if DEBUGGING: | |
print command | |
self.ssl_connection.sendall(command + "\r\n") | |
def gsmtp_connect(self): | |
# Tenta-se Criar um Contexto SMTP com o GOOGLE | |
self.gsmtp_create_context() | |
# Tenta-se conectar ao servidor SMTP do gmail através da conexão recém | |
# criada. | |
self.ssl_connection.connect(("smtp.gmail.com", 465)) | |
self.gsmtp_get_response() | |
# Inicia-se a seção de funcionamento do servidor | |
self.gsmtp_send_command("HELO .") | |
self.gsmtp_get_response() | |
# Parser em expressão regular das respostas às requisições SMTP | |
def gsmtp_get_response(self): | |
buff = self.ssl_connection.recv(8192) | |
buff_parsed = re.search("([0-9]{0,1})[0-9]{0,1}[0-9]{0,1}\-{0,1}[0-9]{0,1}\.{0,1}[0-9]{0,1}\.{0,1}[0-9]{0,1} (.*)\r\n(([0-9]{0,1})[0-9]{0,1}[0-9]{0,1} {0,1}[0-9]{0,1}\.{0,1}[0-9]{0,1}\.{0,1}[0-9]{0,1} (.*)\r\n){0,1}", buff) | |
response = ( buff_parsed.group(1), buff_parsed.group(2) + str(buff_parsed.group(5)) ) | |
if DEBUGGING: | |
print buff | |
print response | |
return response | |
def gsmtp_auth(self): | |
while True: | |
# Tenta-se enviar o comando de autenticação ao servidor SMTP | |
self.gsmtp_send_command("AUTH PLAIN "+ self.authcode) | |
# Recebe-se a resposta | |
response = self.gsmtp_get_response() | |
# Se o código da resposta é diferente de 5, encerra-se a | |
# autenticação com sucesso. | |
if response[0] != '5': | |
break | |
# Se o código da resposta é 5, encerra-se a autenticação com erro | |
else: | |
raise Exception("Could not authenticate at GMAIL.") | |
self.user = None | |
self.password = None | |
def gsmtp_send_message(self): | |
# Configuração da Mensagem de E-Mail | |
self.gsmtp_send_command("MAIL FROM: <"+ self.user +">") | |
self.gsmtp_get_response() | |
self.gsmtp_send_command("rcpt to: <"+ self.recipient +">") | |
self.gsmtp_get_response() | |
self.gsmtp_send_command("DATA") | |
self.gsmtp_get_response() | |
self.gsmtp_send_command("From: "+ self.user +"") | |
self.gsmtp_send_command("To: "+ self.recipient +"") | |
self.gsmtp_send_command("Subject: "+ self.subject +"") | |
self.gsmtp_send_command(""+ self.message +"") | |
# Sinal de término da Mensagem de E-Mail | |
self.gsmtp_send_command(".") | |
self.gsmtp_get_response() | |
def __init__(self): | |
try: | |
# Document Options | |
self.args = docopt(__doc__, version="Google's SMTP Client v0.2") | |
# Chama o método de inicialização da conexão | |
self.gsmtp_connect() | |
# Tenta realizar a autenticação. Note que cada parâmetro não | |
# definido e necessário será definido interativamente quando | |
# invocado o getter do atributo referente ao parâmetro. | |
self.gsmtp_auth() | |
# Tenta enviar a mensagem | |
self.gsmtp_send_message() | |
except KeyboardInterrupt, SystemExit: | |
# Se há interrupção pelo teclado ou o sistema operacional tenta | |
# enviar algum sinal de interrupção ao processo, invoca-se a saída | |
# do script. | |
sys.exit() | |
except Exception as e: | |
# Qualquer outra exceção que ocorra, ela será impressa na saída | |
# e o processo será encerrado com sucesso | |
print "Error: " + e.message | |
# Inicializa a classe quando solicitado o nome padrão "__name__" é definido como | |
# '__main__'. | |
if __name__ == '__main__': | |
GoogleSMTPClient() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment