Send email in Python conveniently for gmail using yagmail

Overview

yagmail -- Yet Another GMAIL/SMTP client

Join the chat at https://gitter.im/kootenpv/yagmail PyPI PyPI

For the asynchronous asyncio version, look here: https://github.com/kootenpv/aioyagmail

The goal here is to make it as simple and painless as possible to send emails.

In the end, your code will look something like this:

import yagmail
yag = yagmail.SMTP()
contents = ['This is the body, and here is just text http://somedomain/image.png',
            'You can find an audio file attached.', '/local/path/song.mp3']
yag.send('[email protected]', 'subject', contents)

Or a simple one-liner:

yagmail.SMTP('mygmailusername').send('[email protected]', 'subject', 'This is the body')

Note that it will read the password securely from your keyring (read below). If you don't want this, you can also initialize with:

yag = yagmail.SMTP('mygmailusername', 'mygmailpassword')

In 2020, I personally prefer: using an Application-Specific Password

Table of Contents

Section Explanation
Install Find the instructions on how to install yagmail here
Username and password No more need to fill in username and password in scripts
Start a connection Get started
Usability Shows some usage patterns for sending
Recipients How to send to multiple people, give an alias or send to self
Magical contents Really easy to send text, html, images and attachments
Feedback How to send me feedback
Roadmap (and priorities) Yup
Errors List of common errors for people dealing with sending emails

Install

For Python 2.x and Python 3.x respectively:

pip install yagmail[all]
pip3 install yagmail[all]

If you get problems installing keyring, try installing without, i.e. pip install yagmail.

As a side note, yagmail can now also be used to send emails from the command line.

Username and password

keyring quoted:

The Python keyring lib provides a easy way to access the system keyring service from python. It can be used in any application that needs safe password storage.

You know you want it. Set it up by opening a Python interpreter and running:

import yagmail
yagmail.register('mygmailusername', 'mygmailpassword')

In fact, it is just a wrapper for keyring.set_password('yagmail', 'mygmailusername', 'mygmailpassword').

When no password is given and the user is not found in the keyring, getpass.getpass() is used to prompt the user for a password. Upon entering this once, it can be stored in the keyring and never asked again.

Another convenience can be to save a .yagmail file in your home folder, containing just the email username. You can then omit everything, and simply use yagmail.SMTP() to connect. Of course, this wouldn't work with more accounts, but it might be a nice default. Upon request I'll consider adding more details to this .yagmail file (host, port and other settings).

Start a connection

yag = yagmail.SMTP('mygmailusername')

Note that this connection is reusable, closable and when it leaves scope it will clean up after itself in CPython.

As tilgovi points out in #39, SMTP does not automatically close in PyPy. The context manager with should be used in that case.

Usability

Defining some variables:

to = '[email protected]'
to2 = '[email protected]'
to3 = '[email protected]'
subject = 'This is obviously the subject'
body = 'This is obviously the body'
html = '<a href="https://pypi.python.org/pypi/sky/">Click me!</a>'
img = '/local/file/bunny.png'

