Я участвую в разработке одного проекта на работе. Мы разрабатываем прототипы Raspberry Pi и специальное программное обеспечение. Хоть и разработанное ПО работает блестяще, нам бы хотелось добавить немного дополнительных функций.

Используем Python!

Первое, что мне пришло в голову — это отправка e-mail. Я подумал, что это будет самый сложный фрагмент кода, который мне придётся написать. Если закончу с ним, остальная работа для меня будет довольно лёгкой. Ну или я так думал…

Первое, что я сделал — пошёл на Stack Overflow и нашёл ответ на свой вопрос.

Кажется, довольно просто.

Отправка e-mail

Добавив smtplib из стандартной библиотеки, вы можете отсылать письма очень легко. Мне пришлось посмотреть синтаксис определения функций и прочитать про код-стайл Python. Я всегда предпочитаю использовать имена функций, которые больше всего подходят для языка. Это привело меня к созданию следующей функции:

def send_mail(
        sender,
        receivers: List[str],
        subject,
        body,
        username,
        password,
        server_address
):
    """Sends an email to the specified receivers using an Exchange server."""
    message = MIMEMultipart()
    message["From"] = sender
    message["To"] = ",".join(receivers)
    message["Subject"] = subject
    message.attach(MIMEText(body))

    server = smtplib.SMTP(server_address, 587)
    server.starttls()
    server.login(username, password)
    server.sendmail(sender, receivers, message.as_string())
    server.quit()

Поскольку я использую Exchange сервер, мне приходится инициализировать TLS. Не считая этого, всё довольно просто.

Запускаем скрипт в терминале

Я также хотел иметь возможность запуска скрипта в терминале. Это можно сделать, вызвав функцию после её определения. Когда интерпретатор Python будет проходить через файл, он выполнит её вызов.

Однако в Python хорошим тоном считается поместить вызов внутри аргумента __name__ == » __main__». Это делается для того, чтобы определить, запущен файл напрямую или импортирован другим файлом или модулем.

Когда интерпретатор Python запускает файл напрямую (например, в терминале), он устанавливает глобальную переменную __name__ в __main__.
Когда файл импортируется другим файлом или модулем, __name__ будет установлено как имя файла или модуля.

Поместив выполняемый код внутри if __name__ == » __main__», мы убеждаемся, что код запускается только тогда, когда файл используется напрямую, а не импортируется в другую часть кода.

Анализ входных данных

Я хотел бы указать параметры для функции send_mail, передав их при запуске файла в терминале. Оказывается, у Python тоже есть библиотека для этого!
Импортируя argparse, у меня появляется возможность определить параметры, добавить типовые подсказки и справочные тексты. argparse автоматически добавляет ключ -h, который показывает все возможные параметры и справочные тексты.

Чтобы было поинтереснее, я добавил функцию, которая может использовать файл с текстом, вместо обычного ввода текста. Скрипт получает текст из файла и использует его как контент письма.

if __name__ == " __main__":  
    parser = argparse.ArgumentParser(description="Sends an email to the specified receivers using the Sykehuspartner Exchange server.")
    parser.add_argument("sender", type=str, help="Sender's email address.")
    parser.add_argument("receivers", type=str, help="Comma-seperated list of email addresses.")
    parser.add_argument("subject", type=str, help="Subject of the email.")
    parser.add_argument("body", type=str, help="Body text of the email. Can be plain text or a file path when -f is passed.")
    parser.add_argument("username", type=str, help="The username to authenticate with on mail server.")
    parser.add_argument("password", type=str, help="The password to authenticate with on mail server.")
    parser.add_argument("server", type=str, help="The address of the mail server.")
    parser.add_argument("-f", "--file", action="store_true", help="Specifies that the body argument contains a file path instead of plain text")
    args = parser.parse_args()

    if args.file:
        with open(args.body) as file:
            args.body = file.read()

    send_mail(args.sender, args.receivers.split(","), args.subject, args.body, args.username, args.password, args.server)

Перевод статьи Jon Stødle: Sending an email with Python