En este capítulo del tutorial de Python 3 más PyQt5 crearemos una sencilla aplicación que nos permita enviar correos con servidores que dispongan del protocolo SMTP (protocolo para transferencia simple de correo) tales como Hotmail, Gmail, Yahoo, ...
El programa permitirá al usuario configurar sus preferencias tales como el servidor STMP, puerto, credenciales, uso opcional del protocolo starttls, adjuntar multiples archivos (QFileDialog), agregar múltiples destinatarios, etc.
El programa mostrará en una etiqueta QLabel el proceso de envío del correo así como cualquier excepción que pudiera ocurrir.
Configuración para servidores SMTP clásicos:
Hotmail:
– SMTP - smtp.live.com (TLS enabled, port 25)
GMail by Google:
– SMTP - smtp.gmail.com (TLS enabled, port 587)
Yahoo! Mail:
– SMTP - smtp.mail.yahoo.com (port 25)
Lycos Mail:
– SMTP - smtp.mail.lycos.com (port 25)
AOL Mail Settings:
– SMTP - smtp.aol.com (port 25)
smtp.pyw
import sys, smtplib, email from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders from PyQt5.QtWidgets import QApplication, QDialog, QGridLayout, QMessageBox, QPushButton, QLabel, QLineEdit, QFileDialog, QTextEdit, QCheckBox class FileDialog(QFileDialog): def __init__(self): QFileDialog.__init__(self) self.setFileMode(QFileDialog.ExistingFiles) #Selección múltiple self.files = [] #Lista que guardará las rutas de los archivos self.filesSelected.connect(self.getFiles) #Activar la señal al seleccionar archivos def getFiles(self): self.files = self.selectedFiles() #Agregar las rutas de archivos a la lista class Dialogo(QDialog): def __init__(self): QDialog.__init__(self) self.setWindowTitle("Enviar email SMTP") self.resize(450, 600) #Crear objetos en el cuadro de diálogo self.layout = QGridLayout() self.setLayout(self.layout) self.label_host = QLabel("Host SMTP:") self.txt_host = QLineEdit() self.chk_tls = QCheckBox("STARTTLS") self.chk_tls.setChecked(True) self.label_port = QLabel("Puerto:") self.txt_port = QLineEdit() self.label_user = QLabel("Usuario:") self.txt_user = QLineEdit() self.label_pass = QLabel("Password:") self.txt_pass = QLineEdit() self.txt_pass.setEchoMode(QLineEdit.Password) self.label_from = QLabel("Remitente:") self.txt_from = QLineEdit() self.label_to = QLabel("Destinatario/s:") self.txt_to = QLineEdit() self.label_subject = QLabel("Asunto:") self.txt_subject = QLineEdit() self.label_dialog = QLabel("Adjunto:") self.btn_dialog = QPushButton("Seleccionar ...") self.label_body = QLabel("Mensaje: ") self.txt_body = QTextEdit() self.label_state = QLabel("") self.btn_send = QPushButton("Enviar") #Crear objeto de la clase FileDialog() self.fileDialog = FileDialog() #Agregar objetos al layout grid self.layout.addWidget(self.label_host) self.layout.addWidget(self.txt_host) self.layout.addWidget(self.chk_tls) self.layout.addWidget(self.label_port) self.layout.addWidget(self.txt_port) self.layout.addWidget(self.label_user) self.layout.addWidget(self.txt_user) self.layout.addWidget(self.label_pass) self.layout.addWidget(self.txt_pass) self.layout.addWidget(self.label_from) self.layout.addWidget(self.txt_from) self.layout.addWidget(self.label_to) self.layout.addWidget(self.txt_to) self.layout.addWidget(self.label_subject) self.layout.addWidget(self.txt_subject) self.layout.addWidget(self.label_dialog) self.layout.addWidget(self.btn_dialog) self.layout.addWidget(self.label_body) self.layout.addWidget(self.txt_body) self.layout.addWidget(self.label_state) self.layout.addWidget(self.btn_send) #Señal para abrir el cuadro de diálogo de selección de archivos self.btn_dialog.clicked.connect(self.openDialog) #Señal para proceder a enviar los correos self.btn_send.clicked.connect(self.sendMail) #Método encargado de abrir el cuadro de diálogo de selección de archivos def openDialog(self): self.fileDialog.open() #Método encargado de procesar el envío de correos def sendMail(self): To = self.txt_to.text().split(", ") #Lista con los destinatarios #Capturar cualquier posible excepción y mostrarlo en el label label_state try: #Recorrer los destinatarios for destinatario in To: #Guardar los valores del formulario Host = self.txt_host.text() Port = self.txt_port.text() User = self.txt_user.text() Pass = self.txt_pass.text() From = self.txt_from.text() Subject = self.txt_subject.text() Body = self.txt_body.toPlainText() #Objeto para procesar el envío de correo smtp = smtplib.SMTP(Host, Port) #Si el servidor utilizar el protocolo starttls activarlo if self.chk_tls.isChecked(): smtp.starttls() #Credenciales smtp.login(User, Pass) #Iniciar la cabecera header = MIMEMultipart() header['From'] = From header['To'] = destinatario header["Subject"] = Subject msg = MIMEText(Body, 'html') #Content-type:text/html header.attach(msg) #Lista para agregrar en la cabecera los archivos a enviar parts = [] for file in self.fileDialog.files: parts.append(MIMEBase('application', "octet-stream")) #Nos permite indexar la ruta de los archivos que se encuentran #en el atributo files del objeto fileDialog x = 0 #Recorrer archivo a archivo for part in parts: #Lectura del archivo part.set_payload(open(self.fileDialog.files[x], "rb").read()) #Codificar el archivo en base64 encoders.encode_base64(part) #Extracción del nombre del archivo explode = self.fileDialog.files[x].split("/") filename = explode[len(explode)-1] #Añadir archivo a la cabecera part.add_header('Content-Disposition', 'attachment; filename="'+filename+'"') header.attach(part) x = x + 1 #Enviar el correo al destinatario smtp.sendmail(From, destinatario, header.as_string()) #Terminar la conexión con el servidor smtp.quit() #Mostrar el proceso self.label_state.setText("Enviando a " + destinatario + " ... ") except Exception as e: #Capturar cualquier posible excepción y mostrarla self.label_state.setText(str(e)) parts[:] = [] #Limpiar la lista de archivos self.fileDialog.files[:] = [] #Limpiar la lista de archivos self.label_state.setText("Envío finalizado") app = QApplication(sys.argv) dialogo = Dialogo() dialogo.show() app.exec_()
1 comentario:
Muchas gracias por este tutorial, me ha sido de mucha utilidad.
Publicar un comentario