From 5528ff3e9a403249f5d957b85b3be4213c028a78 Mon Sep 17 00:00:00 2001 From: PavelMuhortov Date: Tue, 15 Jun 2021 13:30:14 +0300 Subject: [PATCH] add sendmail.py --- sendmail.py | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 sendmail.py diff --git a/sendmail.py b/sendmail.py new file mode 100644 index 0000000..df5837b --- /dev/null +++ b/sendmail.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 + + +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.mime.base import MIMEBase +from email import encoders +from os import path +from smtplib import SMTP +from socket import error + + +class Mail: + """ + Sending email from Python + """ + def __init__(self, smtp_user: str, smtp_pass: str, mail_dest: str, + smtp_host: str = 'smtp.gmail.com', smtp_port: str = '587', smtp_stls: bool = True, + mail_from: str = None, mail_subj: str = 'no subject', + mail_text: str = 'no text', mail_type: str = 'plain', + mail_file: str = None): + """ + Object constructor + :param smtp_user: smtp valid user + :param smtp_pass: smtp valid password + :param mail_dest: destination addresses + :param smtp_host: smtp hostname or ip address + :param smtp_port: smtp port number + :param smtp_stls: smtp required tls + :param mail_from: mail from alias + :param mail_subj: mail subject + :param mail_text: mail body text + :param mail_type: mail body type: plain, html + :param mail_file: mail attachment files + """ + self._smtpUser = self._getText(smtp_user) + self._smtpPass = self._getText(smtp_pass) + self._mailList = list(filter(None, ''.join(self._getText(mail_dest).split()).split(','))) + self._smtpHost = self._getText(smtp_host) + self._smtpPort = self._getText(smtp_port) + self._smtpStls = smtp_stls + self._mailSubj = self._getText(mail_subj) + self._mailText = self._getText(mail_text) + self._mailType = self._getText(mail_type) + if mail_from: + self._mailFrom = self._getText(mail_from) + else: + self._mailFrom = self._smtpUser + if mail_file: + self._fileList = list(filter(None, ''.join(mail_file.split()).split(','))) + else: + self._fileList = None + self._session = None + self._mailData = MIMEMultipart() + self._mailData['From'] = self._mailFrom + self._mailData['Subject'] = self._mailSubj + self._mailData.attach(MIMEText(self._mailText, self._mailType)) + if self._fileList: + for file in self._fileList: + if path.exists(file): + attachment = open(file, "rb") + content = MIMEBase('application', 'octet-stream') + content.set_payload(attachment.read()) + encoders.encode_base64(content) + content.add_header("Content-Disposition", f"attachment; filename= {path.basename(file)}") + self._mailData.attach(content) + + def send(self): + """ + Sending the generated email to the destination list + :return: delivery report string + """ + report = '' + try: + self._session = SMTP(self._smtpHost, int(self._smtpPort)) + if self._smtpStls: + self._session.starttls() + self._session.login(self._smtpUser, self._smtpPass) + for mailTo in self._mailList: + del self._mailData['To'] + self._mailData['To'] = mailTo + self._session.sendmail(self._mailFrom, mailTo, self._mailData.as_string()) + report += '"' + self._mailData['Subject'] + '"' + ' send to ' + self._mailData['To'] + '\n' + self._session.quit() + except error as err: + report += "Socket Error: %s" % err + finally: + return report + + @staticmethod + def _getText(string: str): + """ + If text is a file - read text from this file + :param string: string of text or file path + :return: string of input text or file content + """ + if path.exists(string): + return open(string).read() + else: + return string + + +def str2bool(value: str): + """ + Converts a string value to boolean + :param value: string containing "true" or "false", "yes" or "no", "1" or "0" + :return: bool True or False + """ + return str(value).lower() in ("true", "yes", "1") + + +if __name__ == "__main__": + from argparse import ArgumentParser + + args = ArgumentParser( + prog='Mail', + description='Sending email from Python', + epilog='Dependencies: Python 3 (tested version 3.9.5)' + ) + args.add_argument('-u', '--user', type=str, required=True, + help='smtp valid user') + args.add_argument('-p', '--pass', type=str, required=True, + help='smtp valid password') + args.add_argument('-d', '--dest', type=str, required=True, + help='destination addresses') + args.add_argument('--smtp', type=str, default='smtp.gmail.com', required=False, + help='smtp hostname or ip address (default: smtp.gmail.com)') + args.add_argument('--port', type=str, default='587', required=False, + help='smtp port number (default: 587)') + args.add_argument('--stls', type=str2bool, default=True, required=False, + help='smtp required tls (default: True)') + args.add_argument('--from', type=str, default=None, required=False, + help='mail from alias (default: )') + args.add_argument('--subj', type=str, default='no subject', required=False, + help='mail subject (default: "no subject")') + args.add_argument('--text', type=str, default='no text', required=False, + help='mail body text (default: "no text")') + args.add_argument('--type', type=str, default='plain', required=False, + help='mail body type: plain, html (default: plain)') + args.add_argument('--file', type=str, default=None, required=False, + help='mail attachment files (default: None)') + args = vars(args.parse_args()) + + print(Mail(smtp_user=args['user'], smtp_pass=args['pass'], mail_dest=args['dest'], + smtp_host=args['smtp'], smtp_port=args['port'], smtp_stls=args['stls'], + mail_from=args['from'], mail_subj=args['subj'], mail_text=args['text'], + mail_type=args['type'], mail_file=args['file'] + ).send() + )