All variables are optional, and know that not even to is required (you'll send an email to yourself):

yag.send(to = to, subject = subject, contents = body)
yag.send(to = to, subject = subject, contents = [body, html, img])
yag.send(contents = [body, img])

Furthermore, if you do not want to be explicit, you can do the following:

yag.send(to, subject, [body, img])

Recipients

It is also possible to send to a group of people by providing a list of email strings rather than a single string:

yag.send(to = to)
yag.send(to = [to, to2]) # List or tuples for emailadresses *without* aliases
yag.send(to = {to : 'Alias1'}) # Dictionary for emailaddress *with* aliases
yag.send(to = {to : 'Alias1', to2 : 'Alias2'}

Giving no to argument will send an email to yourself. In that sense, yagmail.SMTP().send() can already send an email. Be aware that if no explicit to = ... is used, the first argument will be used to send to. Can be avoided like:

yag.send(subject = 'to self', contents = 'hi!')

Note that by default all email addresses are conservatively validated using soft_email_validation==True (default).

Oauth2

It is even safer to use Oauth2 for authentication, as you can revoke the rights of tokens.

This is one of the best sources, upon which the oauth2 code is heavily based.

The code:

yag = SMTP("[email protected]", oauth2_file="~/oauth2_creds.json")
yag.send(subject="Great!")

It will prompt for a google_client_id and a google_client_secret, when the file cannot be found. These variables can be obtained following the previous link.

After you provide them, a link will be shown in the terminal that you should followed to obtain a google_refresh_token. Paste this again, and you're set up!

Note that people who obtain the file can send emails, but nothing else. As soon as you notice, you can simply disable the token.

Magical contents

The contents argument will be smartly guessed. It can be passed a string (which will be turned into a list); or a list. For each object in the list:

  • If it is a dictionary it will assume the key is the content and the value is an alias (only for images currently!) e.g. {'/path/to/image.png' : 'MyPicture'}
  • It will try to see if the content (string) can be read as a file locally, e.g. '/path/to/image.png'
  • if impossible, it will check if the string is valid html e.g. <h1>This is a big title</h1>
  • if not, it must be text. e.g. 'Hi Dorika!'

Note that local files can be html (inline); everything else will be attached.

Local files require to have an extension for their content type to be inferred.

As of version 0.4.94, raw and inline have been added.

  • raw ensures a string will not receive any "magic" (inlining, html, attaching)
  • inline will make an image appear in the text.

Feedback

I'll try to respond to issues within 24 hours at Github.....

And please send me a line of feedback with SMTP().feedback('Great job!') :-)

Roadmap (and priorities)

  • Added possibility of Image
  • Optional SMTP arguments should go with **kwargs to my SMTP
  • CC/BCC (high)
  • Custom names (high)
  • Allow send to return a preview rather than to actually send
  • Just use attachments in "contents", being smart guessed (high, complex)
  • Attachments (contents) in a list so they actually define the order (medium)
  • Use lxml to see if it can parse the html (low)
  • Added tests (high)
  • Allow caching of content (low)
  • Extra other types (low) (for example, mp3 also works, let me know if something does not work)
  • Probably a naming issue with content type/default type
  • Choose inline or not somehow (high)
  • Make lxml module optional magic (high)
  • Provide automatic fallback for complex content(medium) (should work)
  • yagmail as a command on CLI upon install
  • Added feedback function on SMTP to be able to send me feedback directly :-)
  • Added the option to validate emailaddresses...
  • however, I'm unhappy with the error handling/logging of wrong emails
  • Logging count & mail capability (very low)
  • Add documentation to exception classes (low)
  • add raw and inline
  • oauth2
  • ~~Travis CI integration ~~
  • ~~ Add documentation to all functions (high, halfway) ~~
  • Prepare for official 1.0
  • Go over documentation again (medium)
  • Allow .yagmail file to contain more parameters (medium)
  • Add option to shrink images (low)

Errors

  • Make sure you have a keyring entry (see section No more password and username), or use getpass to register. I discourage to use username / password in scripts.

  • smtplib.SMTPException: SMTP AUTH extension not supported by server

  • SMTPAuthenticationError: Application-specific password required

  • YagAddressError: This means that the address was given in an invalid format. Note that From can either be a string, or a dictionary where the key is an email, and the value is an alias {'[email protected]': 'Sam'}. In the case of 'to', it can either be a string (email), a list of emails (email addresses without aliases) or a dictionary where keys are the email addresses and the values indicate the aliases.

  • YagInvalidEmailAddress: Note that this will only filter out syntax mistakes in emailaddresses. If a human would think it is probably a valid email, it will most likely pass. However, it could still very well be that the actual emailaddress has simply not be claimed by anyone (so then this function fails to devalidate).

  • Click to enable the email for being used externally https://www.google.com/settings/security/lesssecureapps

  • Make sure you have a working internet connection

  • If you get an ImportError try to install with sudo, see issue #13

Donate

If you like yagmail, feel free (no pun intended) to donate any amount you'd like :-)

PayPal

Owner
Pascal van Kooten
AI / Deep learning enthusiast
Pascal van Kooten
Python script for imap, pop3, smtp and IPv4 analyze

Python script for imap, pop3, smtp and IPv4 analyze

Vladislav Kotletkin 1 Jan 30, 2022
A news curator and newsletter subscription package for Django

django-newsfeed What is django-newsfeed? django-newsfeed is a news curator and newsletter subscription package for django. It can be used to create a

Maksudul Haque 179 Nov 14, 2022
ghotok mail - lets you find available contact email addresses from target website

