Giter Club home page Giter Club logo

yagmail's Introduction

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('mygmailusername', 'mygmailpassword')
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)

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
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
Attaching files How attach files to the email
DKIM Support Add DKIM signature to your emails with your private key
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]

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

Start a connection

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

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 = yagmail.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.

Preventing OAuth authorization from expiring after 7 days

Your Google Cloud Platform project's OAuth consent screen must be in "In production" publishing status before authorizing to not have the authorization expire after 7 days. See status at https://console.cloud.google.com/apis/credentials/consent

Your OAuth client ID must be of type "Desktop". Check at https://console.cloud.google.com/apis/credentials

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.

Attaching Files

There are multiple ways to attach files in the attachments parameter (in addition to magical contents parameter).

  1. One can pass a list of paths i.e.
yag.send(to=recipients,
         subject=email_subject,
         contents=contents,
         attachments=['path/to/attachment1.png', 'path/to/attachment2.pdf', 'path/to/attachment3.zip']
)
  1. One can pass an instance of io.IOBase.
with open('path/to/attachment', 'rb') as f:
    yag.send(to=recipients,
             subject=email_subject,
             contents=contents,
             attachments=f
             )

In this example f is an instance of _io.BufferedReader a subclass of the abstract class io.IOBase.

f has in this example the attribute .name, which is used by yagmail as filename as well as to detect the correct MIME-type. Not all io.IOBase instances have the .name attribute in which case yagmail names the attachments attachment1, attachment2, ... without a file extension! Therefore, it is highly recommended setting the filename with extension manually e.g. f.name = 'my_document.pdf'

A real-world example would be if the attachment is retrieved from a different source than the disk (e.g. downloaded from the internet or uploaded by a user in a web-application)

DKIM Support

To send emails with dkim signature, you need to install the package with all related packages.

pip install yagmail[all]
# or
pip install yagmail[dkim]

Usage:

from yagmail import SMTP
from yagmail.dkim import DKIM
from pathlib import Path

# load private key from file/secrets manager
private_key = Path("privkey.pem").read_bytes()

dkim_obj = DKIM(
  domain=b"a.com",
  selector=b"selector",
  private_key=private_key,
  include_headers=[b"To", b"From", b"Subject"],
  # To include all default headers just pass None instead
  # include_headers=None,
)

yag = SMTP(dkim=dkim_obj)

# all the rest is the same

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

  • 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

yagmail's People

Contributors

alphamodel avatar biogeek avatar bityob avatar dethwalker avatar dingxuefeng avatar doughoyt avatar gitter-badger avatar godod avatar jchristgit avatar jrkerns avatar kant-li avatar kootenpv avatar leffss avatar lin-ww avatar m2kar avatar madhav-datt avatar n0bel avatar nfg avatar nicdom avatar pyscriptbug avatar pyup-bot avatar shuding avatar sleepaqua avatar timgates42 avatar vikas-parashar avatar xnumad avatar xrisk avatar york-schlabrendorff-liqid avatar yvanz avatar zhengxiaowai avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

yagmail's Issues

pep8 fixes

The package contains a lot of pep8 issues, as per the standard. A package like pep8 can help you find non-compliant pep8 code.

Cannot make blank line in plaintext email

Hello,

Thanks for what's been a great tool so far.
However, I'm running into an issue where I can't seem to be able to send an entirely blank line in a plaintext email (i.e. no HTML).
My call looks something like this:

def send_email(self):
   self._yag.send(to = '<my email here>',
                  subject = '<subject here>',
                  contents = create_email_body())

where create_email_body() returns a list of strings, something like this:

def create_email_body():
    body = ['First line.', '\n', 'Second line.', 'Third line.']
    return [yagmail.yagmail.raw(s) for s in body]

And I would have wanted this to email as:

First line.

Second line.
Third line.

However, it always emails as:

First line.
Second line.
Third line.

I.e., I can't seem to be able to have a blank line in my plaintext email.

I have tried the above, and passing it as raw, passing it as a concatenated string, passing it as a raw'd concatenated string, having the newline character appear at the end/beginning of a value, other space characters like ' ' or '\t', etc., but no luck.
It always requires at least one normal character, upon which just that string shows up in the line.

Any thoughts?
I am currently using yagmail 0.4.110 on python 3.4.3.

PDF attachment is corrupt

I'm trying to send an email with a pdf attachment.