ghotok-mail ghotok mail - lets you find available contact email addresses from target website git clone https://github.com/josifkhan/ghotok-mail cd gh

Md Josif Khan 3 Mar 14, 2022
Python Email Sender (PES) is a program made with Python using smtplib, socket and tkinter.

Python Email Sender (PES) is a program made with Python using smtplib, socket and tkinter. This program was made for sender email to be a gmail account because that's what I used when testing it out,

Zacky2613 1 Aug 26, 2022
A functional demo of the O365 Module to send an email on an authenticated, tokenized account.

O365_email A functional demo of the O365 Module to send an email on an authenticated, tokenized account. Prep Create an app in Azure Developer's porta

2 Oct 14, 2022
A simple library project, a library function to make a temporary email, receive all messages

fake-email A simple library project, a library function to make a temporary email, receive all messages Installation : pip install fake-email Example

muntazir halim 13 Sep 15, 2022
An API to send emails through python3's smtplib module.

An API to send emails through python3's smtplib module. Just configure your SMTP server credentials and you are ready to send a lot of emails through API, designed to be used as a newsletter service.

Adnan Ahmad 15 Nov 24, 2022
This library is helpful when creating accounts, it has everything you need for this

AccountGeneratorHelper Library to facilitate accounts generation. Unofficial API for temp email services. Receive SMS from free services. Parsing and

Denis 52 Jan 07, 2023
利用阿里的云函数发送电子邮件

alifc_email 主要特性 利用阿里的云函数发送电子邮件 使用场景 hw中的钓鱼邮件发送,一些邮服会解析出邮件的来源ip(此来源ip并不是邮服的ip,而是从客户端发送邮件时,邮服自动带上的客户端ip),对于这些来源ip可能会做一些风控。 本项目利用云函数出口ip较多来绕过这些风控 使用方法 首

19 Dec 01, 2022
Send e-mails asyncronously using cron

django-yubin Django Yubin allows the programmer to control when he wants to send the e-mail in this application, making the web application to answer

APSL 44 Sep 24, 2022
Search email inbox with python and filter with search criteria via IMAP4 and fastapi or console

Search email inbox with python and filter with search criteria via IMAP4 and fastapi or console

Karma Computing 0 Sep 07, 2021
ParaskinioTouristOffices - This program sends a message to various email adresses

ParaskinioTouristOffices This program sends a message to various email adresses.

Odysseas Psomaderis 2 Feb 11, 2022
An OSINT program that allows you to uncover a censored domain in an email adress

An OSINT program that allows you to uncover a censored domain in an email adress. Useful when you extract email from Instagram or Twitter password recovery function.

aet 3 Dec 16, 2021
A Django app that allows you to send email asynchronously in Django. Supports HTML email, database backed templates and logging.

Django Post Office Django Post Office is a simple app to send and manage your emails in Django. Some awesome features are: Allows you to send email as

User Inspired 856 Dec 25, 2022
Simple, powerfull and nonobstructive django email middleware.

djmail djmail is a BSD Licensed, simple and nonobstructive django email middleware. Why use djmail? Because it: Sends emails asynchronously without ad

David Barragán Merino 77 Aug 30, 2021
Command line interface for sending email using SMTP (ships with Gmail configuration).

mailsend Description Lightweight command line interface for sending email using SMTP. Default configuration is set for Gmail (smtp.gmail.com at port 5

Keith Mathe 1 Mar 22, 2022
An email sending system with random confirmation code.

email_sending An email sending system with random confirmation code. Description Confirmation emails are sent based on the list of email addresses. Ea

Larissa Queiroz 2 Mar 22, 2022
Read/sync your IMAP mailboxes (python2)

Upstream status (master branch): Upstream status (next branch): Financial contributors: Links: Official github code repository: offlineimap Website: w

OfflineIMAP 1.7k Dec 29, 2022
ok-mail-helper是一个基于imap/smtp协议邮件客户端,使用python3.x开发

ok-mail-helper ok-mail-helper是一个基于imap/smtp协议邮件客户端,使用python3.x开发,支持邮件接收并解析、邮件发送,用户可在自己的项目中直接引入、开箱即用,或者结合flask等web框架轻松做成http接口供前端调用、把邮箱管理集成到自己的系统中,亦可通过

xlvchao 1 Feb 08, 2022
A small system for writing via email.

A small system for writing via email.

0 Nov 24, 2021