yag = yagmail.SMTP('[email protected]')
contents = ['This is the body, and here is just text', 'You can find a PDF file attached.', 'report.pdf']

yag.send('[email protected]', 'subject', contents)

The PDF cannot be opened by the receiver (it appears to be corrupt), but it's fine on the sender end. Is this an issue with Gmail SMTP?

python3 - SyntaxError: Missing parentheses in call to 'print'

I installed yagmail using pip for python3.
But when i want to import it in python intepreter i get the folowing error.

Python 3.5.0 (default, Sep 20 2015, 11:28:25) 
[GCC 5.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import yagmail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/site-packages/yagmail/__init__.py", line 6, in <module>
    from .yagmail import SMTP
  File "/usr/lib/python3.5/site-packages/yagmail/yagmail.py", line 7, in <module>
    import keyring
  File "/usr/lib/python3.5/site-packages/keyring/__init__.py", line 12, in <module>
    from .core import (set_keyring, get_keyring, set_password, get_password,
  File "/usr/lib/python3.5/site-packages/keyring/core.py", line 158, in <module>
    init_backend()
  File "/usr/lib/python3.5/site-packages/keyring/core.py", line 58, in init_backend
    set_keyring(load_config() or _get_best_keyring())
  File "/usr/lib/python3.5/site-packages/keyring/core.py", line 66, in _get_best_keyring
    keyrings = backend.get_all_keyring()
  File "/usr/lib/python3.5/site-packages/keyring/util/__init__.py", line 24, in wrapper
    func.always_returns = func(*args, **kwargs)
  File "/usr/lib/python3.5/site-packages/keyring/backend.py", line 179, in get_all_keyring
    _load_backends()
  File "/usr/lib/python3.5/site-packages/keyring/backend.py", line 139, in _load_backends
    list(map(_load_backend, backends))
  File "/usr/lib/python3.5/site-packages/keyring/backend.py", line 124, in _load_backend
    mod = importlib.import_module('.'+name, package)
  File "/usr/lib/python3.5/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "/usr/lib/python3.5/site-packages/keyring/backends/Gnome.py", line 4, in <module>
    import gi
  File "/usr/lib/python3.5/site-packages/gi/__init__.py", line 39
    print url
            ^
SyntaxError: Missing parentheses in call to 'print'
>>> 

using yagmail.smtp(), pyCharm asks for 'keyrings.alt'

Before reporting some issues, I'd like to thanks so much for making this module!
I was using Flask-mail, and there was some trouble with using it.
(it's last updated date was about 2 years ago , so i moved on to Yagmail!)

I was having some troubles with yagmail connections, so i changed my code like this. (left -> right)
(for some reason, it sometimes prints "[Error] Please run Connect() first" - maybe connection timed out?)
image
image

by changing this (one-liner) there were no more errors, but my pyCharm keeps prints "package requirement message." (though it works well!)

image

my question is
1.Why the Connect error occurs?
2.Why there is package requirement message?

Automatic cleanup should not be encouraged or relied upon

The README says "Note that this connection is reusable, closable and when it leaves scope it will clean up after itself."

I suspect that this is referring to CPython's reference counting garbage collection, but this is an implementation detail of CPython and not a specified behavior of the language.

On PyPy, I suspect following this advice would lead to leaks.

See also: http://doc.pypy.org/en/latest/cpython_differences.html#differences-related-to-garbage-collection-strategies

I would recommend removing this language from the README and encouraging people to always explicitly close connections.

Exception AttributeError: "SMTP instance has no attribute 'is_closed'"

I'm trying to send a mail but get the following error:

yag = yagmail.SMTP(conf['sender_username'], conf['sender_password'])
  File "/usr/local/lib/python2.7/dist-packages/yagmail/yagmail.py", line 54, in __init__
    self.user, self.useralias = self._make_addr_alias_user(user)
  File "/usr/local/lib/python2.7/dist-packages/yagmail/yagmail.py", line 305, in _make_addr_alias_user
    raise YagAddressError
yagmail.error.YagAddressError
Exception AttributeError: "SMTP instance has no attribute 'is_closed'" in <bound method SMTP.__del__ of <yagmail.yagmail.SMTP instance at 0x7fb99cb8ccf8>> ignored

Where my code looks like this, username and password are read from a JSON file and successfully printed.

contents='test \n test'
with yagmail.SMTP(conf['sender_username'], conf['sender_password']) as yag:
    yag.send(to=['[email protected]"], subject='testmail', content=contents)

Attachments corrupted

Following my tests on 'from' issue, I added attachments to the mail message using contents. I realized that almost all of them are coming corrupted (xslx, docx, pdf, zip -after changing extension to pass smtp security).
I believe I tested this option with older version a few days ago - but I am not sure about file formats used at that time.
Using the latest version of yagmail from 10/6/2015.

html strings not rendering

#...
contents = ['<h1>This is a big title</h1>', ]
yag.send(
    to=to,
    subject='html test',
    contents=contents)

email gets sent but renders as plain text with html tags.

OS: ubuntu 14.04
python: pyenv 3.4
client: thunderbird

HTML sent is not what is received

Using the code suggested here:
http://stackoverflow.com/questions/32911945/how-do-i-send-email-line-feeds-python-3-in-plain-text-mode-as-a-mime-alternate-w

I made slight modifications. I used '' (empty string) as the filename. Recipients was passed as a list instead of just one string.

With my HTML I specified some CSS also which I wrapped in the HTML header. It seems the CSS is ignored in the receive client; somehow it got mangled by yagmail.

I am passing this as HTML:

'css = <style>#stuff {border-radius: 25px;#etc..}</style>'

'safe_html = my_safe_html'

html ="

"+css+""+safe_html+""

'complete_html = add_styling(html, css)'

For the life of me I can't get the markdown here to display HTML code. It says use a quote for inline code but that doesn't work. Basically, though you probably can't see it, the css is in a header part of the HTML and the body is separated into a body part with div ids for the css tags (not included here). It works, just not in yagmail. Please use edit to see the gist.

issues with keyring dependency

Trying out yagmail on OS X El Capitan, Python 2.7.

I'm prevented from evaluating yagmail by errors coming from keyring. See jaraco/keyring#219.

Yagmail correctly retrieved the password once.

[Edit:] Yagmail/keyring works correctly outside of the virtualenv. This is a virtualenv issue.

bash: yagmail.register('username', 'password'): command not found

I've tried two methods to get the password out of my code:

yagmail.register('[email protected]', 'password)
that gives bash: syntax error near unexpected token `'[email protected]','
I looked up this error and added quotation marks because of this: http://askubuntu.com/questions/372926/bash-syntax-error-near-unexpected-token

So I now have: yagmail.register"('[email protected]', 'password"
that gives bash: yagmail.register('[email protected]', 'password'): command not found

Any ideas what I can change to do better here?

keyring for Rasberry Pi?

Does the keyring feature work on a rasberry pi? I have tried it on two of them and get the same error about no backend. How do I install a backend? pip import keyring shows keyring is installed. yagmail works great if I put the password in the script, but if I try to use yagmail.register or yagmail.SMTP() without a password I get the following error:

File "yag.py", line 2, in
yagmail.SMTP('[email protected]')
File "/usr/local/lib/python2.7/dist-packages/yagmail/yagmail.py", line 63, in init
self.login(password)
File "/usr/local/lib/python2.7/dist-packages/yagmail/yagmail.py", line 173, in login
password = self._handle_password(password)
File "/usr/local/lib/python2.7/dist-packages/yagmail/yagmail.py", line 137, in _handle_password
password = keyring.get_password('yagmail', self.user)
File "/usr/local/lib/python2.7/dist-packages/keyring/core.py", line 42, in get_password
return _keyring_backend.get_password(service_name, username)
File "/usr/local/lib/python2.7/dist-packages/keyring/backends/fail.py", line 18, in get_password
raise RuntimeError("No recommended backend was available. Install the "
RuntimeError: No recommended backend was available. Install the keyrings.alt package if you want to use the non-recommended backends. See README.rst for details.

From sender broken

Using the code suggested here:
http://stackoverflow.com/questions/32911945/how-do-i-send-email-line-feeds-python-3-in-plain-text-mode-as-a-mime-alternate-w

I made slight modifications. I used '' (empty string) as the filename. Recipients was passed as a list instead of just one string. However, the received 'From' title for the user who sent the email is recorded as 'username@'
Also, when you look at the email content in say a preview pane (this is Thunderbird on Linux Mint btw), I see the from as """username@ <"gmail.com username"@gmail.com>"""

Looking for contributor who could add OAuth2 to yagmail

I'm looking for someone who would want to write OAuth2 for yagmail. Remember: the goal of yagmail is to make it stupid simple for people to safely send emails with HTML, inline images and attachments.

Story:

Currently, I feel like yagmail provides plenty of options of running safely on a local PC. Passwordless scripts, getpass, manual password.

However, there are many situations in which people will want to automate a script (see also #16). This is not possible at the moment with a cronjob unfortunately; unless one is allowing a terminal to contain username/password, or some script to hold the username/password combination.

OAuth2, while a lot of effort to setup, would most certainly cater to other use cases / groups of people.

Implementation details: try to make it fit with the current code (no username/password, but oauth stuff as arguments), and I appreciate PEP8.

smtplib.SMTPServerDisconnected: please run connect()

Hi. When trying to send with a mail within a with section and with a body and an HTML file attached, I have this error.

Exception ignored in: <bound method SMTP.__del__ of <yagmail.yagmail.SMTP object at 0x101f08c18>>
Traceback (most recent call last):
  File "/Users/Steve/Library/Python/3.5/lib/python/site-packages/yagmail/yagmail.py", line 388, in __del__
    self.close()
  File "/Users/Steve/Library/Python/3.5/lib/python/site-packages/yagmail/yagmail.py", line 131, in close
    self.smtp.quit()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/smtplib.py", line 974, in quit
    res = self.docmd("quit")
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/smtplib.py", line 419, in docmd
    self.putcmd(cmd, args)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/smtplib.py", line 366, in putcmd
    self.send(str)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/smtplib.py", line 358, in send
    raise SMTPServerDisconnected('please run connect() first')
smtplib.SMTPServerDisconnected: please run connect() first

Displaying Styled Dataframes Inline

Hi - thanks for building this module.

Pandas 0.18 includes a style attribute that makes dataframes pretty. When rendered in html for inclusion in an email using render, the dataframe is nicely displayed inline as html and can be saved to an html file on the local path.

yagmail is able to send an email form a notebook, but the resulting message body contains degraded versions of the html dataframe rendering, irrespective of the method with which it was added to the yagmail code.

Code below shows an example of a styled dataframe which looks nice in a notebook. It is then converted to html and attempts are made to embed the html in-line with fidelity to the original styling. All attempts fail.

import numpy as np
import pandas as pd
import yagmail

#Create Array
num = np.array([[ 0.17899619,  0.33093259,  0.2076353,   0.06130814,],
            [ 0.20392888,  0.42653105,  0.33325891,  0.10473969,],
            [ 0.17038247,  0.19081956,  0.10119709,  0.09032416,],
            [-0.10606583, -0.13680513, -0.13129103, -0.03684349,],
            [ 0.20319428,  0.28340985,  0.20994867,  0.11728491,],
            [ 0.04396872,  0.23703525,  0.09359683,  0.11486036,],
            [ 0.27801304, -0.05769304, -0.06202813,  0.04722761,],])

days = ['5 days', '10 days', '20 days', '60 days']

prices = ['AAPL', 'ADBE', 'AMD', 'AMZN', 'CRM', 'EXPE', 'FB']

#Convert Array to DataFrame
df = pd.DataFrame(num, index=prices, columns=days)

#Style the DataFrame

df_styled = df.style\
  .bar(color='#d65f5f')\
  .set_precision(2)\
  .set_caption('Set Title of the Table')

# Render the styled df in html
df_styled_html = df_styled.render()

#Save the styled/rendered html tables as a file
with open('styled_rendered.html', 'w') as f:
    f.write(df_styled_html)

#Send email

yag = yagmail.SMTP()

subject = 'Styled DataFrame in HTML Format'

contents = [df_styled_html,
        'styled_rendered.html', 
        yagmail.inline(df_styled),
        yagmail.inline(df_styled_html),
        yagmail.inline('styled_rendered.html')]


yag.send('[email protected]', subject, contents)

When df_styled_html is passed, we get a CSS string in the body of the email. Perhaps the email code is not appplying CSS styules to the dataframe natively?

Thanks.

Adding from string

I have a fully functioning setup (BTW: great package!). I am not able only to add one point from my test list, adding name of the sender, next to email address itself. Is it possible in the current version?

Weirdness with smtp_skip_login

Hello!

I'm trying out yagmail at work. We have an internal SMTP server without any authentication, so when I instantiate the object, I have to pass in a true value for smtp_skip_login. However, when I send a message, I get an error like...

send: 'mail FROM:<@gmail.com> size=1089\r\n'
reply: '501 5.1.7 Invalid address\r\n'
reply: retcode (501); Msg: 5.1.7 Invalid address

From looking at the code, it looks like passing in smtp_skip_login wipes out user, and then self.user and self.useralias are set improperly. I can get around it by manually setting those two attributes after construction, but that seems weird.

Why is the constructor getting rid of the user data in this case? Am I doing something wrong?

Cheers!

How to specify 'raw'?

Hi there
Thanks for the package, working well.
I am using it with a textarea on a cherrypy site as follows.

def thankyou(self, feedback):
    import yagmail
    yag = yagmail.SMTP('greenbay.graham')
    yag.send(subject = 'subject', contents = feedback)

The email is being sent but I get this error in the error log

[yagmail] [ERROR] : Sending as text email since `lxml` is not installed

Reading the documentation it seems I need to specify that the 'feedback' is 'raw'
I am just not sure how to do this and I can't find any examples via google.
tia orotau

Proxy support

ps : socks project is clearly not working and outdated,

Using encrypted kering(yagmail.register) in production mode?

What I understand with keyrings,

Normally, in production environment (such as Ubuntu 16.04 without X11)
those environment might not have such kerying backends.

So, in these case, in yagmail recommends for keyrings.alt for one of keyring backend which is implemented by python.

But in this case, If I try to call yagmail.register , it keeps to pop-up prompt's with encrypted keyrings (such like this one)

Warning: Password input may be echoed.
Please enter password for encrypted keyring:

I think i understood why those password prompts are keep asking me for password
(to securely store password managed by OS , such as mac's keychain or Kde's KWallet (or Kleopatra))

So, It is totally legit (fine) for asking password when we access those keyrings.

But, If in production mode (deploying web-server application), we might demonize the process and manage them with system & service manager. (such as systemctl or systemd)

And in this case, the process will be run in daemon, so no one can input that ecrypted keyring password!!

  1. Is there are any possible ways to pass the password for encrypted keyring password with using yagmail.register in production mode? (When in Demonized process)
  • One solution is not using yagmail.register and use yagmail.smtp(), but I really won't look foward to use this solution...
  1. In Production mode, How people usually implements with these yagmail register thing?

Auto suffix adding on email authentication - why?

With this code:

import yagmail

def send_email():
"""Send an email"""
yag = yagmail.SMTP(user='[email protected]', password='password',
host='mail.mycompany.com', port=587,
smtp_starttls = False, smtp_skip_login = True) # also tried port 25

attachments = []
yag.send('[email protected]', 'Some text', ['The content of the email'], attachments)

if name == 'main':
send_email()

I see the error:
smtplib.SMTPSenderRefused: (501, b'5.1.7 Invalid address', '@gmail.com')

Why is it adding @gmail.com when I choose to smtp_skip_login? I simply want to avoid all authentication, gmail is not relevant here.

MIMEPart alternative support

Using the code suggested here:
http://stackoverflow.com/questions/32911945/how-do-i-send-email-line-feeds-python-3-in-plain-text-mode-as-a-mime-alternate-w

I made slight modifications. I used '' (empty string) as the filename. Recipients was passed as a list instead of just one string. I was keen to see MIMEpart alternative supported. My understanding of this is you send both HTML and text in your email to a receiver and the receiver's email client has a setting to view as pure text or pure HTML. That said, it should only display the text part or only display the HTML part. At present if you view HTML in Thunderbird on Linux Mint (Ubuntu/deb variant), you see poorly formatted HTML (not what I sent) and the text below in HTML viewing mode. In text viewing mode I see the HTML part with tags removed AND the text part below. Basically I should see one OR the other, not both HTML and text in either case. Also, the HTML is broken even in HTML mode but perhaps that is another ticket.

no module named error

Hello,

Right after installing yagmail with pip install I get this error as soon as I import the module:

import yagmail
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python2.7/site-packages/yagmail/init.py", line 6, in
from .yagmail import SMTP
File "/usr/local/lib/python2.7/site-packages/yagmail/yagmail.py", line 16, in
from .validate import validate_email_with_regex
File "/usr/local/lib/python2.7/site-packages/yagmail/validate.py", line 31, in
from yagmail.error import YagInvalidEmailAddress
ImportError: No module named error

What could this be?

user / useralias for non gmail address

when specifiying an username without an "@" gmail.com is always appended as a suffix. This prevents from authenticating with my smtp server.

Also is it inteded behaviour that user and useralias are always the same thing?

I would propse to have an option that disables this autocompletion.
If you agree I could prepare a pull request if you like.

always prompts for keyring password on Ubuntu

After registering the user and email, it prompts everytime for the encrypted keyring password.
yag = yagmail.SMTP()
Please enter password for encrypted keyring:

Works fine on Mac Os

ValueError: stat: path too long for Windows

I'm sending a long-ish email (HTML) and am receiving this error when sending on Windows. I'm assuming this happens because of Windows file path limit and because, as the README says, the contents argument 'will try to see if the content (string) can be read as a file locally, e.g. '/path/to/image.png''.

The last few entries from the traceback are

...
  File "[path]\yagmail\yagmail.py", line 98, in send
    msg = self._prepare_message(addresses, subject, contents, attachments, headers)
  File "[path]\yagmail\yagmail.py", line 217, in _prepare_message
    has_included_images, content_objects = self._prepare_contents(contents)
  File "[path]\yagmail\yagmail.py", line 276, in _prepare_contents
    content_object = self._get_mime_object(content)
  File "[path]\yagmail\yagmail.py", line 347, in _get_mime_object
    if os.path.isfile(content_string) and not is_raw:
  File "[path]\lib\genericpath.py", line 30, in isfile
    st = os.stat(path)
ValueError: stat: path too long for Windows

Is there a way to get around this?

import yagmail

As noob I tried yagmail. But I got pretty fast stuckted in an error
I installed both
pip install yagmail
pip3 install yagmail

Ended in:
Successfully installed yagmail keyring secretstorage pycrypto
Cleaning up...

then I copied the example as provide

import yagmail

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

With this as result.

File "test.py", line 1, in
import yagmail
ImportError: No module named yagmail

Tried serveral things like starting from different directories..
Any clue how to solve this?

smtplib.SMTPAuthenticationError, Unrecognized command, gsmtp

Python 3.5.0 (default, Sep 20 2015, 11:28:25) 
[GCC 5.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import yagmail
>>> yag = yagmail.SMTP('mymail', 'pass')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/site-packages/yagmail/yagmail.py", line 68, in __init__
    self.login(password)
  File "/usr/lib/python3.5/site-packages/yagmail/yagmail.py", line 179, in login
    self.smtp.login(self.user, password)
  File "/usr/lib/python3.5/smtplib.py", line 730, in login
    raise last_exception
  File "/usr/lib/python3.5/smtplib.py", line 721, in login
    initial_response_ok=initial_response_ok)
  File "/usr/lib/python3.5/smtplib.py", line 627, in auth
    initial_response = (authobject() if initial_response_ok else None)
  File "/usr/lib/python3.5/smtplib.py", line 664, in auth_login
    raise SMTPAuthenticationError(code, resp)
smtplib.SMTPAuthenticationError: (502, b'5.5.1 Unrecognized command. s189sm27502265wmf.16 - gsmtp')
>>> 

AttributeError: Connect instance has no attribute 'host'

Running your simple test example..

File "/usr/local/lib/python2.7/dist-packages/yagmail/init.py", line 31, in init
self.login(password)
File "/usr/local/lib/python2.7/dist-packages/yagmail/init.py", line 65, in login
self.smtp = smtplib.SMTP(self.host, self.port)
AttributeError: Connect instance has no attribute 'host'
shutting...
Exception AttributeError: "Connect instance has no attribute 'smtp'" in <bound method Connect.del of <yagmail.Connect instance at 0x7fad75949998>> ignored

yagmail fails when smtplib triumphs

Ran this code and got the dreadful SMTPAuthenticationError:

import yagmail
yag = yagmail.SMTP('[email protected]', 'xx')
contents = ['This is the body text']
yag.send('[email protected]', 'subject', contents)

If I replace the contents of the file with plain smtplib code, it works great:
http://pastie.org/private/f4vbuy9ivcioqiutwbg

Ouch!! Now somebody tell me why :-)

Disclamer: Evrything has been taken care on gmail side to allow access, that's why smtplib works, btw

Insecure Gmail access

Running yagmail against a Gmail account returns an error from the Gmail server rejecting the connection. Following the links provided from Google, it seems this app would require lowering the security on the email account to "allow access for less secure apps".

Unneccessarily long error message

When I enter the password for the keychain, if I get it wrong, I get the error message:

File "yagtest.py", line 4, in <module>
    yag = yagmail.Connect('[email protected]')
  File "/usr/local/lib/python2.7/dist-packages/yagmail/yagmail.py", line 42, in __init__
    self.login(password)
  File "/usr/local/lib/python2.7/dist-packages/yagmail/yagmail.py", line 120, in login
    password = keyring.get_password('yagmail', self.user)
  File "/usr/local/lib/python2.7/dist-packages/keyring/core.py", line 38, in get_password
    return _keyring_backend.get_password(service_name, username)
  File "/usr/local/lib/python2.7/dist-packages/keyring/backends/file.py", line 75, in get_password
    password = self.decrypt(password_encrypted).decode('utf-8')
  File "/usr/local/lib/python2.7/dist-packages/keyring/backends/file.py", line 286, in decrypt
    cipher = self._create_cipher(self.keyring_key, data['salt'],
  File "/usr/local/lib/python2.7/dist-packages/keyring/util/properties.py", line 52, in __get__
    return self.fget(obj)
  File "/usr/local/lib/python2.7/dist-packages/keyring/backends/file.py", line 213, in keyring_key
    self._unlock()
  File "/usr/local/lib/python2.7/dist-packages/keyring/backends/file.py", line 258, in _unlock
    raise ValueError("Incorrect Password")
ValueError: Incorrect Password

Instead, you could use:
try: main()
except IncorrectPasswordError: print 'Incorrect Password'
And create an IncorrectPasswordError class:
class IncorrectPasswordError(Exception):
pass

Image compression

I am working on image compression for attachments. Should I try lossy or losslesss compresion?

AttributeError: 'UUID' object has no attribute 'rfind'`

Hello!

I'm getting this error when I try to send an email with yagmail. At this point, I have my password in the code, since I am just testing it out. Here is what my code looks like, followed by the error message:

yag = yagmail.SMTP('<MYEMAILREDACTED>', '<MYPWREDACTED>') contents = ['This is the body, and here is your pwreset key:', key, 'Did that work?'] yag.send('<EMAILREDACTED>', 'TEST', contents)

error below:

Traceback (most recent call last): File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/flask/app.py", line 1836, in __call__ return self.wsgi_app(environ, start_response) File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/flask/app.py", line 1820, in wsgi_app response = self.make_response(self.handle_exception(e)) File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/flask/app.py", line 1403, in handle_exception reraise(exc_type, exc_value, tb) File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise raise value File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/flask/app.py", line 1817, in wsgi_app response = self.full_dispatch_request() File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/flask/app.py", line 1477, in full_dispatch_request rv = self.handle_user_exception(e) File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/flask/app.py", line 1381, in handle_user_exception reraise(exc_type, exc_value, tb) File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise raise value File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/flask/app.py", line 1475, in full_dispatch_request rv = self.dispatch_request() File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/flask/app.py", line 1461, in dispatch_request return self.view_functions[rule.endpoint](**req.view_args) File "/home/ubuntu/workspace/crossword/crossword/views.py", line 405, in pwresetrq_post yag.send('<REDACTED>', 'TEST', contents) File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/yagmail/yagmail.py", line 98, in send msg = self._prepare_message(addresses, subject, contents, attachments, headers) File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/yagmail/yagmail.py", line 217, in _prepare_message has_included_images, content_objects = self._prepare_contents(contents) File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/yagmail/yagmail.py", line 276, in _prepare_contents content_object = self._get_mime_object(content) File "/home/ubuntu/workspace/crossword/env/lib/python3.4/site-packages/yagmail/yagmail.py", line 343, in _get_mime_object content_name = os.path.basename(content_string) File "/usr/lib/python3.4/posixpath.py", line 139, in basename i = p.rfind(sep) + 1 AttributeError: 'UUID' object has no attribute 'rfind'

Can you help me figure out what I need to fix this? Thanks!

smtplib.SMTPServerDisconnected: Server not connected

Getting error mentioned in title. Someone please help.

code:

#!/usr/bin/env python3

import yagmail

from hackerutils import get_dotenv

dotenv = get_dotenv()

GMAIL_USERNAME = dotenv['GMAIL_USERNAME']
GMAIL_PASSWORD = dotenv['GMAIL_PASSWORD']

yagmail.register(GMAIL_USERNAME, GMAIL_PASSWORD)

def main():
    yag = yagmail.SMTP(GMAIL_USERNAME)
    yag.send(
        '[email protected]',
        'testing',
        'This is a fucking test you BITCH!',
        )

if __name__ == '__main__':
    main()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.